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