1 /*
2 * Copyright (c) 2021-2022 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 <algorithm>
19 #include <chrono>
20 #include <cinttypes>
21 #include <dirent.h>
22 #include <fcntl.h>
23 #include <fstream>
24 #include <random>
25 #include <set>
26 #include <sys/stat.h>
27 #include <sys/statfs.h>
28 #include <thread>
29 #include <unistd.h>
30
31 #include "app_log_wrapper.h"
32 #include "bundle_constants.h"
33 #include "hitrace_meter.h"
34 #include "directory_ex.h"
35 #include "ipc_skeleton.h"
36 #include "string_ex.h"
37
38 namespace OHOS {
39 namespace AppExecFwk {
40 namespace {
41 const std::string::size_type EXPECT_SPLIT_SIZE = 2;
42 const std::string DEC_TO_HEX = "0123456789abcdef";
43 const std::string::size_type DATA_GROUP_DIR_SIZE = 36;
44 const char DATA_GROUP_DIR_SEPARATOR = '-';
45 const std::set<int32_t> SEPARATOR_POSITIONS { 8, 13, 18, 23};
46 const int32_t RANDOM_NUM_START = 0;
47 const int32_t RANDOM_NUM_END = 15;
48 const int64_t HALF_GB = 1024 * 1024 * 512; // 0.5GB
49 const double SAVE_SPACE_PERCENT = 0.05;
50 static std::string g_deviceUdid;
51 static std::mutex g_mutex;
52 // hmdfs and sharefs config
53 constexpr const char* BUNDLE_ID_FILE = "appid";
54 }
55
CheckFilePath(const std::string & bundlePath,std::string & realPath)56 ErrCode BundleUtil::CheckFilePath(const std::string &bundlePath, std::string &realPath)
57 {
58 if (!CheckFileName(bundlePath)) {
59 APP_LOGE("bundle file path invalid");
60 return ERR_APPEXECFWK_INSTALL_FILE_PATH_INVALID;
61 }
62 if (!CheckFileType(bundlePath, Constants::INSTALL_FILE_SUFFIX) &&
63 !CheckFileType(bundlePath, Constants::INSTALL_SHARED_FILE_SUFFIX) &&
64 !CheckFileType(bundlePath, Constants::QUICK_FIX_FILE_SUFFIX) &&
65 !CheckFileType(bundlePath, Constants::CODE_SIGNATURE_FILE_SUFFIX)) {
66 APP_LOGE("file is not hap, hsp, hqf or sig");
67 return ERR_APPEXECFWK_INSTALL_INVALID_HAP_NAME;
68 }
69 if (!PathToRealPath(bundlePath, realPath)) {
70 APP_LOGE("file is not real path");
71 return ERR_APPEXECFWK_INSTALL_FILE_PATH_INVALID;
72 }
73 if (access(realPath.c_str(), F_OK) != 0) {
74 APP_LOGE("can not access the bundle file path: %{private}s", realPath.c_str());
75 return ERR_APPEXECFWK_INSTALL_INVALID_BUNDLE_FILE;
76 }
77 if (!CheckFileSize(realPath, Constants::MAX_HAP_SIZE)) {
78 APP_LOGE("file size is larger than max hap size Max size is: %{public}" PRId64, Constants::MAX_HAP_SIZE);
79 return ERR_APPEXECFWK_INSTALL_INVALID_HAP_SIZE;
80 }
81 return ERR_OK;
82 }
83
CheckFilePath(const std::vector<std::string> & bundlePaths,std::vector<std::string> & realPaths)84 ErrCode BundleUtil::CheckFilePath(const std::vector<std::string> &bundlePaths, std::vector<std::string> &realPaths)
85 {
86 HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
87 // there are three cases for bundlePaths:
88 // 1. one bundle direction in the bundlePaths, some hap files under this bundle direction.
89 // 2. one hap direction in the bundlePaths.
90 // 3. some hap file directions in the bundlePaths.
91 APP_LOGD("check file path");
92 if (bundlePaths.empty()) {
93 APP_LOGE("bundle file paths invalid");
94 return ERR_APPEXECFWK_INSTALL_FILE_PATH_INVALID;
95 }
96 ErrCode ret = ERR_OK;
97
98 if (bundlePaths.size() == 1) {
99 struct stat s;
100 std::string bundlePath = bundlePaths.front();
101 if (stat(bundlePath.c_str(), &s) == 0) {
102 std::string realPath = "";
103 // it is a direction
104 if ((s.st_mode & S_IFDIR) && !GetHapFilesFromBundlePath(bundlePath, realPaths)) {
105 APP_LOGE("GetHapFilesFromBundlePath failed with bundlePath:%{private}s", bundlePaths.front().c_str());
106 return ERR_APPEXECFWK_INSTALL_FILE_PATH_INVALID;
107 }
108 // it is a file
109 if ((s.st_mode & S_IFREG) && (ret = CheckFilePath(bundlePaths.front(), realPath)) == ERR_OK) {
110 realPaths.emplace_back(realPath);
111 }
112 return ret;
113 } else {
114 APP_LOGE("bundlePath is not existed with :%{private}s", bundlePaths.front().c_str());
115 return ERR_APPEXECFWK_INSTALL_FILE_PATH_INVALID;
116 }
117 } else {
118 for (const std::string& bundlePath : bundlePaths) {
119 std::string realPath = "";
120 ret = CheckFilePath(bundlePath, realPath);
121 if (ret != ERR_OK) {
122 return ret;
123 }
124 realPaths.emplace_back(realPath);
125 }
126 }
127 APP_LOGD("finish check file path");
128 return ret;
129 }
130
CheckFileType(const std::string & fileName,const std::string & extensionName)131 bool BundleUtil::CheckFileType(const std::string &fileName, const std::string &extensionName)
132 {
133 APP_LOGD("path is %{private}s, support suffix is %{public}s", fileName.c_str(), extensionName.c_str());
134 if (!CheckFileName(fileName)) {
135 return false;
136 }
137
138 auto position = fileName.rfind('.');
139 if (position == std::string::npos) {
140 APP_LOGE("filename no extension name");
141 return false;
142 }
143
144 std::string suffixStr = fileName.substr(position);
145 return LowerStr(suffixStr) == extensionName;
146 }
147
CheckFileName(const std::string & fileName)148 bool BundleUtil::CheckFileName(const std::string &fileName)
149 {
150 if (fileName.empty()) {
151 APP_LOGE("the file name is empty");
152 return false;
153 }
154 if (fileName.size() > Constants::PATH_MAX_SIZE) {
155 APP_LOGE("bundle file path length %{public}zu too long", fileName.size());
156 return false;
157 }
158 return true;
159 }
160
CheckFileSize(const std::string & bundlePath,const int64_t fileSize)161 bool BundleUtil::CheckFileSize(const std::string &bundlePath, const int64_t fileSize)
162 {
163 APP_LOGD("fileSize is %{public}" PRId64, fileSize / Constants::ONE_GB);
164 struct stat fileInfo = { 0 };
165 if (stat(bundlePath.c_str(), &fileInfo) != 0) {
166 APP_LOGE("call stat error");
167 return false;
168 }
169 if (fileInfo.st_size > fileSize) {
170 return false;
171 }
172 return true;
173 }
174
CheckSystemSize(const std::string & bundlePath,const std::string & diskPath)175 bool BundleUtil::CheckSystemSize(const std::string &bundlePath, const std::string &diskPath)
176 {
177 struct statfs diskInfo = { 0 };
178 if (statfs(diskPath.c_str(), &diskInfo) != 0) {
179 APP_LOGE("call statfs error");
180 return false;
181 }
182 int64_t freeSize = diskInfo.f_bfree * diskInfo.f_bsize;
183 APP_LOGD("left free size in the disk path is %{public}" PRId64, freeSize / Constants::ONE_GB);
184
185 // bundleSize + keepSize <= system-freeSize needs to be satisfied
186 return CheckFileSize(bundlePath, freeSize - std::min(freeSize * SAVE_SPACE_PERCENT, static_cast<double>(HALF_GB)));
187 }
188
GetHapFilesFromBundlePath(const std::string & currentBundlePath,std::vector<std::string> & hapFileList)189 bool BundleUtil::GetHapFilesFromBundlePath(const std::string& currentBundlePath, std::vector<std::string>& hapFileList)
190 {
191 APP_LOGD("GetHapFilesFromBundlePath with path is %{private}s", currentBundlePath.c_str());
192 if (currentBundlePath.empty()) {
193 return false;
194 }
195 DIR* dir = opendir(currentBundlePath.c_str());
196 if (dir == nullptr) {
197 char errMsg[256] = {0};
198 strerror_r(errno, errMsg, sizeof(errMsg));
199 APP_LOGE("GetHapFilesFromBundlePath open bundle dir:%{private}s is failure due to %{public}s",
200 currentBundlePath.c_str(), errMsg);
201 return false;
202 }
203 std::string bundlePath = currentBundlePath;
204 if (bundlePath.back() != Constants::FILE_SEPARATOR_CHAR) {
205 bundlePath.append(Constants::PATH_SEPARATOR);
206 }
207 struct dirent *entry = nullptr;
208 while ((entry = readdir(dir)) != nullptr) {
209 if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
210 continue;
211 }
212 const std::string hapFilePath = bundlePath + entry->d_name;
213 std::string realPath = "";
214 if (CheckFilePath(hapFilePath, realPath) != ERR_OK) {
215 APP_LOGE("find invalid hap path %{private}s", hapFilePath.c_str());
216 closedir(dir);
217 return false;
218 }
219 hapFileList.emplace_back(realPath);
220 APP_LOGD("find hap path %{private}s", realPath.c_str());
221
222 if (!hapFileList.empty() && (hapFileList.size() > Constants::MAX_HAP_NUMBER)) {
223 APP_LOGE("reach the max hap number 128, stop to add more.");
224 closedir(dir);
225 return false;
226 }
227 }
228 closedir(dir);
229 return true;
230 }
231
GetCurrentTime()232 int64_t BundleUtil::GetCurrentTime()
233 {
234 int64_t time =
235 std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::now().time_since_epoch())
236 .count();
237 APP_LOGD("the current time in seconds is %{public}" PRId64, time);
238 return time;
239 }
240
GetCurrentTimeMs()241 int64_t BundleUtil::GetCurrentTimeMs()
242 {
243 int64_t time =
244 std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch())
245 .count();
246 APP_LOGD("the current time in milliseconds is %{public}" PRId64, time);
247 return time;
248 }
249
DeviceAndNameToKey(const std::string & deviceId,const std::string & bundleName,std::string & key)250 void BundleUtil::DeviceAndNameToKey(
251 const std::string &deviceId, const std::string &bundleName, std::string &key)
252 {
253 key.append(deviceId);
254 key.append(Constants::FILE_UNDERLINE);
255 key.append(bundleName);
256 APP_LOGD("bundleName = %{public}s", bundleName.c_str());
257 }
258
KeyToDeviceAndName(const std::string & key,std::string & deviceId,std::string & bundleName)259 bool BundleUtil::KeyToDeviceAndName(
260 const std::string &key, std::string &deviceId, std::string &bundleName)
261 {
262 bool ret = false;
263 std::vector<std::string> splitStrs;
264 OHOS::SplitStr(key, Constants::FILE_UNDERLINE, splitStrs);
265 // the expect split size should be 2.
266 // key rule is <deviceId>_<bundleName>
267 if (splitStrs.size() == EXPECT_SPLIT_SIZE) {
268 deviceId = splitStrs[0];
269 bundleName = splitStrs[1];
270 ret = true;
271 }
272 APP_LOGD("bundleName = %{public}s", bundleName.c_str());
273 return ret;
274 }
275
GetUserIdByCallingUid()276 int32_t BundleUtil::GetUserIdByCallingUid()
277 {
278 int32_t uid = IPCSkeleton::GetCallingUid();
279 APP_LOGD("get calling uid(%{public}d)", uid);
280 return GetUserIdByUid(uid);
281 }
282
GetUserIdByUid(int32_t uid)283 int32_t BundleUtil::GetUserIdByUid(int32_t uid)
284 {
285 if (uid <= Constants::INVALID_UID) {
286 APP_LOGE("uid is illegal: %{public}d", uid);
287 return Constants::INVALID_USERID;
288 }
289
290 return uid / Constants::BASE_USER_RANGE;
291 }
292
MakeFsConfig(const std::string & bundleName,int32_t bundleId,const std::string & configPath)293 void BundleUtil::MakeFsConfig(const std::string &bundleName, int32_t bundleId, const std::string &configPath)
294 {
295 std::string bundleDir = configPath + Constants::PATH_SEPARATOR + bundleName;
296 if (access(bundleDir.c_str(), F_OK) != 0) {
297 if (mkdir(bundleDir.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) != 0) {
298 APP_LOGE("make bundle dir error");
299 return;
300 }
301 }
302
303 std::string realBundleDir;
304 if (!PathToRealPath(bundleDir, realBundleDir)) {
305 APP_LOGE("bundleIdFile is not real path");
306 return;
307 }
308
309 realBundleDir += (Constants::PATH_SEPARATOR + BUNDLE_ID_FILE);
310
311 int32_t bundleIdFd = open(realBundleDir.c_str(), O_WRONLY | O_TRUNC);
312 if (bundleIdFd > 0) {
313 std::string bundleIdStr = std::to_string(bundleId);
314 if (write(bundleIdFd, bundleIdStr.c_str(), bundleIdStr.size()) < 0) {
315 APP_LOGE("write bundleId error");
316 }
317 }
318 close(bundleIdFd);
319 }
320
RemoveFsConfig(const std::string & bundleName,const std::string & configPath)321 void BundleUtil::RemoveFsConfig(const std::string &bundleName, const std::string &configPath)
322 {
323 std::string bundleDir = configPath + Constants::PATH_SEPARATOR + bundleName;
324 std::string realBundleDir;
325 if (!PathToRealPath(bundleDir, realBundleDir)) {
326 APP_LOGE("bundleDir is not real path");
327 return;
328 }
329 if (rmdir(realBundleDir.c_str()) != 0) {
330 APP_LOGE("remove hmdfs bundle dir error");
331 }
332 }
333
CreateTempDir(const std::string & tempDir)334 std::string BundleUtil::CreateTempDir(const std::string &tempDir)
335 {
336 if (!OHOS::ForceCreateDirectory(tempDir)) {
337 APP_LOGE("mkdir %{private}s failed", tempDir.c_str());
338 return "";
339 }
340 if (chown(tempDir.c_str(), Constants::FOUNDATION_UID, Constants::BMS_GID) != 0) {
341 APP_LOGE("fail to change %{private}s ownership", tempDir.c_str());
342 return "";
343 }
344 mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
345 if (!OHOS::ChangeModeFile(tempDir, mode)) {
346 APP_LOGE("change mode failed, temp install dir : %{private}s", tempDir.c_str());
347 return "";
348 }
349 return tempDir;
350 }
351
CreateInstallTempDir(uint32_t installerId,const DirType & type)352 std::string BundleUtil::CreateInstallTempDir(uint32_t installerId, const DirType &type)
353 {
354 std::time_t curTime = std::time(0);
355 std::string tempDir = Constants::HAP_COPY_PATH;
356 if (type == DirType::STREAM_INSTALL_DIR) {
357 tempDir += Constants::PATH_SEPARATOR + Constants::STREAM_INSTALL_PATH;
358 } else if (type == DirType::QUICK_FIX_DIR) {
359 tempDir += Constants::PATH_SEPARATOR + Constants::QUICK_FIX_PATH;
360 } else if (type == DirType::SIG_FILE_DIR) {
361 tempDir += Constants::PATH_SEPARATOR + Constants::SIGNATURE_FILE_PATH;
362 } else {
363 return "";
364 }
365
366 if (CreateTempDir(tempDir).empty()) {
367 APP_LOGE("create tempDir failed");
368 return "";
369 }
370
371 tempDir += Constants::PATH_SEPARATOR + std::to_string(curTime) +
372 std::to_string(installerId) + Constants::PATH_SEPARATOR;
373 return CreateTempDir(tempDir);
374 }
375
CreateSharedBundleTempDir(uint32_t installerId,uint32_t index)376 std::string BundleUtil::CreateSharedBundleTempDir(uint32_t installerId, uint32_t index)
377 {
378 std::time_t curTime = std::time(0);
379 std::string tempDir = Constants::HAP_COPY_PATH;
380 tempDir += Constants::PATH_SEPARATOR + Constants::STREAM_INSTALL_PATH;
381 tempDir += Constants::PATH_SEPARATOR + std::to_string(curTime) +
382 std::to_string(installerId) + Constants::FILE_UNDERLINE + std::to_string(index) + Constants::PATH_SEPARATOR;
383 return CreateTempDir(tempDir);
384 }
385
CreateFileDescriptor(const std::string & bundlePath,long long offset)386 int32_t BundleUtil::CreateFileDescriptor(const std::string &bundlePath, long long offset)
387 {
388 int fd = -1;
389 if (bundlePath.length() > Constants::PATH_MAX_SIZE) {
390 APP_LOGE("the length of the bundlePath exceeds maximum limitation");
391 return fd;
392 }
393 if ((fd = open(bundlePath.c_str(), O_CREAT | O_RDWR, S_IRUSR | S_IWUSR)) < 0) {
394 APP_LOGE("open bundlePath %{public}s failed", bundlePath.c_str());
395 return fd;
396 }
397 if (offset > 0) {
398 lseek(fd, offset, SEEK_SET);
399 }
400 return fd;
401 }
402
CreateFileDescriptorForReadOnly(const std::string & bundlePath,long long offset)403 int32_t BundleUtil::CreateFileDescriptorForReadOnly(const std::string &bundlePath, long long offset)
404 {
405 int fd = -1;
406 if (bundlePath.length() > Constants::PATH_MAX_SIZE) {
407 APP_LOGE("the length of the bundlePath exceeds maximum limitation");
408 return fd;
409 }
410 std::string realPath;
411 if (!PathToRealPath(bundlePath, realPath)) {
412 APP_LOGE("file is not real path");
413 return fd;
414 }
415
416 if ((fd = open(realPath.c_str(), O_RDONLY)) < 0) {
417 APP_LOGE("open bundlePath %{public}s failed", realPath.c_str());
418 return fd;
419 }
420 if (offset > 0) {
421 lseek(fd, offset, SEEK_SET);
422 }
423 return fd;
424 }
425
CloseFileDescriptor(std::vector<int32_t> & fdVec)426 void BundleUtil::CloseFileDescriptor(std::vector<int32_t> &fdVec)
427 {
428 for_each(fdVec.begin(), fdVec.end(), [](const auto &fd) {
429 if (fd > 0) {
430 close(fd);
431 }
432 });
433 fdVec.clear();
434 }
435
IsExistFile(const std::string & path)436 bool BundleUtil::IsExistFile(const std::string &path)
437 {
438 if (path.empty()) {
439 return false;
440 }
441
442 struct stat buf = {};
443 if (stat(path.c_str(), &buf) != 0) {
444 return false;
445 }
446
447 return S_ISREG(buf.st_mode);
448 }
449
IsExistDir(const std::string & path)450 bool BundleUtil::IsExistDir(const std::string &path)
451 {
452 if (path.empty()) {
453 return false;
454 }
455
456 struct stat buf = {};
457 if (stat(path.c_str(), &buf) != 0) {
458 return false;
459 }
460
461 return S_ISDIR(buf.st_mode);
462 }
463
RenameFile(const std::string & oldPath,const std::string & newPath)464 bool BundleUtil::RenameFile(const std::string &oldPath, const std::string &newPath)
465 {
466 if (oldPath.empty() || newPath.empty()) {
467 APP_LOGE("oldPath or newPath is empty");
468 return false;
469 }
470
471 if (!DeleteDir(newPath)) {
472 APP_LOGE("delete newPath failed");
473 return false;
474 }
475
476 return rename(oldPath.c_str(), newPath.c_str()) == 0;
477 }
478
DeleteDir(const std::string & path)479 bool BundleUtil::DeleteDir(const std::string &path)
480 {
481 if (IsExistFile(path)) {
482 return OHOS::RemoveFile(path);
483 }
484
485 if (IsExistDir(path)) {
486 return OHOS::ForceRemoveDirectory(path);
487 }
488
489 return true;
490 }
491
GetBoolStrVal(bool val)492 std::string BundleUtil::GetBoolStrVal(bool val)
493 {
494 return val ? "true" : "false";
495 }
496
CopyFile(const std::string & sourceFile,const std::string & destinationFile)497 bool BundleUtil::CopyFile(
498 const std::string &sourceFile, const std::string &destinationFile)
499 {
500 if (sourceFile.empty() || destinationFile.empty()) {
501 APP_LOGE("Copy file failed due to sourceFile or destinationFile is empty");
502 return false;
503 }
504
505 std::ifstream in(sourceFile);
506 if (!in.is_open()) {
507 APP_LOGE("Copy file failed due to open sourceFile failed");
508 return false;
509 }
510
511 std::ofstream out(destinationFile);
512 if (!out.is_open()) {
513 APP_LOGE("Copy file failed due to open destinationFile failed");
514 in.close();
515 return false;
516 }
517
518 out << in.rdbuf();
519 in.close();
520 out.close();
521 return true;
522 }
523
GetResource(const std::string & bundleName,const std::string & moduleName,int32_t resId)524 Resource BundleUtil::GetResource(const std::string &bundleName, const std::string &moduleName, int32_t resId)
525 {
526 Resource resource;
527 resource.bundleName = bundleName;
528 resource.moduleName = moduleName;
529 resource.id = resId;
530 return resource;
531 }
532
CreateDir(const std::string & dir)533 bool BundleUtil::CreateDir(const std::string &dir)
534 {
535 if (dir.empty()) {
536 APP_LOGE("path is empty");
537 return false;
538 }
539
540 if (IsExistFile(dir)) {
541 return true;
542 }
543
544 if (!OHOS::ForceCreateDirectory(dir)) {
545 APP_LOGE("mkdir %{public}s failed", dir.c_str());
546 return false;
547 }
548
549 if (chown(dir.c_str(), Constants::FOUNDATION_UID, Constants::BMS_GID) != 0) {
550 APP_LOGE("fail to change %{public}s ownership", dir.c_str());
551 return false;
552 }
553
554 mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
555 if (!OHOS::ChangeModeFile(dir, mode)) {
556 APP_LOGE("change mode failed, temp install dir : %{public}s", dir.c_str());
557 return false;
558 }
559 return true;
560 }
561
RevertToRealPath(const std::string & sandBoxPath,const std::string & bundleName,std::string & realPath)562 bool BundleUtil::RevertToRealPath(const std::string &sandBoxPath, const std::string &bundleName, std::string &realPath)
563 {
564 if (sandBoxPath.empty() || bundleName.empty() ||
565 sandBoxPath.find(Constants::SANDBOX_DATA_PATH) == std::string::npos) {
566 APP_LOGE("input sandboxPath or bundleName invalid");
567 return false;
568 }
569
570 realPath = sandBoxPath;
571 std::string relaDataPath = Constants::REAL_DATA_PATH + Constants::PATH_SEPARATOR
572 + std::to_string(BundleUtil::GetUserIdByCallingUid()) + Constants::BASE + bundleName;
573 realPath.replace(realPath.find(Constants::SANDBOX_DATA_PATH),
574 std::string(Constants::SANDBOX_DATA_PATH).size(), relaDataPath);
575 return true;
576 }
577
StartWith(const std::string & source,const std::string & prefix)578 bool BundleUtil::StartWith(const std::string &source, const std::string &prefix)
579 {
580 if (source.empty() || prefix.empty()) {
581 return false;
582 }
583
584 return source.find(prefix) == 0;
585 }
586
EndWith(const std::string & source,const std::string & suffix)587 bool BundleUtil::EndWith(const std::string &source, const std::string &suffix)
588 {
589 if (source.empty() || suffix.empty()) {
590 return false;
591 }
592
593 auto position = source.rfind(suffix);
594 if (position == std::string::npos) {
595 return false;
596 }
597
598 std::string suffixStr = source.substr(position);
599 return suffixStr == suffix;
600 }
601
GetFileSize(const std::string & filePath)602 int64_t BundleUtil::GetFileSize(const std::string &filePath)
603 {
604 struct stat fileInfo = { 0 };
605 if (stat(filePath.c_str(), &fileInfo) != 0) {
606 APP_LOGE("call stat error");
607 return 0;
608 }
609 return fileInfo.st_size;
610 }
611
CopyFileToSecurityDir(const std::string & filePath,const DirType & dirType,std::vector<std::string> & toDeletePaths)612 std::string BundleUtil::CopyFileToSecurityDir(const std::string &filePath, const DirType &dirType,
613 std::vector<std::string> &toDeletePaths)
614 {
615 APP_LOGD("the original dir is %{public}s", filePath.c_str());
616 std::string destination = "";
617 std::string subStr = "";
618 destination.append(Constants::HAP_COPY_PATH).append(Constants::PATH_SEPARATOR);
619 if (dirType == DirType::STREAM_INSTALL_DIR) {
620 subStr = Constants::STREAM_INSTALL_PATH;
621 destination.append(Constants::SECURITY_STREAM_INSTALL_PATH);
622 }
623 if (dirType == DirType::SIG_FILE_DIR) {
624 subStr = Constants::SIGNATURE_FILE_PATH;
625 destination.append(Constants::SECURITY_SIGNATURE_FILE_PATH);
626 }
627 destination.append(Constants::PATH_SEPARATOR).append(std::to_string(GetCurrentTimeMs()));
628 destination = CreateTempDir(destination);
629 auto pos = filePath.find(subStr);
630 if (pos == std::string::npos) { // this circumstance could not be considered laterly
631 auto lastPathSeperator = filePath.rfind(Constants::PATH_SEPARATOR);
632 if ((lastPathSeperator != std::string::npos) && (lastPathSeperator != filePath.length() - 1)) {
633 toDeletePaths.emplace_back(destination);
634 destination.append(filePath.substr(lastPathSeperator));
635 }
636 } else {
637 auto secondLastPathSep = filePath.find(Constants::PATH_SEPARATOR, pos);
638 if ((secondLastPathSep == std::string::npos) || (secondLastPathSep == filePath.length() - 1)) {
639 return "";
640 }
641 auto thirdLastPathSep =
642 filePath.find(Constants::PATH_SEPARATOR, secondLastPathSep + 1);
643 if ((thirdLastPathSep == std::string::npos) || (thirdLastPathSep == filePath.length() - 1)) {
644 return "";
645 }
646 toDeletePaths.emplace_back(destination);
647 std::string innerSubstr =
648 filePath.substr(secondLastPathSep, thirdLastPathSep - secondLastPathSep + 1);
649 destination = CreateTempDir(destination.append(innerSubstr));
650 destination.append(filePath.substr(thirdLastPathSep + 1));
651 }
652 APP_LOGD("the destination dir is %{public}s", destination.c_str());
653 if (destination.empty()) {
654 return "";
655 }
656 if (!CopyFile(filePath, destination)) {
657 APP_LOGE("copy file from %{public}s to %{public}s failed", filePath.c_str(), destination.c_str());
658 return "";
659 }
660 return destination;
661 }
662
DeleteTempDirs(const std::vector<std::string> & tempDirs)663 void BundleUtil::DeleteTempDirs(const std::vector<std::string> &tempDirs)
664 {
665 for (const auto &tempDir : tempDirs) {
666 APP_LOGD("the temp hap dir %{public}s needs to be deleted", tempDir.c_str());
667 BundleUtil::DeleteDir(tempDir);
668 }
669 }
670
GenerateDataGroupDirName()671 std::string BundleUtil::GenerateDataGroupDirName()
672 {
673 std::string res(DATA_GROUP_DIR_SIZE, DATA_GROUP_DIR_SEPARATOR);
674 int32_t size = static_cast<int32_t>(DATA_GROUP_DIR_SIZE);
675 for (auto i = 0; i < size; i++) {
676 if (SEPARATOR_POSITIONS.find(i) == SEPARATOR_POSITIONS.end()) {
677 std::random_device seed;
678 std::ranlux48 engine(seed());
679 std::uniform_int_distribution<> distrib(RANDOM_NUM_START, RANDOM_NUM_END);
680 int32_t random = distrib(engine);
681 res[i] = DEC_TO_HEX[random];
682 }
683 }
684 return res;
685 }
686 } // namespace AppExecFwk
687 } // namespace OHOS
688