• 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 "installd/installd_host_impl.h"
17 
18 #include <cstdio>
19 #include <fstream>
20 #include <map>
21 #include <memory>
22 #include <sstream>
23 #include <string>
24 #include <sys/stat.h>
25 #include <sys/types.h>
26 #include <unistd.h>
27 
28 #include "app_log_wrapper.h"
29 #include "bundle_constants.h"
30 #include "common_profile.h"
31 #include "directory_ex.h"
32 #ifdef WITH_SELINUX
33 #include "hap_restorecon.h"
34 #endif // WITH_SELINUX
35 #include "installd/installd_operator.h"
36 #include "parameters.h"
37 
38 namespace OHOS {
39 namespace AppExecFwk {
InstalldHostImpl()40 InstalldHostImpl::InstalldHostImpl()
41 {
42     APP_LOGI("installd service instance is created");
43 }
44 
~InstalldHostImpl()45 InstalldHostImpl::~InstalldHostImpl()
46 {
47     APP_LOGI("installd service instance is destroyed");
48 }
49 
CreateBundleDir(const std::string & bundleDir)50 ErrCode InstalldHostImpl::CreateBundleDir(const std::string &bundleDir)
51 {
52     if (bundleDir.empty()) {
53         APP_LOGE("Calling the function CreateBundleDir with invalid param");
54         return ERR_APPEXECFWK_INSTALLD_PARAM_ERROR;
55     }
56     if (InstalldOperator::IsExistDir(bundleDir)) {
57         APP_LOGW("bundleDir %{public}s is exist", bundleDir.c_str());
58         OHOS::ForceRemoveDirectory(bundleDir);
59     }
60     if (!InstalldOperator::MkRecursiveDir(bundleDir, true)) {
61         APP_LOGE("create bundle dir %{public}s failed", bundleDir.c_str());
62         return ERR_APPEXECFWK_INSTALLD_CREATE_DIR_FAILED;
63     }
64     return ERR_OK;
65 }
66 
ExtractModuleFiles(const std::string & srcModulePath,const std::string & targetPath,const std::string & targetSoPath,const std::string & cpuAbi)67 ErrCode InstalldHostImpl::ExtractModuleFiles(const std::string &srcModulePath, const std::string &targetPath,
68     const std::string &targetSoPath, const std::string &cpuAbi)
69 {
70     APP_LOGD("ExtractModuleFiles extract original src %{public}s and target src %{public}s",
71         srcModulePath.c_str(), targetPath.c_str());
72     if (srcModulePath.empty() || targetPath.empty()) {
73         APP_LOGE("Calling the function ExtractModuleFiles with invalid param");
74         return ERR_APPEXECFWK_INSTALLD_PARAM_ERROR;
75     }
76     if (!InstalldOperator::MkRecursiveDir(targetPath, true)) {
77         APP_LOGE("create target dir %{public}s failed", targetPath.c_str());
78         return ERR_APPEXECFWK_INSTALLD_CREATE_DIR_FAILED;
79     }
80     if (!InstalldOperator::ExtractFiles(srcModulePath, targetPath, targetSoPath, cpuAbi)) {
81         APP_LOGE("extract %{public}s to %{public}s failed", srcModulePath.c_str(), targetPath.c_str());
82         InstalldOperator::DeleteDir(targetPath);
83         return ERR_APPEXECFWK_INSTALL_DISK_MEM_INSUFFICIENT;
84     }
85     return ERR_OK;
86 }
87 
RenameModuleDir(const std::string & oldPath,const std::string & newPath)88 ErrCode InstalldHostImpl::RenameModuleDir(const std::string &oldPath, const std::string &newPath)
89 {
90     APP_LOGD("rename %{public}s to %{public}s", oldPath.c_str(), newPath.c_str());
91     if (oldPath.empty() || newPath.empty()) {
92         APP_LOGE("Calling the function RenameModuleDir with invalid param");
93         return ERR_APPEXECFWK_INSTALLD_PARAM_ERROR;
94     }
95     if (!InstalldOperator::RenameDir(oldPath, newPath)) {
96         APP_LOGE("rename module dir %{public}s to %{public}s failed", oldPath.c_str(), newPath.c_str());
97         return ERR_APPEXECFWK_INSTALLD_RNAME_DIR_FAILED;
98     }
99     return ERR_OK;
100 }
101 
CreateBundleDataDir(const std::string & bundleDataDir,const int userid,const int uid,const int gid,const std::string & apl,bool onlyOneUser)102 ErrCode InstalldHostImpl::CreateBundleDataDir(const std::string &bundleDataDir,
103     const int userid, const int uid, const int gid, const std::string &apl, bool onlyOneUser)
104 {
105     if (bundleDataDir.empty() || uid < 0 || gid < 0) {
106         APP_LOGE("Calling the function CreateBundleDataDir with invalid param");
107         return ERR_APPEXECFWK_INSTALLD_PARAM_ERROR;
108     }
109     std::string bundleName = strrchr(bundleDataDir.c_str(), Constants::FILE_SEPARATOR_CHAR);
110     if (onlyOneUser) {
111         std::string createDir;
112         if (bundleDataDir.back() != Constants::PATH_SEPARATOR[0]) {
113             createDir = bundleDataDir + Constants::PATH_SEPARATOR;
114         } else {
115             createDir = bundleDataDir;
116         }
117         if (!InstalldOperator::MkOwnerDir(createDir + Constants::DATA_DIR, true, uid, gid)) {
118             APP_LOGE("CreateBundleDataDir MkOwnerDir DATA_DIR failed");
119             return ERR_APPEXECFWK_INSTALLD_CREATE_DIR_FAILED;
120         }
121 
122         if (!InstalldOperator::MkOwnerDir(createDir + Constants::DATA_BASE_DIR,
123                                           S_IRWXU | S_IRWXG | S_ISGID,
124                                           uid,
125                                           Constants::DATABASE_DIR_GID)) {
126             APP_LOGE("CreateBundleDataDir MkOwnerDir DATA_BASE_DIR failed");
127             return ERR_APPEXECFWK_INSTALLD_CREATE_DIR_FAILED;
128         }
129 
130         if (!InstalldOperator::MkOwnerDir(createDir + Constants::CACHE_DIR, true, uid, gid)) {
131             APP_LOGE("CreateBundleDataDir MkOwnerDir CACHE_DIR failed");
132             return ERR_APPEXECFWK_INSTALLD_CREATE_DIR_FAILED;
133         }
134 
135         if (!InstalldOperator::MkOwnerDir(createDir + Constants::SHARED_PREFERENCE_DIR, true, uid, gid)) {
136             APP_LOGE("CreateBundleDataDir MkOwnerDir SHARED_PREFERENCE_DIR failed");
137             return ERR_APPEXECFWK_INSTALLD_CREATE_DIR_FAILED;
138         }
139     }
140 
141     if (CreateNewBundleDataDir(bundleName, userid, uid, gid, apl) != ERR_OK) {
142         APP_LOGE("CreateNewBundleDataDir MkOwnerDir failed");
143     }
144     return ERR_OK;
145 }
146 
CreateNewBundleDataDir(const std::string & bundleName,const int userid,const int uid,const int gid,const std::string & apl)147 ErrCode InstalldHostImpl::CreateNewBundleDataDir(
148     const std::string &bundleName, const int userid, const int uid, const int gid, const std::string &apl)
149 {
150     if (bundleName.empty() || userid < 0 || uid < 0 || gid < 0) {
151         APP_LOGE("Calling the function CreateBundleDataDir with invalid param");
152         return ERR_APPEXECFWK_INSTALLD_PARAM_ERROR;
153     }
154     for (const auto &el : Constants::BUNDLE_EL) {
155         std::string bundleDataDir = GetBundleDataDir(el, userid) + Constants::BASE + bundleName;
156         if (!InstalldOperator::MkOwnerDir(bundleDataDir, S_IRWXU, uid, gid)) {
157             APP_LOGE("CreateBundledatadir MkOwnerDir failed");
158             return ERR_APPEXECFWK_INSTALLD_CREATE_DIR_FAILED;
159         }
160         if (el == Constants::BUNDLE_EL[1]) {
161             for (const auto &dir : Constants::BUNDLE_DATA_DIR) {
162                 if (!InstalldOperator::MkOwnerDir(bundleDataDir + dir, S_IRWXU, uid, gid)) {
163                     APP_LOGE("CreateBundledatadir MkOwnerDir el2 failed");
164                     return ERR_APPEXECFWK_INSTALLD_CREATE_DIR_FAILED;
165                 }
166             }
167         }
168         ErrCode ret = SetDirApl(bundleDataDir, bundleName, apl);
169         if (ret != ERR_OK) {
170             APP_LOGE("CreateBundleDataDir SetDirApl failed");
171             return ret;
172         }
173         std::string databaseDir = GetBundleDataDir(el, userid) + Constants::DATABASE + bundleName;
174         if (!InstalldOperator::MkOwnerDir(
175             databaseDir, S_IRWXU | S_IRWXG | S_ISGID, uid, Constants::DATABASE_DIR_GID)) {
176             APP_LOGE("CreateBundle databaseDir MkOwnerDir failed");
177             return ERR_APPEXECFWK_INSTALLD_CREATE_DIR_FAILED;
178         }
179         ret = SetDirApl(databaseDir, bundleName, apl);
180         if (ret != ERR_OK) {
181             APP_LOGE("CreateBundleDataDir SetDirApl failed");
182             return ret;
183         }
184     }
185     if (system::GetBoolParameter(Constants::DISTRIBUTED_FILE_PROPERTY, false)) {
186         std::string distributedfile = Constants::DISTRIBUTED_FILE;
187         distributedfile = distributedfile.replace(distributedfile.find("%"), 1, std::to_string(userid));
188         if (!InstalldOperator::MkOwnerDir(distributedfile + bundleName, S_IRWXU | S_IRWXG | S_ISGID, uid, gid)) {
189             APP_LOGE("Failed to mk dir for distributedfile");
190             return ERR_APPEXECFWK_INSTALLD_CREATE_DIR_FAILED;
191         }
192 
193         distributedfile = Constants::DISTRIBUTED_FILE_NON_ACCOUNT;
194         distributedfile = distributedfile.replace(distributedfile.find("%"), 1, std::to_string(userid));
195         if (!InstalldOperator::MkOwnerDir(distributedfile + bundleName,
196             S_IRWXU | S_IRWXG | S_ISGID, uid, Constants::DFS_GID)) {
197             APP_LOGE("Failed to mk dir for non account distributedfile");
198             return ERR_APPEXECFWK_INSTALLD_CREATE_DIR_FAILED;
199         }
200     }
201     return ERR_OK;
202 }
203 
RemoveBundleDataDir(const std::string & bundleName,const int userid)204 ErrCode InstalldHostImpl::RemoveBundleDataDir(const std::string &bundleName, const int userid)
205 {
206     APP_LOGD("InstalldHostImpl::RemoveBundleDataDir bundleName:%{public}s", bundleName.c_str());
207     if (bundleName.empty() || userid < 0) {
208         APP_LOGE("Calling the function CreateBundleDataDir with invalid param");
209         return ERR_APPEXECFWK_INSTALLD_PARAM_ERROR;
210     }
211     for (const auto &el : Constants::BUNDLE_EL) {
212         std::string bundleDataDir = GetBundleDataDir(el, userid) + Constants::BASE + bundleName;
213         if (!InstalldOperator::DeleteDir(bundleDataDir)) {
214             APP_LOGE("remove dir %{public}s failed", bundleDataDir.c_str());
215             return ERR_APPEXECFWK_INSTALLD_REMOVE_DIR_FAILED;
216         }
217         std::string databaseDir = GetBundleDataDir(el, userid) + Constants::DATABASE + bundleName;
218         if (!InstalldOperator::DeleteDir(databaseDir)) {
219             APP_LOGE("remove dir %{public}s failed", databaseDir.c_str());
220             return ERR_APPEXECFWK_INSTALLD_REMOVE_DIR_FAILED;
221         }
222     }
223     return ERR_OK;
224 }
225 
CreateModuleDataDir(const std::string & ModuleDir,const std::vector<std::string> & abilityDirs,const int uid,const int gid)226 ErrCode InstalldHostImpl::CreateModuleDataDir(
227     const std::string &ModuleDir, const std::vector<std::string> &abilityDirs, const int uid, const int gid)
228 {
229     if (ModuleDir.empty() || uid < 0 || gid < 0) {
230         APP_LOGE("Calling the function CreateModuleDataDir with invalid param");
231         return ERR_APPEXECFWK_INSTALLD_PARAM_ERROR;
232     }
233     std::string createDir;
234     if (ModuleDir.back() != Constants::PATH_SEPARATOR[0]) {
235         createDir = ModuleDir + Constants::PATH_SEPARATOR;
236     } else {
237         createDir = ModuleDir;
238     }
239 
240     if (!InstalldOperator::MkOwnerDir(createDir + Constants::SHARED_DIR, true, uid, gid)) {
241         APP_LOGE("CreateModuleDataDir MkOwnerDir %{public}s failed", Constants::SHARED_DIR.c_str());
242         return ERR_APPEXECFWK_INSTALLD_CREATE_DIR_FAILED;
243     }
244 
245     for (auto &abilityDir : abilityDirs) {
246         std::string dataDir = createDir + abilityDir + Constants::PATH_SEPARATOR + Constants::DATA_DIR;
247         if (!InstalldOperator::MkOwnerDir(dataDir, true, uid, gid)) {
248             APP_LOGE("CreateModuleDataDir MkOwnerDir %{public}s failed", dataDir.c_str());
249             return ERR_APPEXECFWK_INSTALLD_CREATE_DIR_FAILED;
250         }
251         std::string cacheDir = createDir + abilityDir + Constants::PATH_SEPARATOR + Constants::CACHE_DIR;
252         if (!InstalldOperator::MkOwnerDir(cacheDir, true, uid, gid)) {
253             APP_LOGE("CreateModuleDataDir MkOwnerDir %{public}s failed", cacheDir.c_str());
254             return ERR_APPEXECFWK_INSTALLD_CREATE_DIR_FAILED;
255         }
256         std::string dataBaseDir = createDir + abilityDir + Constants::PATH_SEPARATOR + Constants::DATA_BASE_DIR;
257         if (!InstalldOperator::MkOwnerDir(dataBaseDir, true, uid, gid)) {
258             APP_LOGE("CreateModuleDataDir MkOwnerDir %{public}s failed", dataBaseDir.c_str());
259             return ERR_APPEXECFWK_INSTALLD_CREATE_DIR_FAILED;
260         }
261         std::string sharedDir = createDir + abilityDir + Constants::PATH_SEPARATOR + Constants::SHARED_PREFERENCE_DIR;
262         if (!InstalldOperator::MkOwnerDir(sharedDir, true, uid, gid)) {
263             APP_LOGE("CreateModuleDataDir MkOwnerDir %{public}s failed", sharedDir.c_str());
264             return ERR_APPEXECFWK_INSTALLD_CREATE_DIR_FAILED;
265         }
266     }
267     return ERR_OK;
268 }
269 
RemoveModuleDataDir(const std::string & ModuleDir,const int userid)270 ErrCode InstalldHostImpl::RemoveModuleDataDir(const std::string &ModuleDir, const int userid)
271 {
272     APP_LOGD("InstalldHostImpl::RemoveModuleDataDir ModuleDir:%{public}s", ModuleDir.c_str());
273     if (ModuleDir.empty() || userid < 0) {
274         APP_LOGE("Calling the function CreateModuleDataDir with invalid param");
275         return ERR_APPEXECFWK_INSTALLD_PARAM_ERROR;
276     }
277 
278     for (const auto &el : Constants::BUNDLE_EL) {
279         std::string moduleDataDir = GetBundleDataDir(el, userid) + Constants::BASE + ModuleDir;
280         if (!InstalldOperator::DeleteDir(moduleDataDir)) {
281             APP_LOGE("remove dir %{public}s failed", moduleDataDir.c_str());
282         }
283     }
284     return ERR_OK;
285 }
286 
RemoveDir(const std::string & dir)287 ErrCode InstalldHostImpl::RemoveDir(const std::string &dir)
288 {
289     if (dir.empty()) {
290         APP_LOGE("Calling the function RemoveDir with invalid param");
291         return ERR_APPEXECFWK_INSTALLD_PARAM_ERROR;
292     }
293     if (!InstalldOperator::DeleteDir(dir)) {
294         APP_LOGE("remove dir %{public}s failed", dir.c_str());
295         return ERR_APPEXECFWK_INSTALLD_REMOVE_DIR_FAILED;
296     }
297     return ERR_OK;
298 }
299 
CleanBundleDataDir(const std::string & dataDir)300 ErrCode InstalldHostImpl::CleanBundleDataDir(const std::string &dataDir)
301 {
302     APP_LOGD("InstalldHostImpl::CleanBundleDataDir start");
303     if (dataDir.empty()) {
304         APP_LOGE("Calling the function CleanBundleDataDir with invalid param");
305         return ERR_APPEXECFWK_INSTALLD_PARAM_ERROR;
306     }
307 
308     if (!InstalldOperator::DeleteFiles(dataDir)) {
309         APP_LOGE("CleanBundleDataDir delete files failed");
310         return ERR_APPEXECFWK_INSTALLD_CLEAN_DIR_FAILED;
311     }
312     return ERR_OK;
313 }
314 
GetBundleDataDir(const std::string & el,const int userid) const315 std::string InstalldHostImpl::GetBundleDataDir(const std::string &el, const int userid) const
316 {
317     std::string dataDir = Constants::BUNDLE_APP_DATA_BASE_DIR +
318                           el +
319                           Constants::FILE_SEPARATOR_CHAR +
320                           std::to_string(userid);
321     return dataDir;
322 }
323 
GetBundleStats(const std::string & bundleName,const int32_t userId,std::vector<int64_t> & bundleStats)324 ErrCode InstalldHostImpl::GetBundleStats(
325     const std::string &bundleName, const int32_t userId, std::vector<int64_t> &bundleStats)
326 {
327     if (bundleName.empty()) {
328         return ERR_APPEXECFWK_INSTALLD_PARAM_ERROR;
329     }
330     std::string path = Constants::BUNDLE_CODE_DIR + Constants::FILE_SEPARATOR_CHAR + bundleName;
331     int64_t fileSize = InstalldOperator::GetDiskUsage(path);
332     std::vector<std::string> bundlePath;
333     std::vector<std::string> cachePath;
334     int64_t allBundleLocalSize = 0;
335     for (const auto &el : Constants::BUNDLE_EL) {
336         std::string filePath = Constants::BUNDLE_APP_DATA_BASE_DIR + el + Constants::FILE_SEPARATOR_CHAR +
337             std::to_string(userId) + Constants::BASE + bundleName;
338         allBundleLocalSize += InstalldOperator::GetDiskUsage(filePath);
339         if (el == Constants::BUNDLE_EL[1]) {
340             for (const auto &dataDir : Constants::BUNDLE_DATA_DIR) {
341                 bundlePath.push_back(filePath + dataDir);
342             }
343         } else {
344             bundlePath.push_back(filePath);
345         }
346         InstalldOperator::TraverseCacheDirectory(filePath, cachePath);
347     }
348     int64_t bundleLocalSize = InstalldOperator::GetDiskUsageFromPath(bundlePath);
349     int64_t systemFolderSize = allBundleLocalSize - bundleLocalSize;
350     // index 0 : bundle data size
351     bundleStats.push_back(fileSize + systemFolderSize);
352     int64_t cacheSize = InstalldOperator::GetDiskUsageFromPath(cachePath);
353     bundleLocalSize -= cacheSize;
354     // index 1 : local bundle data size
355     bundleStats.push_back(bundleLocalSize);
356 
357     // index 2 : distributed data size
358     std::string distributedfilePath = Constants::DISTRIBUTED_FILE;
359     distributedfilePath = distributedfilePath.replace(distributedfilePath.find("%"), 1, std::to_string(userId)) +
360         bundleName;
361     int64_t distributedFileSize = InstalldOperator::GetDiskUsage(distributedfilePath);
362     bundleStats.push_back(distributedFileSize);
363 
364     // index 3 : database size
365     std::vector<std::string> dataBasePath;
366     for (auto &el : Constants::BUNDLE_EL) {
367         std::string filePath = Constants::BUNDLE_APP_DATA_BASE_DIR + el + Constants::FILE_SEPARATOR_CHAR +
368             std::to_string(userId) + Constants::DATABASE + bundleName;
369         dataBasePath.push_back(filePath);
370     }
371     int64_t databaseFileSize = InstalldOperator::GetDiskUsageFromPath(dataBasePath);
372     bundleStats.push_back(databaseFileSize);
373 
374     // index 4 : cache size
375     bundleStats.push_back(cacheSize);
376     return ERR_OK;
377 }
378 
SetDirApl(const std::string & dir,const std::string & bundleName,const std::string & apl)379 ErrCode InstalldHostImpl::SetDirApl(const std::string &dir, const std::string &bundleName, const std::string &apl)
380 {
381 #ifdef WITH_SELINUX
382     if (dir.empty() || bundleName.empty()) {
383         APP_LOGE("Calling the function SetDirApl with invalid param");
384         return ERR_APPEXECFWK_INSTALLD_PARAM_ERROR;
385     }
386     std::string aplLevel = Profile::AVAILABLELEVEL_NORMAL;
387     if (!apl.empty()) {
388         aplLevel = apl;
389     }
390     HapContext hapContext;
391     int ret = hapContext.HapFileRestorecon(dir, aplLevel, bundleName, SELINUX_HAP_RESTORECON_RECURSE);
392     if (ret != 0) {
393         APP_LOGE("HapFileRestorecon path: %{public}s failed, ret:%{public}d", dir.c_str(), ret);
394     }
395     return ret;
396 #else
397     return ERR_OK;
398 #endif // WITH_SELINUX
399 }
400 
GetBundleCachePath(const std::string & dir,std::vector<std::string> & cachePath)401 ErrCode InstalldHostImpl::GetBundleCachePath(const std::string &dir, std::vector<std::string> &cachePath)
402 {
403     APP_LOGD("InstalldHostImpl::GetBundleCachePath start");
404     if (dir.empty()) {
405         APP_LOGE("Calling the function GetBundleCachePathl with invalid param");
406         return ERR_APPEXECFWK_INSTALLD_PARAM_ERROR;
407     }
408     InstalldOperator::TraverseCacheDirectory(dir, cachePath);
409     return ERR_OK;
410 }
411 }  // namespace AppExecFwk
412 }  // namespace OHOS
413