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