• 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 <chrono>
19 #include <cinttypes>
20 #include <dirent.h>
21 #include <fcntl.h>
22 #include <sys/stat.h>
23 #include <sys/statfs.h>
24 #include <thread>
25 #include <unistd.h>
26 
27 #include "app_log_wrapper.h"
28 #include "bundle_constants.h"
29 #include "bytrace.h"
30 #include "directory_ex.h"
31 #include "ipc_skeleton.h"
32 #include "string_ex.h"
33 
34 namespace OHOS {
35 namespace AppExecFwk {
36 namespace {
37 const std::string::size_type EXPECT_SPLIT_SIZE = 2;
38 static std::string g_deviceUdid;
39 static std::mutex g_mutex;
40 }
41 
CheckFilePath(const std::string & bundlePath,std::string & realPath)42 ErrCode BundleUtil::CheckFilePath(const std::string &bundlePath, std::string &realPath)
43 {
44     if (!CheckFileName(bundlePath)) {
45         APP_LOGE("bundle file path invalid");
46         return ERR_APPEXECFWK_INSTALL_FILE_PATH_INVALID;
47     }
48     if (!CheckFileType(bundlePath, Constants::INSTALL_FILE_SUFFIX)) {
49         APP_LOGE("file is not hap");
50         return ERR_APPEXECFWK_INSTALL_INVALID_HAP_NAME;
51     }
52     if (!PathToRealPath(bundlePath, realPath)) {
53         APP_LOGE("file is not real path");
54         return ERR_APPEXECFWK_INSTALL_FILE_PATH_INVALID;
55     }
56     if (access(realPath.c_str(), F_OK) != 0) {
57         APP_LOGE("can not access the bundle file path: %{private}s", realPath.c_str());
58         return ERR_APPEXECFWK_INSTALL_INVALID_BUNDLE_FILE;
59     }
60     if (!CheckFileSize(realPath, Constants::MAX_HAP_SIZE)) {
61         APP_LOGE("file size is larger than max hap size Max size is: %{public}" PRId64, Constants::MAX_HAP_SIZE);
62         return ERR_APPEXECFWK_INSTALL_INVALID_HAP_SIZE;
63     }
64     return ERR_OK;
65 }
66 
CheckFilePath(const std::vector<std::string> & bundlePaths,std::vector<std::string> & realPaths)67 ErrCode BundleUtil::CheckFilePath(const std::vector<std::string> &bundlePaths, std::vector<std::string> &realPaths)
68 {
69     BYTRACE_NAME(BYTRACE_TAG_APP, __PRETTY_FUNCTION__);
70     // there are three cases for bundlePaths:
71     // 1. one bundle direction in the bundlePaths, some hap files under this bundle direction.
72     // 2. one hap direction in the bundlePaths.
73     // 3. some hap file directions in the bundlePaths.
74     APP_LOGD("check file path");
75     if (bundlePaths.empty()) {
76         APP_LOGE("bundle file paths invalid");
77         return ERR_APPEXECFWK_INSTALL_FILE_PATH_INVALID;
78     }
79     ErrCode ret = ERR_OK;
80 
81     if (bundlePaths.size() == 1) {
82         struct stat s;
83         std::string bundlePath = bundlePaths.front();
84         std::string realPath = "";
85         if (stat(bundlePath.c_str(), &s) == 0) {
86             // it is a direction
87             if ((s.st_mode & S_IFDIR) && !GetHapFilesFromBundlePath(bundlePath, realPaths)) {
88                 APP_LOGE("GetHapFilesFromBundlePath failed with bundlePath:%{private}s", bundlePaths.front().c_str());
89                 return ERR_APPEXECFWK_INSTALL_FILE_PATH_INVALID;
90             }
91             // it is a file
92             if ((s.st_mode & S_IFREG) && (ret = CheckFilePath(bundlePaths.front(), realPath)) == ERR_OK) {
93                 realPaths.emplace_back(realPath);
94             }
95             return ret;
96         } else {
97             APP_LOGE("bundlePath is not existed with :%{private}s", bundlePaths.front().c_str());
98             return ERR_APPEXECFWK_INSTALL_FILE_PATH_INVALID;
99         }
100     } else {
101         for (const std::string& bundlePath : bundlePaths) {
102             std::string realPath = "";
103             ret = CheckFilePath(bundlePath, realPath);
104             if (ret != ERR_OK) {
105                 return ret;
106             }
107             realPaths.emplace_back(realPath);
108         }
109     }
110     APP_LOGD("finish check file path");
111     return ret;
112 }
113 
CheckFileType(const std::string & fileName,const std::string & extensionName)114 bool BundleUtil::CheckFileType(const std::string &fileName, const std::string &extensionName)
115 {
116     APP_LOGD("path is %{public}s, support suffix is %{public}s", fileName.c_str(), extensionName.c_str());
117     if (!CheckFileName(fileName)) {
118         return false;
119     }
120 
121     auto position = fileName.rfind('.');
122     if (position == std::string::npos) {
123         APP_LOGE("filename no extension name");
124         return false;
125     }
126 
127     std::string suffixStr = fileName.substr(position);
128     return LowerStr(suffixStr) == extensionName;
129 }
130 
CheckFileName(const std::string & fileName)131 bool BundleUtil::CheckFileName(const std::string &fileName)
132 {
133     if (fileName.empty()) {
134         APP_LOGE("the file name is empty");
135         return false;
136     }
137     if (fileName.size() > Constants::PATH_MAX_SIZE) {
138         APP_LOGE("bundle file path length %{public}zu too long", fileName.size());
139         return false;
140     }
141     return true;
142 }
143 
CheckFileSize(const std::string & bundlePath,const int64_t fileSize)144 bool BundleUtil::CheckFileSize(const std::string &bundlePath, const int64_t fileSize)
145 {
146     struct stat fileInfo = { 0 };
147     if (stat(bundlePath.c_str(), &fileInfo) != 0) {
148         APP_LOGE("call stat error");
149         return false;
150     }
151     if (fileInfo.st_size > fileSize) {
152         return false;
153     }
154     return true;
155 }
156 
CheckSystemSize(const std::string & bundlePath,const std::string & diskPath)157 bool BundleUtil::CheckSystemSize(const std::string &bundlePath, const std::string &diskPath)
158 {
159     struct statfs diskInfo = { 0 };
160     if (statfs(diskPath.c_str(), &diskInfo) != 0) {
161         APP_LOGE("call statfs error");
162         return false;
163     }
164     int64_t freeSize = diskInfo.f_bfree * diskInfo.f_bsize;
165     APP_LOGD("left free size in the disk path is %{public}" PRId64, freeSize / Constants::ONE_GB);
166 
167     return CheckFileSize(bundlePath, freeSize);
168 }
169 
GetHapFilesFromBundlePath(const std::string & currentBundlePath,std::vector<std::string> & hapFileList)170 bool BundleUtil::GetHapFilesFromBundlePath(const std::string& currentBundlePath, std::vector<std::string>& hapFileList)
171 {
172     APP_LOGD("GetHapFilesFromBundlePath with path is %{public}s", currentBundlePath.c_str());
173     if (currentBundlePath.empty()) {
174         return false;
175     }
176     DIR* dir = opendir(currentBundlePath.c_str());
177     if (dir == nullptr) {
178         APP_LOGE("GetHapFilesFromBundlePath open bundle dir:%{private}s is failure", currentBundlePath.c_str());
179         return false;
180     }
181     std::string bundlePath = currentBundlePath;
182     if (bundlePath.back() != Constants::FILE_SEPARATOR_CHAR) {
183         bundlePath.append(Constants::PATH_SEPARATOR);
184     }
185     struct dirent *entry = nullptr;
186     while ((entry = readdir(dir)) != nullptr) {
187         if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
188             continue;
189         }
190         const std::string hapFilePath = bundlePath + entry->d_name;
191         std::string realPath = "";
192         if (CheckFilePath(hapFilePath, realPath) != ERR_OK) {
193             APP_LOGE("find invalid hap path %{public}s", hapFilePath.c_str());
194             closedir(dir);
195             return false;
196         }
197         hapFileList.emplace_back(realPath);
198         APP_LOGD("find hap path %{public}s", realPath.c_str());
199 
200         if (!hapFileList.empty() && (hapFileList.size() > Constants::MAX_HAP_NUMBER)) {
201             APP_LOGE("reach the max hap number 128, stop to add more.");
202             closedir(dir);
203             return false;
204         }
205     }
206     closedir(dir);
207     return true;
208 }
209 
GetCurrentTime()210 int64_t BundleUtil::GetCurrentTime()
211 {
212     int64_t time =
213         std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::now().time_since_epoch())
214         .count();
215     APP_LOGD("the current time is %{public}" PRId64, time);
216     return time;
217 }
218 
DeviceAndNameToKey(const std::string & deviceId,const std::string & bundleName,std::string & key)219 void BundleUtil::DeviceAndNameToKey(
220     const std::string &deviceId, const std::string &bundleName, std::string &key)
221 {
222     key.append(deviceId);
223     key.append(Constants::FILE_UNDERLINE);
224     key.append(bundleName);
225     APP_LOGD("bundleName = %{public}s", bundleName.c_str());
226 }
227 
KeyToDeviceAndName(const std::string & key,std::string & deviceId,std::string & bundleName)228 bool BundleUtil::KeyToDeviceAndName(
229     const std::string &key, std::string &deviceId, std::string &bundleName)
230 {
231     bool ret = false;
232     std::vector<std::string> splitStrs;
233     OHOS::SplitStr(key, Constants::FILE_UNDERLINE, splitStrs);
234     // the expect split size should be 2.
235     // key rule is <deviceId>_<bundleName>
236     if (splitStrs.size() == EXPECT_SPLIT_SIZE) {
237         deviceId = splitStrs[0];
238         bundleName = splitStrs[1];
239         ret = true;
240     }
241     APP_LOGD("bundleName = %{public}s", bundleName.c_str());
242     return ret;
243 }
244 
GetUserIdByCallingUid()245 int32_t BundleUtil::GetUserIdByCallingUid()
246 {
247     int32_t uid = IPCSkeleton::GetCallingUid();
248     APP_LOGI("get calling uid(%{public}d)", uid);
249     return GetUserIdByUid(uid);
250 }
251 
GetUserIdByUid(int32_t uid)252 int32_t BundleUtil::GetUserIdByUid(int32_t uid)
253 {
254     if (uid <= Constants::INVALID_UID) {
255         APP_LOGE("uid is illegal: %{public}d", uid);
256         return Constants::INVALID_USERID;
257     }
258 
259     return uid / Constants::BASE_USER_RANGE;
260 }
261 
MakeHmdfsConfig(const std::string & bundleName,int32_t bundleId)262 void BundleUtil::MakeHmdfsConfig(const std::string &bundleName, int32_t bundleId)
263 {
264     std::string bundleDir = Constants::HMDFS_CONFIG_PATH + Constants::PATH_SEPERATE + bundleName;
265     if (access(bundleDir.c_str(), F_OK) != 0) {
266         if (mkdir(bundleDir.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) != 0) {
267             APP_LOGE("make bundle dir error");
268             return;
269         }
270     }
271 
272     std::string realBundleDir;
273     if (!PathToRealPath(bundleDir, realBundleDir)) {
274         APP_LOGE("bundleIdFile is not real path");
275         return;
276     }
277 
278     realBundleDir += (Constants::PATH_SEPERATE + Constants::BUNDLE_ID_FILE);
279 
280     int32_t bundleIdFd = open(realBundleDir.c_str(), O_WRONLY | O_TRUNC);
281     if (bundleIdFd > 0) {
282         std::string bundleIdStr = std::to_string(bundleId);
283         if (write(bundleIdFd, bundleIdStr.c_str(), bundleIdStr.size()) < 0) {
284             APP_LOGE("write bundleId error");
285         }
286     }
287     close(bundleIdFd);
288 }
289 
RemoveHmdfsConfig(const std::string & bundleName)290 void BundleUtil::RemoveHmdfsConfig(const std::string &bundleName)
291 {
292     std::string bundleDir = Constants::HMDFS_CONFIG_PATH + Constants::PATH_SEPERATE + bundleName;
293     std::string realBundleDir;
294     if (!PathToRealPath(bundleDir, realBundleDir)) {
295         APP_LOGE("bundleDir is not real path");
296         return;
297     }
298     if (rmdir(realBundleDir.c_str()) != 0) {
299         APP_LOGE("remove hmdfs bundle dir error");
300     }
301 }
302 }  // namespace AppExecFwk
303 }  // namespace OHOS
304