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