4f3d25b023aa45d05682d938e36156c0f9b82806
[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/utils/paths.h"
38 #include "common/security_registration.h"
39 #include "common/utils/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 =
96       bf::owner_read | bf::owner_write | bf::group_read | bf::others_read;
97   bf::perms perms_setgid = perms755 | bf::set_gid_on_exe;
98   boost::optional<gid_t> system_share =
99     ci::GetGidByGroupName(kSystemShareGroupName);
100   // root path
101   if (!ci::SetDirOwnershipAndPermissions(path, perms755, uid, *gid))
102     return false;
103
104   for (bf::recursive_directory_iterator iter(path);
105       iter != bf::recursive_directory_iterator(); ++iter) {
106     if (bf::is_symlink(symlink_status(iter->path()))) {
107       // skip symlink path
108       continue;
109     } else if (bf::is_directory(iter->path()) && iter.level() == 0 &&
110         (iter->path().filename() == ".mmc" ||
111             iter->path().filename() == ".pkg" ||
112             iter->path().filename() == "tep")) {
113       // skip path which is related to mount or directory installer creates
114       continue;
115     } else if (bf::is_directory(iter->path())) {
116       bool is_rw = false;
117       if (iter.level() == 0 &&
118               (iter->path().filename() == kData ||
119                iter->path().filename() == kCache))
120         is_rw = true;
121       if (!ci::SetDirOwnershipAndPermissions(
122               iter->path(), is_rw ? perms_setgid : perms755, uid,
123               is_rw ? *system_share : *gid))
124         return false;
125     } else {
126       bool is_bin = false;
127       if (iter.level() == 1 && iter->path().parent_path().filename() == "bin")
128         is_bin = true;
129       if (!ci::SetDirOwnershipAndPermissions(
130               iter->path(), is_bin ? perms755 : perms644, uid, *gid))
131         return false;
132     }
133   }
134   return true;
135 }
136
137 bf::path GetDirectoryPathForStorage(uid_t user, std::string apps_prefix) {
138   std::string username = ci::GetUsernameByUid(user);
139   if (username.empty())
140     return {};
141
142   bf::path apps_rw;
143   apps_rw = bf::path(apps_prefix.c_str()) / username / "apps_rw";
144   return apps_rw;
145 }
146
147 bool DeleteSharedDataDirectories(const bf::path& path,
148                                  const std::string& pkgid) {
149   if (!ci::RemoveAll(path / pkgid / kSharedDataDir))
150     return false;
151
152   std::vector<std::string> shared_dirs(kSharedDataEntries);
153   for (auto entry : shared_dirs) {
154     if (!ci::RemoveAll(path / entry / pkgid))
155       return false;
156   }
157
158   return true;
159 }
160
161 bool CreateSharedDataDirectories(const bf::path& path,
162                                  const std::string& pkgid) {
163   if (!ci::CreateDir(path / kSharedDir / pkgid / kData) ||
164       !ci::CreateDir(path / kSharedTmpDir / pkgid))
165     return false;
166
167   bf::current_path(path / pkgid / kShared);
168   if (bf::exists(path / pkgid / kShared / kData))
169     return true;
170   bf::path relative_path = ci::RelativePath(path / kSharedDir / pkgid / kData,
171                                             bf::current_path() / kData);
172   bs::error_code error;
173   bf::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 bf::path& app_dir, const std::string& pkgid) {
183   bf::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 bf::path& src_dir, const bf::path& dst_dir) {
192   std::vector<std::string> rofiles(kReadOnlyEntries);
193   for (bf::directory_iterator file(src_dir);
194       file != bf::directory_iterator();
195       ++file) {
196     if (bf::is_regular_file(file->path())) {
197       bf::path current(file->path());
198       bf::path file_name = current.filename();
199       LOG(DEBUG) << "file_name: " << file_name;
200       rofiles.push_back(file_name.string());
201     }
202   }
203
204   bs::error_code error;
205   for (auto& entry : rofiles) {
206     bf::path src_path = src_dir / entry;
207     bf::path dst_path = dst_dir / entry;
208     if (!bf::exists(src_path)) {
209       // check if symlink for .mmc/bin,lib,res, then do not skip
210       if (!bf::is_symlink(symlink_status(src_path))) {
211         LOG(INFO) << "src_path not exist : " << src_path;
212         continue;
213       }
214     }
215     if (bf::exists(dst_path) || bf::is_symlink(symlink_status(dst_path))) {
216       LOG(WARNING) << "dst_path exist, skip : " << dst_path;
217       continue;
218     }
219     bf::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 bf::path& src_dir, const bf::path& dst_dir) {
231   bs::error_code error;
232   for (bf::directory_iterator file(dst_dir);
233       file != bf::directory_iterator();
234       ++file) {
235     bf::path current(file->path());
236     if (!bf::is_symlink(symlink_status(current)))
237       continue;
238     bf::path resolved_path = bf::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     bf::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     bf::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   bf::path shared_res = dst_dir / kSharedResDir;
261   if (bf::is_symlink(symlink_status(shared_res))) {
262       bf::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 boost::filesystem::path& root_path,
273                               const std::string& pkgid,
274                               bool trusted, bool shareddata,
275                               const std::vector<const char*> additional_dirs) {
276   bf::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   bs::error_code error;
288   for (auto& entry : dirs) {
289     bf::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   bf::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 bf::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 bf::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 bf::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   boost::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   bf::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   bf::path storage_path = GetExternalCardPath();
394
395   if (!bf::exists(storage_path)) {
396     LOG(WARNING) << "External storage (SD Card) is not mounted.";
397     return false;
398   }
399
400   bf::path storage_apps_path = storage_path / "apps";
401   if (!bf::exists(storage_apps_path)) {
402     bs::error_code error;
403     bf::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   return true;
415 }
416
417 bool PerformExternalDirectoryDeletionForUser(uid_t user,
418                                              const std::string& pkgid) {
419   bf::path storage_path = GetExternalCardPath();
420   if (!bf::exists(storage_path)) {
421     LOG(WARNING) << "External storage (SD Card) is not mounted. "
422         << "It will be ignored";
423     return true;
424   }
425
426   bf::path storage_apps_path = bf::path(storage_path) / "apps";
427   return DeleteDirectories(
428       GetDirectoryPathForStorage(user, storage_apps_path.string()), pkgid);
429 }
430
431 bool PerformExternalDirectoryCreationForAllUsers(const std::string& pkgid) {
432   UserList list = ci::GetUserList();
433   for (auto l : list) {
434     if (!PerformExternalDirectoryCreationForUser(std::get<0>(l),
435                                                  pkgid))
436       LOG(WARNING) << "Could not create external storage directories for user: "
437                    << std::get<0>(l);
438   }
439   return true;
440 }
441
442 bool PerformExternalDirectoryCreationForAllPkgs() {
443   UserList list = ci::GetUserList();
444   for (auto l  : list) {
445     uid_t uid = std::get<0>(l);
446     pkgmgrinfo_pkginfo_filter_h filter_handle = nullptr;
447     int ret = pkgmgrinfo_pkginfo_filter_create(&filter_handle);
448     if (ret != PMINFO_R_OK)
449       return false;
450     ret = pkgmgrinfo_pkginfo_filter_add_string(filter_handle,
451         PMINFO_PKGINFO_PROP_PACKAGE_PRIVILEGE, kExternalStoragePrivilege);
452     if (ret != PMINFO_R_OK) {
453       pkgmgrinfo_pkginfo_filter_destroy(filter_handle);
454       return false;
455     }
456
457     ret = pkgmgrinfo_pkginfo_filter_foreach_pkginfo(filter_handle,
458         [](const pkgmgrinfo_pkginfo_h handle, void* user_data) -> int {
459           uid_t uid =
460               static_cast<uid_t>(reinterpret_cast<uintptr_t>(user_data));
461           char* pkgid = nullptr;
462
463           int ret = pkgmgrinfo_pkginfo_get_pkgid(handle, &pkgid);
464           if (ret != PMINFO_R_OK)
465             return -1;
466           if (!PerformExternalDirectoryCreationForUser(uid, pkgid))
467             return -1;
468
469           return 0;
470         },
471         reinterpret_cast<void*>(static_cast<uintptr_t>(uid)));
472     if (ret != PMINFO_R_OK) {
473       LOG(DEBUG) << "Failed to create external directoy";
474       pkgmgrinfo_pkginfo_filter_destroy(filter_handle);
475       return false;
476     }
477     pkgmgrinfo_pkginfo_filter_destroy(filter_handle);
478   }
479
480   return true;
481 }
482
483 bool PerformExternalDirectoryDeletionForAllUsers(const std::string& pkgid) {
484   UserList list = ci::GetUserList();
485   for (auto l : list) {
486     uid_t uid = std::get<0>(l);
487     ci::PkgQueryInterface pkg_query(pkgid, uid);
488     LOG(DEBUG) << "Deleting directories for user: " << uid;
489     if (pkg_query.IsPackageInstalled()) {
490       LOG(DEBUG) << "Package: " << pkgid << " for uid: " << uid
491                  << " still exists. Skipping";
492       continue;
493     }
494
495     if (!PerformExternalDirectoryDeletionForUser(uid, pkgid))
496       LOG(WARNING) << "Could not delete external storage directories for user: "
497                    << uid;
498   }
499   return true;
500 }
501
502 bool CreatePerUserStorageDirectories(const std::string& pkgid, bool trusted,
503     bool shareddata, bool is_readonly,
504     const std::vector<const char*> additional_dirs) {
505   // create skel dir
506   bf::path skel_apps_rw = bf::path(tzplatform_getenv(TZ_SYS_ETC)) /
507       bf::path(kSkelAppDir);
508   if (!::CreateStorageDirectories(skel_apps_rw, pkgid, trusted, shareddata,
509           additional_dirs)) {
510     LOG(ERROR) << "Failed to create skeleton storage directories";
511     return false;
512   }
513
514   std::string error_message;
515   if (!RegisterSecurityContextForPath(pkgid, skel_apps_rw / pkgid,
516           kGlobalUserUid, is_readonly, &error_message)) {
517     LOG(ERROR) << "Failed to register security context for path: "
518                << skel_apps_rw / pkgid << ", error_message: " << error_message;
519     return false;
520   }
521
522   // create per user dir
523   UserList list = ci::GetUserList();
524   for (auto l : list) {
525     uid_t uid = std::get<0>(l);
526     bf::path apps_rw = std::get<2>(l) / "apps_rw";
527     LOG(DEBUG) << "Creating directories for user: " << uid;
528     if (!::CreateStorageDirectories(apps_rw, pkgid, trusted, shareddata,
529          additional_dirs)) {
530       LOG(ERROR) << "Failed to create storage directory for user: " << uid;
531       return false;
532     }
533
534     if (!::SetPackageDirectoryOwnerAndPermissions(apps_rw / pkgid, uid))
535       return false;
536
537     if (shareddata) {
538       std::vector<std::string> shared_dirs(kSharedDataEntries);
539       for (auto entry : shared_dirs) {
540         bf::path shared_dst = apps_rw / entry / pkgid;
541         if (!::SetPackageDirectoryOwnerAndPermissions(shared_dst, uid))
542           return false;
543       }
544     }
545
546     if (!RegisterSecurityContextForPath(pkgid, apps_rw / pkgid, uid,
547             false, &error_message)) {
548       LOG(ERROR) << "Failed to register security context for path: "
549                  << apps_rw / pkgid << ", error_message: " << error_message;
550       return false;
551     }
552   }
553
554   return true;
555 }
556
557 bool DeletePerUserStorageDirectories(const std::string& pkgid,
558     bool keep_rwdata) {
559   // delete skel dir
560   bf::path skel_apps_rw = bf::path(tzplatform_getenv(TZ_SYS_ETC)) /
561       bf::path(kSkelAppDir);
562   if (!ci::RemoveAll(skel_apps_rw / pkgid)) {
563     LOG(ERROR) << "Failed to delete skeleton storage directories";
564     return false;
565   }
566
567   if (keep_rwdata)
568     return true;
569
570   // delete per user dir
571   UserList list = ci::GetUserList();
572   for (auto l : list) {
573     uid_t uid = std::get<0>(l);
574     bf::path apps_rw = std::get<2>(l) / "apps_rw";
575     LOG(DEBUG) << "Deleting directories for user: " << uid;
576     if (!ci::RemoveAll(apps_rw / pkgid)) {
577       LOG(ERROR) << "Failed to delete storage directory for user: " << uid;
578       return false;
579     }
580
581     if (!ci::DeletePerUserSharedDataDir(pkgid)) {
582       LOG(ERROR) << "Failed to delete per user shared data dir";
583       return false;
584     }
585   }
586
587   return true;
588 }
589
590 bool CreateStorageDirectories(const boost::filesystem::path& path,
591                               const std::string& pkgid, uid_t uid,
592                               bool trusted, bool shareddata) {
593   if (!::CreateStorageDirectories(path, pkgid, trusted,
594                                   shareddata, std::vector<const char*>())) {
595     LOG(ERROR) << "Failed to create storage directory for path: " << path;
596     return false;
597   }
598
599   if (!::SetPackageDirectoryOwnerAndPermissions(path / pkgid, uid))
600     return false;
601
602   if (shareddata) {
603     std::vector<std::string> shared_dirs(kSharedDataEntries);
604     for (auto entry : shared_dirs) {
605       bf::path shared_dst = path / entry / pkgid;
606       if (!::SetPackageDirectoryOwnerAndPermissions(shared_dst, uid))
607         return false;
608     }
609   }
610
611   std::string error_message;
612   if (!RegisterSecurityContextForPath(pkgid, path / pkgid, uid, false,
613                                       &error_message)) {
614     LOG(ERROR) << "Failed to register security context for path: " << path
615                << ", error_message: " << error_message;
616     return false;
617   }
618
619   return true;
620 }
621
622 void RemoveRWDirectories(const boost::filesystem::path& root) {
623   if (!RemoveAll(root / kCache))
624     LOG(ERROR) << "Failed to remove packaged cache directory";
625   if (!RemoveAll(root / kData))
626     LOG(ERROR) << "Failed to remove packaged data directory";
627   if (!RemoveAll(root / kSharedCacheDir))
628     LOG(ERROR) << "Failed to remove packaged shared/cache directory";
629   if (!RemoveAll(root / kSharedDataDir))
630     LOG(ERROR) << "Failed to remove packaged shared/data directory";
631   if (!RemoveAll(root / kSharedTrustedDir))
632     LOG(ERROR) << "Failed to remove packaged shared/trusted directory";
633 }
634
635 bool DeleteSharedDirectories(const bf::path& path,
636                              const std::string& pkgid) {
637   return DeleteSharedDataDirectories(path, pkgid);
638 }
639
640 bool DeleteUserExternalDirectories(const std::string& pkgid) {
641   UserList list = ci::GetUserList();
642   for (auto l : list) {
643     uid_t uid = std::get<0>(l);
644     ci::PkgQueryInterface pkg_query(pkgid, uid);
645     if (pkg_query.IsPackageInstalled()) {
646       LOG(INFO) << pkgid << " is installed for user " << uid;
647       continue;
648     }
649
650     LOG(DEBUG) << "Deleting external directories of " << pkgid
651                << ", for uid: " << uid;
652     bf::path apps_rw(std::get<2>(l) / "apps_rw");
653     if (!DeleteDirectories(apps_rw, pkgid)) {
654       return false;
655     }
656   }
657   return true;
658 }
659
660 bool CreateGlobalAppSymlinksForAllUsers(const std::string& pkgid) {
661   bf::path src_dir = bf::path(tzplatform_getenv(TZ_SYS_RW_APP)) / pkgid;
662   if (!bf::exists(src_dir)) {
663     LOG(ERROR) << "src_dir not exists";
664     return false;
665   }
666
667   bool result = true;
668   UserList list = ci::GetUserList();
669   for (auto l : list) {
670     uid_t uid = std::get<0>(l);
671     LOG(DEBUG) << "Creating symlinks for uid: " << uid;
672     // check installed user private app.
673     ci::PkgQueryInterface pkg_query(pkgid, uid);
674     if (pkg_query.IsPackageInstalled())
675       continue;
676     bf::path apps_rw(std::get<2>(l) / "apps_rw");
677     bf::path dst_dir = apps_rw / pkgid;
678     if (!bf::exists(dst_dir)) {
679       LOG(WARNING) << "dst_dir not exists";
680       continue;
681     }
682     result = CreateSymlinkFiles(src_dir, dst_dir);
683   }
684   return result;
685 }
686
687 bool CreateGlobalAppSymlinksForUser(const std::string& pkgid, uid_t uid) {
688   bf::path src_dir = bf::path(tzplatform_getenv(TZ_SYS_RW_APP)) / pkgid;
689   if (!bf::exists(src_dir)) {
690     LOG(WARNING) << "src_dir(" << src_dir << ") not exists";
691     return true;
692   }
693
694   tzplatform_set_user(uid);
695   bf::path dst_dir = bf::path(tzplatform_getenv(TZ_USER_APP)) / pkgid;
696   tzplatform_reset_user();
697   if (!bf::exists(dst_dir)) {
698     LOG(WARNING) << "dst_dir not exists";
699     return true;
700   }
701   bool result = CreateSymlinkFiles(src_dir, dst_dir);
702
703   return result;
704 }
705
706 bool DeleteGlobalAppSymlinksForAllUsers(const std::string& pkgid) {
707   bf::path src_dir = bf::path(tzplatform_getenv(TZ_SYS_RW_APP)) / pkgid;
708   if (!bf::exists(src_dir)) {
709     LOG(WARNING) << "src_dir(" << src_dir << ") not exists";
710     return true;
711   }
712
713   bool result = true;
714   UserList list = ci::GetUserList();
715   for (auto l : list) {
716     uid_t uid = std::get<0>(l);
717     LOG(DEBUG) << "Deleting symlinks for uid: " << uid;
718     // check installed user private app.
719     ci::PkgQueryInterface pkg_query(pkgid, uid);
720     if (pkg_query.IsPackageInstalled())
721       continue;
722     bf::path apps_rw(std::get<2>(l) / "apps_rw");
723     bf::path dst_dir = apps_rw / pkgid;
724     if (!bf::exists(dst_dir)) {
725       LOG(WARNING) << "dst_dir not exists";
726       continue;
727     }
728     result = DeleteSymlinkFiles(src_dir, dst_dir);
729   }
730   return result;
731 }
732
733 bool DeleteGlobalAppSymlinksForUser(const std::string& pkgid, uid_t uid) {
734   bf::path src_dir = bf::path(tzplatform_getenv(TZ_SYS_RW_APP)) / pkgid;
735   if (!bf::exists(src_dir)) {
736     LOG(ERROR) << "src_dir not exists";
737     return false;
738   }
739
740   tzplatform_set_user(uid);
741   bf::path dst_dir = bf::path(tzplatform_getenv(TZ_USER_APP)) / pkgid;
742   tzplatform_reset_user();
743   if (!bf::exists(dst_dir)) {
744     LOG(WARNING) << "dst_dir not exists";
745     return true;
746   }
747   bool result = DeleteSymlinkFiles(src_dir, dst_dir);
748   return result;
749 }
750
751 bool SetPackageDirectoryOwnerAndPermissions(const bf::path& path, uid_t uid) {
752   return ::SetPackageDirectoryOwnerAndPermissions(path, uid);
753 }
754
755 bool ShouldSupportLegacySharedDataDir(const std::string& api_version) {
756   if (bf::exists(kDisableLegacySharedDataDirSupport))
757     return false;
758   utils::VersionNumber api_ver(api_version);
759   if (api_ver < ver30)
760     return true;
761   else
762     return false;
763 }
764
765 bool CreateSharedDataDir(const std::string& pkgid, uid_t uid) {
766   bf::path apps_rw = ci::GetRootAppPath(false, uid);
767   if (!CreateSharedDataDirectories(apps_rw, pkgid))
768     return false;
769
770   bf::path path = apps_rw / pkgid;
771   std::string error_message;
772   if (!ci::RegisterSecurityContextForPath(pkgid, path, uid, false,
773           &error_message)) {
774     LOG(ERROR) << "Failed to register security context for path: " << path
775                << ", error_message: " << error_message;
776     return false;
777   }
778
779   return true;
780 }
781
782 bool CreatePerUserSharedDataDir(const std::string& pkgid) {
783   // create skel dir
784   bf::path skel_apps_rw = bf::path(tzplatform_getenv(TZ_SYS_ETC)) /
785       bf::path(kSkelAppDir);
786   LOG(DEBUG) <<  "Creating directory : " << skel_apps_rw;
787   if (!CreateSharedDataDirectories(skel_apps_rw, pkgid))
788     return false;
789
790   std::string error_message;
791   if (!ci::RegisterSecurityContextForPath(pkgid, skel_apps_rw / pkgid,
792           kGlobalUserUid, false, &error_message)) {
793     LOG(ERROR) << "Failed to register security context for path: "
794                << skel_apps_rw / pkgid << ", error_message: " << error_message;
795     return false;
796   }
797
798   // create per user dir
799   ci::UserList list = ci::GetUserList();
800   for (auto l : list) {
801     uid_t uid = std::get<0>(l);
802     LOG(DEBUG) << "Adding shareddata directory for uid: " << uid;
803
804     bf::path apps_rw = ci::GetRootAppPath(false, uid);
805     if (!CreateSharedDataDirectories(apps_rw, pkgid))
806       return false;
807
808     std::vector<std::string> shared_dirs(kSharedDataEntries);
809     for (auto entry : shared_dirs) {
810       bf::path shared_dst = apps_rw / entry / pkgid;
811       if (!::SetPackageDirectoryOwnerAndPermissions(shared_dst, uid))
812         return false;
813     }
814
815     std::string error_message;
816     if (!ci::RegisterSecurityContextForPath(pkgid, apps_rw / pkgid, uid,
817         false, &error_message)) {
818       LOG(ERROR) << "Failed to register security context for path: "
819                  << apps_rw / pkgid << ", error_message: " << error_message;
820       return false;
821     }
822   }
823
824   return true;
825 }
826
827 bool DeleteSharedDataDir(const std::string& pkgid, uid_t uid) {
828   bf::path apps_rw = ci::GetRootAppPath(false, uid);
829   return DeleteSharedDataDirectories(apps_rw, pkgid);
830 }
831
832 bool DeletePerUserSharedDataDir(const std::string& pkgid) {
833   bf::path skel_apps_rw = bf::path(tzplatform_getenv(TZ_SYS_ETC)) /
834       bf::path(kSkelAppDir);
835   if (!DeleteSharedDataDirectories(skel_apps_rw, pkgid))
836     return false;
837
838   ci::UserList list = ci::GetUserList();
839   for (auto l : list) {
840     uid_t uid = std::get<0>(l);
841     bf::path apps_rw = ci::GetRootAppPath(false, uid);
842     if (!DeleteSharedDataDirectories(apps_rw, pkgid))
843       return false;
844   }
845
846   return true;
847 }
848
849 bool BackupSharedDataDir(const std::string& pkgid, uid_t uid) {
850   bf::path apps_rw = ci::GetRootAppPath(false, uid);
851   return BackupSharedDataDirectories(apps_rw, pkgid);
852 }
853
854 bool BackupPerUserSharedDataDir(const std::string& pkgid) {
855   bf::path skel_apps_rw = bf::path(tzplatform_getenv(TZ_SYS_ETC)) /
856       bf::path(kSkelAppDir);
857   if (!BackupSharedDataDirectories(skel_apps_rw, pkgid))
858     return false;
859
860   ci::UserList list = ci::GetUserList();
861   for (auto l : list) {
862     uid_t uid = std::get<0>(l);
863     if (!BackupSharedDataDir(pkgid, uid))
864       return false;
865   }
866
867   return true;
868 }
869
870 bool RestoreSharedDataDir(const std::string& pkgid, uid_t uid) {
871   bf::path apps_rw = ci::GetRootAppPath(false, uid);
872   return RestoreSharedDataDirectories(apps_rw, pkgid);
873 }
874
875 bool RestorePerUserSharedDataDir(const std::string& pkgid) {
876   bf::path skel_apps_rw = bf::path(tzplatform_getenv(TZ_SYS_ETC)) /
877       bf::path(kSkelAppDir);
878   if (!RestoreSharedDataDirectories(skel_apps_rw, pkgid))
879     return false;
880
881   ci::UserList list = ci::GetUserList();
882   for (auto l : list) {
883     uid_t uid = std::get<0>(l);
884     if (!RestoreSharedDataDir(pkgid, uid))
885       return false;
886   }
887
888   return true;
889 }
890
891 bool RemoveBackupSharedDataDir(const std::string& pkgid, uid_t uid) {
892   bf::path apps_rw = ci::GetRootAppPath(false, uid);
893   return RemoveBackupSharedDataDirectories(apps_rw, pkgid);
894 }
895
896 bool RemoveBackupPerUserSharedDataDir(const std::string& pkgid) {
897   bf::path skel_apps_rw = bf::path(tzplatform_getenv(TZ_SYS_ETC)) /
898       bf::path(kSkelAppDir);
899   if (!RemoveBackupSharedDataDirectories(skel_apps_rw, pkgid))
900     return false;
901
902   ci::UserList list = ci::GetUserList();
903   for (auto l : list) {
904     uid_t uid = std::get<0>(l);
905     if (!RemoveBackupSharedDataDir(pkgid, uid))
906       return false;
907   }
908
909   return true;
910 }
911
912 }  // namespace common_installer