• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "b_filesystem/b_file_hash.h"
17 
18 #include <algorithm>
19 #include <chrono>
20 #include <cinttypes>
21 #include <filesystem>
22 #include <fstream>
23 #include <functional>
24 #include <iomanip>
25 #include <memory>
26 #include <openssl/sha.h>
27 #include <sstream>
28 #include <unistd.h>
29 #include "b_resources/b_constants.h"
30 
31 namespace OHOS::FileManagement::Backup {
32 using namespace std;
33 
HashFinal(int err,const unique_ptr<unsigned char[]> & hashBuf,size_t hashLen)34 static tuple<int, string> HashFinal(int err, const unique_ptr<unsigned char[]> &hashBuf, size_t hashLen)
35 {
36     if (err) {
37         return { err, "" };
38     }
39 
40     stringstream ss;
41     for (size_t i = 0; i < hashLen; ++i) {
42         const int hexPerByte = 2;
43         ss << std::uppercase << std::setfill('0') << std::setw(hexPerByte) << std::hex <<
44             static_cast<uint32_t>(hashBuf[i]);
45     }
46 
47     return { err, ss.str() };
48 }
49 
ForEachFileSegment(const string & fpath,function<void (char *,size_t)> executor)50 static int ForEachFileSegment(const string &fpath, function<void(char *, size_t)> executor)
51 {
52     unique_ptr<FILE, decltype(&fclose)> filp = { fopen(fpath.c_str(), "r"), fclose };
53     if (!filp) {
54         return errno;
55     }
56 
57     const size_t pageSize { getpagesize() };
58     auto buf = make_unique<char[]>(pageSize);
59     size_t actLen;
60     do {
61         actLen = fread(buf.get(), 1, pageSize, filp.get());
62         if (actLen > 0) {
63             executor(buf.get(), actLen);
64         }
65     } while (actLen == pageSize);
66 
67     return ferror(filp.get()) ? errno : 0;
68 }
69 
HashWithSHA256(const string & fpath)70 tuple<int, string> BackupFileHash::HashWithSHA256(const string &fpath)
71 {
72     auto res = make_unique<unsigned char[]>(SHA256_DIGEST_LENGTH);
73     SHA256_CTX ctx;
74     SHA256_Init(&ctx);
75     auto sha256Update = [ctx = &ctx](char *buf, size_t len) {
76         SHA256_Update(ctx, buf, len);
77     };
78     int err = ForEachFileSegment(fpath, sha256Update);
79     SHA256_Final(res.get(), &ctx);
80     return HashFinal(err, res, SHA256_DIGEST_LENGTH);
81 }
82 
HashFilePath(const string & fileName)83 std::string BackupFileHash::HashFilePath(const string &fileName)
84 {
85     std::filesystem::path filePath = fileName;
86     std::string realFileName = filePath.filename().string();
87     ostringstream strHex;
88     strHex << hex;
89 
90     hash<string> strHash;
91     size_t szHash = strHash(realFileName);
92     strHex << setfill('0') << setw(BConstants::BIG_FILE_NAME_SIZE) << szHash;
93     string hashResult = strHex.str();
94     szHash = strHash(realFileName);
95     strHex << setfill('0') << setw(BConstants::BIG_FILE_NAME_SIZE) << szHash;
96     hashResult = strHex.str();
97     return hashResult;
98 }
99 } // namespace OHOS::FileManagement::Backup