• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-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 "bundle_util.h"
17 
18 #include <cinttypes>
19 #include <dirent.h>
20 #include <fcntl.h>
21 #include <fstream>
22 #include <random>
23 #include <sstream>
24 #include <sys/sendfile.h>
25 #include <sys/statfs.h>
26 #include <vector>
27 
28 #include "bundle_service_constants.h"
29 #ifdef CONFIG_POLOCY_ENABLE
30 #include "config_policy_utils.h"
31 #endif
32 #include "directory_ex.h"
33 #include "hitrace_meter.h"
34 #include "installd_client.h"
35 #include "ipc_skeleton.h"
36 #include "parameter.h"
37 #include "string_ex.h"
38 #ifdef BUNDLE_FRAMEWORK_UDMF_ENABLED
39 #include "type_descriptor.h"
40 #include "utd_client.h"
41 #endif
42 
43 namespace OHOS {
44 namespace AppExecFwk {
45 namespace {
46 const std::string::size_type EXPECT_SPLIT_SIZE = 2;
47 constexpr char UUID_SEPARATOR = '-';
48 constexpr size_t ORIGIN_STRING_LENGTH = 32;
49 const std::vector<int32_t> SEPARATOR_POSITIONS { 8, 13, 18, 23};
50 constexpr int64_t HALF_GB = 1024 * 1024 * 512; // 0.5GB
51 constexpr int8_t SPACE_NEED_DOUBLE = 2;
52 constexpr uint16_t UUID_LENGTH_MAX = 512;
53 static std::string g_deviceUdid;
54 // hmdfs and sharefs config
55 constexpr const char* BUNDLE_ID_FILE = "appid";
56 // single max hap size
57 constexpr int64_t ONE_GB = 1024 * 1024 * 1024;
58 constexpr int64_t MAX_HAP_SIZE = ONE_GB * 4;  // 4GB
59 constexpr const char* ABC_FILE_PATH = "abc_files";
60 constexpr const char* PGO_FILE_PATH = "pgo_files";
61 #ifdef CONFIG_POLOCY_ENABLE
62 const char* NO_DISABLING_CONFIG_PATH = "/etc/ability_runtime/resident_process_in_extreme_memory.json";
63 #endif
64 const char* NO_DISABLING_CONFIG_PATH_DEFAULT =
65     "/system/etc/ability_runtime/resident_process_in_extreme_memory.json";
66 const std::string EMPTY_STRING = "";
67 constexpr int64_t DISK_REMAINING_SIZE_LIMIT = 1024 * 1024 * 10; // 10M
68 constexpr uint32_t RANDOM_NUMBER_LENGTH = 255;
69 constexpr uint32_t SANDBOX_PATH_INDEX = 0;
70 constexpr uint32_t ID_INVALID = 0;
71 constexpr const char* COLON = ":";
72 constexpr const char* DEFAULT_START_WINDOW_BACKGROUND_IMAGE_FIT_VALUE = "Cover";
73 constexpr const char* APP_INSTALL_PREFIX = "+app_install+";
74 }
75 
76 std::mutex BundleUtil::g_mutex;
77 
CheckFilePath(const std::string & bundlePath,std::string & realPath)78 ErrCode BundleUtil::CheckFilePath(const std::string &bundlePath, std::string &realPath)
79 {
80     if (!CheckFileName(bundlePath)) {
81         APP_LOGE("bundle file path invalid");
82         return ERR_APPEXECFWK_INSTALL_FILE_PATH_INVALID;
83     }
84     if (!CheckFileType(bundlePath, ServiceConstants::INSTALL_FILE_SUFFIX) &&
85         !CheckFileType(bundlePath, ServiceConstants::HSP_FILE_SUFFIX) &&
86         !CheckFileType(bundlePath, ServiceConstants::QUICK_FIX_FILE_SUFFIX) &&
87         !CheckFileType(bundlePath, ServiceConstants::CODE_SIGNATURE_FILE_SUFFIX)) {
88         APP_LOGE("file is not hap, hsp, hqf or sig");
89         return ERR_APPEXECFWK_INSTALL_INVALID_HAP_NAME;
90     }
91     if (!PathToRealPath(bundlePath, realPath)) {
92         APP_LOGE("file is not real path");
93         return ERR_APPEXECFWK_INSTALL_FILE_PATH_INVALID;
94     }
95     if (access(realPath.c_str(), F_OK) != 0) {
96         APP_LOGE("not access the bundle file path: %{public}s, errno:%{public}d", realPath.c_str(), errno);
97         return ERR_APPEXECFWK_INSTALL_INVALID_BUNDLE_FILE;
98     }
99     if (!CheckFileSize(realPath, MAX_HAP_SIZE)) {
100         APP_LOGE("file size larger than max hap size Max size is: %{public}" PRId64, MAX_HAP_SIZE);
101         return ERR_APPEXECFWK_INSTALL_INVALID_HAP_SIZE;
102     }
103     return ERR_OK;
104 }
105 
CheckFilePath(const std::vector<std::string> & bundlePaths,std::vector<std::string> & realPaths)106 ErrCode BundleUtil::CheckFilePath(const std::vector<std::string> &bundlePaths, std::vector<std::string> &realPaths)
107 {
108     HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
109     // there are three cases for bundlePaths:
110     // 1. one bundle direction in the bundlePaths, some hap files under this bundle direction.
111     // 2. one hap direction in the bundlePaths.
112     // 3. some hap file directions in the bundlePaths.
113     APP_LOGD("check file path");
114     if (bundlePaths.empty()) {
115         APP_LOGE("bundle file paths invalid");
116         return ERR_APPEXECFWK_INSTALL_FILE_PATH_INVALID;
117     }
118     ErrCode ret = ERR_OK;
119 
120     if (bundlePaths.size() == 1) {
121         struct stat s;
122         std::string bundlePath = bundlePaths.front();
123         if (stat(bundlePath.c_str(), &s) == 0) {
124             std::string realPath = "";
125             // it is a direction
126             if ((s.st_mode & S_IFDIR) && !GetHapFilesFromBundlePath(bundlePath, realPaths)) {
127                 APP_LOGE("GetHapFilesFromBundlePath failed with bundlePath:%{public}s", bundlePaths.front().c_str());
128                 return ERR_APPEXECFWK_INSTALL_FILE_PATH_INVALID;
129             }
130             // it is a file
131             if ((s.st_mode & S_IFREG) && (ret = CheckFilePath(bundlePaths.front(), realPath)) == ERR_OK) {
132                 realPaths.emplace_back(realPath);
133             }
134             return ret;
135         } else {
136             APP_LOGE("bundlePath not existed with :%{public}s errno %{public}d", bundlePaths.front().c_str(), errno);
137             return ERR_APPEXECFWK_INSTALL_FILE_PATH_INVALID;
138         }
139     } else {
140         for (const std::string& bundlePath : bundlePaths) {
141             std::string realPath = "";
142             ret = CheckFilePath(bundlePath, realPath);
143             if (ret != ERR_OK) {
144                 return ret;
145             }
146             realPaths.emplace_back(realPath);
147         }
148     }
149     APP_LOGD("finish check file path");
150     return ret;
151 }
152 
CheckFileType(const std::string & fileName,const std::string & extensionName)153 bool BundleUtil::CheckFileType(const std::string &fileName, const std::string &extensionName)
154 {
155     APP_LOGD("path is %{public}s, support suffix is %{public}s", fileName.c_str(), extensionName.c_str());
156     if (!CheckFileName(fileName)) {
157         return false;
158     }
159 
160     auto position = fileName.rfind('.');
161     if (position == std::string::npos) {
162         APP_LOGE("filename no extension name");
163         return false;
164     }
165 
166     std::string suffixStr = fileName.substr(position);
167     return LowerStr(suffixStr) == extensionName;
168 }
169 
CheckFileName(const std::string & fileName)170 bool BundleUtil::CheckFileName(const std::string &fileName)
171 {
172     if (fileName.empty()) {
173         APP_LOGE("the file name is empty");
174         return false;
175     }
176     if (fileName.size() > ServiceConstants::PATH_MAX_SIZE) {
177         APP_LOGE("bundle file path length %{public}zu too long", fileName.size());
178         return false;
179     }
180     return true;
181 }
182 
CheckFileSize(const std::string & bundlePath,const int64_t fileSize)183 bool BundleUtil::CheckFileSize(const std::string &bundlePath, const int64_t fileSize)
184 {
185     APP_LOGD("fileSize is %{public}" PRId64, fileSize);
186     struct stat fileInfo = { 0 };
187     if (stat(bundlePath.c_str(), &fileInfo) != 0) {
188         APP_LOGE("call stat error:%{public}d", errno);
189         return false;
190     }
191     if (fileInfo.st_size > fileSize) {
192         return false;
193     }
194     return true;
195 }
196 
CheckSystemSize(const std::string & bundlePath,const std::string & diskPath)197 bool BundleUtil::CheckSystemSize(const std::string &bundlePath, const std::string &diskPath)
198 {
199     struct statfs diskInfo = { 0 };
200     if (statfs(diskPath.c_str(), &diskInfo) != 0) {
201         APP_LOGE("call statfs error:%{public}d", errno);
202         return false;
203     }
204     int64_t freeSize = static_cast<int64_t>(diskInfo.f_bavail * diskInfo.f_bsize);
205     APP_LOGD("left free size in the disk path is %{public}" PRId64, freeSize);
206     struct stat fileInfo = { 0 };
207     if (stat(bundlePath.c_str(), &fileInfo) != 0) {
208         APP_LOGE("call stat error:%{public}d", errno);
209         return false;
210     }
211     if (std::max(fileInfo.st_size * SPACE_NEED_DOUBLE, HALF_GB) > freeSize) {
212         return false;
213     }
214     return true;
215 }
216 
CheckSystemFreeSize(const std::string & path,int64_t size)217 bool BundleUtil::CheckSystemFreeSize(const std::string &path, int64_t size)
218 {
219     struct statfs diskInfo = { 0 };
220     if (statfs(path.c_str(), &diskInfo) != 0) {
221         APP_LOGE("call statfs error:%{public}d", errno);
222         return false;
223     }
224     int64_t freeSize = static_cast<int64_t>(diskInfo.f_bavail * diskInfo.f_bsize);
225     return freeSize >= size;
226 }
227 
CheckSystemSizeAndHisysEvent(const std::string & path,const std::string & fileName)228 bool BundleUtil::CheckSystemSizeAndHisysEvent(const std::string &path, const std::string &fileName)
229 {
230     struct statfs diskInfo = { 0 };
231     if (statfs(path.c_str(), &diskInfo) != 0) {
232         APP_LOGE("call statfs error:%{public}d", errno);
233         return false;
234     }
235     int64_t freeSize = static_cast<int64_t>(diskInfo.f_bavail * diskInfo.f_bsize);
236     return freeSize < DISK_REMAINING_SIZE_LIMIT;
237 }
238 
GetHapFilesFromBundlePath(const std::string & currentBundlePath,std::vector<std::string> & hapFileList)239 bool BundleUtil::GetHapFilesFromBundlePath(const std::string& currentBundlePath, std::vector<std::string>& hapFileList)
240 {
241     APP_LOGD("GetHapFilesFromBundlePath with path is %{public}s", currentBundlePath.c_str());
242     if (currentBundlePath.empty()) {
243         return false;
244     }
245     DIR* dir = opendir(currentBundlePath.c_str());
246     if (dir == nullptr) {
247         char errMsg[256] = {0};
248         strerror_r(errno, errMsg, sizeof(errMsg));
249         APP_LOGE("GetHapFilesFromBundlePath open bundle dir:%{public}s failed due to %{public}s, errno:%{public}d",
250             currentBundlePath.c_str(), errMsg, errno);
251         return false;
252     }
253     std::string bundlePath = currentBundlePath;
254     if (bundlePath.back() != ServiceConstants::FILE_SEPARATOR_CHAR) {
255         bundlePath.append(ServiceConstants::PATH_SEPARATOR);
256     }
257     struct dirent *entry = nullptr;
258     while ((entry = readdir(dir)) != nullptr) {
259         if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
260             continue;
261         }
262         const std::string hapFilePath = bundlePath + entry->d_name;
263         std::string realPath = "";
264         if (CheckFilePath(hapFilePath, realPath) != ERR_OK) {
265             APP_LOGE("find invalid hap path %{public}s", hapFilePath.c_str());
266             continue;
267         }
268         hapFileList.emplace_back(realPath);
269         APP_LOGD("find hap path %{public}s", realPath.c_str());
270 
271         if (!hapFileList.empty() && (hapFileList.size() > ServiceConstants::MAX_HAP_NUMBER)) {
272             APP_LOGE("reach the max hap number 128, stop to add more");
273             closedir(dir);
274             return false;
275         }
276     }
277     APP_LOGI("hap number: %{public}zu", hapFileList.size());
278     closedir(dir);
279     return true;
280 }
281 
GetCurrentTime()282 int64_t BundleUtil::GetCurrentTime()
283 {
284     int64_t time =
285         std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::now().time_since_epoch())
286         .count();
287     APP_LOGD("the current time in seconds is %{public}" PRId64, time);
288     return time;
289 }
290 
GetCurrentTimeMs()291 int64_t BundleUtil::GetCurrentTimeMs()
292 {
293     int64_t time =
294         std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch())
295         .count();
296     APP_LOGD("the current time in milliseconds is %{public}" PRId64, time);
297     return time;
298 }
299 
GetCurrentTimeNs()300 int64_t BundleUtil::GetCurrentTimeNs()
301 {
302     int64_t time =
303         std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now().time_since_epoch())
304         .count();
305     APP_LOGD("the current time in nanoseconds is %{public}" PRId64, time);
306     return time;
307 }
308 
DeviceAndNameToKey(const std::string & deviceId,const std::string & bundleName,std::string & key)309 void BundleUtil::DeviceAndNameToKey(
310     const std::string &deviceId, const std::string &bundleName, std::string &key)
311 {
312     key.append(deviceId);
313     key.append(Constants::FILE_UNDERLINE);
314     key.append(bundleName);
315     APP_LOGD("bundleName = %{public}s", bundleName.c_str());
316 }
317 
KeyToDeviceAndName(const std::string & key,std::string & deviceId,std::string & bundleName)318 bool BundleUtil::KeyToDeviceAndName(
319     const std::string &key, std::string &deviceId, std::string &bundleName)
320 {
321     bool ret = false;
322     std::vector<std::string> splitStrs;
323     OHOS::SplitStr(key, Constants::FILE_UNDERLINE, splitStrs);
324     // the expect split size should be 2.
325     // key rule is <deviceId>_<bundleName>
326     if (splitStrs.size() == EXPECT_SPLIT_SIZE) {
327         deviceId = splitStrs[0];
328         bundleName = splitStrs[1];
329         ret = true;
330     }
331     APP_LOGD("bundleName = %{public}s", bundleName.c_str());
332     return ret;
333 }
334 
GetUserIdByCallingUid()335 int32_t BundleUtil::GetUserIdByCallingUid()
336 {
337     int32_t uid = IPCSkeleton::GetCallingUid();
338     APP_LOGD("get calling uid(%{public}d)", uid);
339     return GetUserIdByUid(uid);
340 }
341 
GetUserIdByUid(int32_t uid)342 int32_t BundleUtil::GetUserIdByUid(int32_t uid)
343 {
344     if (uid <= Constants::INVALID_UID) {
345         APP_LOGE("uid illegal: %{public}d", uid);
346         return Constants::INVALID_USERID;
347     }
348 
349     return uid / Constants::BASE_USER_RANGE;
350 }
351 
MakeFsConfig(const std::string & bundleName,int32_t bundleId,const std::string & configPath)352 void BundleUtil::MakeFsConfig(const std::string &bundleName, int32_t bundleId, const std::string &configPath)
353 {
354     std::string bundleDir = configPath + ServiceConstants::PATH_SEPARATOR + bundleName;
355     if (access(bundleDir.c_str(), F_OK) != 0) {
356         APP_LOGD("fail to access error:%{public}d", errno);
357         if (mkdir(bundleDir.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) != 0) {
358             APP_LOGE("make bundle dir error:%{public}d", errno);
359             return;
360         }
361     }
362 
363     std::string realBundleDir;
364     if (!PathToRealPath(bundleDir, realBundleDir)) {
365         APP_LOGE("bundleIdFile is not real path");
366         return;
367     }
368 
369     realBundleDir += (std::string(ServiceConstants::PATH_SEPARATOR) + BUNDLE_ID_FILE);
370 
371     int32_t bundleIdFd = open(realBundleDir.c_str(), O_WRONLY | O_TRUNC);
372     if (bundleIdFd > 0) {
373         std::string bundleIdStr = std::to_string(bundleId);
374         if (write(bundleIdFd, bundleIdStr.c_str(), bundleIdStr.size()) < 0) {
375             APP_LOGE("write bundleId error:%{public}d", errno);
376         }
377     }
378     close(bundleIdFd);
379 }
380 
RemoveFsConfig(const std::string & bundleName,const std::string & configPath)381 void BundleUtil::RemoveFsConfig(const std::string &bundleName, const std::string &configPath)
382 {
383     std::string bundleDir = configPath + ServiceConstants::PATH_SEPARATOR + bundleName;
384     std::string realBundleDir;
385     if (!PathToRealPath(bundleDir, realBundleDir)) {
386         APP_LOGE("bundleDir is not real path");
387         return;
388     }
389     if (rmdir(realBundleDir.c_str()) != 0) {
390         APP_LOGE("remove hmdfs bundle dir error:%{public}d", errno);
391     }
392 }
393 
CreateTempDir(const std::string & tempDir)394 std::string BundleUtil::CreateTempDir(const std::string &tempDir)
395 {
396     if (!OHOS::ForceCreateDirectory(tempDir)) {
397         APP_LOGE("mkdir %{public}s failed", tempDir.c_str());
398         return "";
399     }
400     if (chown(tempDir.c_str(), Constants::FOUNDATION_UID, ServiceConstants::BMS_GID) != 0) {
401         APP_LOGE("fail to change %{public}s ownership errno:%{public}d", tempDir.c_str(), errno);
402         return "";
403     }
404     mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
405     if (!OHOS::ChangeModeFile(tempDir, mode)) {
406         APP_LOGE("change mode failed, temp install dir : %{public}s", tempDir.c_str());
407         return "";
408     }
409     return tempDir;
410 }
411 
CreateInstallTempDir(uint32_t installerId,const DirType & type)412 std::string BundleUtil::CreateInstallTempDir(uint32_t installerId, const DirType &type)
413 {
414     std::time_t curTime = std::time(0);
415     std::string tempDir = ServiceConstants::HAP_COPY_PATH;
416     std::string pathseparator = ServiceConstants::PATH_SEPARATOR;
417     if (type == DirType::STREAM_INSTALL_DIR) {
418         tempDir += pathseparator + ServiceConstants::STREAM_INSTALL_PATH;
419     } else if (type == DirType::QUICK_FIX_DIR) {
420         tempDir += pathseparator + ServiceConstants::QUICK_FIX_PATH;
421     } else if (type == DirType::SIG_FILE_DIR) {
422         tempDir += pathseparator + ServiceConstants::SIGNATURE_FILE_PATH;
423     } else if (type == DirType::PGO_FILE_DIR) {
424         tempDir += pathseparator + PGO_FILE_PATH;
425     } else if (type == DirType::ABC_FILE_DIR) {
426         tempDir += pathseparator + ABC_FILE_PATH;
427     } else if (type == DirType::EXT_RESOURCE_FILE_DIR) {
428         tempDir += pathseparator + ServiceConstants::EXT_RESOURCE_FILE_PATH;
429     } else {
430         return "";
431     }
432 
433     if (CreateTempDir(tempDir).empty()) {
434         APP_LOGE("create tempDir failed");
435         return "";
436     }
437 
438     tempDir += ServiceConstants::PATH_SEPARATOR + std::to_string(curTime) +
439         std::to_string(installerId) + ServiceConstants::PATH_SEPARATOR;
440     return CreateTempDir(tempDir);
441 }
442 
CreateSharedBundleTempDir(uint32_t installerId,uint32_t index)443 std::string BundleUtil::CreateSharedBundleTempDir(uint32_t installerId, uint32_t index)
444 {
445     std::time_t curTime = std::time(0);
446     std::string tempDir = ServiceConstants::HAP_COPY_PATH;
447     tempDir += std::string(ServiceConstants::PATH_SEPARATOR) + ServiceConstants::STREAM_INSTALL_PATH;
448     tempDir += ServiceConstants::PATH_SEPARATOR + std::to_string(curTime) + std::to_string(installerId)
449         + Constants::FILE_UNDERLINE + std::to_string(index)+ ServiceConstants::PATH_SEPARATOR;
450     return CreateTempDir(tempDir);
451 }
452 
CreateFileDescriptor(const std::string & bundlePath,long long offset)453 int32_t BundleUtil::CreateFileDescriptor(const std::string &bundlePath, long long offset)
454 {
455     int fd = -1;
456     if (bundlePath.length() > ServiceConstants::PATH_MAX_SIZE) {
457         APP_LOGE("the length of the bundlePath exceeds maximum limitation");
458         return fd;
459     }
460     if ((fd = open(bundlePath.c_str(), O_CREAT | O_RDWR, S_IRUSR | S_IWUSR)) < 0) {
461         APP_LOGE("open bundlePath %{public}s failed errno:%{public}d", bundlePath.c_str(), errno);
462         return fd;
463     }
464     if (offset > 0) {
465         lseek(fd, offset, SEEK_SET);
466     }
467     return fd;
468 }
469 
CreateFileDescriptorForReadOnly(const std::string & bundlePath,long long offset)470 int32_t BundleUtil::CreateFileDescriptorForReadOnly(const std::string &bundlePath, long long offset)
471 {
472     int fd = -1;
473     if (bundlePath.length() > ServiceConstants::PATH_MAX_SIZE) {
474         APP_LOGE("the length of the bundlePath exceeds maximum limitation");
475         return fd;
476     }
477     std::string realPath;
478     if (!PathToRealPath(bundlePath, realPath)) {
479         APP_LOGE("file is not real path");
480         return fd;
481     }
482 
483     if ((fd = open(realPath.c_str(), O_RDONLY)) < 0) {
484         APP_LOGE("open bundlePath %{public}s failed errno:%{public}d", realPath.c_str(), errno);
485         return fd;
486     }
487     if (offset > 0) {
488         lseek(fd, offset, SEEK_SET);
489     }
490     return fd;
491 }
492 
CloseFileDescriptor(std::vector<int32_t> & fdVec)493 void BundleUtil::CloseFileDescriptor(std::vector<int32_t> &fdVec)
494 {
495     for_each(fdVec.begin(), fdVec.end(), [](const auto &fd) {
496         if (fd > 0) {
497             close(fd);
498         }
499     });
500     fdVec.clear();
501 }
502 
IsExistFile(const std::string & path)503 bool BundleUtil::IsExistFile(const std::string &path)
504 {
505     if (path.empty()) {
506         return false;
507     }
508 
509     struct stat buf = {};
510     if (stat(path.c_str(), &buf) != 0) {
511         APP_LOGE("fail stat errno:%{public}d", errno);
512         return false;
513     }
514 
515     return S_ISREG(buf.st_mode);
516 }
517 
IsExistFileNoLog(const std::string & path)518 bool BundleUtil::IsExistFileNoLog(const std::string &path)
519 {
520     if (path.empty()) {
521         return false;
522     }
523 
524     struct stat buf = {};
525     if (stat(path.c_str(), &buf) != 0) {
526         return false;
527     }
528 
529     return S_ISREG(buf.st_mode);
530 }
531 
IsExistDir(const std::string & path)532 bool BundleUtil::IsExistDir(const std::string &path)
533 {
534     if (path.empty()) {
535         return false;
536     }
537 
538     struct stat buf = {};
539     if (stat(path.c_str(), &buf) != 0) {
540         APP_LOGE("fail stat errno:%{public}d", errno);
541         return false;
542     }
543 
544     return S_ISDIR(buf.st_mode);
545 }
546 
IsExistDirNoLog(const std::string & path)547 bool BundleUtil::IsExistDirNoLog(const std::string &path)
548 {
549     if (path.empty()) {
550         return false;
551     }
552 
553     struct stat buf = {};
554     if (stat(path.c_str(), &buf) != 0) {
555         return false;
556     }
557 
558     return S_ISDIR(buf.st_mode);
559 }
560 
IsPathInformationConsistent(const std::string & path,int32_t uid,int32_t gid)561 bool BundleUtil::IsPathInformationConsistent(const std::string &path, int32_t uid, int32_t gid)
562 {
563     if (path.empty()) {
564         return false;
565     }
566     struct stat buf = {};
567     if (stat(path.c_str(), &buf) != 0) {
568         return false;
569     }
570     if ((static_cast<int32_t>(buf.st_uid) != uid) || ((static_cast<int32_t>(buf.st_gid) != gid))) {
571         APP_LOGE("path uid or gid is not same");
572         return false;
573     }
574     return true;
575 }
576 
CalculateFileSize(const std::string & bundlePath)577 int64_t BundleUtil::CalculateFileSize(const std::string &bundlePath)
578 {
579     struct stat fileInfo = { 0 };
580     if (stat(bundlePath.c_str(), &fileInfo) != 0) {
581         APP_LOGE("call stat error:%{public}d", errno);
582         return 0;
583     }
584 
585     return static_cast<int64_t>(fileInfo.st_size);
586 }
587 
RenameFile(const std::string & oldPath,const std::string & newPath)588 bool BundleUtil::RenameFile(const std::string &oldPath, const std::string &newPath)
589 {
590     if (oldPath.empty() || newPath.empty()) {
591         APP_LOGE("oldPath or newPath is empty");
592         return false;
593     }
594 
595     if (!DeleteDir(newPath)) {
596         APP_LOGE("delete newPath failed");
597         return false;
598     }
599 
600     if (rename(oldPath.c_str(), newPath.c_str()) != 0) {
601         APP_LOGE("rename failed, errno:%{public}d", errno);
602         return false;
603     }
604     return true;
605 }
606 
DeleteDir(const std::string & path)607 bool BundleUtil::DeleteDir(const std::string &path)
608 {
609     if (IsExistFile(path)) {
610         return OHOS::RemoveFile(path);
611     }
612 
613     if (IsExistDir(path)) {
614         return OHOS::ForceRemoveDirectoryBMS(path);
615     }
616 
617     return true;
618 }
619 
IsUtd(const std::string & param)620 bool BundleUtil::IsUtd(const std::string &param)
621 {
622 #ifdef BUNDLE_FRAMEWORK_UDMF_ENABLED
623     bool isUtd = false;
624     auto ret = UDMF::UtdClient::GetInstance().IsUtd(param, isUtd);
625     return ret == ERR_OK && isUtd;
626 #else
627     return false;
628 #endif
629 }
630 
IsSpecificUtd(const std::string & param)631 bool BundleUtil::IsSpecificUtd(const std::string &param)
632 {
633     if (!IsUtd(param)) {
634         return false;
635     }
636 #ifdef BUNDLE_FRAMEWORK_UDMF_ENABLED
637     std::shared_ptr<UDMF::TypeDescriptor> typeDescriptor;
638     auto ret = UDMF::UtdClient::GetInstance().GetTypeDescriptor(param, typeDescriptor);
639     if (ret != ERR_OK || typeDescriptor == nullptr) {
640         return false;
641     }
642     std::vector<std::string> mimeTypes = typeDescriptor->GetMimeTypes();
643     std::vector<std::string> filenameExtensions = typeDescriptor->GetFilenameExtensions();
644     return !mimeTypes.empty() || !filenameExtensions.empty();
645 #else
646     return false;
647 #endif
648 }
649 
GetUtdVectorByMimeType(const std::string & mimeType)650 std::vector<std::string> BundleUtil::GetUtdVectorByMimeType(const std::string &mimeType)
651 {
652 #ifdef BUNDLE_FRAMEWORK_UDMF_ENABLED
653     std::vector<std::string> utdVector;
654     auto ret = UDMF::UtdClient::GetInstance().GetUniformDataTypesByMIMEType(mimeType, utdVector);
655     if (ret != ERR_OK || utdVector.empty()) {
656         return {};
657     }
658     return utdVector;
659 #else
660     return {};
661 #endif
662 }
663 
GetBoolStrVal(bool val)664 std::string BundleUtil::GetBoolStrVal(bool val)
665 {
666     return val ? "true" : "false";
667 }
668 
CopyFile(const std::string & sourceFile,const std::string & destinationFile)669 bool BundleUtil::CopyFile(
670     const std::string &sourceFile, const std::string &destinationFile)
671 {
672     if (sourceFile.empty() || destinationFile.empty()) {
673         APP_LOGE("Copy file failed due to sourceFile or destinationFile is empty");
674         return false;
675     }
676 
677     std::ifstream in(sourceFile);
678     if (!in.is_open()) {
679         APP_LOGE("Copy file failed due to open sourceFile failed errno:%{public}d", errno);
680         return false;
681     }
682 
683     std::ofstream out(destinationFile);
684     if (!out.is_open()) {
685         APP_LOGE("Copy file failed due to open destinationFile failed errno:%{public}d", errno);
686         in.close();
687         return false;
688     }
689 
690     out << in.rdbuf();
691     in.close();
692     out.close();
693     return true;
694 }
695 
CopyFileFast(const std::string & sourcePath,const std::string & destPath)696 bool BundleUtil::CopyFileFast(const std::string &sourcePath, const std::string &destPath)
697 {
698     APP_LOGI("sourcePath : %{private}s, destPath : %{private}s", sourcePath.c_str(), destPath.c_str());
699     if (sourcePath.empty() || destPath.empty()) {
700         APP_LOGE("invalid path");
701         return false;
702     }
703 
704     int32_t sourceFd = open(sourcePath.c_str(), O_RDONLY);
705     if (sourceFd == -1) {
706         APP_LOGE("sourcePath open failed, errno : %{public}d", errno);
707         return CopyFile(sourcePath, destPath);
708     }
709 
710     struct stat sourceStat;
711     if (fstat(sourceFd, &sourceStat) == -1) {
712         APP_LOGE("fstat failed, errno : %{public}d", errno);
713         close(sourceFd);
714         return CopyFile(sourcePath, destPath);
715     }
716     if (sourceStat.st_size < 0) {
717         APP_LOGE("invalid st_size");
718         close(sourceFd);
719         return CopyFile(sourcePath, destPath);
720     }
721 
722     int32_t destFd = open(
723         destPath.c_str(), O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
724     if (destFd == -1) {
725         APP_LOGE("destPath open failed, errno : %{public}d", errno);
726         close(sourceFd);
727         return CopyFile(sourcePath, destPath);
728     }
729 
730     size_t buffer = 524288; // 0.5M
731     size_t transferCount = 0;
732     ssize_t singleTransfer = 0;
733     while ((singleTransfer = sendfile(destFd, sourceFd, nullptr, buffer)) > 0) {
734         transferCount += static_cast<size_t>(singleTransfer);
735     }
736 
737     if (singleTransfer == -1 || transferCount != static_cast<size_t>(sourceStat.st_size)) {
738         APP_LOGE("sendfile failed, errno : %{public}d, send count : %{public}zu , file size : %{public}zu",
739             errno, transferCount, static_cast<size_t>(sourceStat.st_size));
740         close(sourceFd);
741         close(destFd);
742         return CopyFile(sourcePath, destPath);
743     }
744 
745     close(sourceFd);
746     close(destFd);
747     APP_LOGD("sendfile success");
748     return true;
749 }
750 
GetResource(const std::string & bundleName,const std::string & moduleName,uint32_t resId)751 Resource BundleUtil::GetResource(const std::string &bundleName, const std::string &moduleName, uint32_t resId)
752 {
753     Resource resource;
754     resource.bundleName = bundleName;
755     resource.moduleName = moduleName;
756     resource.id = resId;
757     return resource;
758 }
759 
CreateDir(const std::string & dir)760 bool BundleUtil::CreateDir(const std::string &dir)
761 {
762     if (dir.empty()) {
763         APP_LOGE("path is empty");
764         return false;
765     }
766 
767     if (IsExistFile(dir)) {
768         return true;
769     }
770 
771     if (!OHOS::ForceCreateDirectory(dir)) {
772         APP_LOGE("mkdir %{public}s failed", dir.c_str());
773         return false;
774     }
775 
776     if (chown(dir.c_str(), Constants::FOUNDATION_UID, ServiceConstants::BMS_GID) != 0) {
777         APP_LOGE("fail change %{public}s ownership, errno:%{public}d", dir.c_str(), errno);
778         return false;
779     }
780 
781     mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
782     if (!OHOS::ChangeModeFile(dir, mode)) {
783         APP_LOGE("change mode failed, temp install dir : %{public}s", dir.c_str());
784         return false;
785     }
786     return true;
787 }
788 
RevertToRealPath(const std::string & sandBoxPath,const std::string & bundleName,std::string & realPath)789 bool BundleUtil::RevertToRealPath(const std::string &sandBoxPath, const std::string &bundleName, std::string &realPath)
790 {
791     if (sandBoxPath.empty() || bundleName.empty() ||
792         (sandBoxPath.find(ServiceConstants::SANDBOX_DATA_PATH) == std::string::npos &&
793         sandBoxPath.find(ServiceConstants::APP_INSTALL_SANDBOX_PATH) == std::string::npos)) {
794         APP_LOGE("input sandboxPath or bundleName invalid");
795         return false;
796     }
797 
798     realPath = sandBoxPath;
799     if (sandBoxPath.find(ServiceConstants::SANDBOX_DATA_PATH) == 0) {
800         std::string relaDataPath = std::string(ServiceConstants::REAL_DATA_PATH) + ServiceConstants::PATH_SEPARATOR
801             + std::to_string(BundleUtil::GetUserIdByCallingUid()) + ServiceConstants::BASE + bundleName;
802         realPath.replace(realPath.find(ServiceConstants::SANDBOX_DATA_PATH),
803             std::string(ServiceConstants::SANDBOX_DATA_PATH).size(), relaDataPath);
804     } else if (sandBoxPath.find(ServiceConstants::APP_INSTALL_SANDBOX_PATH) == 0) {
805         std::string relaDataPath = std::string(ServiceConstants::BUNDLE_MANAGER_SERVICE_PATH) +
806             ServiceConstants::GALLERY_DOWNLOAD_PATH + std::to_string(BundleUtil::GetUserIdByCallingUid());
807         realPath.replace(realPath.find(ServiceConstants::APP_INSTALL_SANDBOX_PATH),
808             std::string(ServiceConstants::APP_INSTALL_SANDBOX_PATH).size(), relaDataPath);
809     } else {
810         APP_LOGE("input sandboxPath invalid");
811         return false;
812     }
813     return true;
814 }
815 
IsSandBoxPath(const std::string & path)816 bool BundleUtil::IsSandBoxPath(const std::string &path)
817 {
818     if (path.empty()) {
819         return false;
820     }
821     return path.find(ServiceConstants::SANDBOX_DATA_PATH) == SANDBOX_PATH_INDEX ||
822            path.find(ServiceConstants::APP_INSTALL_SANDBOX_PATH) == SANDBOX_PATH_INDEX;
823 }
824 
StartWith(const std::string & source,const std::string & prefix)825 bool BundleUtil::StartWith(const std::string &source, const std::string &prefix)
826 {
827     if (source.empty() || prefix.empty()) {
828         return false;
829     }
830 
831     return source.find(prefix) == 0;
832 }
833 
EndWith(const std::string & source,const std::string & suffix)834 bool BundleUtil::EndWith(const std::string &source, const std::string &suffix)
835 {
836     if (source.empty() || suffix.empty()) {
837         return false;
838     }
839 
840     auto position = source.rfind(suffix);
841     if (position == std::string::npos) {
842         return false;
843     }
844 
845     std::string suffixStr = source.substr(position);
846     return suffixStr == suffix;
847 }
848 
GetFileSize(const std::string & filePath)849 int64_t BundleUtil::GetFileSize(const std::string &filePath)
850 {
851     struct stat fileInfo = { 0 };
852     if (stat(filePath.c_str(), &fileInfo) != 0) {
853         APP_LOGE("call stat error:%{public}d", errno);
854         return 0;
855     }
856     return fileInfo.st_size;
857 }
858 
CopyFileToSecurityDir(const std::string & filePath,const DirType & dirType,std::vector<std::string> & toDeletePaths,bool rename)859 std::string BundleUtil::CopyFileToSecurityDir(const std::string &filePath, const DirType &dirType,
860     std::vector<std::string> &toDeletePaths, bool rename)
861 {
862     APP_LOGD("the original dir is %{public}s", filePath.c_str());
863     std::string destination = "";
864     std::string subStr = "";
865     destination.append(ServiceConstants::HAP_COPY_PATH).append(ServiceConstants::PATH_SEPARATOR);
866     if (dirType == DirType::STREAM_INSTALL_DIR) {
867         subStr = ServiceConstants::STREAM_INSTALL_PATH;
868         destination.append(ServiceConstants::SECURITY_STREAM_INSTALL_PATH);
869         mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
870         if (InstalldClient::GetInstance()->Mkdir(
871             destination, mode, Constants::FOUNDATION_UID, ServiceConstants::BMS_GID) != ERR_OK) {
872             APP_LOGW("installd mkdir %{private}s failed", destination.c_str());
873         }
874     }
875     if (dirType == DirType::SIG_FILE_DIR) {
876         subStr = ServiceConstants::SIGNATURE_FILE_PATH;
877         destination.append(ServiceConstants::SECURITY_SIGNATURE_FILE_PATH);
878     }
879     destination.append(ServiceConstants::PATH_SEPARATOR);
880     destination.append(GetAppInstallPrefix(filePath, rename));
881     destination.append(std::to_string(GetCurrentTimeNs()));
882     destination = CreateTempDir(destination);
883     auto pos = filePath.find(subStr);
884     if (pos == std::string::npos) { // this circumstance could not be considered laterly
885         auto lastPathSeperator = filePath.rfind(ServiceConstants::PATH_SEPARATOR);
886         if ((lastPathSeperator != std::string::npos) && (lastPathSeperator != filePath.length() - 1)) {
887             toDeletePaths.emplace_back(destination);
888             destination.append(filePath.substr(lastPathSeperator));
889         }
890     } else {
891         auto secondLastPathSep = filePath.find(ServiceConstants::PATH_SEPARATOR, pos);
892         if ((secondLastPathSep == std::string::npos) || (secondLastPathSep == filePath.length() - 1)) {
893             return "";
894         }
895         auto thirdLastPathSep =
896             filePath.find(ServiceConstants::PATH_SEPARATOR, secondLastPathSep + 1);
897         if ((thirdLastPathSep == std::string::npos) || (thirdLastPathSep == filePath.length() - 1)) {
898             return "";
899         }
900         toDeletePaths.emplace_back(destination);
901         std::string innerSubstr =
902             filePath.substr(secondLastPathSep, thirdLastPathSep - secondLastPathSep + 1);
903         destination = CreateTempDir(destination.append(innerSubstr));
904         destination.append(filePath.substr(thirdLastPathSep + 1));
905     }
906     APP_LOGD("the destination dir is %{public}s", destination.c_str());
907     if (destination.empty()) {
908         return "";
909     }
910     if (rename) {
911         APP_LOGD("rename file from %{public}s to %{public}s", filePath.c_str(), destination.c_str());
912         if (!RenameFile(filePath, destination)) {
913             APP_LOGE("rename file from %{private}s to %{private}s failed", filePath.c_str(), destination.c_str());
914             return "";
915         }
916     } else {
917         if (!CopyFileFast(filePath, destination)) {
918             APP_LOGE("copy file from %{private}s to %{private}s failed", filePath.c_str(), destination.c_str());
919             return "";
920         }
921     }
922     return destination;
923 }
924 
GetAppInstallPrefix(const std::string & filePath,bool rename)925 std::string BundleUtil::GetAppInstallPrefix(const std::string &filePath, bool rename)
926 {
927     // get ${bundleName} and ${userId} from
928     // /data/service/el1/public/bms/bundle_manager_service/app_install/${userId}/${bundleName}/${fileName}.hap
929     if (!rename) {
930         return "";
931     }
932     std::string prefix = std::string(ServiceConstants::BUNDLE_MANAGER_SERVICE_PATH) +
933         ServiceConstants::GALLERY_DOWNLOAD_PATH;
934     if (filePath.find(prefix) != 0) {
935         return "";
936     }
937     // ${userId}/${bundleName}/${fileName}.hap
938     std::string tempStr = filePath.substr(prefix.length());
939     auto pos = tempStr.rfind(ServiceConstants::PATH_SEPARATOR);
940     if (pos == std::string::npos) {
941         return "";
942     }
943     // ${userId}/${bundleName}
944     tempStr = tempStr.substr(0, pos);
945     pos = tempStr.rfind(ServiceConstants::PATH_SEPARATOR);
946     if (pos == std::string::npos) {
947         return "";
948     }
949     if (pos != tempStr.find(ServiceConstants::PATH_SEPARATOR)) {
950         return "";
951     }
952     std::string bundleName = tempStr.substr(pos + 1);
953     std::string userId = tempStr.substr(0, pos);
954     if (bundleName.empty() || userId.empty()) {
955         return "";
956     }
957     // +app_install+${bundleName}+${userId}+
958     std::string newPrefix = std::string(APP_INSTALL_PREFIX) + bundleName + ServiceConstants::PLUS_SIGN + userId +
959         ServiceConstants::PLUS_SIGN;
960     APP_LOGI("newPrefix is %{public}s", newPrefix.c_str());
961     return newPrefix;
962 }
963 
RestoreAppInstallHaps()964 void BundleUtil::RestoreAppInstallHaps()
965 {
966     std::string securityPath = std::string(ServiceConstants::HAP_COPY_PATH) + ServiceConstants::PATH_SEPARATOR +
967         ServiceConstants::SECURITY_STREAM_INSTALL_PATH + ServiceConstants::PATH_SEPARATOR;
968     DIR* dir = opendir(securityPath.c_str());
969     if (dir == nullptr) {
970         APP_LOGE("open security dir failed errno:%{public}d", errno);
971         return;
972     }
973     struct dirent *entry = nullptr;
974     while ((entry = readdir(dir)) != nullptr) {
975         if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
976             continue;
977         }
978         if (entry->d_type != DT_DIR) {
979             continue;
980         }
981         std::string dirName = std::string(entry->d_name);
982         if (dirName.find(APP_INSTALL_PREFIX) != 0) {
983             continue;
984         }
985         // parse bundleName and userId from +app_install+${bundleName}+${userId}+${fileName}
986         std::string temp = dirName.substr(strlen(APP_INSTALL_PREFIX));
987         auto pos = temp.find(ServiceConstants::PLUS_SIGN);
988         if (pos == std::string::npos) {
989             continue;
990         }
991         std::string bundleName = temp.substr(0, pos);
992         temp = temp.substr(pos + 1);
993         pos = temp.find(ServiceConstants::PLUS_SIGN);
994         if (pos == std::string::npos) {
995             continue;
996         }
997         std::string userId = temp.substr(0, pos);
998         RestoreHaps(securityPath + dirName + ServiceConstants::PATH_SEPARATOR, bundleName, userId);
999     }
1000     closedir(dir);
1001 }
1002 
RestoreHaps(const std::string & sourcePath,const std::string & bundleName,const std::string & userId)1003 void BundleUtil::RestoreHaps(const std::string &sourcePath, const std::string &bundleName, const std::string &userId)
1004 {
1005     if (sourcePath.empty() || bundleName.empty() || userId.empty()) {
1006         return;
1007     }
1008     if (OHOS::IsEmptyFolder(sourcePath)) {
1009         return;
1010     }
1011     std::string destPath = std::string(ServiceConstants::HAP_COPY_PATH) + ServiceConstants::GALLERY_DOWNLOAD_PATH +
1012         userId + ServiceConstants::PATH_SEPARATOR + bundleName + ServiceConstants::PATH_SEPARATOR;
1013     struct stat buf = {};
1014     if (stat(destPath.c_str(), &buf) != 0 || !S_ISDIR(buf.st_mode)) {
1015         APP_LOGE("app install bundlename dir not exist");
1016         return;
1017     }
1018     DIR* dir = opendir(sourcePath.c_str());
1019     if (dir == nullptr) {
1020         APP_LOGE("open security dir failed errno:%{public}d", errno);
1021         return;
1022     }
1023     struct dirent *entry = nullptr;
1024     while ((entry = readdir(dir)) != nullptr) {
1025         if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
1026             continue;
1027         }
1028         std::string fileName = std::string(entry->d_name);
1029         std::string sourceFile = sourcePath + fileName;
1030         std::string destFile = destPath + fileName;
1031         APP_LOGI("restore file from %{public}s to %{public}s", sourceFile.c_str(), destFile.c_str());
1032         if (!RenameFile(sourceFile, destFile)) {
1033             APP_LOGE("restore file from %{public}s to %{public}s failed", sourceFile.c_str(), destFile.c_str());
1034         }
1035     }
1036     closedir(dir);
1037     if (OHOS::IsEmptyFolder(sourcePath)) {
1038         BundleUtil::DeleteDir(sourcePath);
1039     }
1040 }
1041 
DeleteTempDirs(const std::vector<std::string> & tempDirs)1042 void BundleUtil::DeleteTempDirs(const std::vector<std::string> &tempDirs)
1043 {
1044     for (const auto &tempDir : tempDirs) {
1045         APP_LOGD("the temp hap dir %{public}s needs to be deleted", tempDir.c_str());
1046         BundleUtil::DeleteDir(tempDir);
1047     }
1048 }
1049 
GetHexHash(const std::string & s)1050 std::string BundleUtil::GetHexHash(const std::string &s)
1051 {
1052     std::hash<std::string> hasher;
1053     size_t hash = hasher(s);
1054 
1055     std::stringstream ss;
1056     ss << std::hex << hash;
1057 
1058     std::string hash_str = ss.str();
1059     return hash_str;
1060 }
1061 
RecursiveHash(std::string & s)1062 void BundleUtil::RecursiveHash(std::string& s)
1063 {
1064     if (s.size() >= ORIGIN_STRING_LENGTH) {
1065         s = s.substr(s.size() - ORIGIN_STRING_LENGTH);
1066         return;
1067     }
1068     std::string hash = GetHexHash(s);
1069     s += hash;
1070     RecursiveHash(s);
1071 }
1072 
GenerateUuid()1073 std::string BundleUtil::GenerateUuid()
1074 {
1075     std::lock_guard<std::mutex> lock(g_mutex);
1076     auto currentTime = std::chrono::system_clock::now();
1077     auto timestampNanoseconds =
1078         std::chrono::duration_cast<std::chrono::nanoseconds>(currentTime.time_since_epoch()).count();
1079 
1080     // convert nanosecond timestamps to string
1081     std::string s = std::to_string(timestampNanoseconds);
1082     std::string timeStr = GetHexHash(s);
1083 
1084     char deviceId[UUID_LENGTH_MAX] = { 0 };
1085     auto ret = GetDevUdid(deviceId, UUID_LENGTH_MAX);
1086     std::string deviceUdid;
1087     std::string deviceStr;
1088     if (ret != 0) {
1089         APP_LOGW("GetDevUdid failed");
1090     } else {
1091         deviceUdid = std::string{ deviceId };
1092         deviceStr = GetHexHash(deviceUdid);
1093     }
1094 
1095     std::string uuid = timeStr + deviceStr;
1096     RecursiveHash(uuid);
1097 
1098     for (int32_t index : SEPARATOR_POSITIONS) {
1099         uuid.insert(index, 1, UUID_SEPARATOR);
1100     }
1101     return uuid;
1102 }
1103 
GenerateUuidByKey(const std::string & key)1104 std::string BundleUtil::GenerateUuidByKey(const std::string &key)
1105 {
1106     std::string keyHash = GetHexHash(key);
1107 
1108     char deviceId[UUID_LENGTH_MAX] = { 0 };
1109     auto ret = GetDevUdid(deviceId, UUID_LENGTH_MAX);
1110     std::string deviceUdid;
1111     std::string deviceStr;
1112     if (ret != 0) {
1113         APP_LOGW("GetDevUdid failed");
1114     } else {
1115         deviceUdid = std::string{ deviceId };
1116         deviceStr = GetHexHash(deviceUdid);
1117     }
1118 
1119     std::string uuid = keyHash + deviceStr;
1120     RecursiveHash(uuid);
1121 
1122     for (int32_t index : SEPARATOR_POSITIONS) {
1123         uuid.insert(index, 1, UUID_SEPARATOR);
1124     }
1125     return uuid;
1126 }
1127 
GenerateRandomNumbers(uint8_t size,uint8_t lRange,uint8_t rRange)1128 std::vector<uint8_t> BundleUtil::GenerateRandomNumbers(uint8_t size, uint8_t lRange, uint8_t rRange)
1129 {
1130     std::vector<uint8_t> rangeV;
1131     if (size == 0 || size > RANDOM_NUMBER_LENGTH) {
1132         return rangeV;
1133     }
1134     rangeV.resize(size);
1135     std::random_device rd;
1136     std::mt19937 gen(rd());
1137     std::uniform_int_distribution<uint8_t> distributionNum(lRange, rRange);
1138 
1139     std::generate(rangeV.begin(), rangeV.end(), [&]() { return distributionNum(gen); });
1140     return rangeV;
1141 }
1142 
ExtractGroupIdByDevelopId(const std::string & developerId)1143 std::string BundleUtil::ExtractGroupIdByDevelopId(const std::string &developerId)
1144 {
1145     std::string::size_type dot_position = developerId.find('.');
1146     if (dot_position == std::string::npos) {
1147         // If cannot find '.' , the input string is developerId, return developerId
1148         return developerId;
1149     }
1150     if (dot_position == 0) {
1151         // if'.' In the first place, then groupId is empty, return developerId
1152         return developerId.substr(1);
1153     }
1154     // If '.' If it is not the first place, there is a groupId, and the groupId is returned
1155     return developerId.substr(0, dot_position);
1156 }
1157 
ToString(const std::vector<std::string> & vector)1158 std::string BundleUtil::ToString(const std::vector<std::string> &vector)
1159 {
1160     std::string ret;
1161     for (const std::string &item : vector) {
1162         ret.append(item).append(",");
1163     }
1164     return ret;
1165 }
1166 
GetNoDisablingConfigPath()1167 std::string BundleUtil::GetNoDisablingConfigPath()
1168 {
1169 #ifdef CONFIG_POLOCY_ENABLE
1170     char buf[MAX_PATH_LEN] = { 0 };
1171     char *configPath = GetOneCfgFile(NO_DISABLING_CONFIG_PATH, buf, MAX_PATH_LEN);
1172     if (configPath == nullptr || configPath[0] == '\0') {
1173         APP_LOGE("BundleUtil GetOneCfgFile failed");
1174         return NO_DISABLING_CONFIG_PATH_DEFAULT;
1175     }
1176     if (strlen(configPath) > MAX_PATH_LEN) {
1177         APP_LOGE("length exceeds");
1178         return NO_DISABLING_CONFIG_PATH_DEFAULT;
1179     }
1180     return configPath;
1181 #else
1182     return NO_DISABLING_CONFIG_PATH_DEFAULT;
1183 #endif
1184 }
1185 
ExtractNumberFromString(nlohmann::json & jsonObject,const std::string & key)1186 uint32_t BundleUtil::ExtractNumberFromString(nlohmann::json &jsonObject, const std::string &key)
1187 {
1188     std::string str;
1189     if (jsonObject.find(key) == jsonObject.end()) {
1190         APP_LOGE("not find key");
1191         return ID_INVALID;
1192     }
1193     if (!jsonObject.at(key).is_string()) {
1194         APP_LOGE("key is not string");
1195         return ID_INVALID;
1196     }
1197     str = jsonObject.at(key).get<std::string>();
1198     if (str.empty() || str.length() > Constants::MAX_JSON_STRING_LENGTH) {
1199         APP_LOGE("exceeding the maximum string length");
1200         return ID_INVALID;
1201     }
1202     size_t index = str.find(COLON);
1203     if ((index == std::string::npos) || (index == str.length() - 1)) {
1204         APP_LOGE("not find colon or format error");
1205         return ID_INVALID;
1206     }
1207     std::string numberStr = str.substr(index + 1);
1208     if (numberStr.empty()) {
1209         APP_LOGE("number string is empty");
1210         return ID_INVALID;
1211     }
1212     uint32_t data = 0;
1213     if (!StrToUint32(numberStr, data)) {
1214         APP_LOGE("conversion failure");
1215         return ID_INVALID;
1216     }
1217     return data;
1218 }
1219 
StrToUint32(const std::string & str,uint32_t & value)1220 bool BundleUtil::StrToUint32(const std::string &str, uint32_t &value)
1221 {
1222     if (str.empty() || !isdigit(str.front())) {
1223         APP_LOGE("str is empty!");
1224         return false;
1225     }
1226     char* end = nullptr;
1227     errno = 0;
1228     auto addr = str.c_str();
1229     auto result = strtoul(addr, &end, 10); /* 10 means decimal */
1230     if ((end == addr) || (end[0] != '\0') || (errno == ERANGE) ||
1231         (result > UINT32_MAX)) {
1232         APP_LOGE("the result was incorrect!");
1233         return false;
1234     }
1235     value = static_cast<uint32_t>(result);
1236     return true;
1237 }
1238 
ExtractStringFromJson(nlohmann::json & jsonObject,const std::string & key)1239 std::string BundleUtil::ExtractStringFromJson(nlohmann::json &jsonObject, const std::string &key)
1240 {
1241     std::string str = DEFAULT_START_WINDOW_BACKGROUND_IMAGE_FIT_VALUE;
1242     if (jsonObject.find(key) == jsonObject.end()) {
1243         APP_LOGW("the default value is Cover");
1244         return str;
1245     }
1246     if (!jsonObject.at(key).is_string()) {
1247         APP_LOGE("key is not string");
1248         return str;
1249     }
1250     str = jsonObject.at(key).get<std::string>();
1251     if (str.empty() || str.length() > Constants::MAX_JSON_STRING_LENGTH) {
1252         APP_LOGE("exceeding the maximum string length");
1253         return DEFAULT_START_WINDOW_BACKGROUND_IMAGE_FIT_VALUE;
1254     }
1255     return str;
1256 }
1257 
ParseMapFromJson(const std::string & jsonStr)1258 std::unordered_map<std::string, std::string> BundleUtil::ParseMapFromJson(const std::string &jsonStr)
1259 {
1260     std::unordered_map<std::string, std::string> result;
1261     if (jsonStr.empty()) {
1262         APP_LOGD("jsonStr is empty");
1263         return result;
1264     }
1265     APP_LOGD("ParseMapFromJson from %{public}s", jsonStr.c_str());
1266     nlohmann::json jsonBuf = nlohmann::json::parse(jsonStr, nullptr, false);
1267     if (jsonBuf.is_discarded()) {
1268         APP_LOGE("json file discarded");
1269         return result;
1270     }
1271     if (!jsonBuf.is_object()) {
1272         APP_LOGE("jsonBuf is not object");
1273         return result;
1274     }
1275     for (const auto& [key, value] : jsonBuf.items()) {
1276         result[key] = value.dump();
1277     }
1278     return result;
1279 }
1280 }  // namespace AppExecFwk
1281 }  // namespace OHOS
1282