• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024-2025 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 "utils.h"
17 
18 #include <algorithm>
19 #include <cmath>
20 #include <cstdlib>
21 #include <cstring>
22 #include <dirent.h>
23 #include <fstream>
24 #include <iomanip>
25 #include <random>
26 #include <sstream>
27 #include <sys/stat.h>
28 #include <sys/types.h>
29 #include <unistd.h>
30 #include <vector>
31 
32 #include "log.h"
33 #include "pt_json.h"
34 
35 namespace OHOS {
36 namespace AppPackingTool {
37 namespace {
38 const int BUFFER_SIZE = 1024;
39 const int HEX_WIDTH = 2;
40 const char PATH_DELIMITER = '/';
41 const long FILE_LENGTH_1KB = 1024L;
42 const double FILE_SIZE_OFFSET_DOUBLE = 0.01;
43 const int FILE_SIZE_DECIMAL_PRECISION = 2;
44 const int MAX_UUID_LENGTH = 32;
45 const int RANGE_MIN = 0;
46 const int RANGE_MAX = 15;
47 const int TEN = 10;
48 }
49 
GetFileContent(const std::string filePath)50 std::string Utils::GetFileContent(const std::string filePath)
51 {
52     std::string realFilePath;
53     if (!Utils::GetRealPath(filePath, realFilePath)) {
54         LOGE("get real file path failed! filePath=%s", filePath.c_str());
55         return nullptr;
56     }
57     std::ifstream inFile(realFilePath, std::ios::in);
58     if (!inFile.is_open()) {
59         LOGE("open file path failed![filePath=%s][realFilePath=%s]", filePath.c_str(), realFilePath.c_str());
60         return nullptr;
61     }
62     std::string fileContent((std::istreambuf_iterator<char>(inFile)), std::istreambuf_iterator<char>());
63     inFile.close();
64     return fileContent;
65 }
66 
ListToString(const std::list<std::string> & lst)67 std::string Utils::ListToString(const std::list<std::string>& lst)
68 {
69     std::stringstream ss;
70     for (auto str : lst) {
71         ss << str;
72     }
73     return ss.str();
74 }
75 
CopyListToSet(const std::list<std::string> & lst,std::set<std::string> & st)76 void Utils::CopyListToSet(const std::list<std::string>& lst, std::set<std::string>& st)
77 {
78     for (auto& em : lst) {
79         st.insert(em);
80     }
81 }
82 
ReplaceAll(std::string str,const std::string & from,const std::string & to)83 std::string Utils::ReplaceAll(std::string str, const std::string& from, const std::string& to)
84 {
85     size_t startPos = 0;
86     while ((startPos = str.find(from, startPos)) != std::string::npos) {
87         str.replace(startPos, from.length(), to);
88         startPos += to.length();
89     }
90     return str;
91 }
92 
GetFileLength(const std::string filePath)93 int64_t Utils::GetFileLength(const std::string filePath)
94 {
95     struct stat statbuf = { 0 };
96     if (stat(filePath.c_str(), &statbuf) != 0) {
97         LOGE("file stat failed! filePath=%s", filePath.c_str());
98         return -1;
99     }
100     return statbuf.st_size;
101 }
102 
EndsWith(const std::string & str,const std::string & suffix)103 bool Utils::EndsWith(const std::string& str, const std::string& suffix)
104 {
105     if (str.size() >= suffix.size() && std::equal(suffix.rbegin(), suffix.rend(), str.rbegin())) {
106         return true;
107     }
108     return false;
109 }
110 
111 // If there is no same element then returns true, else then returns false
CheckDisjoint(const std::list<std::string> & list1,const std::list<std::string> & list2)112 bool Utils::CheckDisjoint(const std::list<std::string>& list1, const std::list<std::string>& list2)
113 {
114     for (const std::string& str1 : list1) {
115         for (const std::string& str2 : list2) {
116             if (str1.compare(str2) == 0) {
117                 return false;
118             }
119         }
120     }
121     return true;
122 }
123 
124 // If list1 contains all elements in list2, returns true, else returns false
CheckContainsAll(const std::list<std::string> & list1,const std::list<std::string> & list2)125 bool Utils::CheckContainsAll(const std::list<std::string>& list1, const std::list<std::string>& list2)
126 {
127     bool isFind = false;
128     for (const std::string& str2 : list2) {
129         isFind = false;
130         for (const std::string& str1 : list1) {
131             if (str2.compare(str1) == 0) {
132                 isFind = true;
133                 break;
134             }
135         }
136         if (!isFind) {
137             return false;
138         }
139     }
140     return true;
141 }
142 
CheckListContain(const std::list<std::string> & lst,const std::string & value)143 bool Utils::CheckListContain(const std::list<std::string>& lst, const std::string& value)
144 {
145     return std::find(lst.begin(), lst.end(), value) != lst.end();
146 }
147 
GetListDistinctCount(const std::list<std::string> & lst)148 long Utils::GetListDistinctCount(const std::list<std::string>& lst)
149 {
150     std::set<std::string> st;
151     std::copy(lst.begin(), lst.end(), std::inserter(st, st.end()));
152     return st.size();
153 }
154 
GetSha256Str(const std::string & str)155 std::string Utils::GetSha256Str(const std::string &str)
156 {
157     unsigned char hash[SHA256_DIGEST_LENGTH];
158     SHA256_CTX ctx;
159     SHA256_Init(&ctx);
160     SHA256_Update(&ctx, str.c_str(), str.length());
161     SHA256_Final(hash, &ctx);
162 
163     // Convert hash to hex string
164     std::stringstream ss;
165     for (int i = 0; i < SHA256_DIGEST_LENGTH; ++i) {
166         ss << std::hex << std::setw(HEX_WIDTH) << std::setfill('0') << static_cast<uint32_t>(hash[i]);
167     }
168     return ss.str();
169 }
170 
GetSha256File(const std::string & filePath)171 std::string Utils::GetSha256File(const std::string &filePath)
172 {
173     std::string realFilePath;
174     if (!GetRealPath(filePath, realFilePath)) {
175         LOGE("get real file path failed! jsonFile=%s", filePath.c_str());
176         return "";
177     }
178     std::ifstream file(realFilePath, std::ios::binary);
179     if (!file) {
180         return "";
181     }
182     SHA256_CTX ctx;
183     SHA256_Init(&ctx);
184     std::vector<char> buffer(BUFFER_SIZE);
185     while (!file.eof()) {
186         file.read(buffer.data(), BUFFER_SIZE);
187         SHA256_Update(&ctx, buffer.data(), file.gcount());
188     }
189     unsigned char hash[SHA256_DIGEST_LENGTH];
190     SHA256_Final(hash, &ctx);
191 
192     // Convert hash to hex string
193     std::stringstream ss;
194     for (int i = 0; i < SHA256_DIGEST_LENGTH; ++i) {
195         ss << std::hex << std::setw(HEX_WIDTH) << std::setfill('0') << static_cast<uint32_t>(hash[i]);
196     }
197     return ss.str();
198 }
199 
GetSha256Folder(const std::string & filePath)200 std::string Utils::GetSha256Folder(const std::string &filePath)
201 {
202     SHA256_CTX ctx;
203     SHA256_Init(&ctx);
204     for (const auto& entry : fs::recursive_directory_iterator(filePath)) {
205         if (fs::is_regular_file(entry)) {
206             std::ifstream file(entry, std::ios::binary);
207             if (!file.is_open()) {
208                 LOGE("file open failed! filePath=%s", entry.path().string().c_str());
209                 return "";
210             }
211             std::vector<char> buffer((std::istreambuf_iterator<char>(file)),
212                     std::istreambuf_iterator<char>());
213             SHA256_Update(&ctx, buffer.data(), buffer.size());
214         }
215     }
216     unsigned char hash[SHA256_DIGEST_LENGTH];
217     SHA256_Final(hash, &ctx);
218 
219     // Convert hash to hex string
220     std::stringstream ss;
221     for (int i = 0; i < SHA256_DIGEST_LENGTH; ++i) {
222         ss << std::hex << std::setw(HEX_WIDTH) << std::setfill('0') << static_cast<uint32_t>(hash[i]);
223     }
224     return ss.str();
225 }
226 
IsFileExists(const std::string & file)227 bool Utils::IsFileExists(const std::string& file)
228 {
229     return access(file.c_str(), F_OK) == 0;
230 }
231 
IsFile(const std::string & file)232 bool Utils::IsFile(const std::string& file)
233 {
234     struct stat statBuf {};
235     return lstat(file.c_str(), &statBuf) == 0 ? S_ISREG(statBuf.st_mode) : false;
236 }
237 
IsDirectory(const std::string & dir)238 bool Utils::IsDirectory(const std::string& dir)
239 {
240     struct stat statBuf {};
241     return lstat(dir.c_str(), &statBuf) == 0 ? S_ISDIR(statBuf.st_mode) : false;
242 }
243 
RemoveFile(const std::string & file)244 bool Utils::RemoveFile(const std::string& file)
245 {
246     return !IsFileExists(file) || (remove(file.c_str()) == 0);
247 }
248 
RemoveDirectory(const std::string & dir)249 bool Utils::RemoveDirectory(const std::string& dir)
250 {
251     return !IsFileExists(dir) || (rmdir(dir.c_str()) == 0);
252 }
253 
GetFilePathByDir(const std::string & dir,const std::string & fileName)254 std::string Utils::GetFilePathByDir(const std::string& dir, const std::string& fileName)
255 {
256     if (dir.empty()) {
257         return fileName;
258     }
259     std::string filePath = dir;
260     if (filePath.back() != '/') {
261         filePath.push_back(PATH_DELIMITER);
262     }
263     filePath.append(fileName);
264     return filePath;
265 }
266 
ForceCreateDirectory(const std::string & dir)267 bool Utils::ForceCreateDirectory(const std::string& dir)
268 {
269     std::string::size_type index = 0;
270     do {
271         std::string subPath;
272         index = dir.find('/', index + 1); // (index + 1) means the next char traversed
273         if (index == std::string::npos) {
274             subPath = dir;
275         } else {
276             subPath = dir.substr(0, index);
277         }
278 
279         if (!IsFileExists(subPath) && mkdir(subPath.c_str(), S_IRWXU) != 0) {
280             return false;
281         }
282     } while (index != std::string::npos);
283     return IsFileExists(dir);
284 }
285 
ForceRemoveDirectory(const std::string & dir,bool isDeleteSelf)286 bool Utils::ForceRemoveDirectory(const std::string& dir, bool isDeleteSelf)
287 {
288     if (IsFile(dir)) {
289         return RemoveFile(dir);
290     } else if (IsDirectory(dir)) {
291         DIR* dirPtr = opendir(dir.c_str());
292         if (dirPtr == nullptr) {
293             return false;
294         }
295         struct dirent* dirInfo = nullptr;
296         while ((dirInfo = readdir(dirPtr)) != nullptr) {
297             // do not process the special dir
298             if (strcmp(dirInfo->d_name, ".") == 0 || strcmp(dirInfo->d_name, "..") == 0) {
299                 continue;
300             }
301             std::string filePath = GetFilePathByDir(dir, dirInfo->d_name);
302             if (!ForceRemoveDirectory(filePath)) {
303                 closedir(dirPtr);
304                 return false;
305             }
306         }
307         closedir(dirPtr);
308         if (isDeleteSelf && !RemoveDirectory(dir)) {
309             return false;
310         }
311     } else {
312         return false;
313     }
314     return true;
315 }
316 
GetCeilFileSize(long fileSize,int sizeLimit)317 double Utils::GetCeilFileSize(long fileSize, int sizeLimit)
318 {
319     double threshold = static_cast<double>(sizeLimit) + FILE_SIZE_OFFSET_DOUBLE;
320     double size = static_cast<double>(fileSize) / FILE_LENGTH_1KB;
321     size = std::round(size * std::pow(TEN, FILE_SIZE_DECIMAL_PRECISION)) / std::pow(TEN, FILE_SIZE_DECIMAL_PRECISION);
322     if (size < threshold && size >= sizeLimit) {
323         size = threshold;
324     }
325     return size;
326 }
327 
IsPositiveInteger(const std::string & str,int min,int max)328 bool Utils::IsPositiveInteger(const std::string& str, int min, int max)
329 {
330     if (str.empty()) {
331         return false;
332     }
333     for (char c : str) {
334         if (!std::isdigit(c)) {
335             return false;
336         }
337     }
338     try {
339         int number = std::stoi(str);
340         return number >= min && number <= max;
341     } catch (const std::out_of_range& e) {
342         LOGE("Number %s is Out of Range!", str.c_str());
343         return false;
344     }
345     return true;
346 }
347 
StringToBool(const std::string & str)348 bool Utils::StringToBool(const std::string& str)
349 {
350     std::string lowerStr = str;
351     std::transform(lowerStr.begin(), lowerStr.end(), lowerStr.begin(), ::tolower);
352     if (lowerStr == "true") {
353         return true;
354     }
355     return false;
356 }
357 
StringToArray(const std::string & str,std::list<std::string> & array)358 bool Utils::StringToArray(const std::string& str, std::list<std::string>& array)
359 {
360     array.clear();
361     std::istringstream iss(str);
362     std::string item;
363 
364     while (std::getline(iss, item, ',')) {
365         array.push_back(item);
366     }
367     return true;
368 }
369 
CheckFileName(const std::string & filePath,const std::string & fileName)370 bool Utils::CheckFileName(const std::string& filePath, const std::string& fileName)
371 {
372     fs::path fsFilePath(filePath);
373     if (fs::is_regular_file(fsFilePath) && fsFilePath.filename().compare(fileName) == 0) {
374         return true;
375     }
376     return false;
377 }
378 
CheckFileSuffix(const std::string & filePath,const std::string & suffix)379 bool Utils::CheckFileSuffix(const std::string& filePath, const std::string& suffix)
380 {
381     fs::path fsFilePath(filePath);
382     if (fs::is_regular_file(fsFilePath) && EndsWith(fsFilePath.filename(), suffix)) {
383         return true;
384     }
385     return false;
386 }
387 
GenerateUUID()388 std::string Utils::GenerateUUID()
389 {
390     static const char* hexDigits = "0123456789abcdef";
391     std::random_device rd;
392     std::mt19937 gen(rd());
393     std::uniform_int_distribution<> dis(RANGE_MIN, RANGE_MAX);
394 
395     std::stringstream ss;
396     std::vector<int> format = {8, 4, 4, 4, 12};
397     int flag = 1;
398     for (int i = 0; i < MAX_UUID_LENGTH; ++i) {
399         ss << hexDigits[dis(gen)];
400         if ((i + 1) == format[0] && i != MAX_UUID_LENGTH - 1) {
401             ss << "-";
402             format[0] += format[flag];
403             flag++;
404         }
405     }
406     return ss.str();
407 }
408 
CopyFile(const std::string & srcPath,const std::string & dstPath)409 bool Utils::CopyFile(const std::string& srcPath, const std::string& dstPath)
410 {
411     std::string realSrcPath;
412     std::string realDstPath;
413     if (!GetRealPath(srcPath, realSrcPath)) {
414         LOGE("get real src path failed! srcPath=%s", srcPath.c_str());
415         return false;
416     }
417     fs::path fsDstPath(dstPath);
418     std::string parentOfDstPath = fsDstPath.parent_path().string();
419     std::string dstFileName = fsDstPath.filename();
420     if (!GetRealPathOfNoneExistFile(parentOfDstPath, realDstPath)) {
421         LOGE("get real dst path failed! dstPath=%s", dstPath.c_str());
422         return false;
423     }
424     realDstPath += fs::path::preferred_separator + dstFileName;
425     std::ifstream srcFile(realSrcPath, std::ios::binary);
426     std::ofstream dstFile(realDstPath, std::ios::binary);
427     if (!srcFile.is_open()) {
428         LOGE("Open srcPath failed![srcPath=%s][realSrcPath=%s]", srcPath.c_str(), realSrcPath.c_str());
429         return false;
430     }
431     if (!dstFile.is_open()) {
432         LOGE("Open dstPath failed![dstPath=%s][realDstPath=%s]", dstPath.c_str(), realDstPath.c_str());
433         return false;
434     }
435     dstFile << srcFile.rdbuf();
436     srcFile.close();
437     dstFile.close();
438     return true;
439 }
440 
GetFormattedPath(const std::string & path,std::string & formattedPath)441 bool Utils::GetFormattedPath(const std::string& path, std::string& formattedPath)
442 {
443     if (path.empty()) {
444         formattedPath = "";
445         return true;
446     }
447     try {
448         formattedPath = fs::canonical(path).string();
449     } catch (const fs::filesystem_error& err) {
450         LOGE("GetFormattedPath exception: ", err.what());
451         return false;
452     }
453     return true;
454 }
455 
GetRealPath(const std::string & path,std::string & realPath)456 bool Utils::GetRealPath(const std::string& path, std::string& realPath)
457 {
458     if (path.length() >= PATH_MAX) {
459         return false;
460     }
461     char buffer[PATH_MAX] = {0};
462     if (realpath(path.c_str(), buffer) == nullptr) {
463         return false;
464     }
465     realPath = std::string(buffer);
466     return true;
467 }
468 
GetRealPathOfNoneExistFile(const std::string & path,std::string & realPath)469 bool Utils::GetRealPathOfNoneExistFile(const std::string& path, std::string& realPath)
470 {
471     fs::path fsPath = fs::path(path);
472     std::string filePath = fsPath.parent_path().string();
473     std::string fileName = fsPath.filename().string();
474     if (path.length() >= PATH_MAX) {
475         return false;
476     }
477     char buffer[PATH_MAX] = {0};
478     if (realpath(filePath.c_str(), buffer) == nullptr) {
479         return false;
480     }
481     realPath = std::string(buffer) + fs::path::preferred_separator + fileName;
482     return true;
483 }
484 
RemoveAllFilesInDirectory(const std::string & directoryPath)485 bool Utils::RemoveAllFilesInDirectory(const std::string& directoryPath)
486 {
487     fs::path fsPath(directoryPath);
488     if (!fs::exists(fsPath) || !fs::is_directory(fsPath)) {
489         return false;
490     }
491     for (auto& entry : fs::directory_iterator(fsPath)) {
492         if (fs::is_regular_file(entry)) {
493             fs::remove(entry);
494         }
495     }
496     return true;
497 }
498 
499 } // namespace AppPackingTool
500 } // namespace OHOS
501