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