/src/storage/ChecksumValidator.cpp

https://gitlab.com/github-cloud-corporation/cynara · C++ · 128 lines · 87 code · 20 blank · 21 comment · 17 complexity · ede5a5c5e4c97d9240d16f35e05d8696 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/storage/ChecksumValidator.cpp
  18. * @author Pawel Wieczorek <p.wieczorek2@samsung.com>
  19. * @version 1.0
  20. * @brief This file contains ChecksumValidator implementation.
  21. */
  22. #include <algorithm>
  23. #include <cstdlib>
  24. #include <cstring>
  25. #include <fstream>
  26. #include <memory>
  27. #include <new>
  28. #include <sstream>
  29. #include <config/PathConfig.h>
  30. #include <exceptions/ChecksumRecordCorruptedException.h>
  31. #include <exceptions/UnexpectedErrorException.h>
  32. #include <log/log.h>
  33. #include <md5wrapper.h>
  34. #include "ChecksumValidator.h"
  35. namespace Cynara {
  36. void ChecksumValidator::load(std::istream &stream) {
  37. m_sums.clear();
  38. std::string line;
  39. std::size_t lineNum = 1;
  40. while (std::getline(stream, line, PathConfig::StoragePath::recordSeparator)) {
  41. try {
  42. std::size_t beginToken = 0;
  43. std::string filename = parseFilename(line, beginToken);
  44. std::string checksum = parseChecksum(line, beginToken);
  45. m_sums.insert({ filename, checksum });
  46. ++lineNum;
  47. } catch (const ChecksumRecordCorruptedException &ex) {
  48. throw ex.withLineNumber(lineNum);
  49. }
  50. }
  51. };
  52. const std::string ChecksumValidator::generate(const std::string &data) {
  53. return generateMD5(data);
  54. }
  55. void ChecksumValidator::compare(std::istream &stream, const std::string &pathname,
  56. bool isBackupValid) {
  57. if (isChecksumIndex(pathname)) {
  58. return;
  59. }
  60. std::unique_ptr<char, decltype(free)*> pathnameDuplicate(strdup(pathname.c_str()), free);
  61. if (pathnameDuplicate == nullptr) {
  62. LOGE("Insufficient memory available to allocate duplicate filename: <%s>",
  63. pathname.c_str());
  64. throw std::bad_alloc();
  65. }
  66. std::string filename(::basename(pathnameDuplicate.get()));
  67. std::stringstream copyStream;
  68. if (isBackupValid) {
  69. auto backupSuffixPos = filename.rfind(PathConfig::StoragePath::backupFilenameSuffix);
  70. size_t suffixSize = PathConfig::StoragePath::backupFilenameSuffix.size();
  71. if ((std::string::npos != backupSuffixPos) &&
  72. (filename.size() == (backupSuffixPos + suffixSize))) {
  73. filename.erase(backupSuffixPos);
  74. }
  75. }
  76. std::copy(std::istreambuf_iterator<char>(stream),
  77. std::istreambuf_iterator<char>(),
  78. std::ostreambuf_iterator<char>(copyStream));
  79. stream.seekg(0);
  80. if (m_sums[filename] != generate(copyStream.str())) {
  81. throw ChecksumRecordCorruptedException(m_sums[filename]);
  82. }
  83. };
  84. const std::string ChecksumValidator::parseFilename(const std::string &line,
  85. std::size_t &beginToken) {
  86. std::size_t filenameEndToken = line.find(PathConfig::StoragePath::fieldSeparator, beginToken);
  87. if (filenameEndToken != beginToken && filenameEndToken != std::string::npos) {
  88. auto filename = line.substr(beginToken, filenameEndToken - beginToken);
  89. beginToken = filenameEndToken + 1;
  90. return filename;
  91. }
  92. throw ChecksumRecordCorruptedException(line);
  93. }
  94. const std::string ChecksumValidator::parseChecksum(const std::string &line,
  95. std::size_t &beginToken) {
  96. if (beginToken >= line.size()) {
  97. throw ChecksumRecordCorruptedException(line);
  98. }
  99. auto checksum = line.substr(beginToken);
  100. beginToken = line.size();
  101. return checksum;
  102. }
  103. bool ChecksumValidator::isChecksumIndex(const std::string &filename) const {
  104. auto checksum = m_dbPath + PathConfig::StoragePath::checksumFilename;
  105. return (filename == checksum ||
  106. filename == checksum + PathConfig::StoragePath::backupFilenameSuffix);
  107. }
  108. } // namespace Cynara