0c4f07f9259037cde6e874f5f1f7bf8056260166
[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 <boost/filesystem/operations.hpp>
11 #include <boost/filesystem/path.hpp>
12 #include <boost/program_options.hpp>
13 #include <boost/system/error_code.hpp>
14
15 #include <glib.h>
16 #include <gio/gio.h>
17 #include <vcore/Certificate.h>
18 #include <pkgmgr-info.h>
19 #include <sys/types.h>
20 #include <unistd.h>
21 #include <fcntl.h>
22 #include <tzplatform_config.h>
23 #include <sys/xattr.h>
24
25 #include <algorithm>
26 #include <cassert>
27 #include <cstring>
28 #include <cstdio>
29 #include <exception>
30 #include <iterator>
31 #include <regex>
32 #include <string>
33 #include <utility>
34 #include <vector>
35 #include <tuple>
36
37 #include "common/paths.h"
38 #include "common/security_registration.h"
39 #include "common/pkgmgr_query.h"
40 #include "common/utils/base64.h"
41 #include "common/utils/file_util.h"
42 #include "common/utils/user_util.h"
43 #include "common/utils/glist_range.h"
44
45 namespace bf = boost::filesystem;
46 namespace bpo = boost::program_options;
47 namespace bs = boost::system;
48 namespace ci = common_installer;
49
50 namespace {
51
52 const uid_t kGlobalUserUid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
53 const utils::VersionNumber ver30("3.0");
54 const char kDisableLegacySharedDataDirSupport[] =
55     "/usr/share/app-installers/disable_legacy_shareddata_support";
56
57 const std::vector<const char*> kEntries = {
58   {"shared"},
59   {"cache"},
60   {"data"},
61 };
62 const std::vector<std::string> kReadOnlyEntries = {
63   {"bin"},
64   {"lib"},
65   {"res"},
66   {"shared/res"},
67 };
68 const std::vector<std::string> kSharedDataEntries = {
69   {".shared"},
70   {".shared_tmp"},
71 };
72
73 const char kSharedResDir[] = "shared/res";
74 const char kSharedCacheDir[] = "shared/cache";
75 const char kSharedDataDir[] = "shared/data";
76 const char kShared[] = "shared";
77 const char kData[] = "data";
78 const char kCache[] = "cache";
79 const char kSharedDir[] = ".shared";
80 const char kSharedTmpDir[] = ".shared_tmp";
81 const char kSharedTrustedDir[] = "shared/trusted";
82 const char kSkelAppDir[] = "skel/apps_rw";
83 const char kExternalStoragePrivilege[] =
84     "http://tizen.org/privilege/externalstorage.appdata";
85 const char kSystemShareGroupName[] = "system_share";
86
87 // the input path should be root directory of package.
88 // for example: "../apps_rw/pkgid" or "../.shared/pkgid"
89 bool SetPackageDirectoryOwnerAndPermissions(const bf::path& path, uid_t uid) {
90   boost::optional<gid_t> gid = ci::GetGidByUid(uid);
91   if (!gid)
92     return false;
93
94   bf::perms perms755 = bf::all_all ^ bf::group_write ^ bf::others_write;
95   bf::perms perms644 = perms755 ^ bf::group_exe ^ bf::others_exe;
96   bf::perms perms_setgid = perms755 | bf::set_gid_on_exe;
97   boost::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 (bf::recursive_directory_iterator iter(path);
104       iter != bf::recursive_directory_iterator(); ++iter) {
105     if (bf::is_symlink(symlink_status(iter->path()))) {
106       // skip symlink path
107       continue;
108     } else if (bf::is_directory(iter->path()) && iter.level() == 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 (bf::is_directory(iter->path())) {
115       bool is_rw = false;
116       if (iter.level() == 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.level() == 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 bf::path GetDirectoryPathForStorage(uid_t user, std::string apps_prefix) {
137   std::string username = ci::GetUsernameByUid(user);
138   if (username.empty())
139     return {};
140
141   bf::path apps_rw;
142   apps_rw = bf::path(apps_prefix.c_str()) / username / "apps_rw";
143   return apps_rw;
144 }
145
146 bool DeleteSharedDataDirectories(const bf::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 (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 bf::path& path,
161                                  const std::string& pkgid) {
162   if (!ci::CreateDir(path / kSharedDir / pkgid / kData) ||
163       !ci::CreateDir(path / kSharedTmpDir / pkgid))
164     return false;
165
166   bf::current_path(path / pkgid / kShared);
167   if (bf::exists(path / pkgid / kShared / kData))
168     return true;
169   bf::path relative_path = ci::RelativePath(path / kSharedDir / pkgid / kData,
170                                             bf::current_path() / kData);
171   bs::error_code error;
172   bf::create_symlink(relative_path, kData, error);
173   if (error) {
174     LOG(ERROR) << "Failed to create symlink : " << error.message();
175     return false;
176   }
177
178   return true;
179 }
180
181 bool DeleteDirectories(const bf::path& app_dir, const std::string& pkgid) {
182   bf::path base_dir = app_dir / pkgid;
183   if (!ci::RemoveAll(base_dir))
184     return false;
185   if (!DeleteSharedDataDirectories(app_dir, pkgid))
186     return false;
187   return true;
188 }
189
190 bool CreateSymlinkFiles(const bf::path& src_dir, const bf::path& dst_dir) {
191   std::vector<std::string> rofiles(kReadOnlyEntries);
192   for (bf::directory_iterator file(src_dir);
193       file != bf::directory_iterator();
194       ++file) {
195     if (bf::is_regular_file(file->path())) {
196       bf::path current(file->path());
197       bf::path file_name = current.filename();
198       LOG(DEBUG) << "file_name: " << file_name;
199       rofiles.push_back(file_name.string());
200     }
201   }
202
203   bs::error_code error;
204   for (auto& entry : rofiles) {
205     bf::path src_path = src_dir / entry;
206     bf::path dst_path = dst_dir / entry;
207     if (!bf::exists(src_path)) {
208       // check if symlink for .mmc/bin,lib,res, then do not skip
209       if (!bf::is_symlink(symlink_status(src_path))) {
210         LOG(INFO) << "src_path not exist : " << src_path;
211         continue;
212       }
213     }
214     if (bf::exists(dst_path) || bf::is_symlink(symlink_status(dst_path))) {
215       LOG(WARNING) << "dst_path exist, skip : " << dst_path;
216       continue;
217     }
218     bf::create_symlink(src_path, dst_path, error);
219     if (error) {
220       LOG(ERROR) << "Symlink creation failure src_path: " << src_path
221                  << " dst_path: " << dst_path;
222       LOG(ERROR) << "error: " << error.message();
223       return false;
224     }
225   }
226   return true;
227 }
228
229 bool DeleteSymlinkFiles(const bf::path& src_dir, const bf::path& dst_dir) {
230   bs::error_code error;
231   for (bf::directory_iterator file(dst_dir);
232       file != bf::directory_iterator();
233       ++file) {
234     bf::path current(file->path());
235     if (bf::is_symlink(symlink_status(current))) {
236       bf::path resolved_path = bf::read_symlink(current, error);
237       if (error) {
238         LOG(ERROR) << "Getting resolved path of symlink: " << current;
239         LOG(ERROR) << "resolved_path: " << resolved_path;
240         LOG(ERROR) << "error: " << error.message();
241         return false;
242       }
243       LOG(DEBUG) << "resolved_path: " << resolved_path;
244       bf::path parent = resolved_path.parent_path();
245       if (!parent.empty() && (parent == src_dir)) {
246         bf::remove(current, error);
247         if (error) {
248           LOG(ERROR) << "Symlink deletion failure for: " << current
249                      << ", error: " << error.message();
250           return false;
251         }
252         LOG(DEBUG) << "removed: " << current;
253       } else {
254         LOG(WARNING) << "Parent is empty or not equal to src, parenet: ("
255                    << parent << ")";
256       }
257     }
258   }
259   bf::path shared_res = dst_dir / kSharedResDir;
260   if (bf::is_symlink(symlink_status(shared_res))) {
261       bf::remove(shared_res, error);
262       if (error) {
263           LOG(ERROR) << "Symlink deletion failure for: " << shared_res
264                      << ", error: " << error.message();
265           return false;
266       }
267   }
268   return true;
269 }
270
271 bool CreateStorageDirectories(const boost::filesystem::path& root_path,
272                               const std::string& pkgid,
273                               bool trusted, bool shareddata,
274                               const std::vector<const char*> additional_dirs) {
275   bf::path path(root_path / pkgid);
276   if (!ci::CreateDir(path)) {
277     LOG(ERROR) << "Failed to create dir: " << path;
278     return false;
279   }
280
281   std::vector<const char*> dirs(kEntries);
282   dirs.insert(dirs.end(), additional_dirs.begin(), additional_dirs.end());
283   if (trusted)
284     dirs.push_back(kSharedTrustedDir);
285
286   bs::error_code error;
287   for (auto& entry : dirs) {
288     bf::path subpath = path / entry;
289     if (!ci::CreateDir(subpath)) {
290       LOG(ERROR) << "Failed to create directory: " << subpath;
291       return false;
292     }
293   }
294
295   if (shareddata) {
296     if (!CreateSharedDataDirectories(root_path, pkgid))
297       return false;
298   } else {
299     if (!DeleteSharedDataDirectories(root_path, pkgid))
300       return false;
301   }
302
303   bf::path shared_cache_path = path / kSharedCacheDir;
304   // remove shared/cache (do not support)
305   if (!ci::RemoveAll(shared_cache_path))
306     return false;
307
308   return true;
309 }
310
311 bool BackupSharedDataDirectories(const bf::path& apps_rw,
312     const std::string& pkgid) {
313   if (!ci::MakeBackup(apps_rw / pkgid / kSharedDataDir))
314     return false;
315   if (!ci::MakeBackup(apps_rw / kSharedDir / pkgid))
316     return false;
317   if (!ci::MakeBackup(apps_rw / kSharedTmpDir / pkgid))
318     return false;
319   return true;
320 }
321
322 bool RestoreSharedDataDirectories(const bf::path& apps_rw,
323     const std::string& pkgid) {
324   if (!ci::RestoreBackup(apps_rw / pkgid / kSharedDataDir))
325     return false;
326   if (!ci::RestoreBackup(apps_rw / kSharedDir / pkgid))
327     return false;
328   if (!ci::RestoreBackup(apps_rw / kSharedTmpDir / pkgid))
329     return false;
330   return true;
331 }
332
333 bool RemoveBackupSharedDataDirectories(const bf::path& apps_rw,
334     const std::string& pkgid) {
335   if (!ci::RemoveBackup(apps_rw / pkgid / kSharedDataDir))
336     return false;
337   if (!ci::RemoveBackup(apps_rw / kSharedDir / pkgid))
338     return false;
339   if (!ci::RemoveBackup(apps_rw / kSharedTmpDir / pkgid))
340     return false;
341   return true;
342 }
343
344 bool CreateExternalUserDirectories(uid_t user, const std::string& pkgid,
345     const std::string& apps_prefix) {
346   boost::optional<gid_t> gid = ci::GetGidByUid(user);
347   if (!gid)
348     return false;
349
350   std::string group_name = ci::GetGroupNameByGid(*gid);
351   if (group_name != tzplatform_getenv(TZ_SYS_USER_GROUP)) {
352     LOG(ERROR) << "Failed to get group name of gid: " << *gid;
353     return false;
354   }
355
356   LOG(DEBUG) << "Creating directories for uid: " << user << ", gid: "
357              << *gid;
358
359   bf::path apps_rw = GetDirectoryPathForStorage(user, apps_prefix);
360   if (apps_rw.empty()) {
361     LOG(DEBUG) << "Directory not exists: " << apps_rw;
362     return false;
363   }
364
365   if (!CreateStorageDirectories(apps_rw, pkgid, true, false,
366           std::vector<const char*>()))
367     return false;
368
369   if (!::SetPackageDirectoryOwnerAndPermissions(apps_rw / pkgid, user))
370     return false;
371
372   return true;
373 }
374
375 }  // namespace
376
377 namespace common_installer {
378
379 std::string GetDirectoryPathForInternalStorage() {
380   const char* internal_storage_prefix = tzplatform_getenv(TZ_SYS_HOME);
381   if (internal_storage_prefix)
382     return std::string(internal_storage_prefix);
383   return tzplatform_getenv(TZ_SYS_HOME);
384 }
385
386 std::string GetDirectoryPathForExternalStorage() {
387   return GetExternalCardPath().string();
388 }
389
390 bool PerformExternalDirectoryCreationForUser(uid_t user,
391                                              const std::string& pkgid) {
392   bf::path storage_path = GetExternalCardPath();
393
394   if (!bf::exists(storage_path)) {
395     LOG(WARNING) << "External storage (SD Card) is not mounted.";
396     return false;
397   }
398
399   bf::path storage_apps_path = storage_path / "apps";
400   if (!bf::exists(storage_apps_path)) {
401     bs::error_code error;
402     bf::create_directories(storage_apps_path, error);
403     if (error) {
404       LOG(ERROR) << "Failed to create directory: "
405           << storage_apps_path.c_str();
406       return false;
407     }
408   }
409
410   if (CreateExternalUserDirectories(user, pkgid, storage_apps_path.string()))
411     return false;
412
413   return true;
414 }
415
416 bool PerformExternalDirectoryDeletionForUser(uid_t user,
417                                              const std::string& pkgid) {
418   bf::path storage_path = GetExternalCardPath();
419   if (!bf::exists(storage_path)) {
420     LOG(WARNING) << "External storage (SD Card) is not mounted. "
421         << "It will be ignored";
422     return true;
423   }
424
425   bf::path storage_apps_path = bf::path(storage_path) / "apps";
426   return DeleteDirectories(
427       GetDirectoryPathForStorage(user, storage_apps_path.string()), pkgid);
428 }
429
430 bool PerformExternalDirectoryCreationForAllUsers(const std::string& pkgid) {
431   UserList list = ci::GetUserList();
432   for (auto l : list) {
433     if (!PerformExternalDirectoryCreationForUser(std::get<0>(l),
434                                                  pkgid))
435       LOG(WARNING) << "Could not create external storage directories for user: "
436                    << std::get<0>(l);
437   }
438   return true;
439 }
440
441 bool PerformExternalDirectoryCreationForAllPkgs() {
442   UserList list = ci::GetUserList();
443   for (auto l  : list) {
444     uid_t uid = std::get<0>(l);
445     pkgmgrinfo_pkginfo_filter_h filter_handle = nullptr;
446     int ret = pkgmgrinfo_pkginfo_filter_create(&filter_handle);
447     if (ret != PMINFO_R_OK)
448       return false;
449     ret = pkgmgrinfo_pkginfo_filter_add_string(filter_handle,
450         PMINFO_PKGINFO_PROP_PACKAGE_PRIVILEGE, kExternalStoragePrivilege);
451     if (ret != PMINFO_R_OK) {
452       pkgmgrinfo_pkginfo_filter_destroy(filter_handle);
453       return false;
454     }
455
456     ret = pkgmgrinfo_pkginfo_filter_foreach_pkginfo(filter_handle,
457         [](const pkgmgrinfo_pkginfo_h handle, void* user_data) -> int {
458           uid_t uid =
459               static_cast<uid_t>(reinterpret_cast<uintptr_t>(user_data));
460           char* pkgid = nullptr;
461
462           int ret = pkgmgrinfo_pkginfo_get_pkgid(handle, &pkgid);
463           if (ret != PMINFO_R_OK)
464             return -1;
465           if (!PerformExternalDirectoryCreationForUser(uid, pkgid))
466             return -1;
467
468           return 0;
469         },
470         reinterpret_cast<void*>(static_cast<uintptr_t>(uid)));
471     if (ret != PMINFO_R_OK) {
472       LOG(DEBUG) << "Failed to create external directoy";
473       pkgmgrinfo_pkginfo_filter_destroy(filter_handle);
474       return false;
475     }
476     pkgmgrinfo_pkginfo_filter_destroy(filter_handle);
477   }
478
479   return true;
480 }
481
482 bool PerformExternalDirectoryDeletionForAllUsers(const std::string& pkgid) {
483   UserList list = ci::GetUserList();
484   for (auto l : list) {
485     uid_t uid = std::get<0>(l);
486     ci::PkgQueryInterface pkg_query(pkgid, uid);
487     LOG(DEBUG) << "Deleting directories for user: " << uid;
488     if (pkg_query.IsPackageInstalled()) {
489       LOG(DEBUG) << "Package: " << pkgid << " for uid: " << uid
490                  << " still exists. Skipping";
491       continue;
492     }
493
494     if (!PerformExternalDirectoryDeletionForUser(uid, pkgid))
495       LOG(WARNING) << "Could not delete external storage directories for user: "
496                    << uid;
497   }
498   return true;
499 }
500
501 bool CreatePerUserStorageDirectories(const std::string& pkgid, bool trusted,
502     bool shareddata, bool is_readonly,
503     const std::vector<const char*> additional_dirs) {
504   // create skel dir
505   bf::path skel_apps_rw = bf::path(tzplatform_getenv(TZ_SYS_ETC)) /
506       bf::path(kSkelAppDir);
507   if (!::CreateStorageDirectories(skel_apps_rw, pkgid, trusted, shareddata,
508           additional_dirs)) {
509     LOG(ERROR) << "Failed to create skeleton storage directories";
510     return false;
511   }
512
513   std::string error_message;
514   if (!RegisterSecurityContextForPath(pkgid, skel_apps_rw / pkgid,
515           kGlobalUserUid, is_readonly, &error_message)) {
516     LOG(ERROR) << "Failed to register security context for path: "
517                << skel_apps_rw / pkgid << ", error_message: " << error_message;
518     return false;
519   }
520
521   // create per user dir
522   UserList list = ci::GetUserList();
523   for (auto l : list) {
524     uid_t uid = std::get<0>(l);
525     bf::path apps_rw = std::get<2>(l) / "apps_rw";
526     LOG(DEBUG) << "Creating directories for user: " << uid;
527     if (!::CreateStorageDirectories(apps_rw, pkgid, trusted, shareddata,
528          additional_dirs)) {
529       LOG(ERROR) << "Failed to create storage directory for user: " << uid;
530       return false;
531     }
532
533     if (!::SetPackageDirectoryOwnerAndPermissions(apps_rw / pkgid, uid))
534       return false;
535
536     if (shareddata) {
537       std::vector<std::string> shared_dirs(kSharedDataEntries);
538       for (auto entry : shared_dirs) {
539         bf::path shared_dst = apps_rw / entry / pkgid;
540         if (!::SetPackageDirectoryOwnerAndPermissions(shared_dst, uid))
541           return false;
542       }
543     }
544
545     if (!RegisterSecurityContextForPath(pkgid, apps_rw / pkgid, uid,
546             false, &error_message)) {
547       LOG(ERROR) << "Failed to register security context for path: "
548                  << apps_rw / pkgid << ", error_message: " << error_message;
549       return false;
550     }
551   }
552
553   return true;
554 }
555
556 bool DeletePerUserStorageDirectories(const std::string& pkgid) {
557   // delete skel dir
558   bf::path skel_apps_rw = bf::path(tzplatform_getenv(TZ_SYS_ETC)) /
559       bf::path(kSkelAppDir);
560   if (!ci::RemoveAll(skel_apps_rw / pkgid)) {
561     LOG(ERROR) << "Failed to delete skeleton storage directories";
562     return false;
563   }
564
565   // delete per user dir
566   UserList list = ci::GetUserList();
567   for (auto l : list) {
568     uid_t uid = std::get<0>(l);
569     bf::path apps_rw = std::get<2>(l) / "apps_rw";
570     LOG(DEBUG) << "Deleting directories for user: " << uid;
571     if (!ci::RemoveAll(apps_rw / pkgid)) {
572       LOG(ERROR) << "Failed to delete storage directory for user: " << uid;
573       return false;
574     }
575
576     if (!ci::DeletePerUserSharedDataDir(pkgid)) {
577       LOG(ERROR) << "Failed to delete per user shared data dir";
578       return false;
579     }
580   }
581
582   return true;
583 }
584
585 bool CreateStorageDirectories(const boost::filesystem::path& path,
586                               const std::string& pkgid, uid_t uid,
587                               bool trusted, bool shareddata) {
588   if (!::CreateStorageDirectories(path, pkgid, trusted,
589                                   shareddata, std::vector<const char*>())) {
590     LOG(ERROR) << "Failed to create storage directory for path: " << path;
591     return false;
592   }
593
594   if (!::SetPackageDirectoryOwnerAndPermissions(path / pkgid, uid))
595     return false;
596
597   std::string error_message;
598   if (!RegisterSecurityContextForPath(pkgid, path / pkgid, uid, false,
599                                       &error_message)) {
600     LOG(ERROR) << "Failed to register security context for path: " << path
601                << ", error_message: " << error_message;
602     return false;
603   }
604
605   return true;
606 }
607
608 bool DeleteStorageDirectories(const boost::filesystem::path& path,
609                               const std::string& pkgid) {
610   std::vector<const char*> dirs;
611   dirs.assign(kEntries.begin() + 1, kEntries.end());
612   dirs.push_back(kSharedTrustedDir);
613   dirs.push_back(kSharedCacheDir);
614   for (auto& entry : dirs) {
615     bf::path subpath = path / pkgid / entry;
616     if (!ci::RemoveAll(subpath))
617       return false;
618   }
619   if (!DeleteSharedDataDirectories(path, pkgid))
620     return false;
621
622   return true;
623 }
624
625 bool DeleteSharedDirectories(const bf::path& path,
626                              const std::string& pkgid) {
627   return DeleteSharedDataDirectories(path, pkgid);
628 }
629
630 bool DeleteUserExternalDirectories(const std::string& pkgid) {
631   UserList list = ci::GetUserList();
632   for (auto l : list) {
633     uid_t uid = std::get<0>(l);
634     ci::PkgQueryInterface pkg_query(pkgid, uid);
635     if (pkg_query.IsPackageInstalled()) {
636       LOG(INFO) << pkgid << " is installed for user " << uid;
637       continue;
638     }
639
640     LOG(DEBUG) << "Deleting external directories of " << pkgid
641                << ", for uid: " << uid;
642     bf::path apps_rw(std::get<2>(l) / "apps_rw");
643     if (!DeleteDirectories(apps_rw, pkgid)) {
644       return false;
645     }
646   }
647   return true;
648 }
649
650 bool CreateGlobalAppSymlinksForAllUsers(const std::string& pkgid) {
651   bf::path src_dir = bf::path(tzplatform_getenv(TZ_SYS_RW_APP)) / pkgid;
652   if (!bf::exists(src_dir)) {
653     LOG(ERROR) << "src_dir not exists";
654     return false;
655   }
656
657   bool result = true;
658   UserList list = ci::GetUserList();
659   for (auto l : list) {
660     uid_t uid = std::get<0>(l);
661     LOG(DEBUG) << "Creating symlinks for uid: " << uid;
662     // check installed user private app.
663     ci::PkgQueryInterface pkg_query(pkgid, uid);
664     if (pkg_query.IsPackageInstalled())
665       continue;
666     bf::path apps_rw(std::get<2>(l) / "apps_rw");
667     bf::path dst_dir = apps_rw / pkgid;
668     if (!bf::exists(dst_dir)) {
669       LOG(WARNING) << "dst_dir not exists";
670       continue;
671     }
672     result = CreateSymlinkFiles(src_dir, dst_dir);
673   }
674   return result;
675 }
676
677 bool CreateGlobalAppSymlinksForUser(const std::string& pkgid, uid_t uid) {
678   bf::path src_dir = bf::path(tzplatform_getenv(TZ_SYS_RW_APP)) / pkgid;
679   if (!bf::exists(src_dir)) {
680     LOG(WARNING) << "src_dir(" << src_dir << ") not exists";
681     return true;
682   }
683
684   tzplatform_set_user(uid);
685   bf::path dst_dir = bf::path(tzplatform_getenv(TZ_USER_APP)) / pkgid;
686   tzplatform_reset_user();
687   if (!bf::exists(dst_dir)) {
688     LOG(WARNING) << "dst_dir not exists";
689     return true;
690   }
691   bool result = CreateSymlinkFiles(src_dir, dst_dir);
692
693   return result;
694 }
695
696 bool DeleteGlobalAppSymlinksForAllUsers(const std::string& pkgid) {
697   bf::path src_dir = bf::path(tzplatform_getenv(TZ_SYS_RW_APP)) / pkgid;
698   if (!bf::exists(src_dir)) {
699     LOG(WARNING) << "src_dir(" << src_dir << ") not exists";
700     return true;
701   }
702
703   bool result = true;
704   UserList list = ci::GetUserList();
705   for (auto l : list) {
706     uid_t uid = std::get<0>(l);
707     LOG(DEBUG) << "Deleting symlinks for uid: " << uid;
708     // check installed user private app.
709     ci::PkgQueryInterface pkg_query(pkgid, uid);
710     if (pkg_query.IsPackageInstalled())
711       continue;
712     bf::path apps_rw(std::get<2>(l) / "apps_rw");
713     bf::path dst_dir = apps_rw / pkgid;
714     if (!bf::exists(dst_dir)) {
715       LOG(WARNING) << "dst_dir not exists";
716       continue;
717     }
718     result = DeleteSymlinkFiles(src_dir, dst_dir);
719   }
720   return result;
721 }
722
723 bool DeleteGlobalAppSymlinksForUser(const std::string& pkgid, uid_t uid) {
724   bf::path src_dir = bf::path(tzplatform_getenv(TZ_SYS_RW_APP)) / pkgid;
725   if (!bf::exists(src_dir)) {
726     LOG(ERROR) << "src_dir not exists";
727     return false;
728   }
729
730   tzplatform_set_user(uid);
731   bf::path dst_dir = bf::path(tzplatform_getenv(TZ_USER_APP)) / pkgid;
732   tzplatform_reset_user();
733   if (!bf::exists(dst_dir)) {
734     LOG(WARNING) << "dst_dir not exists";
735     return true;
736   }
737   bool result = DeleteSymlinkFiles(src_dir, dst_dir);
738   return result;
739 }
740
741 bool SetPackageDirectoryOwnerAndPermissions(const bf::path& path, uid_t uid) {
742   return ::SetPackageDirectoryOwnerAndPermissions(path, uid);
743 }
744
745 bool ShouldSupportLegacySharedDataDir(const std::string& api_version) {
746   if (bf::exists(kDisableLegacySharedDataDirSupport))
747     return false;
748   utils::VersionNumber api_ver(api_version);
749   if (api_ver < ver30)
750     return true;
751   else
752     return false;
753 }
754
755 bool CreateSharedDataDir(const std::string& pkgid, uid_t uid) {
756   bf::path apps_rw = ci::GetRootAppPath(false, uid);
757   if (!CreateSharedDataDirectories(apps_rw, pkgid))
758     return false;
759
760   bf::path path = apps_rw / pkgid;
761   std::string error_message;
762   if (!ci::RegisterSecurityContextForPath(pkgid, path, uid, false,
763           &error_message)) {
764     LOG(ERROR) << "Failed to register security context for path: " << path
765                << ", error_message: " << error_message;
766     return false;
767   }
768
769   return true;
770 }
771
772 bool CreatePerUserSharedDataDir(const std::string& pkgid) {
773   // create skel dir
774   bf::path skel_apps_rw = bf::path(tzplatform_getenv(TZ_SYS_ETC)) /
775       bf::path(kSkelAppDir);
776   LOG(DEBUG) <<  "Creating directory : " << skel_apps_rw;
777   if (!CreateSharedDataDirectories(skel_apps_rw, pkgid))
778     return false;
779
780   std::string error_message;
781   if (!ci::RegisterSecurityContextForPath(pkgid, skel_apps_rw / pkgid,
782           kGlobalUserUid, false, &error_message)) {
783     LOG(ERROR) << "Failed to register security context for path: "
784                << skel_apps_rw / pkgid << ", error_message: " << error_message;
785     return false;
786   }
787
788   // create per user dir
789   ci::UserList list = ci::GetUserList();
790   for (auto l : list) {
791     uid_t uid = std::get<0>(l);
792     LOG(DEBUG) << "Adding shareddata directory for uid: " << uid;
793
794     bf::path apps_rw = ci::GetRootAppPath(false, uid);
795     if (!CreateSharedDataDirectories(apps_rw, pkgid))
796       return false;
797
798     std::vector<std::string> shared_dirs(kSharedDataEntries);
799     for (auto entry : shared_dirs) {
800       bf::path shared_dst = apps_rw / entry / pkgid;
801       if (!::SetPackageDirectoryOwnerAndPermissions(shared_dst, uid))
802         return false;
803     }
804
805     std::string error_message;
806     if (!ci::RegisterSecurityContextForPath(pkgid, apps_rw / pkgid, uid,
807         false, &error_message)) {
808       LOG(ERROR) << "Failed to register security context for path: "
809                  << apps_rw / pkgid << ", error_message: " << error_message;
810       return false;
811     }
812   }
813
814   return true;
815 }
816
817 bool DeleteSharedDataDir(const std::string& pkgid, uid_t uid) {
818   bf::path apps_rw = ci::GetRootAppPath(false, uid);
819   return DeleteSharedDataDirectories(apps_rw, pkgid);
820 }
821
822 bool DeletePerUserSharedDataDir(const std::string& pkgid) {
823   bf::path skel_apps_rw = bf::path(tzplatform_getenv(TZ_SYS_ETC)) /
824       bf::path(kSkelAppDir);
825   if (!DeleteSharedDataDirectories(skel_apps_rw, pkgid))
826     return false;
827
828   ci::UserList list = ci::GetUserList();
829   for (auto l : list) {
830     uid_t uid = std::get<0>(l);
831     bf::path apps_rw = ci::GetRootAppPath(false, uid);
832     if (!DeleteSharedDataDirectories(apps_rw, pkgid))
833       return false;
834   }
835
836   return true;
837 }
838
839 bool BackupSharedDataDir(const std::string& pkgid, uid_t uid) {
840   bf::path apps_rw = ci::GetRootAppPath(false, uid);
841   return BackupSharedDataDirectories(apps_rw, pkgid);
842 }
843
844 bool BackupPerUserSharedDataDir(const std::string& pkgid) {
845   bf::path skel_apps_rw = bf::path(tzplatform_getenv(TZ_SYS_ETC)) /
846       bf::path(kSkelAppDir);
847   if (!BackupSharedDataDirectories(skel_apps_rw, pkgid))
848     return false;
849
850   ci::UserList list = ci::GetUserList();
851   for (auto l : list) {
852     uid_t uid = std::get<0>(l);
853     if (!BackupSharedDataDir(pkgid, uid))
854       return false;
855   }
856
857   return true;
858 }
859
860 bool RestoreSharedDataDir(const std::string& pkgid, uid_t uid) {
861   bf::path apps_rw = ci::GetRootAppPath(false, uid);
862   return RestoreSharedDataDirectories(apps_rw, pkgid);
863 }
864
865 bool RestorePerUserSharedDataDir(const std::string& pkgid) {
866   bf::path skel_apps_rw = bf::path(tzplatform_getenv(TZ_SYS_ETC)) /
867       bf::path(kSkelAppDir);
868   if (!RestoreSharedDataDirectories(skel_apps_rw, pkgid))
869     return false;
870
871   ci::UserList list = ci::GetUserList();
872   for (auto l : list) {
873     uid_t uid = std::get<0>(l);
874     if (!RestoreSharedDataDir(pkgid, uid))
875       return false;
876   }
877
878   return true;
879 }
880
881 bool RemoveBackupSharedDataDir(const std::string& pkgid, uid_t uid) {
882   bf::path apps_rw = ci::GetRootAppPath(false, uid);
883   return RemoveBackupSharedDataDirectories(apps_rw, pkgid);
884 }
885
886 bool RemoveBackupPerUserSharedDataDir(const std::string& pkgid) {
887   bf::path skel_apps_rw = bf::path(tzplatform_getenv(TZ_SYS_ETC)) /
888       bf::path(kSkelAppDir);
889   if (!RemoveBackupSharedDataDirectories(skel_apps_rw, pkgid))
890     return false;
891
892   ci::UserList list = ci::GetUserList();
893   for (auto l : list) {
894     uid_t uid = std::get<0>(l);
895     if (!RemoveBackupSharedDataDir(pkgid, uid))
896       return false;
897   }
898
899   return true;
900 }
901
902 }  // namespace common_installer