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 ¶m)
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 ¶m)
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