Remove boost dependency
[platform/core/appfw/app-installers.git] / src / common / shared_dirs.cc
1 // Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
2 // Use of this source code is governed by an apache-2.0 license that can be
3 // found in the LICENSE file.
4
5 #include "common/shared_dirs.h"
6
7 #include <manifest_parser/utils/logging.h>
8 #include <manifest_parser/utils/version_number.h>
9
10 #include <glib.h>
11 #include <gio/gio.h>
12 #include <vcore/Certificate.h>
13 #include <pkgmgr-info.h>
14 #include <sys/types.h>
15 #include <unistd.h>
16 #include <fcntl.h>
17 #include <tzplatform_config.h>
18 #include <sys/xattr.h>
19
20 #include <algorithm>
21 #include <cassert>
22 #include <cstring>
23 #include <cstdio>
24 #include <exception>
25 #include <filesystem>
26 #include <iterator>
27 #include <optional>
28 #include <regex>
29 #include <string>
30 #include <system_error>
31 #include <utility>
32 #include <vector>
33 #include <tuple>
34
35 #include "common/utils/paths.h"
36 #include "common/security_registration.h"
37 #include "common/utils/pkgmgr_query.h"
38 #include "common/utils/base64.h"
39 #include "common/utils/file_util.h"
40 #include "common/utils/user_util.h"
41 #include "common/utils/glist_range.h"
42
43 namespace ci = common_installer;
44 namespace fs = std::filesystem;
45
46 namespace {
47
48 const uid_t kGlobalUserUid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
49 const utils::VersionNumber ver30("3.0");
50 const char kDisableLegacySharedDataDirSupport[] =
51     "/usr/share/app-installers/disable_legacy_shareddata_support";
52
53 const std::vector<const char*> kEntries = {
54   {"shared"},
55   {"cache"},
56   {"data"},
57 };
58 const std::vector<std::string> kReadOnlyEntries = {
59   {"bin"},
60   {"lib"},
61   {"res"},
62   {"shared/res"},
63 };
64 const std::vector<std::string> kSharedDataEntries = {
65   {".shared"},
66   {".shared_tmp"},
67 };
68
69 const char kSharedResDir[] = "shared/res";
70 const char kSharedCacheDir[] = "shared/cache";
71 const char kSharedDataDir[] = "shared/data";
72 const char kShared[] = "shared";
73 const char kData[] = "data";
74 const char kCache[] = "cache";
75 const char kSharedDir[] = ".shared";
76 const char kSharedTmpDir[] = ".shared_tmp";
77 const char kSharedTrustedDir[] = "shared/trusted";
78 const char kSkelAppDir[] = "skel/apps_rw";
79 const char kExternalStoragePrivilege[] =
80     "http://tizen.org/privilege/externalstorage.appdata";
81 const char kSystemShareGroupName[] = "system_share";
82 const char kSubssesionDir[] = "subsession";
83
84 // the input path should be root directory of package.
85 // for example: "../apps_rw/pkgid" or "../.shared/pkgid"
86 bool SetPackageDirectoryOwnerAndPermissions(const fs::path& path, uid_t uid) {
87   std::optional<gid_t> gid = ci::GetGidByUid(uid);
88   if (!gid)
89     return false;
90
91   using fs::perms;
92   perms perms755 = perms::all ^ perms::group_write ^ perms::others_write;
93   perms perms644 = perms::owner_read | perms::owner_write |
94       perms::group_read | perms::others_read;
95   perms perms_setgid = perms755 | perms::set_gid;
96
97   std::optional<gid_t> system_share =
98     ci::GetGidByGroupName(kSystemShareGroupName);
99   // root path
100   if (!ci::SetDirOwnershipAndPermissions(path, perms755, uid, *gid))
101     return false;
102
103   for (fs::recursive_directory_iterator iter(path);
104       iter != fs::recursive_directory_iterator(); ++iter) {
105     if (fs::is_symlink(symlink_status(iter->path()))) {
106       // skip symlink path
107       continue;
108     } else if (fs::is_directory(iter->path()) && iter.depth() == 0 &&
109         (iter->path().filename() == ".mmc" ||
110             iter->path().filename() == ".pkg" ||
111             iter->path().filename() == "tep")) {
112       // skip path which is related to mount or directory installer creates
113       continue;
114     } else if (fs::is_directory(iter->path())) {
115       bool is_rw = false;
116       if (iter.depth() == 0 &&
117               (iter->path().filename() == kData ||
118                iter->path().filename() == kCache))
119         is_rw = true;
120       if (!ci::SetDirOwnershipAndPermissions(
121               iter->path(), is_rw ? perms_setgid : perms755, uid,
122               is_rw ? *system_share : *gid))
123         return false;
124     } else {
125       bool is_bin = false;
126       if (iter.depth() == 1 && iter->path().parent_path().filename() == "bin")
127         is_bin = true;
128       if (!ci::SetDirOwnershipAndPermissions(
129               iter->path(), is_bin ? perms755 : perms644, uid, *gid))
130         return false;
131     }
132   }
133   return true;
134 }
135
136 fs::path GetDirectoryPathForStorage(uid_t user, std::string apps_prefix) {
137   std::string username = ci::GetUsernameByUid(user);
138   if (username.empty())
139     return {};
140
141   fs::path apps_rw;
142   apps_rw = fs::path(apps_prefix.c_str()) / username / "apps_rw";
143   return apps_rw;
144 }
145
146 bool DeleteSharedDataDirectories(const fs::path& path,
147                                  const std::string& pkgid) {
148   if (!ci::RemoveAll(path / pkgid / kSharedDataDir))
149     return false;
150
151   std::vector<std::string> shared_dirs(kSharedDataEntries);
152   for (const auto& entry : shared_dirs) {
153     if (!ci::RemoveAll(path / entry / pkgid))
154       return false;
155   }
156
157   return true;
158 }
159
160 bool CreateSharedDataDirectories(const fs::path& path,
161                                  const std::string& pkgid) {
162   if (!ci::CreateDir(path / kSharedDir / pkgid / kData) ||
163       !ci::CreateDir(path / kSharedTmpDir / pkgid) ||
164       !ci::CreateDir(path / pkgid / kShared))
165     return false;
166
167   fs::current_path(path / pkgid / kShared);
168   if (fs::exists(path / pkgid / kShared / kData))
169     return true;
170   fs::path relative_path = fs::relative(path / kSharedDir / pkgid / kData,
171       fs::current_path());
172   std::error_code error;
173   fs::create_symlink(relative_path, kData, error);
174   if (error) {
175     LOG(ERROR) << "Failed to create symlink : " << error.message();
176     return false;
177   }
178
179   return true;
180 }
181
182 bool DeleteDirectories(const fs::path& app_dir, const std::string& pkgid) {
183   fs::path base_dir = app_dir / pkgid;
184   if (!ci::RemoveAll(base_dir))
185     return false;
186   if (!DeleteSharedDataDirectories(app_dir, pkgid))
187     return false;
188   return true;
189 }
190
191 bool CreateSymlinkFiles(const fs::path& src_dir, const fs::path& dst_dir) {
192   std::vector<std::string> rofiles(kReadOnlyEntries);
193   for (fs::directory_iterator file(src_dir);
194       file != fs::directory_iterator();
195       ++file) {
196     if (fs::is_regular_file(file->path())) {
197       fs::path current(file->path());
198       fs::path file_name = current.filename();
199       LOG(DEBUG) << "file_name: " << file_name;
200       rofiles.push_back(file_name.string());
201     }
202   }
203
204   std::error_code error;
205   for (auto& entry : rofiles) {
206     fs::path src_path = src_dir / entry;
207     fs::path dst_path = dst_dir / entry;
208     if (!fs::exists(src_path)) {
209       // check if symlink for .mmc/bin,lib,res, then do not skip
210       if (!fs::is_symlink(symlink_status(src_path))) {
211         LOG(INFO) << "src_path not exist : " << src_path;
212         continue;
213       }
214     }
215     if (fs::exists(dst_path) || fs::is_symlink(symlink_status(dst_path))) {
216       LOG(WARNING) << "dst_path exist, skip : " << dst_path;
217       continue;
218     }
219     fs::create_symlink(src_path, dst_path, error);
220     if (error) {
221       LOG(ERROR) << "Symlink creation failure src_path: " << src_path
222                  << " dst_path: " << dst_path;
223       LOG(ERROR) << "error: " << error.message();
224       return false;
225     }
226   }
227   return true;
228 }
229
230 bool DeleteSymlinkFiles(const fs::path& src_dir, const fs::path& dst_dir) {
231   std::error_code error;
232   for (fs::directory_iterator file(dst_dir);
233       file != fs::directory_iterator();
234       ++file) {
235     fs::path current(file->path());
236     if (!fs::is_symlink(symlink_status(current)))
237       continue;
238     fs::path resolved_path = fs::read_symlink(current, error);
239     if (error) {
240       LOG(ERROR) << "Failed to get resolved path of symlink: " << current
241                  << ", error: " << error.message();
242       return false;
243     }
244
245     LOG(DEBUG) << "resolved_path: " << resolved_path;
246     fs::path parent = resolved_path.parent_path();
247     if (parent.empty() || (parent != src_dir)) {
248       LOG(WARNING) << "Parent is empty or not equal to src, parent: ("
249                    << parent << ")";
250       continue;
251     }
252     fs::remove(current, error);
253     if (error) {
254       LOG(ERROR) << "Symlink deletion failure for: " << current
255                   << ", error: " << error.message();
256       return false;
257     }
258     LOG(DEBUG) << "removed: " << current;
259   }
260   fs::path shared_res = dst_dir / kSharedResDir;
261   if (fs::is_symlink(symlink_status(shared_res))) {
262       fs::remove(shared_res, error);
263       if (error) {
264           LOG(ERROR) << "Symlink deletion failure for: " << shared_res
265                      << ", error: " << error.message();
266           return false;
267       }
268   }
269   return true;
270 }
271
272 bool CreateStorageDirectories(const fs::path& root_path,
273                               const std::string& pkgid,
274                               bool trusted, bool shareddata,
275                               const std::vector<const char*> additional_dirs) {
276   fs::path path(root_path / pkgid);
277   if (!ci::CreateDir(path)) {
278     LOG(ERROR) << "Failed to create dir: " << path;
279     return false;
280   }
281
282   std::vector<const char*> dirs(kEntries);
283   dirs.insert(dirs.end(), additional_dirs.begin(), additional_dirs.end());
284   if (trusted)
285     dirs.push_back(kSharedTrustedDir);
286
287   std::error_code error;
288   for (auto& entry : dirs) {
289     fs::path subpath = path / entry;
290     if (!ci::CreateDir(subpath)) {
291       LOG(ERROR) << "Failed to create directory: " << subpath;
292       return false;
293     }
294   }
295
296   if (shareddata) {
297     if (!CreateSharedDataDirectories(root_path, pkgid))
298       return false;
299   } else {
300     if (!DeleteSharedDataDirectories(root_path, pkgid))
301       return false;
302   }
303
304   fs::path shared_cache_path = path / kSharedCacheDir;
305   // remove shared/cache (do not support)
306   if (!ci::RemoveAll(shared_cache_path))
307     return false;
308
309   return true;
310 }
311
312 bool BackupSharedDataDirectories(const fs::path& apps_rw,
313     const std::string& pkgid) {
314   if (!ci::MakeBackup(apps_rw / pkgid / kSharedDataDir))
315     return false;
316   if (!ci::MakeBackup(apps_rw / kSharedDir / pkgid))
317     return false;
318   if (!ci::MakeBackup(apps_rw / kSharedTmpDir / pkgid))
319     return false;
320   return true;
321 }
322
323 bool RestoreSharedDataDirectories(const fs::path& apps_rw,
324     const std::string& pkgid) {
325   if (!ci::RestoreBackup(apps_rw / pkgid / kSharedDataDir))
326     return false;
327   if (!ci::RestoreBackup(apps_rw / kSharedDir / pkgid))
328     return false;
329   if (!ci::RestoreBackup(apps_rw / kSharedTmpDir / pkgid))
330     return false;
331   return true;
332 }
333
334 bool RemoveBackupSharedDataDirectories(const fs::path& apps_rw,
335     const std::string& pkgid) {
336   if (!ci::RemoveBackup(apps_rw / pkgid / kSharedDataDir))
337     return false;
338   if (!ci::RemoveBackup(apps_rw / kSharedDir / pkgid))
339     return false;
340   if (!ci::RemoveBackup(apps_rw / kSharedTmpDir / pkgid))
341     return false;
342   return true;
343 }
344
345 bool CreateExternalUserDirectories(uid_t user, const std::string& pkgid,
346     const std::string& apps_prefix) {
347   std::optional<gid_t> gid = ci::GetGidByUid(user);
348   if (!gid)
349     return false;
350
351   std::string group_name = ci::GetGroupNameByGid(*gid);
352   if (group_name != tzplatform_getenv(TZ_SYS_USER_GROUP)) {
353     LOG(ERROR) << "Failed to get group name of gid: " << *gid;
354     return false;
355   }
356
357   LOG(DEBUG) << "Creating directories for uid: " << user << ", gid: "
358              << *gid;
359
360   fs::path apps_rw = GetDirectoryPathForStorage(user, apps_prefix);
361   if (apps_rw.empty()) {
362     LOG(DEBUG) << "Directory not exists: " << apps_rw;
363     return false;
364   }
365
366   if (!CreateStorageDirectories(apps_rw, pkgid, true, false,
367           std::vector<const char*>()))
368     return false;
369
370   if (!::SetPackageDirectoryOwnerAndPermissions(apps_rw / pkgid, user))
371     return false;
372
373   return true;
374 }
375
376 }  // namespace
377
378 namespace common_installer {
379
380 std::string GetDirectoryPathForInternalStorage() {
381   const char* internal_storage_prefix = tzplatform_getenv(TZ_SYS_HOME);
382   if (internal_storage_prefix)
383     return std::string(internal_storage_prefix);
384   return tzplatform_getenv(TZ_SYS_HOME);
385 }
386
387 std::string GetDirectoryPathForExternalStorage() {
388   return GetExternalCardPath().string();
389 }
390
391 bool PerformExternalDirectoryCreationForUser(uid_t user,
392                                              const std::string& pkgid) {
393   fs::path storage_path = GetExternalCardPath();
394
395   if (!fs::exists(storage_path)) {
396     LOG(WARNING) << "External storage (SD Card) is not mounted.";
397     return false;
398   }
399
400   fs::path storage_apps_path = storage_path / "apps";
401   if (!fs::exists(storage_apps_path)) {
402     std::error_code error;
403     fs::create_directories(storage_apps_path, error);
404     if (error) {
405       LOG(ERROR) << "Failed to create directory: "
406           << storage_apps_path.c_str();
407       return false;
408     }
409   }
410
411   if (CreateExternalUserDirectories(user, pkgid, storage_apps_path.string()))
412     return false;
413
414   for (auto& lw_user : GetLightUserList(user)) {
415     fs::path storage_apps_lw_path = storage_apps_path
416         / kSubssesionDir / lw_user / "apps";
417     if (!fs::exists(storage_apps_lw_path)) {
418       std::error_code error;
419       fs::create_directories(storage_apps_lw_path, error);
420       if (error) {
421         LOG(ERROR) << "Failed to create directory: "
422                    << storage_apps_lw_path.c_str();
423         return false;
424       }
425     }
426
427     if (CreateExternalUserDirectories(user, pkgid,
428         storage_apps_lw_path.string()))
429       return false;
430   }
431
432   return true;
433 }
434
435 bool PerformExternalDirectoryDeletionForUser(uid_t user,
436                                              const std::string& pkgid) {
437   fs::path storage_path = GetExternalCardPath();
438   if (!fs::exists(storage_path)) {
439     LOG(WARNING) << "External storage (SD Card) is not mounted. "
440         << "It will be ignored";
441     return true;
442   }
443
444   fs::path storage_apps_path = fs::path(storage_path) / "apps";
445   if (!DeleteDirectories(
446       GetDirectoryPathForStorage(user, storage_apps_path.string()), pkgid))
447     return false;
448
449   for (auto& lw_user : GetLightUserList(user)) {
450     fs::path storage_apps_lw_path =
451         storage_apps_path / kSubssesionDir / lw_user / "apps";
452     if (!DeleteDirectories(
453             GetDirectoryPathForStorage(user, storage_apps_lw_path.string()),
454             pkgid))
455       return false;
456   }
457
458   return true;
459 }
460
461 bool PerformExternalDirectoryCreationForAllUsers(const std::string& pkgid) {
462   UserList list = ci::GetUserList();
463   for (const auto& l : list) {
464     if (!PerformExternalDirectoryCreationForUser(std::get<0>(l),
465                                                  pkgid))
466       LOG(WARNING) << "Could not create external storage directories for user: "
467                    << std::get<0>(l);
468   }
469   return true;
470 }
471
472 bool PerformExternalDirectoryCreationForAllPkgs() {
473   UserList list = ci::GetUserList();
474   for (const auto& l  : list) {
475     uid_t uid = std::get<0>(l);
476     pkgmgrinfo_pkginfo_filter_h filter_handle = nullptr;
477     int ret = pkgmgrinfo_pkginfo_filter_create(&filter_handle);
478     if (ret != PMINFO_R_OK)
479       return false;
480     ret = pkgmgrinfo_pkginfo_filter_add_string(filter_handle,
481         PMINFO_PKGINFO_PROP_PACKAGE_PRIVILEGE, kExternalStoragePrivilege);
482     if (ret != PMINFO_R_OK) {
483       pkgmgrinfo_pkginfo_filter_destroy(filter_handle);
484       return false;
485     }
486
487     ret = pkgmgrinfo_pkginfo_filter_foreach_pkginfo(filter_handle,
488         [](const pkgmgrinfo_pkginfo_h handle, void* user_data) -> int {
489           uid_t u =
490               static_cast<uid_t>(reinterpret_cast<uintptr_t>(user_data));
491           char* pkgid = nullptr;
492
493           int r = pkgmgrinfo_pkginfo_get_pkgid(handle, &pkgid);
494           if (r != PMINFO_R_OK)
495             return -1;
496           if (!PerformExternalDirectoryCreationForUser(u, pkgid))
497             return -1;
498
499           return 0;
500         },
501         reinterpret_cast<void*>(static_cast<uintptr_t>(uid)));
502     if (ret != PMINFO_R_OK) {
503       LOG(DEBUG) << "Failed to create external directoy";
504       pkgmgrinfo_pkginfo_filter_destroy(filter_handle);
505       return false;
506     }
507     pkgmgrinfo_pkginfo_filter_destroy(filter_handle);
508   }
509
510   return true;
511 }
512
513 bool PerformExternalDirectoryDeletionForAllUsers(const std::string& pkgid) {
514   UserList list = ci::GetUserList();
515   for (const auto& l : list) {
516     uid_t uid = std::get<0>(l);
517     ci::PkgQueryInterface pkg_query(pkgid, uid);
518     LOG(DEBUG) << "Deleting directories for user: " << uid;
519     if (pkg_query.IsPackageInstalled()) {
520       LOG(DEBUG) << "Package: " << pkgid << " for uid: " << uid
521                  << " still exists. Skipping";
522       continue;
523     }
524
525     if (!PerformExternalDirectoryDeletionForUser(uid, pkgid))
526       LOG(WARNING) << "Could not delete external storage directories for user: "
527                    << uid;
528   }
529   return true;
530 }
531
532 bool CreatePerUserStorageDirectories(const std::string& pkgid, bool trusted,
533     bool shareddata, bool is_readonly,
534     const std::vector<const char*> additional_dirs) {
535   // create skel dir
536   fs::path skel_apps_rw = fs::path(tzplatform_getenv(TZ_SYS_ETC)) /
537       fs::path(kSkelAppDir);
538   if (!::CreateStorageDirectories(skel_apps_rw, pkgid, trusted, shareddata,
539           additional_dirs)) {
540     LOG(ERROR) << "Failed to create skeleton storage directories";
541     return false;
542   }
543
544   std::string error_message;
545   if (!RegisterSecurityContextForPath(pkgid, {}, skel_apps_rw / pkgid,
546       kGlobalUserUid, is_readonly, &error_message)) {
547     LOG(ERROR) << "Failed to register security context for path: "
548                << skel_apps_rw / pkgid << ", error_message: " << error_message;
549     return false;
550   }
551
552   if (!is_readonly) {
553     fs::path src_dir = fs::path(tzplatform_getenv(TZ_SYS_RW_APP)) / pkgid;
554     if (!CreateSymlinkFiles(src_dir, skel_apps_rw / pkgid))
555       return false;
556   }
557
558   // create per user dir
559   UserList list = ci::GetUserList();
560   for (const auto& l : list) {
561     uid_t uid = std::get<0>(l);
562     fs::path owner_apps_rw = std::get<2>(l) / "apps_rw";
563     std::vector<fs::path> apps_rw_paths;
564     apps_rw_paths.push_back(std::move(owner_apps_rw));
565
566     for (auto& lw_user : GetLightUserList(uid))
567       apps_rw_paths.push_back(std::get<2>(l)
568           / kSubssesionDir / lw_user / "apps_rw");
569
570     LOG(DEBUG) << "Creating directories for user: " << uid;
571     for (auto& apps_rw : apps_rw_paths) {
572       if (!::CreateStorageDirectories(apps_rw, pkgid, trusted, shareddata,
573           additional_dirs)) {
574         LOG(ERROR) << "Failed to create storage directory for user: " << uid;
575         return false;
576       }
577
578       if (!::SetPackageDirectoryOwnerAndPermissions(apps_rw / pkgid, uid))
579         return false;
580
581       if (shareddata) {
582         std::vector<std::string> shared_dirs(kSharedDataEntries);
583         for (const auto& entry : shared_dirs) {
584           fs::path shared_dst = apps_rw / entry / pkgid;
585           if (!::SetPackageDirectoryOwnerAndPermissions(shared_dst, uid))
586             return false;
587         }
588       }
589
590       if (!RegisterSecurityContextForPath(pkgid, {}, apps_rw / pkgid, uid,
591           false, &error_message)) {
592         LOG(ERROR) << "Failed to register security context for path: "
593                    << apps_rw / pkgid << ", error_message: " << error_message;
594         return false;
595       }
596     }
597   }
598
599   return true;
600 }
601
602 bool DeletePerUserStorageDirectories(const std::string& pkgid,
603     bool keep_rwdata) {
604   // delete skel dir
605   fs::path skel_apps_rw = fs::path(tzplatform_getenv(TZ_SYS_ETC)) /
606       fs::path(kSkelAppDir);
607   if (!ci::RemoveAll(skel_apps_rw / pkgid)) {
608     LOG(ERROR) << "Failed to delete skeleton storage directories";
609     return false;
610   }
611
612   if (keep_rwdata)
613     return true;
614
615   // delete per user dir
616   UserList list = ci::GetUserList();
617   for (const auto& l : list) {
618     uid_t uid = std::get<0>(l);
619     fs::path owner_apps_rw = std::get<2>(l) / "apps_rw";
620     std::vector<fs::path> apps_rw_paths;
621     apps_rw_paths.push_back(std::move(owner_apps_rw));
622
623     for (auto& lw_user : GetLightUserList(uid))
624       apps_rw_paths.push_back(std::get<2>(l) / kSubssesionDir / lw_user /
625                               "apps_rw");
626
627     LOG(DEBUG) << "Deleting directories for user: " << uid;
628     for (auto& apps_rw : apps_rw_paths) {
629       if (!ci::RemoveAll(apps_rw / pkgid)) {
630         LOG(ERROR) << "Failed to delete storage directory for user: " << uid;
631         return false;
632       }
633     }
634   }
635
636   if (!ci::DeletePerUserSharedDataDir(pkgid)) {
637     LOG(ERROR) << "Failed to delete per user shared data dir";
638     return false;
639   }
640
641   return true;
642 }
643
644 bool CreateStorageDirectories(const fs::path& path,
645                               const std::string& pkgid, uid_t uid,
646                               bool trusted, bool shareddata) {
647   if (!::CreateStorageDirectories(path, pkgid, trusted,
648                                   shareddata, std::vector<const char*>())) {
649     LOG(ERROR) << "Failed to create storage directory for path: " << path;
650     return false;
651   }
652
653   if (!::SetPackageDirectoryOwnerAndPermissions(path / pkgid, uid))
654     return false;
655
656   if (shareddata) {
657     std::vector<std::string> shared_dirs(kSharedDataEntries);
658     for (const auto& entry : shared_dirs) {
659       fs::path shared_dst = path / entry / pkgid;
660       if (!::SetPackageDirectoryOwnerAndPermissions(shared_dst, uid))
661         return false;
662     }
663   }
664
665   std::string error_message;
666   if (!RegisterSecurityContextForPath(pkgid, {}, path / pkgid, uid, false,
667       &error_message)) {
668     LOG(ERROR) << "Failed to register security context for path: " << path
669                << ", error_message: " << error_message;
670     return false;
671   }
672
673   return true;
674 }
675
676 void RemoveRWDirectories(const fs::path& root) {
677   if (!RemoveAll(root / kCache))
678     LOG(ERROR) << "Failed to remove packaged cache directory";
679   if (!RemoveAll(root / kData))
680     LOG(ERROR) << "Failed to remove packaged data directory";
681   if (!RemoveAll(root / kSharedCacheDir))
682     LOG(ERROR) << "Failed to remove packaged shared/cache directory";
683   if (!RemoveAll(root / kSharedDataDir))
684     LOG(ERROR) << "Failed to remove packaged shared/data directory";
685   if (!RemoveAll(root / kSharedTrustedDir))
686     LOG(ERROR) << "Failed to remove packaged shared/trusted directory";
687 }
688
689 bool DeleteSharedDirectories(const fs::path& path,
690                              const std::string& pkgid) {
691   return DeleteSharedDataDirectories(path, pkgid);
692 }
693
694 bool DeleteUserExternalDirectories(const std::string& pkgid) {
695   UserList list = ci::GetUserList();
696   for (const auto& l : list) {
697     uid_t uid = std::get<0>(l);
698     ci::PkgQueryInterface pkg_query(pkgid, uid);
699     if (pkg_query.IsPackageInstalled()) {
700       LOG(INFO) << pkgid << " is installed for user " << uid;
701       continue;
702     }
703
704     LOG(DEBUG) << "Deleting external directories of " << pkgid
705                << ", for uid: " << uid;
706     fs::path apps_rw(std::get<2>(l) / "apps_rw");
707     if (!DeleteDirectories(apps_rw, pkgid)) {
708       return false;
709     }
710
711     for (auto& lw_user : GetLightUserList(uid)) {
712       fs::path apps_rw_lw(std::get<2>(l) / kSubssesionDir / lw_user / "apps_rw");
713       if (!DeleteDirectories(apps_rw_lw, pkgid))
714         return false;
715     }
716   }
717
718   return true;
719 }
720
721 bool CreateGlobalAppSymlinksForAllUsers(const std::string& pkgid) {
722   fs::path src_dir = fs::path(tzplatform_getenv(TZ_SYS_RW_APP)) / pkgid;
723   if (!fs::exists(src_dir)) {
724     LOG(ERROR) << "src_dir not exists";
725     return false;
726   }
727
728   UserList list = ci::GetUserList();
729   for (const auto& l : list) {
730     uid_t uid = std::get<0>(l);
731     LOG(DEBUG) << "Creating symlinks for uid: " << uid;
732     // check installed user private app.
733     ci::PkgQueryInterface pkg_query(pkgid, uid);
734     if (pkg_query.IsPackageInstalled())
735       continue;
736
737     fs::path owner_apps_rw = std::get<2>(l) / "apps_rw";
738     std::vector<fs::path> apps_rw_paths;
739     apps_rw_paths.push_back(std::move(owner_apps_rw));
740
741     for (auto& lw_user : GetLightUserList(uid))
742       apps_rw_paths.push_back(std::get<2>(l) / kSubssesionDir / lw_user /
743                               "apps_rw");
744
745     for (auto& apps_rw : apps_rw_paths) {
746       fs::path dst_dir = apps_rw / pkgid;
747       if (!fs::exists(dst_dir)) {
748         LOG(WARNING) << "dst_dir not exists";
749         continue;
750       }
751
752       if (!CreateSymlinkFiles(src_dir, dst_dir))
753         return false;
754     }
755   }
756
757   return true;
758 }
759
760 bool CreateGlobalAppSymlinksForUser(const std::string& pkgid, uid_t uid) {
761   fs::path src_dir = fs::path(tzplatform_getenv(TZ_SYS_RW_APP)) / pkgid;
762   if (!fs::exists(src_dir)) {
763     LOG(WARNING) << "src_dir(" << src_dir << ") not exists";
764     return true;
765   }
766
767   tzplatform_set_user(uid);
768   fs::path dst_dir = fs::path(tzplatform_getenv(TZ_USER_APP)) / pkgid;
769   tzplatform_reset_user();
770   if (!fs::exists(dst_dir)) {
771     LOG(WARNING) << "dst_dir not exists";
772     return true;
773   }
774   bool result = CreateSymlinkFiles(src_dir, dst_dir);
775
776   return result;
777 }
778
779 bool DeleteGlobalAppSymlinksForAllUsers(const std::string& pkgid) {
780   fs::path src_dir = fs::path(tzplatform_getenv(TZ_SYS_RW_APP)) / pkgid;
781   if (!fs::exists(src_dir)) {
782     LOG(WARNING) << "src_dir(" << src_dir << ") not exists";
783     return true;
784   }
785
786   UserList list = ci::GetUserList();
787   for (const auto& l : list) {
788     uid_t uid = std::get<0>(l);
789     LOG(DEBUG) << "Deleting symlinks for uid: " << uid;
790
791     // check installed user private app.
792     ci::PkgQueryInterface pkg_query(pkgid, uid);
793     if (pkg_query.IsPackageInstalled())
794       continue;
795
796     fs::path owner_apps_rw = std::get<2>(l) / "apps_rw";
797     std::vector<fs::path> apps_rw_paths;
798     apps_rw_paths.push_back(std::move(owner_apps_rw));
799     for (auto& lw_user : GetLightUserList(uid))
800       apps_rw_paths.push_back(std::get<2>(l) / kSubssesionDir / lw_user /
801                               "apps_rw");
802
803     for (auto& apps_rw : apps_rw_paths) {
804       fs::path dst_dir = apps_rw / pkgid;
805       if (!fs::exists(dst_dir)) {
806         LOG(WARNING) << "dst_dir not exists";
807         continue;
808       }
809
810       if (!DeleteSymlinkFiles(src_dir, dst_dir))
811         return false;
812     }
813   }
814
815   return true;
816 }
817
818 bool DeleteGlobalAppSymlinksForUser(const std::string& pkgid, uid_t uid) {
819   fs::path src_dir = fs::path(tzplatform_getenv(TZ_SYS_RW_APP)) / pkgid;
820   if (!fs::exists(src_dir)) {
821     LOG(ERROR) << "src_dir not exists";
822     return false;
823   }
824
825   tzplatform_set_user(uid);
826   fs::path dst_dir = fs::path(tzplatform_getenv(TZ_USER_APP)) / pkgid;
827   tzplatform_reset_user();
828   if (!fs::exists(dst_dir)) {
829     LOG(WARNING) << "dst_dir not exists";
830     return true;
831   }
832   bool result = DeleteSymlinkFiles(src_dir, dst_dir);
833   return result;
834 }
835
836 bool SetPackageDirectoryOwnerAndPermissions(const fs::path& path, uid_t uid) {
837   return ::SetPackageDirectoryOwnerAndPermissions(path, uid);
838 }
839
840 bool ShouldSupportLegacySharedDataDir(const std::string& api_version) {
841   if (fs::exists(kDisableLegacySharedDataDirSupport))
842     return false;
843   utils::VersionNumber api_ver(api_version);
844   if (api_ver < ver30)
845     return true;
846   else
847     return false;
848 }
849
850 bool CreateSharedDataDir(const std::string& pkgid, uid_t uid) {
851   fs::path apps_rw = ci::GetRootAppPath(false, uid);
852   if (!CreateSharedDataDirectories(apps_rw, pkgid))
853     return false;
854
855   fs::path path = apps_rw / pkgid;
856   std::string error_message;
857   if (!ci::RegisterSecurityContextForPath(pkgid, {}, path, uid, false,
858       &error_message)) {
859     LOG(ERROR) << "Failed to register security context for path: " << path
860                << ", error_message: " << error_message;
861     return false;
862   }
863
864   return true;
865 }
866
867 bool CreatePerUserSharedDataDir(const std::string& pkgid) {
868   // create skel dir
869   fs::path skel_apps_rw = fs::path(tzplatform_getenv(TZ_SYS_ETC)) /
870       fs::path(kSkelAppDir);
871   LOG(DEBUG) <<  "Creating directory : " << skel_apps_rw;
872   if (!CreateSharedDataDirectories(skel_apps_rw, pkgid))
873     return false;
874
875   std::string error_message;
876   if (!ci::RegisterSecurityContextForPath(pkgid, {}, skel_apps_rw / pkgid,
877       kGlobalUserUid, false, &error_message)) {
878     LOG(ERROR) << "Failed to register security context for path: "
879                << skel_apps_rw / pkgid << ", error_message: " << error_message;
880     return false;
881   }
882
883   // create per user dir
884   ci::UserList list = ci::GetUserList();
885   for (const auto& l : list) {
886     uid_t uid = std::get<0>(l);
887     LOG(DEBUG) << "Adding shareddata directory for uid: " << uid;
888
889     fs::path owner_apps_rw = ci::GetRootAppPath(false, uid);
890     std::vector<fs::path> apps_rw_paths;
891     apps_rw_paths.push_back(std::move(owner_apps_rw));
892     for (auto& lw_user : GetLightUserList(uid))
893       apps_rw_paths.push_back(std::get<2>(l) / kSubssesionDir / lw_user /
894                               "apps_rw");
895
896     for (auto& apps_rw : apps_rw_paths) {
897       if (!CreateSharedDataDirectories(apps_rw, pkgid))
898         return false;
899
900       std::vector<std::string> shared_dirs(kSharedDataEntries);
901       for (const auto& entry : shared_dirs) {
902         fs::path shared_dst = apps_rw / entry / pkgid;
903         if (!::SetPackageDirectoryOwnerAndPermissions(shared_dst, uid))
904           return false;
905       }
906
907       if (!ci::RegisterSecurityContextForPath(pkgid, {}, apps_rw / pkgid, uid,
908                                               false, &error_message)) {
909         LOG(ERROR) << "Failed to register security context for path: "
910                    << apps_rw / pkgid << ", error_message: " << error_message;
911         return false;
912       }
913     }
914   }
915
916   return true;
917 }
918
919 bool DeleteSharedDataDir(const std::string& pkgid, uid_t uid) {
920   fs::path apps_rw = ci::GetRootAppPath(false, uid);
921   return DeleteSharedDataDirectories(apps_rw, pkgid);
922 }
923
924 bool DeletePerUserSharedDataDir(const std::string& pkgid) {
925   fs::path skel_apps_rw = fs::path(tzplatform_getenv(TZ_SYS_ETC)) /
926       fs::path(kSkelAppDir);
927   if (!DeleteSharedDataDirectories(skel_apps_rw, pkgid))
928     return false;
929
930   ci::UserList list = ci::GetUserList();
931   for (const auto& l : list) {
932     uid_t uid = std::get<0>(l);
933
934     fs::path owner_apps_rw = ci::GetRootAppPath(false, uid);
935     std::vector<fs::path> apps_rw_paths;
936     apps_rw_paths.push_back(std::move(owner_apps_rw));
937     for (auto& lw_user : GetLightUserList(uid))
938       apps_rw_paths.push_back(std::get<2>(l) / kSubssesionDir / lw_user /
939                               "apps_rw");
940
941     for (auto& apps_rw : apps_rw_paths) {
942       if (!DeleteSharedDataDirectories(apps_rw, pkgid))
943         return false;
944     }
945   }
946   return true;
947 }
948
949 bool BackupSharedDataDir(const std::string& pkgid, uid_t uid) {
950   fs::path apps_rw = ci::GetRootAppPath(false, uid);
951   return BackupSharedDataDirectories(apps_rw, pkgid);
952 }
953
954 bool BackupPerUserSharedDataDir(const std::string& pkgid) {
955   fs::path skel_apps_rw = fs::path(tzplatform_getenv(TZ_SYS_ETC)) /
956       fs::path(kSkelAppDir);
957   if (!BackupSharedDataDirectories(skel_apps_rw, pkgid))
958     return false;
959
960   ci::UserList list = ci::GetUserList();
961   for (const auto& l : list) {
962     uid_t uid = std::get<0>(l);
963     fs::path owner_apps_rw = ci::GetRootAppPath(false, uid);
964     std::vector<fs::path> apps_rw_paths;
965     apps_rw_paths.push_back(std::move(owner_apps_rw));
966     for (auto& lw_user : GetLightUserList(uid))
967       apps_rw_paths.push_back(std::get<2>(l) / kSubssesionDir / lw_user /
968                               "apps_rw");
969
970     for (auto& apps_rw : apps_rw_paths) {
971       if (!BackupSharedDataDirectories(apps_rw, pkgid))
972         return false;
973     }
974   }
975
976   return true;
977 }
978
979 bool RestoreSharedDataDir(const std::string& pkgid, uid_t uid) {
980   fs::path apps_rw = ci::GetRootAppPath(false, uid);
981   if (!RestoreSharedDataDirectories(apps_rw, pkgid))
982     return false;
983
984   if (!::SetPackageDirectoryOwnerAndPermissions(apps_rw / pkgid, uid))
985     return false;
986
987   std::vector<std::string> shared_dirs(kSharedDataEntries);
988   for (const auto& entry : shared_dirs) {
989     fs::path shared_dst = apps_rw / entry / pkgid;
990     if (!::SetPackageDirectoryOwnerAndPermissions(shared_dst, uid))
991       return false;
992   }
993
994   std::string error_message;
995   if (!RegisterSecurityContextForPath(pkgid, {}, apps_rw / pkgid, uid, false,
996                                       &error_message)) {
997     LOG(ERROR) << "Failed to register security context for path: " << apps_rw
998                << ", error_message: " << error_message;
999     return false;
1000   }
1001
1002   return true;
1003 }
1004
1005 bool RestorePerUserSharedDataDir(const std::string& pkgid) {
1006   fs::path skel_apps_rw = fs::path(tzplatform_getenv(TZ_SYS_ETC)) /
1007       fs::path(kSkelAppDir);
1008   if (!RestoreSharedDataDirectories(skel_apps_rw, pkgid))
1009     return false;
1010
1011   std::string error_message;
1012   ci::UserList list = ci::GetUserList();
1013   for (const auto& l : list) {
1014     uid_t uid = std::get<0>(l);
1015     fs::path owner_apps_rw = ci::GetRootAppPath(false, uid);
1016     std::vector<fs::path> apps_rw_paths;
1017     apps_rw_paths.push_back(std::move(owner_apps_rw));
1018     for (auto& lw_user : GetLightUserList(uid))
1019       apps_rw_paths.push_back(std::get<2>(l) / kSubssesionDir / lw_user /
1020                               "apps_rw");
1021
1022     for (auto& apps_rw : apps_rw_paths) {
1023       if (!RestoreSharedDataDirectories(apps_rw, pkgid))
1024         return false;
1025
1026       if (!::SetPackageDirectoryOwnerAndPermissions(apps_rw / pkgid, uid))
1027         return false;
1028
1029       std::vector<std::string> shared_dirs(kSharedDataEntries);
1030       for (const auto& entry : shared_dirs) {
1031         fs::path shared_dst = apps_rw / entry / pkgid;
1032         if (!::SetPackageDirectoryOwnerAndPermissions(shared_dst, uid))
1033           return false;
1034       }
1035
1036       if (!RegisterSecurityContextForPath(pkgid, {}, apps_rw / pkgid, uid,
1037           false, &error_message)) {
1038         LOG(ERROR) << "Failed to register security context for path: "
1039                    << apps_rw / pkgid << ", error_message: " << error_message;
1040         return false;
1041       }
1042     }
1043   }
1044
1045   return true;
1046 }
1047
1048 bool RemoveBackupSharedDataDir(const std::string& pkgid, uid_t uid) {
1049   fs::path apps_rw = ci::GetRootAppPath(false, uid);
1050   return RemoveBackupSharedDataDirectories(apps_rw, pkgid);
1051 }
1052
1053 bool RemoveBackupPerUserSharedDataDir(const std::string& pkgid) {
1054   fs::path skel_apps_rw = fs::path(tzplatform_getenv(TZ_SYS_ETC)) /
1055       fs::path(kSkelAppDir);
1056   if (!RemoveBackupSharedDataDirectories(skel_apps_rw, pkgid))
1057     return false;
1058
1059   ci::UserList list = ci::GetUserList();
1060   for (const auto& l : list) {
1061     uid_t uid = std::get<0>(l);
1062     fs::path owner_apps_rw = ci::GetRootAppPath(false, uid);
1063     std::vector<fs::path> apps_rw_paths;
1064     apps_rw_paths.push_back(std::move(owner_apps_rw));
1065     for (auto& lw_user : GetLightUserList(uid))
1066       apps_rw_paths.push_back(std::get<2>(l) / kSubssesionDir / lw_user /
1067                               "apps_rw");
1068
1069     for (auto& apps_rw : apps_rw_paths) {
1070       if (!RemoveBackupSharedDataDirectories(apps_rw, pkgid))
1071         return false;
1072     }
1073   }
1074
1075   return true;
1076 }
1077
1078 }  // namespace common_installer