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