--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+/**
+ * @file src/storage/ChecksumValidator.cpp
+ * @author Pawel Wieczorek <p.wieczorek2@samsung.com>
+ * @version 1.0
+ * @brief This file contains ChecksumValidator implementation.
+ */
+
+#include <algorithm>
+#include <cstdlib>
+#include <cstring>
+#include <fstream>
+#include <memory>
+#include <new>
+#include <sstream>
+#include <unistd.h>
+
+#include <config/PathConfig.h>
+#include <exceptions/ChecksumRecordCorruptedException.h>
+#include <exceptions/UnexpectedErrorException.h>
+#include <log/log.h>
+
+#include "ChecksumValidator.h"
+
+namespace Cynara {
+
+const std::string ChecksumValidator::m_checksumFilename(PathConfig::StoragePath::checksumFilename);
+const std::string ChecksumValidator::m_backupFilenameSuffix(
+ PathConfig::StoragePath::backupFilenameSuffix);
+
+void ChecksumValidator::load(std::istream &stream) {
+ m_sums.clear();
+
+ std::string line;
+ std::size_t lineNum = 1;
+ while (std::getline(stream, line, PathConfig::StoragePath::recordSeparator)) {
+ try {
+ std::size_t beginToken = 0;
+ std::string filename = parseFilename(line, beginToken);
+ std::string checksum = parseChecksum(line, beginToken);
+
+ m_sums.insert({ filename, checksum });
+ ++lineNum;
+ } catch (const ChecksumRecordCorruptedException &ex) {
+ throw ex.withLineNumber(lineNum);
+ }
+ }
+};
+
+const std::string ChecksumValidator::generate(const std::string &data) {
+ const char *checksum = crypt(data.c_str(), "$1$");
+
+ if (nullptr != checksum) {
+ return checksum;
+ }
+
+ int err = errno;
+ if (err == ENOSYS) {
+ LOGE("'crypt' function was not implemented; error [%d] : <%s>", err, strerror(err));
+ } else {
+ LOGE("'crypt' function error [%d] : <%s>", err, strerror(err));
+ }
+ throw UnexpectedErrorException(err, strerror(err));
+};
+
+void ChecksumValidator::compare(std::istream &stream, const std::string &pathname,
+ bool isBackupValid) {
+ if (isChecksumIndex(pathname)) {
+ return;
+ }
+
+ std::unique_ptr<char, decltype(free)*> pathnameDuplicate(strdup(pathname.c_str()), free);
+ if (pathnameDuplicate == nullptr) {
+ LOGE("Insufficient memory available to allocate duplicate filename: <%s>",
+ pathname.c_str());
+ throw std::bad_alloc();
+ }
+
+ std::string filename(::basename(pathnameDuplicate.get()));
+ std::stringstream copyStream;
+
+ if (isBackupValid) {
+ auto backupSuffixPos = filename.rfind(m_backupFilenameSuffix);
+
+ if ((std::string::npos != backupSuffixPos) &&
+ (filename.size() == (backupSuffixPos + m_backupFilenameSuffix.size()))) {
+ filename.erase(backupSuffixPos);
+ }
+ }
+
+ std::copy(std::istreambuf_iterator<char>(stream),
+ std::istreambuf_iterator<char>(),
+ std::ostreambuf_iterator<char>(copyStream));
+ stream.seekg(0);
+
+ if (m_sums[filename] != generate(copyStream.str())) {
+ throw ChecksumRecordCorruptedException(m_sums[filename]);
+ }
+};
+
+const std::string ChecksumValidator::parseFilename(const std::string &line,
+ std::size_t &beginToken) {
+ std::size_t filenameEndToken = line.find(PathConfig::StoragePath::fieldSeparator, beginToken);
+ if (filenameEndToken != beginToken && filenameEndToken != std::string::npos) {
+ auto filename = line.substr(beginToken, filenameEndToken - beginToken);
+ beginToken = filenameEndToken + 1;
+ return filename;
+ }
+ throw ChecksumRecordCorruptedException(line);
+}
+
+const std::string ChecksumValidator::parseChecksum(const std::string &line,
+ std::size_t &beginToken) {
+ if (beginToken >= line.size()) {
+ throw ChecksumRecordCorruptedException(line);
+ }
+
+ auto checksum = line.substr(beginToken);
+ beginToken = line.size();
+ return checksum;
+}
+
+bool ChecksumValidator::isChecksumIndex(const std::string &filename) const {
+ auto checksum = m_dbPath + m_checksumFilename;
+ return (filename == checksum || filename == checksum + m_backupFilenameSuffix);
+}
+
+} // namespace Cynara
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+/**
+ * @file src/storage/ChecksumValidator.h
+ * @author Pawel Wieczorek <p.wieczorek2@samsung.com>
+ * @version 1.0
+ * @brief This file contains ChecksumValidator header.
+ */
+
+#ifndef SRC_STORAGE_CHECKSUMVALIDATOR_H_
+#define SRC_STORAGE_CHECKSUMVALIDATOR_H_
+
+#include <fstream>
+#include <memory>
+#include <string>
+#include <unordered_map>
+
+namespace Cynara {
+
+class ChecksumValidator;
+typedef std::unique_ptr<ChecksumValidator> ChecksumValidatorUniquePtr;
+
+class ChecksumValidator {
+public:
+ ChecksumValidator(const std::string &path) : m_dbPath(path) {}
+
+ void load(std::istream &stream);
+ void compare(std::istream &stream, const std::string &pathname, bool isBackupValid);
+
+ void clear(void) {
+ m_sums.clear();
+ }
+
+ static const std::string generate(const std::string &data);
+
+protected:
+ typedef std::unordered_map<std::string, std::string> Checksums;
+
+ bool isChecksumIndex(const std::string &pathname) const;
+
+ static const std::string parseFilename(const std::string &line, std::size_t &beginToken);
+ static const std::string parseChecksum(const std::string &line, std::size_t &beginToken);
+
+ Checksums m_sums;
+ const std::string m_dbPath;
+ static const std::string m_checksumFilename;
+ static const std::string m_backupFilenameSuffix;
+};
+
+} // namespace Cynara
+
+#endif // SRC_STORAGE_CHECKSUMVALIDATOR_H_