From ade975a1adee49a10d31f5967773128f1c1ca9a8 Mon Sep 17 00:00:00 2001 From: zhuruigan Date: Fri, 19 Jan 2024 15:48:28 +0800 Subject: [PATCH] =?UTF-8?q?utils=E6=96=B0=E5=A2=9E=E6=96=87=E4=BB=B6hash?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=92=8C=E5=A2=9E=E9=87=8F=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zhuruigan Change-Id: I2d39f507781f5d72adb84de6039ddacbfaa8e5e7 --- bundle.json | 4 +- utils/BUILD.gn | 6 + utils/include/b_filesystem/b_file_hash.h | 32 +++++ utils/include/b_json/b_report_entity.h | 66 ++++++++++ utils/src/b_filesystem/b_file_hash.cpp | 91 +++++++++++++ utils/src/b_json/b_report_entity.cpp | 159 +++++++++++++++++++++++ 6 files changed, 357 insertions(+), 1 deletion(-) create mode 100644 utils/include/b_filesystem/b_file_hash.h create mode 100644 utils/include/b_json/b_report_entity.h create mode 100644 utils/src/b_filesystem/b_file_hash.cpp create mode 100644 utils/src/b_json/b_report_entity.cpp diff --git a/bundle.json b/bundle.json index b65b71f17..079e67afd 100644 --- a/bundle.json +++ b/bundle.json @@ -42,7 +42,9 @@ ], "third_party": [ "bounds_checking_function", - "jsoncpp" + "googletest", + "jsoncpp", + "openssl" ] }, "adapted_system_type": [ "small", "standard" ], diff --git a/utils/BUILD.gn b/utils/BUILD.gn index ff90af981..80d89ae3e 100644 --- a/utils/BUILD.gn +++ b/utils/BUILD.gn @@ -83,8 +83,10 @@ ohos_shared_library("backup_utils") { "src/b_error/b_excep_utils.cpp", "src/b_filesystem/b_dir.cpp", "src/b_filesystem/b_file.cpp", + "src/b_filesystem/b_file_hash.cpp", "src/b_json/b_json_entity_ext_manage.cpp", "src/b_json/b_json_entity_extension_config.cpp", + "src/b_json/b_report_entity.cpp", "src/b_ohos/startup/backup_para.cpp", "src/b_process/b_guard_cwd.cpp", "src/b_process/b_guard_signal.cpp", @@ -109,6 +111,7 @@ ohos_shared_library("backup_utils") { "${path_backup}/interfaces/inner_api/native/backup_kit_inner/impl", "${path_rust}/crates/cxx/include", "${target_gen_dir}/rust/src", + "//third_party/openssl/include", ] deps = [ @@ -116,8 +119,11 @@ ohos_shared_library("backup_utils") { ":backup_cxx_gen", ":backup_cxx_rust", "${path_jsoncpp}:jsoncpp", + "//third_party/openssl:libcrypto_shared", ] + defines = [ "OPENSSL_SUPPRESS_DEPRECATED" ] + use_exceptions = true innerapi_tags = [ "platformsdk" ] part_name = "app_file_service" diff --git a/utils/include/b_filesystem/b_file_hash.h b/utils/include/b_filesystem/b_file_hash.h new file mode 100644 index 000000000..1234a04b6 --- /dev/null +++ b/utils/include/b_filesystem/b_file_hash.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * 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. + */ + +#ifndef OHOS_FILEMGMT_BACKUP_B_FILE_HASH_H +#define OHOS_FILEMGMT_BACKUP_B_FILE_HASH_H + +#include +#include + +namespace OHOS::FileManagement::Backup { +using namespace std; +class BFileHash { +public: + static std::tuple HashWithMD5(const std::string &fpath); + static std::tuple HashWithSHA1(const std::string &fpath); + static std::tuple HashWithSHA256(const std::string &fpath); +}; +} // namespace OHOS::FileManagement::Backup + +#endif // OHOS_FILEMGMT_BACKUP_B_FILE_HASH_H \ No newline at end of file diff --git a/utils/include/b_json/b_report_entity.h b/utils/include/b_json/b_report_entity.h new file mode 100644 index 000000000..9ebe8965b --- /dev/null +++ b/utils/include/b_json/b_report_entity.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * 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. + */ + +#ifndef OHOS_FILEMGMT_BACKUP_B_REPORT_ENTITY_H +#define OHOS_FILEMGMT_BACKUP_B_REPORT_ENTITY_H + +#include +#include +#include + +#include "unique_fd.h" + +namespace OHOS::FileManagement::Backup { +using namespace std; +struct ReportFileInfo { + string filePath {""}; + string mode {"0660"}; + bool isDir {false}; + off_t size {0}; + off_t mtime {0}; + string hash {""}; + bool isIncremental {false}; +}; + +class BReportEntity { +public: + /** + * @brief 获取Report信息 + * + * @return std::map + */ + map GetReportInfos(); + +public: + /** + * @brief 构造方法 + * + * @param fd + */ + explicit BReportEntity(UniqueFd fd) : srcFile_(move(fd)) {} + + BReportEntity() = delete; + virtual ~BReportEntity() = default; + +public: + string version = ""; + unsigned int attrNum = 0; + +protected: + UniqueFd srcFile_; +}; +} // namespace OHOS::FileManagement::Backup + +#endif // OHOS_FILEMGMT_BACKUP_B_REPORT_ENTITY_H \ No newline at end of file diff --git a/utils/src/b_filesystem/b_file_hash.cpp b/utils/src/b_filesystem/b_file_hash.cpp new file mode 100644 index 000000000..51baf2348 --- /dev/null +++ b/utils/src/b_filesystem/b_file_hash.cpp @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * 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. + */ + +#include "b_filesystem/b_file_hash.h" + +#include +#include +#include +#include +#include +#include +#include + +namespace OHOS::FileManagement::Backup { +using namespace std; + +static tuple HashFinal(int err, const unique_ptr &hashBuf, size_t hashLen) +{ + if (err) { + return { err, "" }; + } + + stringstream ss; + for (size_t i = 0; i < hashLen; ++i) { + const int hexPerByte = 2; + ss << std::uppercase << std::setfill('0') << std::setw(hexPerByte) << std::hex << + static_cast(hashBuf[i]); + } + + return { err, ss.str() }; +} + +static int ForEachFileSegment(const string &fpath, function executor) +{ + unique_ptr filp = { fopen(fpath.c_str(), "r"), fclose }; + if (!filp) { + return errno; + } + + const size_t pageSize { getpagesize() }; + auto buf = make_unique(pageSize); + size_t actLen; + do { + actLen = fread(buf.get(), 1, pageSize, filp.get()); + if (actLen > 0) { + executor(buf.get(), actLen); + } + } while (actLen == pageSize); + + return ferror(filp.get()) ? errno : 0; +} + +tuple BFileHash::HashWithSHA1(const string &fpath) +{ + auto res = make_unique(SHA_DIGEST_LENGTH); + SHA_CTX ctx; + SHA1_Init(&ctx); + auto sha1Update = [ctx = &ctx](char *buf, size_t len) { + SHA1_Update(ctx, buf, len); + }; + int err = ForEachFileSegment(fpath, sha1Update); + SHA1_Final(res.get(), &ctx); + return HashFinal(err, res, SHA_DIGEST_LENGTH); +} + +tuple BFileHash::HashWithSHA256(const string &fpath) +{ + auto res = make_unique(SHA256_DIGEST_LENGTH); + SHA256_CTX ctx; + SHA256_Init(&ctx); + auto sha256Update = [ctx = &ctx](char *buf, size_t len) { + SHA256_Update(ctx, buf, len); + }; + int err = ForEachFileSegment(fpath, sha256Update); + SHA256_Final(res.get(), &ctx); + return HashFinal(err, res, SHA256_DIGEST_LENGTH); +} + +} // namespace OHOS::FileManagement::Backup \ No newline at end of file diff --git a/utils/src/b_json/b_report_entity.cpp b/utils/src/b_json/b_report_entity.cpp new file mode 100644 index 000000000..1708516c8 --- /dev/null +++ b/utils/src/b_json/b_report_entity.cpp @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * 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. + */ + +#include "b_json/b_report_entity.h" + +#include +#include +#include +#include +#include + +#include "b_error/b_error.h" +#include "filemgmt_libhilog.h" +#include "unique_fd.h" + +namespace OHOS::FileManagement::Backup { +using namespace std; +namespace { +const char lineSep_ = '\n'; +const char attrSep_ = ';'; +const int INFO_ALIGN_NUM_ = 2; +const int64_t HASH_BUFFER_SIZE_ = 4096; // 每次读取的siz +} // namespace + +vector SplitStringByChar(const string &str, const char &sep) +{ + vector eles = {}; + stringstream ss = stringstream(str); + string ele = {}; + while (!ss.eof()) { + getline(ss, ele, sep); + eles.push_back(ele); + } + + return eles; +} + +ErrCode ParseReportInfo(struct ReportFileInfo &fileStat, + const vector &splits, + const unordered_map &keys) +{ + // 根据数据拼接结构体 + int len = keys.size(); + int splitsLen = (int)splits.size(); + // 处理path路径 + string path; + vector residue; + try { + for (int i = 0; i < splitsLen; i++) { + if (i <= splitsLen - len) { + path += splits[i] + ";"; + } else { + residue.emplace_back(splits[i]); + } + } + fileStat.filePath = path.substr(0, path.length() - 1); + if (keys.find("mode") != keys.end()) { + fileStat.mode = residue[keys.find("mode")->second]; + } + if (keys.find("dir") != keys.end()) { + fileStat.isDir = residue[keys.find("dir")->second] == "1" ? true : false; + } + if (keys.find("size") != keys.end()) { + stringstream sizeStr(residue[keys.find("size")->second]); + off_t size = 0; + sizeStr >> size; + fileStat.size = size; + } + if (keys.find("mtime") != keys.end()) { + stringstream mtimeStr(residue[keys.find("mtime")->second]); + off_t mtime = 0; + mtimeStr >> mtime; + fileStat.mtime = mtime; + } + if (keys.find("hash") != keys.end()) { + fileStat.hash = residue[keys.find("hash")->second]; + } + if (keys.find("isIncremental") != keys.end()) { + fileStat.isIncremental = residue[keys.find("isIncremental")->second] == "1" ? true : false; + } + return ERR_OK; + } catch (...) { + HILOGE("Failed to ParseReportInfo"); + return EPERM; + } +} + +void DealLine(unordered_map &keys, int &num, const string &line, map &infos) +{ + string currentLine = line; + if (currentLine[currentLine.length() - 1] == '\r') { + currentLine = currentLine.substr(0, currentLine.length() - 1); + } + + vector splits = SplitStringByChar(currentLine, attrSep_); + if (num < INFO_ALIGN_NUM_) { + if (num == 1) { + for (int j = 0; j < (int)splits.size(); j++) { + keys.emplace(splits[j], j - 1); + } + } + num++; + } else { + struct ReportFileInfo fileState; + auto code = ParseReportInfo(fileState, splits, keys); + if (code != ERR_OK) { + HILOGE("ParseReportInfo err:%{public}d, %{public}s", code, currentLine.c_str()); + } else { + infos.try_emplace(fileState.filePath, fileState); + } + } +} + +/** + * @brief 获取Report信息 + * + * @return std::map + */ +map BReportEntity::GetReportInfos() +{ + map infos {}; + + char buffer[HASH_BUFFER_SIZE_]; + ssize_t bytesRead; + string currentLine; + unordered_map keys; + + int num = 0; + while ((bytesRead = read(srcFile_, buffer, sizeof(buffer))) > 0) { + for (ssize_t i = 0; i < bytesRead; i++) { + if (buffer[i] == lineSep_) { + DealLine(keys, num, currentLine, infos); + currentLine.clear(); + } else { + currentLine += buffer[i]; + } + } + } + + // 处理文件中的最后一行 + if (!currentLine.empty()) { + DealLine(keys, num, currentLine, infos); + } + + return infos; +} +} // namespace OHOS::FileManagement::Backup \ No newline at end of file -- Gitee