PageRenderTime 26ms CodeModel.GetById 0ms RepoModel.GetById 0ms app.codeStats 0ms

/src/chsgen/ChecksumGenerator.cpp

https://gitlab.com/github-cloud-corporation/cynara
C++ | 189 lines | 139 code | 28 blank | 22 comment | 21 complexity | c0b9aa90830b4e20cf7d14f5d37b7c4f MD5 | raw file
  1. /*
  2. * Copyright (c) 2015-2016 Samsung Electronics Co., Ltd All Rights Reserved
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. /**
  17. * @file src/chsgen/ChecksumGenerator.cpp
  18. * @author Pawel Wieczorek <p.wieczorek2@samsung.com>
  19. * @version 1.0
  20. * @brief A micro-tool for computing checksums for Cynara's database contents
  21. */
  22. #include <algorithm>
  23. #include <cstring>
  24. #include <iostream>
  25. #include <memory>
  26. #include <new>
  27. #include <sstream>
  28. #include <stdexcept>
  29. #include <string>
  30. #include <unistd.h>
  31. #include <cynara-error.h>
  32. #include <md5wrapper.h>
  33. #include "ChecksumGenerator.h"
  34. namespace Cynara {
  35. namespace {
  36. // command line options
  37. enum CommandLineOption {
  38. ExtraParameter = '-',
  39. Algorithm = 'a',
  40. Help = 'h'
  41. };
  42. const char OptionRequiresParameter = ':';
  43. const int CommandLineExtraParameter = 1;
  44. const std::string OPTION_MD5 = "md5";
  45. const std::string OPTION_CRYPT = "crypt";
  46. void printHelp(const char *exeName) {
  47. static int done = 0;
  48. if (!done) {
  49. std::cout << "Usage: " << exeName << " FILE [OPTION]" << std::endl << std::endl <<
  50. "Options:\n"
  51. "\t-" << static_cast<char>(CommandLineOption::Algorithm) <<
  52. " ALGORITHM use selected algorith to count hash. Currently this "
  53. "tool supports 'crypt' and 'md5'. 'crypt' is used as the default value " <<
  54. "for backward compatibility." << std::endl <<
  55. "\t-" << static_cast<char>(CommandLineOption::Help) <<
  56. " print this help" << std::endl;
  57. done = 1;
  58. }
  59. }
  60. std::string generateCrypt(const std::string &data) {
  61. const char *checksum = crypt(data.c_str(), "$1$");
  62. if (nullptr != checksum) {
  63. return std::string(checksum);
  64. } else {
  65. int err = errno;
  66. if (err == ENOSYS) {
  67. std::cerr << "'crypt' function was not implemented; error [" << err << "] : <"
  68. << strerror(err) << ">" << std::endl;
  69. } else {
  70. std::cerr << "'crypt' function error [" << err << "] : <" << strerror(err) << ">"
  71. << std::endl;
  72. }
  73. throw std::runtime_error(strerror(err));
  74. }
  75. }
  76. std::ostream &operator<<(std::ostream &os, CommandLineOption opt) {
  77. return os << static_cast<char>(opt);
  78. }
  79. } // namespace
  80. const char ChecksumGenerator::m_fieldSeparator(';');
  81. const char ChecksumGenerator::m_recordSeparator('\n');
  82. const std::string ChecksumGenerator::m_backupFilenameSuffix("~");
  83. ChecksumGenerator::ChecksumGenerator(int argc, char * const *argv)
  84. : m_algorithm(OPTION_CRYPT)
  85. {
  86. optind = 0;
  87. const char *exeName = "cynara-db-chsgen";
  88. if (argc > 0 && argv[0])
  89. exeName = argv[0];
  90. int option;
  91. std::stringstream shortOptions;
  92. shortOptions << CommandLineOption::ExtraParameter << CommandLineOption::Help
  93. << CommandLineOption::Algorithm << OptionRequiresParameter;
  94. while ((option = getopt(argc, argv, shortOptions.str().c_str())) != -1) {
  95. switch(option) {
  96. default:
  97. throw std::runtime_error("Unknown option. Please read help for list of supported "
  98. "options.");
  99. break;
  100. case CommandLineExtraParameter:
  101. m_pathname = optarg;
  102. break;
  103. case CommandLineOption::Algorithm:
  104. m_algorithm = optarg;
  105. break;
  106. case CommandLineOption::Help:
  107. printHelp(exeName);
  108. break;
  109. }
  110. }
  111. }
  112. int ChecksumGenerator::run(void) {
  113. try {
  114. openFileStream();
  115. copyFileStream();
  116. printRecord();
  117. return CYNARA_API_SUCCESS;
  118. } catch (const std::exception &ex) {
  119. std::cerr << ex.what() << std::endl;
  120. return CYNARA_API_UNKNOWN_ERROR;
  121. }
  122. }
  123. const std::string ChecksumGenerator::generate(const std::string &data) const {
  124. if (m_algorithm == OPTION_CRYPT)
  125. return generateCrypt(data);
  126. if (m_algorithm == OPTION_MD5)
  127. return generateMD5(data);
  128. throw std::runtime_error("Unknown option value.");
  129. };
  130. void ChecksumGenerator::openFileStream(void) {
  131. m_inputStream.open(m_pathname);
  132. if (!m_inputStream.is_open()) {
  133. throw std::runtime_error(std::string("File not found: ") + m_pathname);
  134. }
  135. }
  136. void ChecksumGenerator::copyFileStream(void) {
  137. std::copy(std::istreambuf_iterator<char>(m_inputStream),
  138. std::istreambuf_iterator<char>(),
  139. std::ostreambuf_iterator<char>(m_copyStream));
  140. m_inputStream.seekg(0);
  141. }
  142. void ChecksumGenerator::printRecord(void) const {
  143. std::unique_ptr<char, decltype(free)*> pathnameDuplicate(strdup(m_pathname.c_str()), free);
  144. if (pathnameDuplicate == nullptr) {
  145. std::cerr << "Insufficient memory available to allocate duplicate filename: <"
  146. << m_pathname << ">" << std::endl;
  147. throw std::bad_alloc();
  148. }
  149. std::string basename(::basename(pathnameDuplicate.get()));
  150. removeBackupSuffix(basename);
  151. std::cout << basename << m_fieldSeparator << generate(m_copyStream.str())
  152. << m_recordSeparator;
  153. }
  154. void ChecksumGenerator::removeBackupSuffix(std::string &filename) const {
  155. auto backupSuffixPos = filename.rfind(m_backupFilenameSuffix);
  156. if (std::string::npos != backupSuffixPos &&
  157. filename.size() == backupSuffixPos + m_backupFilenameSuffix.size()) {
  158. filename.erase(backupSuffixPos);
  159. }
  160. }
  161. } /* namespace Cynara */