Fix install failure of user package
[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 kSharedDir[] = ".shared";
79 const char kSharedTmpDir[] = ".shared_tmp";
80 const char kSharedTrustedDir[] = "shared/trusted";
81 const char kSkelAppDir[] = "skel/apps_rw";
82 const char kExternalStoragePrivilege[] =
83     "http://tizen.org/privilege/externalstorage.appdata";
84 const char kSystemShareGroupName[] = "system_share";
85
86 bool SetDirectoryOwnerAndPermissions(const bf::path& subpath, uid_t uid,
87                                      gid_t gid) {
88   // symlink and non directory will be skipped
89   if (bf::is_symlink(symlink_status(subpath)) || !bf::is_directory(subpath))
90     return true;
91
92   bf::perms perms = bf::all_all ^ bf::group_write ^ bf::others_write;
93   if (subpath.filename() == "data" || subpath.filename() == "cache") {
94     perms |= bf::group_write | bf::set_gid_on_exe;
95     boost::optional<gid_t> system_share =
96         ci::GetGidByGroupName(kSystemShareGroupName);
97     if (!system_share)
98       return false;
99     gid = *system_share;
100   }
101   return common_installer::SetDirOwnershipAndPermissions(subpath, perms,
102                                                          uid, gid);
103 }
104
105 bool SetSharedDirOwnerAndPermissions(const bf::path& subpath, uid_t uid) {
106   if (!bf::is_directory(subpath) || subpath.filename() != "data")
107     return true;
108   bf::perms perms = (bf::all_all | bf::set_uid_on_exe) ^ bf::others_write;
109   boost::optional<gid_t> system_share =
110     ci::GetGidByGroupName(kSystemShareGroupName);
111   if (!system_share)
112     return false;
113   gid_t gid = *system_share;
114
115   return common_installer::SetDirOwnershipAndPermissions(subpath, perms,
116       uid, gid);
117 }
118
119 bool CreateDirectories(const bf::path& app_dir, const std::string& pkgid,
120                        uid_t uid, gid_t gid, const bool set_permissions,
121                        const std::vector<const char*>
122                        additional_dirs = std::vector<const char*>()) {
123   bf::path base_dir = app_dir / pkgid;
124   if (bf::exists(base_dir)) {
125     LOG(DEBUG) << "Directory for user already exist: " << base_dir;
126     return true;
127   } else {
128     bs::error_code error;
129     bf::create_directories(base_dir, error);
130     if (error) {
131       LOG(ERROR) << "Failed to create directory: " << base_dir;
132       return false;
133     }
134   }
135
136   bs::error_code error;
137   std::vector<const char*> dirs(kEntries);
138   dirs.insert(dirs.end(), additional_dirs.begin(), additional_dirs.end());
139   // always trusted
140   dirs.push_back(kSharedTrustedDir);
141   for (auto& entry : dirs) {
142     bf::path subpath = base_dir / entry;
143     bf::create_directories(subpath, error);
144     if (error) {
145       LOG(ERROR) << "Failed to create directory: " << subpath;
146       return false;
147     }
148
149     if (set_permissions) {
150       if (!SetDirectoryOwnerAndPermissions(subpath, uid, gid))
151         return false;
152
153       // for content
154       for (bf::recursive_directory_iterator iter(subpath);
155            iter != bf::recursive_directory_iterator(); ++iter) {
156         if (!SetDirectoryOwnerAndPermissions(iter->path(), uid, gid))
157           return false;
158       }
159     }
160   }
161
162   return true;
163 }
164
165 bf::path GetDirectoryPathForStorage(uid_t user, std::string apps_prefix) {
166   std::string username = ci::GetUsernameByUid(user);
167   if (username.empty())
168     return {};
169
170   bf::path apps_rw;
171   apps_rw = bf::path(apps_prefix.c_str()) / username / "apps_rw";
172   return apps_rw;
173 }
174
175 bool CreateUserDirectories(uid_t user, const std::string& pkgid,
176     const std::string& apps_prefix, const bool set_permissions) {
177   boost::optional<gid_t> gid = ci::GetGidByUid(user);
178   if (!gid)
179     return false;
180
181   std::string group_name = ci::GetGroupNameByGid(*gid);
182   if (group_name != tzplatform_getenv(TZ_SYS_USER_GROUP))
183     return false;
184
185   LOG(DEBUG) << "Creating directories for uid: " << user << ", gid: "
186              << *gid;
187
188   bf::path apps_rw = GetDirectoryPathForStorage(user, apps_prefix);
189   if (apps_rw.empty()) {
190     LOG(DEBUG) << "Directory not exists: " << apps_rw;
191     return false;
192   }
193
194   if (!CreateDirectories(apps_rw, pkgid,
195      user, *gid, set_permissions)) {
196     return false;
197   }
198   return true;
199 }
200
201 bool DeleteSharedDataDirectories(const bf::path& path,
202                                  const std::string& pkgid) {
203   if (!ci::RemoveAll(path / pkgid / kSharedDataDir))
204     return false;
205
206   std::vector<std::string> shared_dirs(kSharedDataEntries);
207   for (auto entry : shared_dirs) {
208     if (!ci::RemoveAll(path / entry / pkgid))
209       return false;
210   }
211
212   return true;
213 }
214
215 bool CreateSharedDataDirectories(const bf::path& path,
216                                  const std::string& pkgid) {
217   if (!ci::CreateDir(path / kSharedDir / pkgid / kData) ||
218       !ci::CreateDir(path / kSharedTmpDir / pkgid))
219     return false;
220
221   bf::current_path(path / pkgid / kShared);
222   if (bf::exists(path / pkgid / kShared / kData))
223     return true;
224   bf::path relative_path = ci::RelativePath(path / kSharedDir / pkgid / kData,
225                                             bf::current_path() / kData);
226   bs::error_code error;
227   bf::create_symlink(relative_path, kData, error);
228   if (error) {
229     LOG(ERROR) << "Failed to create symlink : " << error.message();
230     return false;
231   }
232
233   return true;
234 }
235
236 bool DeleteDirectories(const bf::path& app_dir, const std::string& pkgid) {
237   bf::path base_dir = app_dir / pkgid;
238   if (!ci::RemoveAll(base_dir))
239     return false;
240   if (!DeleteSharedDataDirectories(app_dir, pkgid))
241     return false;
242   return true;
243 }
244
245 bool CreateSymlinkFiles(const bf::path& src_dir, const bf::path& dst_dir) {
246   std::vector<std::string> rofiles(kReadOnlyEntries);
247   for (bf::directory_iterator file(src_dir);
248       file != bf::directory_iterator();
249       ++file) {
250     if (bf::is_regular_file(file->path())) {
251       bf::path current(file->path());
252       bf::path file_name = current.filename();
253       LOG(DEBUG) << "file_name: " << file_name;
254       rofiles.push_back(file_name.string());
255     }
256   }
257
258   bs::error_code error;
259   for (auto& entry : rofiles) {
260     bf::path src_path = src_dir / entry;
261     bf::path dst_path = dst_dir / entry;
262     if (!bf::exists(src_path)) {
263       // check if symlink for .mmc/bin,lib,res, then do not skip
264       if (!bf::is_symlink(symlink_status(src_path))) {
265         LOG(INFO) << "src_path not exist : " << src_path;
266         continue;
267       }
268     }
269     if (bf::exists(dst_path) || bf::is_symlink(symlink_status(dst_path))) {
270       LOG(WARNING) << "dst_path exist, skip : " << dst_path;
271       continue;
272     }
273     bf::create_symlink(src_path, dst_path, error);
274     if (error) {
275       LOG(ERROR) << "Symlink creation failure src_path: " << src_path
276                  << " dst_path: " << dst_path;
277       LOG(ERROR) << "error: " << error.message();
278       return false;
279     }
280   }
281   return true;
282 }
283
284 bool DeleteSymlinkFiles(const bf::path& src_dir, const bf::path& dst_dir) {
285   bs::error_code error;
286   for (bf::directory_iterator file(dst_dir);
287       file != bf::directory_iterator();
288       ++file) {
289     bf::path current(file->path());
290     if (!bf::is_symlink(symlink_status(current)))
291       continue;
292     bf::path resolved_path = bf::read_symlink(current, error);
293     if (error) {
294       LOG(ERROR) << "Failed to get resolved path of symlink: " << current
295                  << ", error: " << error.message();
296       return false;
297     }
298
299     LOG(DEBUG) << "resolved_path: " << resolved_path;
300     bf::path parent = resolved_path.parent_path();
301     if (parent.empty() || (parent != src_dir)) {
302       LOG(WARNING) << "Parent is empty or not equal to src, parent: ("
303                    << parent << ")";
304       continue;
305     }
306     bf::remove(current, error);
307     if (error) {
308       LOG(ERROR) << "Symlink deletion failure for: " << current
309                   << ", error: " << error.message();
310       return false;
311     }
312     LOG(DEBUG) << "removed: " << current;
313   }
314   bf::path shared_res = dst_dir / kSharedResDir;
315   if (bf::is_symlink(symlink_status(shared_res))) {
316       bf::remove(shared_res, error);
317       if (error) {
318           LOG(ERROR) << "Symlink deletion failure for: " << shared_res
319                      << ", error: " << error.message();
320           return false;
321       }
322   }
323   return true;
324 }
325
326 bool CreateStorageDirectories(const boost::filesystem::path& root_path,
327                               const std::string& pkgid,
328                               bool trusted, bool shareddata,
329                               const std::vector<const char*> additional_dirs) {
330   bf::path path(root_path / pkgid);
331   if (!bf::exists(path)) {
332     LOG(DEBUG) << "Creating directories in: " << path;
333     bs::error_code error;
334     bf::create_directories(path, error);
335     if (error) {
336       LOG(ERROR) << "Failed to create directory: "
337                  << path << ", error: "
338                  << error.message();
339       return false;
340     }
341   }
342
343   std::vector<const char*> dirs(kEntries);
344   dirs.insert(dirs.end(), additional_dirs.begin(), additional_dirs.end());
345   if (trusted)
346     dirs.push_back(kSharedTrustedDir);
347
348   bs::error_code error;
349   for (auto& entry : dirs) {
350     bf::path subpath = path / entry;
351     bf::create_directories(subpath, error);
352     if (error && !bf::exists(subpath)) {
353       LOG(ERROR) << "Failed to create directory: " << subpath;
354       return false;
355     }
356   }
357
358   if (shareddata) {
359     if (!CreateSharedDataDirectories(root_path, pkgid))
360       return false;
361   } else {
362     if (!DeleteSharedDataDirectories(root_path, pkgid))
363       return false;
364   }
365
366   bf::path shared_cache_path = path / kSharedCacheDir;
367   // remove shared/cache (do not support)
368   if (!ci::RemoveAll(shared_cache_path))
369     return false;
370
371   return true;
372 }
373
374 bool BackupSharedDataDirectories(const bf::path& apps_rw,
375     const std::string& pkgid) {
376   if (!ci::MakeBackup(apps_rw / pkgid / kSharedDataDir))
377     return false;
378   if (!ci::MakeBackup(apps_rw / kSharedDir / pkgid / kData))
379     return false;
380   if (!ci::MakeBackup(apps_rw / kSharedTmpDir / pkgid))
381     return false;
382   return true;
383 }
384
385 bool RestoreSharedDataDirectories(const bf::path& apps_rw,
386     const std::string& pkgid) {
387   if (!ci::RestoreBackup(apps_rw / pkgid / kSharedDataDir))
388     return false;
389   if (!ci::RestoreBackup(apps_rw / kSharedDir / pkgid / kData))
390     return false;
391   if (!ci::RestoreBackup(apps_rw / kSharedTmpDir / pkgid))
392     return false;
393   return true;
394 }
395
396 bool RemoveBackupSharedDataDirectories(const bf::path& apps_rw,
397     const std::string& pkgid) {
398   if (!ci::RemoveBackup(apps_rw / pkgid / kSharedDataDir))
399     return false;
400   if (!ci::RemoveBackup(apps_rw / kSharedDir / pkgid / kData))
401     return false;
402   if (!ci::RemoveBackup(apps_rw / kSharedTmpDir / pkgid))
403     return false;
404   return true;
405 }
406
407 }  // namespace
408
409 namespace common_installer {
410
411 std::string GetDirectoryPathForInternalStorage() {
412   const char* internal_storage_prefix = tzplatform_getenv(TZ_SYS_HOME);
413   if (internal_storage_prefix)
414     return std::string(internal_storage_prefix);
415   return tzplatform_getenv(TZ_SYS_HOME);
416 }
417
418 std::string GetDirectoryPathForExternalStorage() {
419   return GetExternalCardPath().string();
420 }
421
422 bool PerformExternalDirectoryCreationForUser(uid_t user,
423                                              const std::string& pkgid) {
424   bf::path storage_path = GetExternalCardPath();
425
426   const bool set_permissions = false;
427   if (!bf::exists(storage_path)) {
428     LOG(WARNING) << "External storage (SD Card) is not mounted.";
429     return false;
430   }
431
432   bf::path storage_apps_path = storage_path / "apps";
433   if (!bf::exists(storage_apps_path)) {
434     bs::error_code error;
435     bf::create_directories(storage_apps_path, error);
436     if (error) {
437       LOG(ERROR) << "Failed to create directory: "
438           << storage_apps_path.c_str();
439       return false;
440     }
441   }
442
443   CreateUserDirectories(user, pkgid,
444                             storage_apps_path.c_str(), set_permissions);
445   return true;
446 }
447
448 bool PerformExternalDirectoryDeletionForUser(uid_t user,
449                                              const std::string& pkgid) {
450   bf::path storage_path = GetExternalCardPath();
451   if (!bf::exists(storage_path)) {
452     LOG(WARNING) << "External storage (SD Card) is not mounted. "
453         << "It will be ignored";
454     return true;
455   }
456
457   bf::path storage_apps_path = bf::path(storage_path) / "apps";
458   return DeleteDirectories(
459       GetDirectoryPathForStorage(user, storage_apps_path.string()), pkgid);
460 }
461
462 bool PerformExternalDirectoryCreationForAllUsers(const std::string& pkgid) {
463   UserList list = ci::GetUserList();
464   for (auto l : list) {
465     if (!PerformExternalDirectoryCreationForUser(std::get<0>(l),
466                                                  pkgid))
467       LOG(WARNING) << "Could not create external storage directories for user: "
468                    << std::get<0>(l);
469   }
470   return true;
471 }
472
473 bool PerformExternalDirectoryCreationForAllPkgs() {
474   UserList list = ci::GetUserList();
475   for (auto l  : list) {
476     uid_t uid = std::get<0>(l);
477     pkgmgrinfo_pkginfo_filter_h filter_handle = nullptr;
478     int ret = pkgmgrinfo_pkginfo_filter_create(&filter_handle);
479     if (ret != PMINFO_R_OK)
480       return false;
481     ret = pkgmgrinfo_pkginfo_filter_add_string(filter_handle,
482         PMINFO_PKGINFO_PROP_PACKAGE_PRIVILEGE, kExternalStoragePrivilege);
483     if (ret != PMINFO_R_OK) {
484       pkgmgrinfo_pkginfo_filter_destroy(filter_handle);
485       return false;
486     }
487
488     ret = pkgmgrinfo_pkginfo_filter_foreach_pkginfo(filter_handle,
489         [](const pkgmgrinfo_pkginfo_h handle, void* user_data) -> int {
490           uid_t uid =
491               static_cast<uid_t>(reinterpret_cast<uintptr_t>(user_data));
492           char* pkgid = nullptr;
493
494           int ret = pkgmgrinfo_pkginfo_get_pkgid(handle, &pkgid);
495           if (ret != PMINFO_R_OK)
496             return -1;
497           if (!PerformExternalDirectoryCreationForUser(uid, pkgid))
498             return -1;
499
500           return 0;
501         },
502         reinterpret_cast<void*>(static_cast<uintptr_t>(uid)));
503     if (ret != PMINFO_R_OK) {
504       LOG(DEBUG) << "Failed to create external directoy";
505       pkgmgrinfo_pkginfo_filter_destroy(filter_handle);
506       return false;
507     }
508     pkgmgrinfo_pkginfo_filter_destroy(filter_handle);
509   }
510
511   return true;
512 }
513
514 bool PerformExternalDirectoryDeletionForAllUsers(const std::string& pkgid) {
515   UserList list = ci::GetUserList();
516   for (auto l : list) {
517     uid_t uid = std::get<0>(l);
518     ci::PkgQueryInterface pkg_query(pkgid, uid);
519     LOG(DEBUG) << "Deleting directories for user: " << uid;
520     if (pkg_query.IsPackageInstalled()) {
521       LOG(DEBUG) << "Package: " << pkgid << " for uid: " << uid
522                  << " still exists. Skipping";
523       continue;
524     }
525
526     if (!PerformExternalDirectoryDeletionForUser(uid, pkgid))
527       LOG(WARNING) << "Could not delete external storage directories for user: "
528                    << uid;
529   }
530   return true;
531 }
532
533 bool CreateStorageDirectories(const boost::filesystem::path& path,
534                               const std::string& pkgid, uid_t uid,
535                               bool trusted, bool shareddata) {
536   if (!::CreateStorageDirectories(path, pkgid, trusted,
537                                   shareddata, std::vector<const char*>())) {
538     LOG(ERROR) << "Failed to create storage directory for path: " << path;
539     return false;
540   }
541
542   std::string error_message;
543   if (!RegisterSecurityContextForPath(pkgid, path / pkgid, uid, false,
544                                       &error_message)) {
545     LOG(ERROR) << "Failed to register security context for path: " << path
546                << ", error_message: " << error_message;
547     return false;
548   }
549
550   return true;
551 }
552
553 bool DeleteStorageDirectories(const boost::filesystem::path& path,
554                               const std::string& pkgid) {
555   std::vector<const char*> dirs;
556   dirs.assign(kEntries.begin() + 1, kEntries.end());
557   dirs.push_back(kSharedTrustedDir);
558   dirs.push_back(kSharedCacheDir);
559   for (auto& entry : dirs) {
560     bf::path subpath = path / pkgid / entry;
561     if (!ci::RemoveAll(subpath))
562       return false;
563   }
564   if (!DeleteSharedDataDirectories(path, pkgid))
565     return false;
566
567   return true;
568 }
569
570 bool DeleteSharedDirectories(const bf::path& path,
571                              const std::string& pkgid) {
572   return DeleteSharedDataDirectories(path, pkgid);
573 }
574
575 bool CreateSkelDirectories(const std::string& pkgid,
576                            bool trusted, bool shareddata, bool is_readonly,
577                            const std::vector<const char*> additional_dirs) {
578   bf::path root_path = bf::path(tzplatform_getenv(TZ_SYS_ETC)) /
579                        bf::path(kSkelAppDir);
580
581   if (!::CreateStorageDirectories(root_path, pkgid, trusted,
582                                   shareddata, additional_dirs)) {
583     LOG(ERROR) << "Failed to create storage directory for path: "
584                << root_path / pkgid;
585     return false;
586   }
587
588   std::string error_message;
589   if (!RegisterSecurityContextForPath(pkgid, root_path / pkgid, kGlobalUserUid,
590                                       is_readonly, &error_message)) {
591     LOG(ERROR) << "Failed to register security context for path: "
592                << root_path / pkgid
593                << ", error_message: " << error_message;
594     return false;
595   }
596
597   bool result = true;
598   if (!is_readonly) {
599     bf::path src_dir = bf::path(tzplatform_getenv(TZ_SYS_RW_APP)) / pkgid;
600     result = CreateSymlinkFiles(src_dir, root_path / pkgid);
601   }
602
603   return result;
604 }
605
606 bool DeleteSkelDirectories(const std::string& pkgid) {
607   bf::path path = bf::path(tzplatform_getenv(TZ_SYS_ETC)) /
608                   bf::path(kSkelAppDir);
609   if (!DeleteDirectories(path, pkgid))
610     return false;
611
612   return DeleteSharedDataDirectories(
613       bf::path(tzplatform_getenv(TZ_SYS_ETC)) / bf::path(kSkelAppDir), pkgid);
614 }
615
616
617 bool DeleteUserDirectories(const std::string& pkgid) {
618   UserList list = ci::GetUserList();
619   for (auto l : list) {
620     uid_t uid = std::get<0>(l);
621     ci::PkgQueryInterface pkg_query(pkgid, uid);
622     if (pkg_query.IsPackageInstalled()) {
623       LOG(INFO) << pkgid << " is installed for user " << std::get<0>(l);
624       continue;
625     }
626
627     LOG(DEBUG) << "Deleting directories of " << pkgid
628                << ", for uid: " << std::get<0>(l);
629     bf::path apps_rw(std::get<2>(l) / "apps_rw");
630     if (!DeleteDirectories(apps_rw, pkgid)) {
631       return false;
632     }
633   }
634   return true;
635 }
636
637 bool DeleteUserExternalDirectories(const std::string& pkgid) {
638   UserList list = ci::GetUserList();
639   for (auto l : list) {
640     uid_t uid = std::get<0>(l);
641     ci::PkgQueryInterface pkg_query(pkgid, uid);
642     if (pkg_query.IsPackageInstalled()) {
643       LOG(INFO) << pkgid << " is installed for user " << uid;
644       continue;
645     }
646
647     LOG(DEBUG) << "Deleting external directories of " << pkgid
648                << ", for uid: " << uid;
649     bf::path apps_rw(std::get<2>(l) / "apps_rw");
650     if (!DeleteDirectories(apps_rw, pkgid)) {
651       return false;
652     }
653   }
654   return true;
655 }
656
657 bool CopyUserDirectories(const std::string& pkgid) {
658   UserList list = ci::GetUserList();
659   for (auto l : list) {
660     uid_t uid = std::get<0>(l);
661     gid_t gid = std::get<1>(l);
662     LOG(DEBUG) << "Copying directories for uid: " << uid;
663     bf::path apps_rw(std::get<2>(l) / "apps_rw");
664     bf::path src = bf::path(tzplatform_getenv(TZ_SYS_ETC)) /
665                    bf::path(kSkelAppDir) / pkgid;
666     bf::path dst = apps_rw / pkgid;
667     if (!ci::CopyDir(src, dst, FSFlag::FS_NONE, false))
668       continue;
669
670     std::vector<std::string> shared_dirs(kSharedDataEntries);
671     for (auto entry : shared_dirs) {
672       bf::path shared_src = bf::path(tzplatform_getenv(TZ_SYS_ETC)) /
673           bf::path(kSkelAppDir) / entry / pkgid;
674       if (!bf::exists(shared_src))
675         break;
676
677       bf::path shared_dst = apps_rw / entry / pkgid;
678       if (!ci::CopyDir(shared_src, shared_dst, FSFlag::FS_NONE, true))
679         continue;
680
681       if (!SetDirectoryOwnerAndPermissions(shared_dst, uid, gid))
682         return false;
683
684       for (bf::recursive_directory_iterator iter(dst);
685           iter != bf::recursive_directory_iterator(); ++iter) {
686         if (!SetSharedDirOwnerAndPermissions(iter->path(), uid))
687           return false;
688       }
689     }
690
691     if (!SetDirectoryOwnerAndPermissions(dst, uid, gid))
692       return false;
693     for (bf::recursive_directory_iterator iter(dst);
694         iter != bf::recursive_directory_iterator(); ++iter) {
695       if (!SetDirectoryOwnerAndPermissions(iter->path(),
696           uid, gid))
697         return false;
698     }
699     std::string error_message;
700     if (!RegisterSecurityContextForPath(pkgid, dst, uid,
701         false, &error_message)) {
702       LOG(ERROR) << "Failed to register security context for path: " << dst
703                  << ", error_message: " << error_message;
704       return false;
705     }
706   }
707   return true;
708 }
709
710 bool CreateGlobalAppSymlinksForAllUsers(const std::string& pkgid) {
711   bf::path src_dir = bf::path(tzplatform_getenv(TZ_SYS_RW_APP)) / pkgid;
712   if (!bf::exists(src_dir)) {
713     LOG(ERROR) << "src_dir not exists";
714     return false;
715   }
716
717   bool result = true;
718   UserList list = ci::GetUserList();
719   for (auto l : list) {
720     uid_t uid = std::get<0>(l);
721     LOG(DEBUG) << "Creating symlinks for uid: " << uid;
722     // check installed user private app.
723     ci::PkgQueryInterface pkg_query(pkgid, uid);
724     if (pkg_query.IsPackageInstalled())
725       continue;
726     bf::path apps_rw(std::get<2>(l) / "apps_rw");
727     bf::path dst_dir = apps_rw / pkgid;
728     if (!bf::exists(dst_dir)) {
729       LOG(WARNING) << "dst_dir not exists";
730       continue;
731     }
732     result = CreateSymlinkFiles(src_dir, dst_dir);
733   }
734   return result;
735 }
736
737 bool CreateGlobalAppSymlinksForUser(const std::string& pkgid, uid_t uid) {
738   bf::path src_dir = bf::path(tzplatform_getenv(TZ_SYS_RW_APP)) / pkgid;
739   if (!bf::exists(src_dir)) {
740     LOG(WARNING) << "src_dir(" << src_dir << ") not exists";
741     return true;
742   }
743
744   tzplatform_set_user(uid);
745   bf::path dst_dir = bf::path(tzplatform_getenv(TZ_USER_APP)) / pkgid;
746   tzplatform_reset_user();
747   if (!bf::exists(dst_dir)) {
748     LOG(WARNING) << "dst_dir not exists";
749     return true;
750   }
751   bool result = CreateSymlinkFiles(src_dir, dst_dir);
752
753   return result;
754 }
755
756 bool DeleteGlobalAppSymlinksForAllUsers(const std::string& pkgid) {
757   bf::path src_dir = bf::path(tzplatform_getenv(TZ_SYS_RW_APP)) / pkgid;
758   if (!bf::exists(src_dir)) {
759     LOG(WARNING) << "src_dir(" << src_dir << ") not exists";
760     return true;
761   }
762
763   bool result = true;
764   UserList list = ci::GetUserList();
765   for (auto l : list) {
766     uid_t uid = std::get<0>(l);
767     LOG(DEBUG) << "Deleting symlinks for uid: " << uid;
768     // check installed user private app.
769     ci::PkgQueryInterface pkg_query(pkgid, uid);
770     if (pkg_query.IsPackageInstalled())
771       continue;
772     bf::path apps_rw(std::get<2>(l) / "apps_rw");
773     bf::path dst_dir = apps_rw / pkgid;
774     if (!bf::exists(dst_dir)) {
775       LOG(WARNING) << "dst_dir not exists";
776       continue;
777     }
778     result = DeleteSymlinkFiles(src_dir, dst_dir);
779   }
780   return result;
781 }
782
783 bool DeleteGlobalAppSymlinksForUser(const std::string& pkgid, uid_t uid) {
784   bf::path src_dir = bf::path(tzplatform_getenv(TZ_SYS_RW_APP)) / pkgid;
785   if (!bf::exists(src_dir)) {
786     LOG(ERROR) << "src_dir not exists";
787     return false;
788   }
789
790   tzplatform_set_user(uid);
791   bf::path dst_dir = bf::path(tzplatform_getenv(TZ_USER_APP)) / pkgid;
792   tzplatform_reset_user();
793   if (!bf::exists(dst_dir)) {
794     LOG(WARNING) << "dst_dir not exists";
795     return true;
796   }
797   bool result = DeleteSymlinkFiles(src_dir, dst_dir);
798   return result;
799 }
800
801 bool SetPackageDirectoryOwnerAndPermissions(const bf::path& path, uid_t uid) {
802   boost::optional<gid_t> gid = ci::GetGidByUid(uid);
803   if (!gid)
804     return false;
805   bf::perms perms644 =
806       bf::owner_read | bf::owner_write | bf::group_read | bf::others_read;
807   bf::perms perms755 =
808       perms644 | bf::owner_exe | bf::group_exe | bf::others_exe;
809   for (bf::recursive_directory_iterator iter(path);
810       iter != bf::recursive_directory_iterator(); ++iter) {
811     if (bf::is_symlink(symlink_status(iter->path())) ||
812         (bf::is_directory(iter->path()) &&
813         (iter->path().filename() == ".mmc" ||
814             iter->path().filename() == ".pkg" ||
815             iter->path().filename() == "tep"))) {
816       // skip symlink or path which is related to
817       // mount or directory installer creates
818       continue;
819     } else if (bf::is_directory(iter->path())) {
820       // directories
821       if (!SetDirectoryOwnerAndPermissions(iter->path(), uid, *gid))
822         return false;
823     } else if (iter.level() == 1 &&
824         iter->path().parent_path().filename() == "bin") {
825       // bin files
826       if (!SetDirOwnershipAndPermissions(iter->path(), perms755, uid, *gid))
827         return false;
828     } else {
829       // other files
830       if (!SetDirOwnershipAndPermissions(iter->path(), perms644, uid, *gid))
831         return false;
832     }
833   }
834   return true;
835 }
836
837 bool ShouldSupportLegacySharedDataDir(const std::string& api_version) {
838   if (bf::exists(kDisableLegacySharedDataDirSupport))
839     return false;
840   utils::VersionNumber api_ver(api_version);
841   if (api_ver < ver30)
842     return true;
843   else
844     return false;
845 }
846
847 bool CreateSharedDataDir(const std::string& pkgid, uid_t uid) {
848   bf::path apps_rw = ci::GetRootAppPath(false, uid);
849   if (!CreateSharedDataDirectories(apps_rw, pkgid))
850     return false;
851
852   bf::path path = apps_rw / pkgid;
853   std::string error_message;
854   if (!ci::RegisterSecurityContextForPath(pkgid, path, uid, false,
855           &error_message)) {
856     LOG(ERROR) << "Failed to register security context for path: " << path
857                << ", error_message: " << error_message;
858     return false;
859   }
860
861   return true;
862 }
863
864 bool CreatePerUserSharedDataDir(const std::string& pkgid) {
865   // create skel dir
866   bf::path skel_apps_rw = bf::path(tzplatform_getenv(TZ_SYS_ETC)) /
867       bf::path(kSkelAppDir);
868   LOG(DEBUG) <<  "Creating directory : " << skel_apps_rw;
869   if (!CreateSharedDataDirectories(skel_apps_rw, pkgid))
870     return false;
871
872   std::string error_message;
873   if (!ci::RegisterSecurityContextForPath(pkgid, skel_apps_rw / pkgid,
874           kGlobalUserUid, false, &error_message)) {
875     LOG(ERROR) << "Failed to register security context for path: "
876                << skel_apps_rw / pkgid << ", error_message: " << error_message;
877     return false;
878   }
879
880   // create per user dir
881   ci::UserList list = ci::GetUserList();
882   for (auto l : list) {
883     uid_t uid = std::get<0>(l);
884     LOG(DEBUG) << "Adding shareddata directory for uid: " << uid;
885
886     bf::path apps_rw = ci::GetRootAppPath(false, uid);
887     if (!CreateSharedDataDirectories(apps_rw, pkgid))
888       return false;
889
890     std::string error_message;
891     if (!ci::RegisterSecurityContextForPath(pkgid, apps_rw / pkgid, uid,
892         false, &error_message)) {
893       LOG(ERROR) << "Failed to register security context for path: "
894                  << apps_rw / pkgid << ", error_message: " << error_message;
895       return false;
896     }
897   }
898
899   return true;
900 }
901
902 bool DeleteSharedDataDir(const std::string& pkgid, uid_t uid) {
903   bf::path apps_rw = ci::GetRootAppPath(false, uid);
904   return DeleteSharedDataDirectories(apps_rw, pkgid);
905 }
906
907 bool DeletePerUserSharedDataDir(const std::string& pkgid) {
908   bf::path skel_apps_rw = bf::path(tzplatform_getenv(TZ_SYS_ETC)) /
909       bf::path(kSkelAppDir);
910   if (!DeleteSharedDataDirectories(skel_apps_rw, pkgid))
911     return false;
912
913   ci::UserList list = ci::GetUserList();
914   for (auto l : list) {
915     uid_t uid = std::get<0>(l);
916     bf::path apps_rw = ci::GetRootAppPath(false, uid);
917     if (!DeleteSharedDataDirectories(apps_rw, pkgid))
918       return false;
919   }
920
921   return true;
922 }
923
924 bool BackupSharedDataDir(const std::string& pkgid, uid_t uid) {
925   bf::path apps_rw = ci::GetRootAppPath(false, uid);
926   return BackupSharedDataDirectories(apps_rw, pkgid);
927 }
928
929 bool BackupPerUserSharedDataDir(const std::string& pkgid) {
930   bf::path skel_apps_rw = bf::path(tzplatform_getenv(TZ_SYS_ETC)) /
931       bf::path(kSkelAppDir);
932   if (!BackupSharedDataDirectories(skel_apps_rw, pkgid))
933     return false;
934
935   ci::UserList list = ci::GetUserList();
936   for (auto l : list) {
937     uid_t uid = std::get<0>(l);
938     if (!BackupSharedDataDir(pkgid, uid))
939       return false;
940   }
941
942   return true;
943 }
944
945 bool RestoreSharedDataDir(const std::string& pkgid, uid_t uid) {
946   bf::path apps_rw = ci::GetRootAppPath(false, uid);
947   return RestoreSharedDataDirectories(apps_rw, pkgid);
948 }
949
950 bool RestorePerUserSharedDataDir(const std::string& pkgid) {
951   bf::path skel_apps_rw = bf::path(tzplatform_getenv(TZ_SYS_ETC)) /
952       bf::path(kSkelAppDir);
953   if (!RestoreSharedDataDirectories(skel_apps_rw, pkgid))
954     return false;
955
956   ci::UserList list = ci::GetUserList();
957   for (auto l : list) {
958     uid_t uid = std::get<0>(l);
959     if (!RestoreSharedDataDir(pkgid, uid))
960       return false;
961   }
962
963   return true;
964 }
965
966 bool RemoveBackupSharedDataDir(const std::string& pkgid, uid_t uid) {
967   bf::path apps_rw = ci::GetRootAppPath(false, uid);
968   return RemoveBackupSharedDataDirectories(apps_rw, pkgid);
969 }
970
971 bool RemoveBackupPerUserSharedDataDir(const std::string& pkgid) {
972   bf::path skel_apps_rw = bf::path(tzplatform_getenv(TZ_SYS_ETC)) /
973       bf::path(kSkelAppDir);
974   if (!RemoveBackupSharedDataDirectories(skel_apps_rw, pkgid))
975     return false;
976
977   ci::UserList list = ci::GetUserList();
978   for (auto l : list) {
979     uid_t uid = std::get<0>(l);
980     if (!RemoveBackupSharedDataDir(pkgid, uid))
981       return false;
982   }
983
984   return true;
985 }
986
987 }  // namespace common_installer