1 /*
2 * Copyright (c) 2023 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 "user_unlocked_event_subscriber.h"
17
18 #include <filesystem>
19 #include <sys/stat.h>
20
21 #include "account_helper.h"
22 #include "app_log_tag_wrapper.h"
23 #include "bundle_mgr_service.h"
24 #if defined (BUNDLE_FRAMEWORK_SANDBOX_APP) && defined (DLP_PERMISSION_ENABLE)
25 #include "dlp_permission_kit.h"
26 #endif
27 #include "installd_client.h"
28
29 namespace OHOS {
30 namespace AppExecFwk {
31 namespace {
32 static constexpr int16_t MODE_BASE = 07777;
33 constexpr const char* BUNDLE_BACKUP_HOME_PATH_EL1_NEW = "/data/app/el1/%/base/";
34 constexpr const char* BUNDLE_BACKUP_HOME_PATH_EL2_NEW = "/data/app/el2/%/base/";
35 constexpr const char* BUNDLE_BACKUP_INNER_DIR = "/.backup";
36 constexpr const char* PERMISSION_PROTECT_SCREEN_LOCK_DATA = "ohos.permission.PROTECT_SCREEN_LOCK_DATA";
37 static std::mutex TASK_MUTEX;
38 static std::atomic<uint32_t> CURRENT_TASK_NUM = 0;
39
40 template<typename Func, typename...Args>
ReturnIfNewTask(Func func,uint32_t tempTask,Args &&...args)41 inline void ReturnIfNewTask(Func func, uint32_t tempTask, Args&&... args)
42 {
43 if (CURRENT_TASK_NUM != tempTask) {
44 APP_LOGI("need stop current task, new first");
45 return;
46 }
47 func(std::forward<Args>(args)...);
48 }
49 }
UserUnlockedEventSubscriber(const EventFwk::CommonEventSubscribeInfo & subscribeInfo)50 UserUnlockedEventSubscriber::UserUnlockedEventSubscriber(
51 const EventFwk::CommonEventSubscribeInfo &subscribeInfo) : EventFwk::CommonEventSubscriber(subscribeInfo)
52 {}
53
~UserUnlockedEventSubscriber()54 UserUnlockedEventSubscriber::~UserUnlockedEventSubscriber()
55 {}
56
OnReceiveEvent(const EventFwk::CommonEventData & data)57 void UserUnlockedEventSubscriber::OnReceiveEvent(const EventFwk::CommonEventData &data)
58 {
59 std::string action = data.GetWant().GetAction();
60 if (action == EventFwk::CommonEventSupport::COMMON_EVENT_USER_UNLOCKED) {
61 int32_t userId = data.GetCode();
62 APP_LOGI_NOFUNC("UserUnlockedEventSubscriber -u %{public}d unlocked", userId);
63 std::lock_guard<std::mutex> lock(mutex_);
64 if ((userId_ != userId)) {
65 userId_ = userId;
66 std::thread updateDataDirThread(UpdateAppDataMgr::UpdateAppDataDirSelinuxLabel, userId);
67 updateDataDirThread.detach();
68 std::thread(UpdateAppDataMgr::DeleteUninstallTmpDirs, userId).detach();
69 #ifdef BUNDLE_FRAMEWORK_APP_CONTROL
70 DelayedSingleton<AppControlManager>::GetInstance()->SetAppInstallControlStatus();
71 #endif
72 }
73 }
74 if (action == EventFwk::CommonEventSupport::COMMON_EVENT_USER_SWITCHED) {
75 int32_t userId = data.GetCode();
76 APP_LOGI_NOFUNC("UserUnlockedEventSubscriber -u %{public}d switched", userId);
77 std::lock_guard<std::mutex> lock(mutex_);
78 if (AccountHelper::IsOsAccountVerified(userId) && (userId_ != userId)) {
79 APP_LOGI_NOFUNC("UserUnlockedEventSubscriber -u %{public}d unlocked", userId);
80 userId_ = userId;
81 std::thread updateDataDirThread(UpdateAppDataMgr::UpdateAppDataDirSelinuxLabel, userId);
82 updateDataDirThread.detach();
83 std::thread(UpdateAppDataMgr::DeleteUninstallTmpDirs, userId).detach();
84 }
85 #if defined (BUNDLE_FRAMEWORK_SANDBOX_APP) && defined (DLP_PERMISSION_ENABLE)
86 APP_LOGI("RemoveUnreservedSandbox call ClearUnreservedSandbox");
87 Security::DlpPermission::DlpPermissionKit::ClearUnreservedSandbox();
88 #endif
89 #ifdef BUNDLE_FRAMEWORK_APP_CONTROL
90 DelayedSingleton<AppControlManager>::GetInstance()->SetAppInstallControlStatus();
91 #endif
92 }
93 }
94
CheckPathAttribute(const std::string & path,const BundleInfo & bundleInfo,bool & isExist)95 void UpdateAppDataMgr::CheckPathAttribute(const std::string &path, const BundleInfo &bundleInfo, bool &isExist)
96 {
97 if (!isExist) {
98 return;
99 }
100 FileStat fileStat;
101 if (InstalldClient::GetInstance()->GetFileStat(path, fileStat) != ERR_OK) {
102 APP_LOGE("GetFileStat path(%{public}s) failed", path.c_str());
103 return;
104 }
105 if (fileStat.uid != bundleInfo.uid) {
106 APP_LOGW("path: %{public}s uid is not same, fileStat.uid:%{public}d, bundleInfo.uid:%{public}d",
107 path.c_str(), static_cast<int32_t>(fileStat.uid), bundleInfo.uid);
108 isExist = false;
109 }
110 if (fileStat.gid != ServiceConstants::DATABASE_DIR_GID) {
111 APP_LOGW("path: %{public}s gid is not same, fileStat.gid:%{public}d, gid:%{public}d",
112 path.c_str(), static_cast<int32_t>(fileStat.gid), ServiceConstants::DATABASE_DIR_GID);
113 isExist = false;
114 }
115 uint32_t fileMode = static_cast<uint32_t>(fileStat.mode);
116 if ((fileMode & MODE_BASE) != (S_IRWXU | S_IRWXG | S_ISGID)) {
117 APP_LOGW("path: %{public}s mode is not same, fileStat.mode:%{public}d, mode:%{public}d",
118 path.c_str(), static_cast<int32_t>(fileStat.mode), static_cast<int32_t>((S_IRWXU | S_IRWXG | S_ISGID)));
119 }
120 }
121
CreateBundleDataDir(const BundleInfo & bundleInfo,int32_t userId,const std::string & elDir)122 bool UpdateAppDataMgr::CreateBundleDataDir(
123 const BundleInfo &bundleInfo, int32_t userId, const std::string &elDir)
124 {
125 std::string baseBundleDataDir = ServiceConstants::BUNDLE_APP_DATA_BASE_DIR + elDir +
126 ServiceConstants::PATH_SEPARATOR + std::to_string(userId) + ServiceConstants::DATABASE + bundleInfo.name;
127 bool isExist = false;
128 if (InstalldClient::GetInstance()->IsExistDir(baseBundleDataDir, isExist) != ERR_OK) {
129 APP_LOGE("path: %{public}s IsExistDir failed", baseBundleDataDir.c_str());
130 return false;
131 }
132 CheckPathAttribute(baseBundleDataDir, bundleInfo, isExist);
133 if (!isExist) {
134 APP_LOGI_NOFUNC("path: %{public}s need CreateBundleDataDir", baseBundleDataDir.c_str());
135 CreateDirParam createDirParam;
136 createDirParam.userId = userId;
137 createDirParam.bundleName = bundleInfo.name;
138 createDirParam.uid = bundleInfo.uid;
139 createDirParam.gid = bundleInfo.gid;
140 createDirParam.apl = bundleInfo.applicationInfo.appPrivilegeLevel;
141 createDirParam.isPreInstallApp = bundleInfo.isPreInstallApp;
142 createDirParam.debug = bundleInfo.applicationInfo.appProvisionType == Constants::APP_PROVISION_TYPE_DEBUG;
143 if (elDir != ServiceConstants::BUNDLE_EL[0]) {
144 createDirParam.createDirFlag = CreateDirFlag::CREATE_DIR_UNLOCKED;
145 }
146 if (elDir == ServiceConstants::DIR_EL5) {
147 return CreateEl5Dir(createDirParam);
148 }
149 ProcessExtensionDir(bundleInfo, createDirParam.extensionDirs);
150 if (InstalldClient::GetInstance()->CreateBundleDataDir(createDirParam) != ERR_OK) {
151 APP_LOGW("failed to CreateBundleDataDir");
152 }
153 }
154 if (elDir == ServiceConstants::BUNDLE_EL[1]) {
155 CreateDataGroupDir(bundleInfo, userId);
156 }
157 return true;
158 }
159
CreateEl5Dir(const CreateDirParam & createDirParam)160 bool UpdateAppDataMgr::CreateEl5Dir(const CreateDirParam &createDirParam)
161 {
162 auto dataMgr = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
163 if (dataMgr == nullptr) {
164 APP_LOGE("CreateDataGroupDir failed for DataMgr is nullptr");
165 return false;
166 }
167 dataMgr->CreateEl5Dir(std::vector<CreateDirParam> {createDirParam});
168 return true;
169 }
170
DeleteUninstallTmpDirs(const int32_t userId)171 void UpdateAppDataMgr::DeleteUninstallTmpDirs(const int32_t userId)
172 {
173 std::vector<std::string> dirs = GetBundleDataDirs(userId);
174 if (dirs.empty()) {
175 LOG_I(BMS_TAG_DEFAULT, "dirs empty");
176 return;
177 }
178 ErrCode ret = InstalldClient::GetInstance()->DeleteUninstallTmpDirs(dirs);
179 if (ret != ERR_OK) {
180 LOG_W(BMS_TAG_DEFAULT, "delete tmp dirs failed:%{public}d", ret);
181 }
182 }
183
GetBundleDataDirs(const int32_t userId)184 std::vector<std::string> UpdateAppDataMgr::GetBundleDataDirs(const int32_t userId)
185 {
186 std::vector<std::string> dirs;
187 std::vector<std::string> dataVector = { "base", "database" };
188 for (const std::string &el : ServiceConstants::BUNDLE_EL) {
189 std::filesystem::path userPath =
190 std::filesystem::path(ServiceConstants::BUNDLE_APP_DATA_BASE_DIR) / el / std::to_string(userId);
191 for (const std::string &data : dataVector) {
192 std::filesystem::path dataPath = userPath / data;
193 dirs.emplace_back(dataPath.string());
194 }
195 }
196 return dirs;
197 }
198
CreateDataGroupDir(const BundleInfo & bundleInfo,int32_t userId)199 void UpdateAppDataMgr::CreateDataGroupDir(const BundleInfo &bundleInfo, int32_t userId)
200 {
201 auto dataMgr = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
202 if (dataMgr == nullptr) {
203 APP_LOGE("CreateDataGroupDir failed for DataMgr is nullptr");
204 return;
205 }
206 std::vector<DataGroupInfo> dataGroupInfos;
207 if (!dataMgr->QueryDataGroupInfos(bundleInfo.name, userId, dataGroupInfos)) {
208 APP_LOGW("QueryDataGroupInfo for bundle %{public}s userId %{public}d failed", bundleInfo.name.c_str(), userId);
209 return;
210 }
211 if (dataGroupInfos.empty()) {
212 return;
213 }
214
215 std::string parentDir = std::string(ServiceConstants::REAL_DATA_PATH) + ServiceConstants::PATH_SEPARATOR
216 + std::to_string(userId);
217 if (!BundleUtil::IsExistDir(parentDir)) {
218 APP_LOGE("parent dir(%{public}s) missing: group", parentDir.c_str());
219 return;
220 }
221 for (const DataGroupInfo &dataGroupInfo : dataGroupInfos) {
222 std::string dir = parentDir + ServiceConstants::DATA_GROUP_PATH + dataGroupInfo.uuid;
223 if (BundleUtil::IsPathInformationConsistent(dir, dataGroupInfo.uid, dataGroupInfo.gid)) {
224 continue;
225 }
226 APP_LOGI("create group dir -n %{public}s uid %{public}d -u %{public}d", bundleInfo.name.c_str(),
227 dataGroupInfo.uid, userId);
228 auto result = InstalldClient::GetInstance()->Mkdir(dir,
229 ServiceConstants::DATA_GROUP_DIR_MODE, dataGroupInfo.uid, dataGroupInfo.gid);
230 if (result != ERR_OK) {
231 APP_LOGW("create data group dir %{private}s userId %{public}d failed", dataGroupInfo.uuid.c_str(), userId);
232 }
233 }
234 }
235
UpdateAppDataDirSelinuxLabel(int32_t userId)236 void UpdateAppDataMgr::UpdateAppDataDirSelinuxLabel(int32_t userId)
237 {
238 uint32_t tempTaskNum = CURRENT_TASK_NUM.fetch_add(1) + 1;
239 std::lock_guard<std::mutex> guard(TASK_MUTEX);
240 APP_LOGI("UpdateAppDataDirSelinuxLabel hold TASK_MUTEX");
241 if (tempTaskNum != CURRENT_TASK_NUM) {
242 APP_LOGI("need stop current task, new first, -u %{public}d", userId);
243 return;
244 }
245 APP_LOGI("UpdateAppDataDirSelinuxLabel userId:%{public}d start", userId);
246 auto dataMgr = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr();
247 if (dataMgr == nullptr) {
248 APP_LOGE("UpdateAppDataDirSelinuxLabel DataMgr is nullptr");
249 return;
250 }
251 std::vector<BundleInfo> bundleInfos;
252 if (!dataMgr->GetBundleInfos(BundleFlag::GET_BUNDLE_WITH_EXTENSION_INFO |
253 BundleFlag::GET_BUNDLE_WITH_REQUESTED_PERMISSION, bundleInfos, userId)) {
254 APP_LOGE("UpdateAppDataDirSelinuxLabel GetAllBundleInfos failed");
255 return;
256 }
257
258 ReturnIfNewTask(ProcessUpdateAppDataDir, tempTaskNum, userId, bundleInfos, ServiceConstants::BUNDLE_EL[1]);
259 #ifdef CHECK_ELDIR_ENABLED
260 ReturnIfNewTask(ProcessUpdateAppDataDir, tempTaskNum, userId, bundleInfos, ServiceConstants::DIR_EL3);
261 ReturnIfNewTask(ProcessUpdateAppDataDir, tempTaskNum, userId, bundleInfos, ServiceConstants::DIR_EL4);
262 #endif
263 ReturnIfNewTask(ProcessUpdateAppDataDir, tempTaskNum, userId, bundleInfos, ServiceConstants::DIR_EL5);
264 ReturnIfNewTask(ProcessUpdateAppLogDir, tempTaskNum, bundleInfos, userId);
265 ReturnIfNewTask(ProcessFileManagerDir, tempTaskNum, bundleInfos, userId);
266 ReturnIfNewTask(ProcessNewBackupDir, tempTaskNum, bundleInfos, userId);
267 APP_LOGI("UpdateAppDataDirSelinuxLabel userId:%{public}d end", userId);
268 }
269
ProcessUpdateAppDataDir(int32_t userId,const std::vector<BundleInfo> & bundleInfos,const std::string & elDir)270 void UpdateAppDataMgr::ProcessUpdateAppDataDir(
271 int32_t userId, const std::vector<BundleInfo> &bundleInfos, const std::string &elDir)
272 {
273 std::string baseBundleDataDir = ServiceConstants::BUNDLE_APP_DATA_BASE_DIR + elDir +
274 ServiceConstants::PATH_SEPARATOR + std::to_string(userId);
275 for (const auto &bundleInfo : bundleInfos) {
276 if (bundleInfo.appIndex > 0) {
277 APP_LOGI("bundleName:%{public}s appIndex:%{public}d clone app no need to change",
278 bundleInfo.name.c_str(), bundleInfo.appIndex);
279 continue;
280 }
281 if (elDir == ServiceConstants::DIR_EL5) {
282 std::vector<std::string> reqPermissions = bundleInfo.reqPermissions;
283 auto it = std::find_if(reqPermissions.begin(), reqPermissions.end(), [](const std::string &permission) {
284 return permission == PERMISSION_PROTECT_SCREEN_LOCK_DATA;
285 });
286 if (it == reqPermissions.end()) {
287 continue;
288 }
289 }
290 if ((userId != Constants::DEFAULT_USERID && bundleInfo.singleton) ||
291 !CreateBundleDataDir(bundleInfo, userId, elDir)) {
292 continue;
293 }
294 std::string baseDir = baseBundleDataDir + ServiceConstants::BASE + bundleInfo.name;
295 if (InstalldClient::GetInstance()->SetDirApl(baseDir, bundleInfo.name,
296 bundleInfo.applicationInfo.appPrivilegeLevel, bundleInfo.isPreInstallApp,
297 bundleInfo.applicationInfo.appProvisionType == Constants::APP_PROVISION_TYPE_DEBUG) != ERR_OK) {
298 APP_LOGW_NOFUNC("failed to SetDirApl baseDir dir");
299 continue;
300 }
301 std::string baseDataDir = baseBundleDataDir + ServiceConstants::DATABASE + bundleInfo.name;
302 if (InstalldClient::GetInstance()->SetDirApl(baseDataDir, bundleInfo.name,
303 bundleInfo.applicationInfo.appPrivilegeLevel, bundleInfo.isPreInstallApp,
304 bundleInfo.applicationInfo.appProvisionType == Constants::APP_PROVISION_TYPE_DEBUG) != ERR_OK) {
305 APP_LOGW_NOFUNC("failed to SetDirApl baseDataDir dir");
306 }
307 }
308 }
309
ProcessExtensionDir(const BundleInfo & bundleInfo,std::vector<std::string> & dirs)310 void UpdateAppDataMgr::ProcessExtensionDir(const BundleInfo &bundleInfo, std::vector<std::string> &dirs)
311 {
312 for (const ExtensionAbilityInfo &info : bundleInfo.extensionInfos) {
313 if (!info.needCreateSandbox) {
314 continue;
315 }
316 std::string extensionDir = ServiceConstants::EXTENSION_DIR + info.moduleName +
317 ServiceConstants::FILE_SEPARATOR_LINE + info.name +
318 ServiceConstants::FILE_SEPARATOR_PLUS + info.bundleName;
319 dirs.emplace_back(extensionDir);
320 }
321 }
322
ProcessUpdateAppLogDir(const std::vector<BundleInfo> & bundleInfos,int32_t userId)323 void UpdateAppDataMgr::ProcessUpdateAppLogDir(const std::vector<BundleInfo> &bundleInfos, int32_t userId)
324 {
325 for (const auto &bundleInfo : bundleInfos) {
326 if (userId != Constants::DEFAULT_USERID && bundleInfo.singleton) {
327 continue;
328 }
329 if (!CreateBundleLogDir(bundleInfo, userId)) {
330 APP_LOGD("log dir create failed or already exists");
331 }
332 }
333 }
334
ProcessNewBackupDir(const std::vector<BundleInfo> & bundleInfos,int32_t userId)335 void UpdateAppDataMgr::ProcessNewBackupDir(const std::vector<BundleInfo> &bundleInfos, int32_t userId)
336 {
337 APP_LOGI_NOFUNC("process new back up dir, start");
338 for (const auto &bundleInfo : bundleInfos) {
339 if (bundleInfo.appIndex > 0) {
340 APP_LOGI("bundleName:%{public}s appIndex %{public}d clone app no need to create",
341 bundleInfo.name.c_str(), bundleInfo.appIndex);
342 continue;
343 }
344 if (bundleInfo.singleton) {
345 CreateNewBackupDir(bundleInfo, Constants::DEFAULT_USERID);
346 continue;
347 }
348 if (userId != Constants::DEFAULT_USERID) {
349 CreateNewBackupDir(bundleInfo, userId);
350 }
351 }
352 APP_LOGI_NOFUNC("process new back up dir, end");
353 }
354
CreateNewBackupDir(const BundleInfo & bundleInfo,int32_t userId)355 void UpdateAppDataMgr::CreateNewBackupDir(const BundleInfo &bundleInfo, int32_t userId)
356 {
357 std::string parentEl1Dir = BUNDLE_BACKUP_HOME_PATH_EL1_NEW;
358 parentEl1Dir = parentEl1Dir.replace(parentEl1Dir.find("%"), 1, std::to_string(userId));
359 std::string parentEl2Dir = BUNDLE_BACKUP_HOME_PATH_EL2_NEW;
360 parentEl2Dir = parentEl2Dir.replace(parentEl2Dir.find("%"), 1, std::to_string(userId));
361 if (!BundleUtil::IsExistDir(parentEl1Dir) || !BundleUtil::IsExistDir(parentEl2Dir)) {
362 APP_LOGE("parent dir(%{public}s or %{public}s) missing: backup", parentEl1Dir.c_str(), parentEl2Dir.c_str());
363 return;
364 }
365 std::string backupDirEl1 = parentEl1Dir + bundleInfo.name + BUNDLE_BACKUP_INNER_DIR;
366 std::string backupDirEl2 = parentEl2Dir + bundleInfo.name + BUNDLE_BACKUP_INNER_DIR;
367 std::vector<std::string> backupDirList;
368 backupDirList.emplace_back(backupDirEl1);
369 backupDirList.emplace_back(backupDirEl2);
370
371 for (const std::string &dir : backupDirList) {
372 bool isDirExisted = false;
373 auto result = InstalldClient::GetInstance()->IsExistDir(dir, isDirExisted);
374 if (result != ERR_OK || isDirExisted) {
375 continue;
376 }
377 APP_LOGI("bundle %{public}s not exist backup dir", bundleInfo.name.c_str());
378 result = InstalldClient::GetInstance()->Mkdir(dir, S_IRWXU | S_IRWXG | S_ISGID,
379 bundleInfo.uid, ServiceConstants::BACKU_HOME_GID);
380 if (result != ERR_OK) {
381 APP_LOGW("bundle %{public}s create backup dir for user %{public}d failed",
382 bundleInfo.name.c_str(), userId);
383 }
384 }
385 }
386
CreateBundleLogDir(const BundleInfo & bundleInfo,int32_t userId)387 bool UpdateAppDataMgr::CreateBundleLogDir(const BundleInfo &bundleInfo, int32_t userId)
388 {
389 std::string parentDir = ServiceConstants::BUNDLE_APP_DATA_BASE_DIR + ServiceConstants::BUNDLE_EL[1] +
390 ServiceConstants::PATH_SEPARATOR + std::to_string(userId) + ServiceConstants::LOG;
391 if (!BundleUtil::IsExistDir(parentDir)) {
392 APP_LOGE("parent dir(%{public}s) missing: log", parentDir.c_str());
393 return false;
394 }
395 std::string bundleLogDir = parentDir + bundleInfo.name;
396 bool isExist = false;
397 if (InstalldClient::GetInstance()->IsExistDir(bundleLogDir, isExist) != ERR_OK) {
398 APP_LOGE("path: %{public}s IsExistDir failed", bundleLogDir.c_str());
399 return false;
400 }
401 if (isExist) {
402 APP_LOGD("path: %{public}s is exist", bundleLogDir.c_str());
403 return false;
404 }
405 if (InstalldClient::GetInstance()->Mkdir(
406 bundleLogDir, S_IRWXU | S_IRWXG, bundleInfo.uid, ServiceConstants::LOG_DIR_GID) != ERR_OK) {
407 APP_LOGE("CreateBundleLogDir failed");
408 return false;
409 }
410 return true;
411 }
412
ProcessFileManagerDir(const std::vector<BundleInfo> & bundleInfos,int32_t userId)413 void UpdateAppDataMgr::ProcessFileManagerDir(const std::vector<BundleInfo> &bundleInfos, int32_t userId)
414 {
415 for (const auto &bundleInfo : bundleInfos) {
416 if (userId != Constants::DEFAULT_USERID && bundleInfo.singleton) {
417 continue;
418 }
419 CreateBundleCloudDir(bundleInfo, userId);
420 }
421 }
422
CreateBundleCloudDir(const BundleInfo & bundleInfo,int32_t userId)423 bool UpdateAppDataMgr::CreateBundleCloudDir(const BundleInfo &bundleInfo, int32_t userId)
424 {
425 std::string parentDir = "/data/service/el2/%/hmdfs/cloud/data/";
426 parentDir = parentDir.replace(parentDir.find("%"), 1, std::to_string(userId));
427 if (!BundleUtil::IsExistDir(parentDir)) {
428 APP_LOGE("parent dir(%{public}s) missing: cloud", parentDir.c_str());
429 return false;
430 }
431 std::string bundleCloudDir = parentDir + bundleInfo.name;
432 bool isExist = false;
433 if (InstalldClient::GetInstance()->IsExistDir(bundleCloudDir, isExist) != ERR_OK) {
434 APP_LOGE("path: %{private}s IsExistDir failed", bundleCloudDir.c_str());
435 return false;
436 }
437 if (isExist) {
438 APP_LOGD("path: %{private}s is exist", bundleCloudDir.c_str());
439 return false;
440 }
441 if (!InstalldClient::GetInstance()->Mkdir(bundleCloudDir, S_IRWXU | S_IRWXG | S_ISGID,
442 bundleInfo.uid, ServiceConstants::DFS_GID)) {
443 static std::once_flag cloudOnce;
444 std::call_once(cloudOnce, [bundleInfo]() {
445 APP_LOGW("CreateCloudDir failed for bundle %{private}s errno:%{public}d",
446 bundleInfo.name.c_str(), errno);
447 });
448 }
449 return true;
450 }
451 } // namespace AppExecFwk
452 } // namespace OHOS