• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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