Fix static analysis issue
[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 const char kSubssesionDir[] = "subsession";
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 (const 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       !ci::CreateDir(path / pkgid / kShared))
166     return false;
167
168   bf::current_path(path / pkgid / kShared);
169   if (bf::exists(path / pkgid / kShared / kData))
170     return true;
171   bf::path relative_path = ci::RelativePath(path / kSharedDir / pkgid / kData,
172                                             bf::current_path() / kData);
173   bs::error_code error;
174   bf::create_symlink(relative_path, kData, error);
175   if (error) {
176     LOG(ERROR) << "Failed to create symlink : " << error.message();
177     return false;
178   }
179
180   return true;
181 }
182
183 bool DeleteDirectories(const bf::path& app_dir, const std::string& pkgid) {
184   bf::path base_dir = app_dir / pkgid;
185   if (!ci::RemoveAll(base_dir))
186     return false;
187   if (!DeleteSharedDataDirectories(app_dir, pkgid))
188     return false;
189   return true;
190 }
191
192 bool CreateSymlinkFiles(const bf::path& src_dir, const bf::path& dst_dir) {
193   std::vector<std::string> rofiles(kReadOnlyEntries);
194   for (bf::directory_iterator file(src_dir);
195       file != bf::directory_iterator();
196       ++file) {
197     if (bf::is_regular_file(file->path())) {
198       bf::path current(file->path());
199       bf::path file_name = current.filename();
200       LOG(DEBUG) << "file_name: " << file_name;
201       rofiles.push_back(file_name.string());
202     }
203   }
204
205   bs::error_code error;
206   for (auto& entry : rofiles) {
207     bf::path src_path = src_dir / entry;
208     bf::path dst_path = dst_dir / entry;
209     if (!bf::exists(src_path)) {
210       // check if symlink for .mmc/bin,lib,res, then do not skip
211       if (!bf::is_symlink(symlink_status(src_path))) {
212         LOG(INFO) << "src_path not exist : " << src_path;
213         continue;
214       }
215     }
216     if (bf::exists(dst_path) || bf::is_symlink(symlink_status(dst_path))) {
217       LOG(WARNING) << "dst_path exist, skip : " << dst_path;
218       continue;
219     }
220     bf::create_symlink(src_path, dst_path, error);
221     if (error) {
222       LOG(ERROR) << "Symlink creation failure src_path: " << src_path
223                  << " dst_path: " << dst_path;
224       LOG(ERROR) << "error: " << error.message();
225       return false;
226     }
227   }
228   return true;
229 }
230
231 bool DeleteSymlinkFiles(const bf::path& src_dir, const bf::path& dst_dir) {
232   bs::error_code error;
233   for (bf::directory_iterator file(dst_dir);
234       file != bf::directory_iterator();
235       ++file) {
236     bf::path current(file->path());
237     if (!bf::is_symlink(symlink_status(current)))
238       continue;
239     bf::path resolved_path = bf::read_symlink(current, error);
240     if (error) {
241       LOG(ERROR) << "Failed to get resolved path of symlink: " << current
242                  << ", error: " << error.message();
243       return false;
244     }
245
246     LOG(DEBUG) << "resolved_path: " << resolved_path;
247     bf::path parent = resolved_path.parent_path();
248     if (parent.empty() || (parent != src_dir)) {
249       LOG(WARNING) << "Parent is empty or not equal to src, parent: ("
250                    << parent << ")";
251       continue;
252     }
253     bf::remove(current, error);
254     if (error) {
255       LOG(ERROR) << "Symlink deletion failure for: " << current
256                   << ", error: " << error.message();
257       return false;
258     }
259     LOG(DEBUG) << "removed: " << current;
260   }
261   bf::path shared_res = dst_dir / kSharedResDir;
262   if (bf::is_symlink(symlink_status(shared_res))) {
263       bf::remove(shared_res, error);
264       if (error) {
265           LOG(ERROR) << "Symlink deletion failure for: " << shared_res
266                      << ", error: " << error.message();
267           return false;
268       }
269   }
270   return true;
271 }
272
273 bool CreateStorageDirectories(const boost::filesystem::path& root_path,
274                               const std::string& pkgid,
275                               bool trusted, bool shareddata,
276                               const std::vector<const char*> additional_dirs) {
277   bf::path path(root_path / pkgid);
278   if (!ci::CreateDir(path)) {
279     LOG(ERROR) << "Failed to create dir: " << path;
280     return false;
281   }
282
283   std::vector<const char*> dirs(kEntries);
284   dirs.insert(dirs.end(), additional_dirs.begin(), additional_dirs.end());
285   if (trusted)
286     dirs.push_back(kSharedTrustedDir);
287
288   bs::error_code error;
289   for (auto& entry : dirs) {
290     bf::path subpath = path / entry;
291     if (!ci::CreateDir(subpath)) {
292       LOG(ERROR) << "Failed to create directory: " << subpath;
293       return false;
294     }
295   }
296
297   if (shareddata) {
298     if (!CreateSharedDataDirectories(root_path, pkgid))
299       return false;
300   } else {
301     if (!DeleteSharedDataDirectories(root_path, pkgid))
302       return false;
303   }
304
305   bf::path shared_cache_path = path / kSharedCacheDir;
306   // remove shared/cache (do not support)
307   if (!ci::RemoveAll(shared_cache_path))
308     return false;
309
310   return true;
311 }
312
313 bool BackupSharedDataDirectories(const bf::path& apps_rw,
314     const std::string& pkgid) {
315   if (!ci::MakeBackup(apps_rw / pkgid / kSharedDataDir))
316     return false;
317   if (!ci::MakeBackup(apps_rw / kSharedDir / pkgid))
318     return false;
319   if (!ci::MakeBackup(apps_rw / kSharedTmpDir / pkgid))
320     return false;
321   return true;
322 }
323
324 bool RestoreSharedDataDirectories(const bf::path& apps_rw,
325     const std::string& pkgid) {
326   if (!ci::RestoreBackup(apps_rw / pkgid / kSharedDataDir))
327     return false;
328   if (!ci::RestoreBackup(apps_rw / kSharedDir / pkgid))
329     return false;
330   if (!ci::RestoreBackup(apps_rw / kSharedTmpDir / pkgid))
331     return false;
332   return true;
333 }
334
335 bool RemoveBackupSharedDataDirectories(const bf::path& apps_rw,
336     const std::string& pkgid) {
337   if (!ci::RemoveBackup(apps_rw / pkgid / kSharedDataDir))
338     return false;
339   if (!ci::RemoveBackup(apps_rw / kSharedDir / pkgid))
340     return false;
341   if (!ci::RemoveBackup(apps_rw / kSharedTmpDir / pkgid))
342     return false;
343   return true;
344 }
345
346 bool CreateExternalUserDirectories(uid_t user, const std::string& pkgid,
347     const std::string& apps_prefix) {
348   boost::optional<gid_t> gid = ci::GetGidByUid(user);
349   if (!gid)
350     return false;
351
352   std::string group_name = ci::GetGroupNameByGid(*gid);
353   if (group_name != tzplatform_getenv(TZ_SYS_USER_GROUP)) {
354     LOG(ERROR) << "Failed to get group name of gid: " << *gid;
355     return false;
356   }
357
358   LOG(DEBUG) << "Creating directories for uid: " << user << ", gid: "
359              << *gid;
360
361   bf::path apps_rw = GetDirectoryPathForStorage(user, apps_prefix);
362   if (apps_rw.empty()) {
363     LOG(DEBUG) << "Directory not exists: " << apps_rw;
364     return false;
365   }
366
367   if (!CreateStorageDirectories(apps_rw, pkgid, true, false,
368           std::vector<const char*>()))
369     return false;
370
371   if (!::SetPackageDirectoryOwnerAndPermissions(apps_rw / pkgid, user))
372     return false;
373
374   return true;
375 }
376
377 }  // namespace
378
379 namespace common_installer {
380
381 std::string GetDirectoryPathForInternalStorage() {
382   const char* internal_storage_prefix = tzplatform_getenv(TZ_SYS_HOME);
383   if (internal_storage_prefix)
384     return std::string(internal_storage_prefix);
385   return tzplatform_getenv(TZ_SYS_HOME);
386 }
387
388 std::string GetDirectoryPathForExternalStorage() {
389   return GetExternalCardPath().string();
390 }
391
392 bool PerformExternalDirectoryCreationForUser(uid_t user,
393                                              const std::string& pkgid) {
394   bf::path storage_path = GetExternalCardPath();
395
396   if (!bf::exists(storage_path)) {
397     LOG(WARNING) << "External storage (SD Card) is not mounted.";
398     return false;
399   }
400
401   bf::path storage_apps_path = storage_path / "apps";
402   if (!bf::exists(storage_apps_path)) {
403     bs::error_code error;
404     bf::create_directories(storage_apps_path, error);
405     if (error) {
406       LOG(ERROR) << "Failed to create directory: "
407           << storage_apps_path.c_str();
408       return false;
409     }
410   }
411
412   if (CreateExternalUserDirectories(user, pkgid, storage_apps_path.string()))
413     return false;
414
415   for (auto& lw_user : GetLightUserList(user)) {
416     bf::path storage_apps_lw_path = storage_apps_path
417         / kSubssesionDir / lw_user / "apps";
418     if (!bf::exists(storage_apps_lw_path)) {
419       bs::error_code error;
420       bf::create_directories(storage_apps_lw_path, error);
421       if (error) {
422         LOG(ERROR) << "Failed to create directory: "
423                    << storage_apps_lw_path.c_str();
424         return false;
425       }
426     }
427
428     if (CreateExternalUserDirectories(user, pkgid,
429         storage_apps_lw_path.string()))
430       return false;
431   }
432
433   return true;
434 }
435
436 bool PerformExternalDirectoryDeletionForUser(uid_t user,
437                                              const std::string& pkgid) {
438   bf::path storage_path = GetExternalCardPath();
439   if (!bf::exists(storage_path)) {
440     LOG(WARNING) << "External storage (SD Card) is not mounted. "
441         << "It will be ignored";
442     return true;
443   }
444
445   bf::path storage_apps_path = bf::path(storage_path) / "apps";
446   if (!DeleteDirectories(
447       GetDirectoryPathForStorage(user, storage_apps_path.string()), pkgid))
448     return false;
449
450   for (auto& lw_user : GetLightUserList(user)) {
451     bf::path storage_apps_lw_path =
452         storage_apps_path / kSubssesionDir / lw_user / "apps";
453     if (!DeleteDirectories(
454             GetDirectoryPathForStorage(user, storage_apps_lw_path.string()),
455             pkgid))
456       return false;
457   }
458
459   return true;
460 }
461
462 bool PerformExternalDirectoryCreationForAllUsers(const std::string& pkgid) {
463   UserList list = ci::GetUserList();
464   for (const 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 (const 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 u =
491               static_cast<uid_t>(reinterpret_cast<uintptr_t>(user_data));
492           char* pkgid = nullptr;
493
494           int r = pkgmgrinfo_pkginfo_get_pkgid(handle, &pkgid);
495           if (r != PMINFO_R_OK)
496             return -1;
497           if (!PerformExternalDirectoryCreationForUser(u, 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 (const 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 CreatePerUserStorageDirectories(const std::string& pkgid, bool trusted,
534     bool shareddata, bool is_readonly,
535     const std::vector<const char*> additional_dirs) {
536   // create skel dir
537   bf::path skel_apps_rw = bf::path(tzplatform_getenv(TZ_SYS_ETC)) /
538       bf::path(kSkelAppDir);
539   if (!::CreateStorageDirectories(skel_apps_rw, pkgid, trusted, shareddata,
540           additional_dirs)) {
541     LOG(ERROR) << "Failed to create skeleton storage directories";
542     return false;
543   }
544
545   std::string error_message;
546   if (!RegisterSecurityContextForPath(pkgid, skel_apps_rw / pkgid,
547           kGlobalUserUid, is_readonly, &error_message)) {
548     LOG(ERROR) << "Failed to register security context for path: "
549                << skel_apps_rw / pkgid << ", error_message: " << error_message;
550     return false;
551   }
552
553   if (!is_readonly) {
554     bf::path src_dir = bf::path(tzplatform_getenv(TZ_SYS_RW_APP)) / pkgid;
555     if (!CreateSymlinkFiles(src_dir, skel_apps_rw / pkgid))
556       return false;
557   }
558
559   // create per user dir
560   UserList list = ci::GetUserList();
561   for (const auto& l : list) {
562     uid_t uid = std::get<0>(l);
563     bf::path owner_apps_rw = std::get<2>(l) / "apps_rw";
564     std::vector<bf::path> apps_rw_paths;
565     apps_rw_paths.push_back(std::move(owner_apps_rw));
566
567     for (auto& lw_user : GetLightUserList(uid))
568       apps_rw_paths.push_back(std::get<2>(l)
569           / kSubssesionDir / lw_user / "apps_rw");
570
571     LOG(DEBUG) << "Creating directories for user: " << uid;
572     for (auto& apps_rw : apps_rw_paths) {
573       if (!::CreateStorageDirectories(apps_rw, pkgid, trusted, shareddata,
574           additional_dirs)) {
575         LOG(ERROR) << "Failed to create storage directory for user: " << uid;
576         return false;
577       }
578
579       if (!::SetPackageDirectoryOwnerAndPermissions(apps_rw / pkgid, uid))
580         return false;
581
582       if (shareddata) {
583         std::vector<std::string> shared_dirs(kSharedDataEntries);
584         for (const auto& entry : shared_dirs) {
585           bf::path shared_dst = apps_rw / entry / pkgid;
586           if (!::SetPackageDirectoryOwnerAndPermissions(shared_dst, uid))
587             return false;
588         }
589       }
590
591       if (!RegisterSecurityContextForPath(pkgid, apps_rw / pkgid, uid, false,
592                                           &error_message)) {
593         LOG(ERROR) << "Failed to register security context for path: "
594                    << apps_rw / pkgid << ", error_message: " << error_message;
595         return false;
596       }
597     }
598   }
599
600   return true;
601 }
602
603 bool DeletePerUserStorageDirectories(const std::string& pkgid,
604     bool keep_rwdata) {
605   // delete skel dir
606   bf::path skel_apps_rw = bf::path(tzplatform_getenv(TZ_SYS_ETC)) /
607       bf::path(kSkelAppDir);
608   if (!ci::RemoveAll(skel_apps_rw / pkgid)) {
609     LOG(ERROR) << "Failed to delete skeleton storage directories";
610     return false;
611   }
612
613   if (keep_rwdata)
614     return true;
615
616   // delete per user dir
617   UserList list = ci::GetUserList();
618   for (const auto& l : list) {
619     uid_t uid = std::get<0>(l);
620     bf::path owner_apps_rw = std::get<2>(l) / "apps_rw";
621     std::vector<bf::path> apps_rw_paths;
622     apps_rw_paths.push_back(std::move(owner_apps_rw));
623
624     for (auto& lw_user : GetLightUserList(uid))
625       apps_rw_paths.push_back(std::get<2>(l) / kSubssesionDir / lw_user /
626                               "apps_rw");
627
628     LOG(DEBUG) << "Deleting directories for user: " << uid;
629     for (auto& apps_rw : apps_rw_paths) {
630       if (!ci::RemoveAll(apps_rw / pkgid)) {
631         LOG(ERROR) << "Failed to delete storage directory for user: " << uid;
632         return false;
633       }
634     }
635   }
636
637   if (!ci::DeletePerUserSharedDataDir(pkgid)) {
638     LOG(ERROR) << "Failed to delete per user shared data dir";
639     return false;
640   }
641
642   return true;
643 }
644
645 bool CreateStorageDirectories(const boost::filesystem::path& path,
646                               const std::string& pkgid, uid_t uid,
647                               bool trusted, bool shareddata) {
648   if (!::CreateStorageDirectories(path, pkgid, trusted,
649                                   shareddata, std::vector<const char*>())) {
650     LOG(ERROR) << "Failed to create storage directory for path: " << path;
651     return false;
652   }
653
654   if (!::SetPackageDirectoryOwnerAndPermissions(path / pkgid, uid))
655     return false;
656
657   if (shareddata) {
658     std::vector<std::string> shared_dirs(kSharedDataEntries);
659     for (const auto& entry : shared_dirs) {
660       bf::path shared_dst = path / entry / pkgid;
661       if (!::SetPackageDirectoryOwnerAndPermissions(shared_dst, uid))
662         return false;
663     }
664   }
665
666   std::string error_message;
667   if (!RegisterSecurityContextForPath(pkgid, path / pkgid, uid, false,
668                                       &error_message)) {
669     LOG(ERROR) << "Failed to register security context for path: " << path
670                << ", error_message: " << error_message;
671     return false;
672   }
673
674   return true;
675 }
676
677 void RemoveRWDirectories(const boost::filesystem::path& root) {
678   if (!RemoveAll(root / kCache))
679     LOG(ERROR) << "Failed to remove packaged cache directory";
680   if (!RemoveAll(root / kData))
681     LOG(ERROR) << "Failed to remove packaged data directory";
682   if (!RemoveAll(root / kSharedCacheDir))
683     LOG(ERROR) << "Failed to remove packaged shared/cache directory";
684   if (!RemoveAll(root / kSharedDataDir))
685     LOG(ERROR) << "Failed to remove packaged shared/data directory";
686   if (!RemoveAll(root / kSharedTrustedDir))
687     LOG(ERROR) << "Failed to remove packaged shared/trusted directory";
688 }
689
690 bool DeleteSharedDirectories(const bf::path& path,
691                              const std::string& pkgid) {
692   return DeleteSharedDataDirectories(path, pkgid);
693 }
694
695 bool DeleteUserExternalDirectories(const std::string& pkgid) {
696   UserList list = ci::GetUserList();
697   for (const auto& l : list) {
698     uid_t uid = std::get<0>(l);
699     ci::PkgQueryInterface pkg_query(pkgid, uid);
700     if (pkg_query.IsPackageInstalled()) {
701       LOG(INFO) << pkgid << " is installed for user " << uid;
702       continue;
703     }
704
705     LOG(DEBUG) << "Deleting external directories of " << pkgid
706                << ", for uid: " << uid;
707     bf::path apps_rw(std::get<2>(l) / "apps_rw");
708     if (!DeleteDirectories(apps_rw, pkgid)) {
709       return false;
710     }
711
712     for (auto& lw_user : GetLightUserList(uid)) {
713       bf::path apps_rw_lw(std::get<2>(l) / kSubssesionDir / lw_user / "apps_rw");
714       if (!DeleteDirectories(apps_rw_lw, pkgid))
715         return false;
716     }
717   }
718
719   return true;
720 }
721
722 bool CreateGlobalAppSymlinksForAllUsers(const std::string& pkgid) {
723   bf::path src_dir = bf::path(tzplatform_getenv(TZ_SYS_RW_APP)) / pkgid;
724   if (!bf::exists(src_dir)) {
725     LOG(ERROR) << "src_dir not exists";
726     return false;
727   }
728
729   UserList list = ci::GetUserList();
730   for (const auto& l : list) {
731     uid_t uid = std::get<0>(l);
732     LOG(DEBUG) << "Creating symlinks for uid: " << uid;
733     // check installed user private app.
734     ci::PkgQueryInterface pkg_query(pkgid, uid);
735     if (pkg_query.IsPackageInstalled())
736       continue;
737
738     bf::path owner_apps_rw = std::get<2>(l) / "apps_rw";
739     std::vector<bf::path> apps_rw_paths;
740     apps_rw_paths.push_back(std::move(owner_apps_rw));
741
742     for (auto& lw_user : GetLightUserList(uid))
743       apps_rw_paths.push_back(std::get<2>(l) / kSubssesionDir / lw_user /
744                               "apps_rw");
745
746     for (auto& apps_rw : apps_rw_paths) {
747       bf::path dst_dir = apps_rw / pkgid;
748       if (!bf::exists(dst_dir)) {
749         LOG(WARNING) << "dst_dir not exists";
750         continue;
751       }
752
753       if (!CreateSymlinkFiles(src_dir, dst_dir))
754         return false;
755     }
756   }
757
758   return true;
759 }
760
761 bool CreateGlobalAppSymlinksForUser(const std::string& pkgid, uid_t uid) {
762   bf::path src_dir = bf::path(tzplatform_getenv(TZ_SYS_RW_APP)) / pkgid;
763   if (!bf::exists(src_dir)) {
764     LOG(WARNING) << "src_dir(" << src_dir << ") not exists";
765     return true;
766   }
767
768   tzplatform_set_user(uid);
769   bf::path dst_dir = bf::path(tzplatform_getenv(TZ_USER_APP)) / pkgid;
770   tzplatform_reset_user();
771   if (!bf::exists(dst_dir)) {
772     LOG(WARNING) << "dst_dir not exists";
773     return true;
774   }
775   bool result = CreateSymlinkFiles(src_dir, dst_dir);
776
777   return result;
778 }
779
780 bool DeleteGlobalAppSymlinksForAllUsers(const std::string& pkgid) {
781   bf::path src_dir = bf::path(tzplatform_getenv(TZ_SYS_RW_APP)) / pkgid;
782   if (!bf::exists(src_dir)) {
783     LOG(WARNING) << "src_dir(" << src_dir << ") not exists";
784     return true;
785   }
786
787   UserList list = ci::GetUserList();
788   for (const auto& l : list) {
789     uid_t uid = std::get<0>(l);
790     LOG(DEBUG) << "Deleting symlinks for uid: " << uid;
791
792     // check installed user private app.
793     ci::PkgQueryInterface pkg_query(pkgid, uid);
794     if (pkg_query.IsPackageInstalled())
795       continue;
796
797     bf::path owner_apps_rw = std::get<2>(l) / "apps_rw";
798     std::vector<bf::path> apps_rw_paths;
799     apps_rw_paths.push_back(std::move(owner_apps_rw));
800     for (auto& lw_user : GetLightUserList(uid))
801       apps_rw_paths.push_back(std::get<2>(l) / kSubssesionDir / lw_user /
802                               "apps_rw");
803
804     for (auto& apps_rw : apps_rw_paths) {
805       bf::path dst_dir = apps_rw / pkgid;
806       if (!bf::exists(dst_dir)) {
807         LOG(WARNING) << "dst_dir not exists";
808         continue;
809       }
810
811       if (!DeleteSymlinkFiles(src_dir, dst_dir))
812         return false;
813     }
814   }
815
816   return true;
817 }
818
819 bool DeleteGlobalAppSymlinksForUser(const std::string& pkgid, uid_t uid) {
820   bf::path src_dir = bf::path(tzplatform_getenv(TZ_SYS_RW_APP)) / pkgid;
821   if (!bf::exists(src_dir)) {
822     LOG(ERROR) << "src_dir not exists";
823     return false;
824   }
825
826   tzplatform_set_user(uid);
827   bf::path dst_dir = bf::path(tzplatform_getenv(TZ_USER_APP)) / pkgid;
828   tzplatform_reset_user();
829   if (!bf::exists(dst_dir)) {
830     LOG(WARNING) << "dst_dir not exists";
831     return true;
832   }
833   bool result = DeleteSymlinkFiles(src_dir, dst_dir);
834   return result;
835 }
836
837 bool SetPackageDirectoryOwnerAndPermissions(const bf::path& path, uid_t uid) {
838   return ::SetPackageDirectoryOwnerAndPermissions(path, uid);
839 }
840
841 bool ShouldSupportLegacySharedDataDir(const std::string& api_version) {
842   if (bf::exists(kDisableLegacySharedDataDirSupport))
843     return false;
844   utils::VersionNumber api_ver(api_version);
845   if (api_ver < ver30)
846     return true;
847   else
848     return false;
849 }
850
851 bool CreateSharedDataDir(const std::string& pkgid, uid_t uid) {
852   bf::path apps_rw = ci::GetRootAppPath(false, uid);
853   if (!CreateSharedDataDirectories(apps_rw, pkgid))
854     return false;
855
856   bf::path path = apps_rw / pkgid;
857   std::string error_message;
858   if (!ci::RegisterSecurityContextForPath(pkgid, path, uid, false,
859           &error_message)) {
860     LOG(ERROR) << "Failed to register security context for path: " << path
861                << ", error_message: " << error_message;
862     return false;
863   }
864
865   return true;
866 }
867
868 bool CreatePerUserSharedDataDir(const std::string& pkgid) {
869   // create skel dir
870   bf::path skel_apps_rw = bf::path(tzplatform_getenv(TZ_SYS_ETC)) /
871       bf::path(kSkelAppDir);
872   LOG(DEBUG) <<  "Creating directory : " << skel_apps_rw;
873   if (!CreateSharedDataDirectories(skel_apps_rw, pkgid))
874     return false;
875
876   std::string error_message;
877   if (!ci::RegisterSecurityContextForPath(pkgid, skel_apps_rw / pkgid,
878           kGlobalUserUid, false, &error_message)) {
879     LOG(ERROR) << "Failed to register security context for path: "
880                << skel_apps_rw / pkgid << ", error_message: " << error_message;
881     return false;
882   }
883
884   // create per user dir
885   ci::UserList list = ci::GetUserList();
886   for (const auto& l : list) {
887     uid_t uid = std::get<0>(l);
888     LOG(DEBUG) << "Adding shareddata directory for uid: " << uid;
889
890     bf::path owner_apps_rw = ci::GetRootAppPath(false, uid);
891     std::vector<bf::path> apps_rw_paths;
892     apps_rw_paths.push_back(std::move(owner_apps_rw));
893     for (auto& lw_user : GetLightUserList(uid))
894       apps_rw_paths.push_back(std::get<2>(l) / kSubssesionDir / lw_user /
895                               "apps_rw");
896
897     for (auto& apps_rw : apps_rw_paths) {
898       if (!CreateSharedDataDirectories(apps_rw, pkgid))
899         return false;
900
901       std::vector<std::string> shared_dirs(kSharedDataEntries);
902       for (const auto& entry : shared_dirs) {
903         bf::path shared_dst = apps_rw / entry / pkgid;
904         if (!::SetPackageDirectoryOwnerAndPermissions(shared_dst, uid))
905           return false;
906       }
907
908       if (!ci::RegisterSecurityContextForPath(pkgid, apps_rw / pkgid, uid,
909                                               false, &error_message)) {
910         LOG(ERROR) << "Failed to register security context for path: "
911                    << apps_rw / pkgid << ", error_message: " << error_message;
912         return false;
913       }
914     }
915   }
916
917   return true;
918 }
919
920 bool DeleteSharedDataDir(const std::string& pkgid, uid_t uid) {
921   bf::path apps_rw = ci::GetRootAppPath(false, uid);
922   return DeleteSharedDataDirectories(apps_rw, pkgid);
923 }
924
925 bool DeletePerUserSharedDataDir(const std::string& pkgid) {
926   bf::path skel_apps_rw = bf::path(tzplatform_getenv(TZ_SYS_ETC)) /
927       bf::path(kSkelAppDir);
928   if (!DeleteSharedDataDirectories(skel_apps_rw, pkgid))
929     return false;
930
931   ci::UserList list = ci::GetUserList();
932   for (const auto& l : list) {
933     uid_t uid = std::get<0>(l);
934
935     bf::path owner_apps_rw = ci::GetRootAppPath(false, uid);
936     std::vector<bf::path> apps_rw_paths;
937     apps_rw_paths.push_back(std::move(owner_apps_rw));
938     for (auto& lw_user : GetLightUserList(uid))
939       apps_rw_paths.push_back(std::get<2>(l) / kSubssesionDir / lw_user /
940                               "apps_rw");
941
942     for (auto& apps_rw : apps_rw_paths) {
943       if (!DeleteSharedDataDirectories(apps_rw, pkgid))
944         return false;
945     }
946   }
947   return true;
948 }
949
950 bool BackupSharedDataDir(const std::string& pkgid, uid_t uid) {
951   bf::path apps_rw = ci::GetRootAppPath(false, uid);
952   return BackupSharedDataDirectories(apps_rw, pkgid);
953 }
954
955 bool BackupPerUserSharedDataDir(const std::string& pkgid) {
956   bf::path skel_apps_rw = bf::path(tzplatform_getenv(TZ_SYS_ETC)) /
957       bf::path(kSkelAppDir);
958   if (!BackupSharedDataDirectories(skel_apps_rw, pkgid))
959     return false;
960
961   ci::UserList list = ci::GetUserList();
962   for (const auto& l : list) {
963     uid_t uid = std::get<0>(l);
964     bf::path owner_apps_rw = ci::GetRootAppPath(false, uid);
965     std::vector<bf::path> apps_rw_paths;
966     apps_rw_paths.push_back(std::move(owner_apps_rw));
967     for (auto& lw_user : GetLightUserList(uid))
968       apps_rw_paths.push_back(std::get<2>(l) / kSubssesionDir / lw_user /
969                               "apps_rw");
970
971     for (auto& apps_rw : apps_rw_paths) {
972       if (!BackupSharedDataDirectories(apps_rw, pkgid))
973         return false;
974     }
975   }
976
977   return true;
978 }
979
980 bool RestoreSharedDataDir(const std::string& pkgid, uid_t uid) {
981   bf::path apps_rw = ci::GetRootAppPath(false, uid);
982   if (!RestoreSharedDataDirectories(apps_rw, pkgid))
983     return false;
984
985   if (!::SetPackageDirectoryOwnerAndPermissions(apps_rw / pkgid, uid))
986     return false;
987
988   std::vector<std::string> shared_dirs(kSharedDataEntries);
989   for (const auto& entry : shared_dirs) {
990     bf::path shared_dst = apps_rw / entry / pkgid;
991     if (!::SetPackageDirectoryOwnerAndPermissions(shared_dst, uid))
992       return false;
993   }
994
995   std::string error_message;
996   if (!RegisterSecurityContextForPath(pkgid, apps_rw / pkgid, uid, false,
997                                       &error_message)) {
998     LOG(ERROR) << "Failed to register security context for path: " << apps_rw
999                << ", error_message: " << error_message;
1000     return false;
1001   }
1002
1003   return true;
1004 }
1005
1006 bool RestorePerUserSharedDataDir(const std::string& pkgid) {
1007   bf::path skel_apps_rw = bf::path(tzplatform_getenv(TZ_SYS_ETC)) /
1008       bf::path(kSkelAppDir);
1009   if (!RestoreSharedDataDirectories(skel_apps_rw, pkgid))
1010     return false;
1011
1012   std::string error_message;
1013   ci::UserList list = ci::GetUserList();
1014   for (const auto& l : list) {
1015     uid_t uid = std::get<0>(l);
1016     bf::path owner_apps_rw = ci::GetRootAppPath(false, uid);
1017     std::vector<bf::path> apps_rw_paths;
1018     apps_rw_paths.push_back(std::move(owner_apps_rw));
1019     for (auto& lw_user : GetLightUserList(uid))
1020       apps_rw_paths.push_back(std::get<2>(l) / kSubssesionDir / lw_user /
1021                               "apps_rw");
1022
1023     for (auto& apps_rw : apps_rw_paths) {
1024       if (!RestoreSharedDataDirectories(apps_rw, pkgid))
1025         return false;
1026
1027       if (!::SetPackageDirectoryOwnerAndPermissions(apps_rw / pkgid, uid))
1028         return false;
1029
1030       std::vector<std::string> shared_dirs(kSharedDataEntries);
1031       for (const auto& entry : shared_dirs) {
1032         bf::path shared_dst = apps_rw / entry / pkgid;
1033         if (!::SetPackageDirectoryOwnerAndPermissions(shared_dst, uid))
1034           return false;
1035       }
1036
1037       if (!RegisterSecurityContextForPath(pkgid, apps_rw / pkgid, uid,
1038               false, &error_message)) {
1039         LOG(ERROR) << "Failed to register security context for path: "
1040                    << apps_rw / pkgid << ", error_message: " << error_message;
1041         return false;
1042       }
1043     }
1044   }
1045
1046   return true;
1047 }
1048
1049 bool RemoveBackupSharedDataDir(const std::string& pkgid, uid_t uid) {
1050   bf::path apps_rw = ci::GetRootAppPath(false, uid);
1051   return RemoveBackupSharedDataDirectories(apps_rw, pkgid);
1052 }
1053
1054 bool RemoveBackupPerUserSharedDataDir(const std::string& pkgid) {
1055   bf::path skel_apps_rw = bf::path(tzplatform_getenv(TZ_SYS_ETC)) /
1056       bf::path(kSkelAppDir);
1057   if (!RemoveBackupSharedDataDirectories(skel_apps_rw, pkgid))
1058     return false;
1059
1060   ci::UserList list = ci::GetUserList();
1061   for (const auto& l : list) {
1062     uid_t uid = std::get<0>(l);
1063     bf::path owner_apps_rw = ci::GetRootAppPath(false, uid);
1064     std::vector<bf::path> apps_rw_paths;
1065     apps_rw_paths.push_back(std::move(owner_apps_rw));
1066     for (auto& lw_user : GetLightUserList(uid))
1067       apps_rw_paths.push_back(std::get<2>(l) / kSubssesionDir / lw_user /
1068                               "apps_rw");
1069
1070     for (auto& apps_rw : apps_rw_paths) {
1071       if (!RemoveBackupSharedDataDirectories(apps_rw, pkgid))
1072         return false;
1073     }
1074   }
1075
1076   return true;
1077 }
1078
1079 }  // namespace common_installer