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 <fstream>
19 #include <functional>
20 #include <iomanip>
21 #include <memory>
22 #include <openssl/sha.h>
23 #include <sstream>
24 #include <unistd.h>
25
26 namespace OHOS::FileManagement::Backup {
27 using namespace std;
28
HashFinal(int err,const unique_ptr<unsigned char[]> & hashBuf,size_t hashLen)29 static tuple<int, string> HashFinal(int err, const unique_ptr<unsigned char[]> &hashBuf, size_t hashLen)
30 {
31 if (err) {
32 return { err, "" };
33 }
34
35 stringstream ss;
36 for (size_t i = 0; i < hashLen; ++i) {
37 const int hexPerByte = 2;
38 ss << std::uppercase << std::setfill('0') << std::setw(hexPerByte) << std::hex <<
39 static_cast<uint32_t>(hashBuf[i]);
40 }
41
42 return { err, ss.str() };
43 }
44
ForEachFileSegment(const string & fpath,function<void (char *,size_t)> executor)45 static int ForEachFileSegment(const string &fpath, function<void(char *, size_t)> executor)
46 {
47 unique_ptr<FILE, decltype(&fclose)> filp = { fopen(fpath.c_str(), "r"), fclose };
48 if (!filp) {
49 return errno;
50 }
51
52 const size_t pageSize { getpagesize() };
53 auto buf = make_unique<char[]>(pageSize);
54 size_t actLen;
55 do {
56 actLen = fread(buf.get(), 1, pageSize, filp.get());
57 if (actLen > 0) {
58 executor(buf.get(), actLen);
59 }
60 } while (actLen == pageSize);
61
62 return ferror(filp.get()) ? errno : 0;
63 }
64
HashWithSHA256(const string & fpath)65 tuple<int, string> BackupFileHash::HashWithSHA256(const string &fpath)
66 {
67 auto res = make_unique<unsigned char[]>(SHA256_DIGEST_LENGTH);
68 SHA256_CTX ctx;
69 SHA256_Init(&ctx);
70 auto sha256Update = [ctx = &ctx](char *buf, size_t len) {
71 SHA256_Update(ctx, buf, len);
72 };
73 int err = ForEachFileSegment(fpath, sha256Update);
74 SHA256_Final(res.get(), &ctx);
75 return HashFinal(err, res, SHA256_DIGEST_LENGTH);
76 }
77 } // namespace OHOS::FileManagement::Backup