Change shared/data handle logic
[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::Remove(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       bf::path resolved_path = bf::read_symlink(current, error);
292       if (error) {
293         LOG(ERROR) << "Getting resolved path of symlink: " << current;
294         LOG(ERROR) << "resolved_path: " << resolved_path;
295         LOG(ERROR) << "error: " << error.message();
296         return false;
297       }
298       LOG(DEBUG) << "resolved_path: " << resolved_path;
299       bf::path parent = resolved_path.parent_path();
300       if (!parent.empty() && (parent == src_dir)) {
301         bf::remove(current, error);
302         if (error) {
303           LOG(ERROR) << "Symlink deletion failure for: " << current
304                      << ", error: " << error.message();
305           return false;
306         }
307         LOG(DEBUG) << "removed: " << current;
308       } else {
309         LOG(WARNING) << "Parent is empty or not equal to src, parenet: ("
310                    << parent << ")";
311       }
312     }
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 }  // namespace
375
376 namespace common_installer {
377
378 std::string GetDirectoryPathForInternalStorage() {
379   const char* internal_storage_prefix = tzplatform_getenv(TZ_SYS_HOME);
380   if (internal_storage_prefix)
381     return std::string(internal_storage_prefix);
382   return tzplatform_getenv(TZ_SYS_HOME);
383 }
384
385 std::string GetDirectoryPathForExternalStorage() {
386   return GetExternalCardPath().string();
387 }
388
389 bool PerformExternalDirectoryCreationForUser(uid_t user,
390                                              const std::string& pkgid) {
391   bf::path storage_path = GetExternalCardPath();
392
393   const bool set_permissions = false;
394   if (!bf::exists(storage_path)) {
395     LOG(WARNING) << "External storage (SD Card) is not mounted.";
396     return false;
397   }
398
399   bf::path storage_apps_path = storage_path / "apps";
400   if (!bf::exists(storage_apps_path)) {
401     bs::error_code error;
402     bf::create_directories(storage_apps_path, error);
403     if (error) {
404       LOG(ERROR) << "Failed to create directory: "
405           << storage_apps_path.c_str();
406       return false;
407     }
408   }
409
410   CreateUserDirectories(user, pkgid,
411                             storage_apps_path.c_str(), set_permissions);
412   return true;
413 }
414
415 bool PerformExternalDirectoryDeletionForUser(uid_t user,
416                                              const std::string& pkgid) {
417   bf::path storage_path = GetExternalCardPath();
418   if (!bf::exists(storage_path)) {
419     LOG(WARNING) << "External storage (SD Card) is not mounted. "
420         << "It will be ignored";
421     return true;
422   }
423
424   bf::path storage_apps_path = bf::path(storage_path) / "apps";
425   return DeleteDirectories(
426       GetDirectoryPathForStorage(user, storage_apps_path.string()), pkgid);
427 }
428
429 bool PerformExternalDirectoryCreationForAllUsers(const std::string& pkgid) {
430   UserList list = ci::GetUserList();
431   for (auto l : list) {
432     if (!PerformExternalDirectoryCreationForUser(std::get<0>(l),
433                                                  pkgid))
434       LOG(WARNING) << "Could not create external storage directories for user: "
435                    << std::get<0>(l);
436   }
437   return true;
438 }
439
440 bool PerformExternalDirectoryCreationForAllPkgs() {
441   UserList list = ci::GetUserList();
442   for (auto l  : list) {
443     uid_t uid = std::get<0>(l);
444     pkgmgrinfo_pkginfo_filter_h filter_handle = nullptr;
445     int ret = pkgmgrinfo_pkginfo_filter_create(&filter_handle);
446     if (ret != PMINFO_R_OK)
447       return false;
448     ret = pkgmgrinfo_pkginfo_filter_add_string(filter_handle,
449         PMINFO_PKGINFO_PROP_PACKAGE_PRIVILEGE, kExternalStoragePrivilege);
450     if (ret != PMINFO_R_OK) {
451       pkgmgrinfo_pkginfo_filter_destroy(filter_handle);
452       return false;
453     }
454
455     ret = pkgmgrinfo_pkginfo_filter_foreach_pkginfo(filter_handle,
456         [](const pkgmgrinfo_pkginfo_h handle, void* user_data) -> int {
457           uid_t uid =
458               static_cast<uid_t>(reinterpret_cast<uintptr_t>(user_data));
459           char* pkgid = nullptr;
460
461           int ret = pkgmgrinfo_pkginfo_get_pkgid(handle, &pkgid);
462           if (ret != PMINFO_R_OK)
463             return -1;
464           if (!PerformExternalDirectoryCreationForUser(uid, pkgid))
465             return -1;
466
467           return 0;
468         },
469         reinterpret_cast<void*>(static_cast<uintptr_t>(uid)));
470     if (ret != PMINFO_R_OK) {
471       LOG(DEBUG) << "Failed to create external directoy";
472       pkgmgrinfo_pkginfo_filter_destroy(filter_handle);
473       return false;
474     }
475     pkgmgrinfo_pkginfo_filter_destroy(filter_handle);
476   }
477
478   return true;
479 }
480
481 bool PerformExternalDirectoryDeletionForAllUsers(const std::string& pkgid) {
482   UserList list = ci::GetUserList();
483   for (auto l : list) {
484     uid_t uid = std::get<0>(l);
485     ci::PkgQueryInterface pkg_query(pkgid, uid);
486     LOG(DEBUG) << "Deleting directories for user: " << uid;
487     if (pkg_query.IsPackageInstalled()) {
488       LOG(DEBUG) << "Package: " << pkgid << " for uid: " << uid
489                  << " still exists. Skipping";
490       continue;
491     }
492
493     if (!PerformExternalDirectoryDeletionForUser(uid, pkgid))
494       LOG(WARNING) << "Could not delete external storage directories for user: "
495                    << uid;
496   }
497   return true;
498 }
499
500 bool CreateStorageDirectories(const boost::filesystem::path& path,
501                               const std::string& pkgid, uid_t uid,
502                               bool trusted, bool shareddata) {
503   if (!::CreateStorageDirectories(path, pkgid, trusted,
504                                   shareddata, std::vector<const char*>())) {
505     LOG(ERROR) << "Failed to create storage directory for path: " << path;
506     return false;
507   }
508
509   std::string error_message;
510   if (!RegisterSecurityContextForPath(pkgid, path, uid, false,
511                                       &error_message)) {
512     LOG(ERROR) << "Failed to register security context for path: " << path
513                << ", error_message: " << error_message;
514     return false;
515   }
516
517   return true;
518 }
519
520 bool DeleteStorageDirectories(const boost::filesystem::path& path,
521                               const std::string& pkgid) {
522   std::vector<const char*> dirs;
523   dirs.assign(kEntries.begin() + 1, kEntries.end());
524   dirs.push_back(kSharedTrustedDir);
525   dirs.push_back(kSharedCacheDir);
526   for (auto& entry : dirs) {
527     bf::path subpath = path / pkgid / entry;
528     if (!ci::RemoveAll(subpath))
529       return false;
530   }
531   if (!DeleteSharedDataDirectories(path, pkgid))
532     return false;
533
534   return true;
535 }
536
537 bool DeleteSharedDirectories(const bf::path& path,
538                              const std::string& pkgid) {
539   return DeleteSharedDataDirectories(path, pkgid);
540 }
541
542 bool CreateSkelDirectories(const std::string& pkgid,
543                            bool trusted, bool shareddata, bool is_readonly,
544                            const std::vector<const char*> additional_dirs) {
545   bf::path root_path = bf::path(tzplatform_getenv(TZ_SYS_ETC)) /
546                        bf::path(kSkelAppDir);
547
548   if (!::CreateStorageDirectories(root_path, pkgid, trusted,
549                                   shareddata, additional_dirs)) {
550     LOG(ERROR) << "Failed to create storage directory for path: "
551                << root_path / pkgid;
552     return false;
553   }
554
555   std::string error_message;
556   if (!RegisterSecurityContextForPath(pkgid, root_path / pkgid, kGlobalUserUid,
557                                       is_readonly, &error_message)) {
558     LOG(ERROR) << "Failed to register security context for path: "
559                << root_path / pkgid
560                << ", error_message: " << error_message;
561     return false;
562   }
563
564   bool result = true;
565   if (!is_readonly) {
566     bf::path src_dir = bf::path(tzplatform_getenv(TZ_SYS_RW_APP)) / pkgid;
567     result = CreateSymlinkFiles(src_dir, root_path / pkgid);
568   }
569
570   return result;
571 }
572
573 bool UpdateSkelDirectories(const std::string& pkgid,
574                            bool is_remove_shareddata) {
575   bf::path root_path = bf::path(tzplatform_getenv(TZ_SYS_ETC)) /
576                        bf::path(kSkelAppDir);
577   LOG(DEBUG) << ((is_remove_shareddata) ? "Removing" : "Creating")
578              << " skel directory for pkgid: " << pkgid;
579   if (is_remove_shareddata) {
580     if (!DeleteSharedDataDirectories(root_path, pkgid))
581       return false;
582     return true;
583   }
584
585   if (!CreateSharedDataDirectories(root_path, pkgid))
586     return false;
587
588   std::string error_message;
589   if (!RegisterSecurityContextForPath(pkgid, root_path / pkgid, kGlobalUserUid,
590                                       false, &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   return true;
598 }
599
600 bool DeleteSkelDirectories(const std::string& pkgid) {
601   bf::path path = bf::path(tzplatform_getenv(TZ_SYS_ETC)) /
602                   bf::path(kSkelAppDir);
603   if (!DeleteDirectories(path, pkgid))
604     return false;
605
606   return DeleteSharedDataDirectories(
607       bf::path(tzplatform_getenv(TZ_SYS_ETC)) / bf::path(kSkelAppDir), pkgid);
608 }
609
610
611 bool DeleteUserDirectories(const std::string& pkgid) {
612   UserList list = ci::GetUserList();
613   for (auto l : list) {
614     uid_t uid = std::get<0>(l);
615     ci::PkgQueryInterface pkg_query(pkgid, uid);
616     if (pkg_query.IsPackageInstalled()) {
617       LOG(INFO) << pkgid << " is installed for user " << std::get<0>(l);
618       continue;
619     }
620
621     LOG(DEBUG) << "Deleting directories of " << pkgid
622                << ", for uid: " << std::get<0>(l);
623     bf::path apps_rw(std::get<2>(l) / "apps_rw");
624     if (!DeleteDirectories(apps_rw, pkgid)) {
625       return false;
626     }
627   }
628   return true;
629 }
630
631 bool DeleteUserExternalDirectories(const std::string& pkgid) {
632   UserList list = ci::GetUserList();
633   for (auto l : list) {
634     uid_t uid = std::get<0>(l);
635     ci::PkgQueryInterface pkg_query(pkgid, uid);
636     if (pkg_query.IsPackageInstalled()) {
637       LOG(INFO) << pkgid << " is installed for user " << uid;
638       continue;
639     }
640
641     LOG(DEBUG) << "Deleting external directories of " << pkgid
642                << ", for uid: " << uid;
643     bf::path apps_rw(std::get<2>(l) / "apps_rw");
644     if (!DeleteDirectories(apps_rw, pkgid)) {
645       return false;
646     }
647   }
648   return true;
649 }
650
651 bool CopyUserDirectories(const std::string& pkgid) {
652   UserList list = ci::GetUserList();
653   for (auto l : list) {
654     uid_t uid = std::get<0>(l);
655     gid_t gid = std::get<1>(l);
656     LOG(DEBUG) << "Copying directories for uid: " << uid;
657     bf::path apps_rw(std::get<2>(l) / "apps_rw");
658     bf::path src = bf::path(tzplatform_getenv(TZ_SYS_ETC)) /
659                    bf::path(kSkelAppDir) / pkgid;
660     bf::path dst = apps_rw / pkgid;
661     if (!ci::CopyDir(src, dst, FSFlag::FS_NONE, false))
662       continue;
663
664     std::vector<std::string> shared_dirs(kSharedDataEntries);
665     for (auto entry : shared_dirs) {
666       bf::path shared_src = bf::path(tzplatform_getenv(TZ_SYS_ETC)) /
667           bf::path(kSkelAppDir) / entry / pkgid;
668       if (!bf::exists(shared_src))
669         break;
670
671       bf::path shared_dst = apps_rw / entry / pkgid;
672       if (!ci::CopyDir(shared_src, shared_dst, FSFlag::FS_NONE, true))
673         continue;
674
675       if (!SetDirectoryOwnerAndPermissions(shared_dst, uid, gid))
676         return false;
677
678       for (bf::recursive_directory_iterator iter(dst);
679           iter != bf::recursive_directory_iterator(); ++iter) {
680         if (!SetSharedDirOwnerAndPermissions(iter->path(), uid))
681           return false;
682       }
683     }
684
685     if (!SetDirectoryOwnerAndPermissions(dst, uid, gid))
686       return false;
687     for (bf::recursive_directory_iterator iter(dst);
688         iter != bf::recursive_directory_iterator(); ++iter) {
689       if (!SetDirectoryOwnerAndPermissions(iter->path(),
690           uid, gid))
691         return false;
692     }
693     std::string error_message;
694     if (!RegisterSecurityContextForPath(pkgid, dst, uid,
695         false, &error_message)) {
696       LOG(ERROR) << "Failed to register security context for path: " << dst
697                  << ", error_message: " << error_message;
698       return false;
699     }
700   }
701   return true;
702 }
703
704 bool CreateSharedData(const bf::path& path,
705                       const std::string& pkgid) {
706   return CreateSharedDataDirectories(path, pkgid);
707 }
708
709 bool UpdateUserDirectory(const std::string& pkgid, bool is_remove_shareddata) {
710   UserList list = ci::GetUserList();
711   for (auto l : list) {
712     bf::path root_path(std::get<2>(l) / "apps_rw");
713     bf::path pkg_path(root_path / pkgid);
714     uid_t uid = std::get<0>(l);
715     LOG(DEBUG) << ((is_remove_shareddata) ? "Deleting" : "Adding")
716                << " shareddata directory for uid: " << uid;
717
718     if (is_remove_shareddata)
719       return DeleteSharedDataDirectories(root_path, pkgid);
720
721     if (!CreateSharedDataDirectories(root_path, pkgid)) {
722       LOG(ERROR) << "Failed to create shared directory: "
723                  << root_path / pkgid;
724       return false;
725     }
726
727     gid_t gid = std::get<1>(l);
728     std::vector<std::string> shared_dirs(kSharedDataEntries);
729     for (auto entry : shared_dirs) {
730       bf::path dst = root_path / entry / pkgid;
731       if (!SetDirectoryOwnerAndPermissions(dst, uid, gid))
732         return false;
733       for (bf::recursive_directory_iterator iter(dst);
734           iter != bf::recursive_directory_iterator(); ++iter) {
735         if (!SetSharedDirOwnerAndPermissions(iter->path(), uid))
736           return false;
737       }
738     }
739
740     if (!SetDirectoryOwnerAndPermissions(pkg_path, uid, gid))
741       return false;
742     for (bf::recursive_directory_iterator iter(pkg_path);
743         iter != bf::recursive_directory_iterator(); ++iter) {
744       if (!SetDirectoryOwnerAndPermissions(iter->path(),
745           uid, gid))
746         return false;
747     }
748
749     std::string error_message;
750     if (!RegisterSecurityContextForPath(pkgid, pkg_path, uid,
751         false, &error_message)) {
752       LOG(ERROR) << "Failed to register security context for path: "
753                   << pkg_path << ", error_message: " << error_message;
754       return false;
755     }
756   }
757   return true;
758 }
759
760 bool CreateGlobalAppSymlinksForAllUsers(const std::string& pkgid) {
761   bf::path src_dir = bf::path(tzplatform_getenv(TZ_SYS_RW_APP)) / pkgid;
762   if (!bf::exists(src_dir)) {
763     LOG(ERROR) << "src_dir not exists";
764     return false;
765   }
766
767   bool result = true;
768   UserList list = ci::GetUserList();
769   for (auto l : list) {
770     uid_t uid = std::get<0>(l);
771     LOG(DEBUG) << "Creating symlinks for uid: " << uid;
772     // check installed user private app.
773     ci::PkgQueryInterface pkg_query(pkgid, uid);
774     if (pkg_query.IsPackageInstalled())
775       continue;
776     bf::path apps_rw(std::get<2>(l) / "apps_rw");
777     bf::path dst_dir = apps_rw / pkgid;
778     if (!bf::exists(dst_dir)) {
779       LOG(WARNING) << "dst_dir not exists";
780       continue;
781     }
782     result = CreateSymlinkFiles(src_dir, dst_dir);
783   }
784   return result;
785 }
786
787 bool CreateGlobalAppSymlinksForUser(const std::string& pkgid, uid_t uid) {
788   bf::path src_dir = bf::path(tzplatform_getenv(TZ_SYS_RW_APP)) / pkgid;
789   if (!bf::exists(src_dir)) {
790     LOG(WARNING) << "src_dir(" << src_dir << ") not exists";
791     return true;
792   }
793
794   tzplatform_set_user(uid);
795   bf::path dst_dir = bf::path(tzplatform_getenv(TZ_USER_APP)) / pkgid;
796   tzplatform_reset_user();
797   if (!bf::exists(dst_dir)) {
798     LOG(WARNING) << "dst_dir not exists";
799     return true;
800   }
801   bool result = CreateSymlinkFiles(src_dir, dst_dir);
802
803   return result;
804 }
805
806 bool DeleteGlobalAppSymlinksForAllUsers(const std::string& pkgid) {
807   bf::path src_dir = bf::path(tzplatform_getenv(TZ_SYS_RW_APP)) / pkgid;
808   if (!bf::exists(src_dir)) {
809     LOG(WARNING) << "src_dir(" << src_dir << ") not exists";
810     return true;
811   }
812
813   bool result = true;
814   UserList list = ci::GetUserList();
815   for (auto l : list) {
816     uid_t uid = std::get<0>(l);
817     LOG(DEBUG) << "Deleting symlinks for uid: " << uid;
818     // check installed user private app.
819     ci::PkgQueryInterface pkg_query(pkgid, uid);
820     if (pkg_query.IsPackageInstalled())
821       continue;
822     bf::path apps_rw(std::get<2>(l) / "apps_rw");
823     bf::path dst_dir = apps_rw / pkgid;
824     if (!bf::exists(dst_dir)) {
825       LOG(WARNING) << "dst_dir not exists";
826       continue;
827     }
828     result = DeleteSymlinkFiles(src_dir, dst_dir);
829   }
830   return result;
831 }
832
833 bool DeleteGlobalAppSymlinksForUser(const std::string& pkgid, uid_t uid) {
834   bf::path src_dir = bf::path(tzplatform_getenv(TZ_SYS_RW_APP)) / pkgid;
835   if (!bf::exists(src_dir)) {
836     LOG(ERROR) << "src_dir not exists";
837     return false;
838   }
839
840   tzplatform_set_user(uid);
841   bf::path dst_dir = bf::path(tzplatform_getenv(TZ_USER_APP)) / pkgid;
842   tzplatform_reset_user();
843   if (!bf::exists(dst_dir)) {
844     LOG(WARNING) << "dst_dir not exists";
845     return true;
846   }
847   bool result = DeleteSymlinkFiles(src_dir, dst_dir);
848   return result;
849 }
850
851 bool SetPackageDirectoryOwnerAndPermissions(const bf::path& path, uid_t uid) {
852   boost::optional<gid_t> gid = ci::GetGidByUid(uid);
853   if (!gid)
854     return false;
855   bf::perms perms644 =
856       bf::owner_read | bf::owner_write | bf::group_read | bf::others_read;
857   bf::perms perms755 =
858       perms644 | bf::owner_exe | bf::group_exe | bf::others_exe;
859   for (bf::recursive_directory_iterator iter(path);
860       iter != bf::recursive_directory_iterator(); ++iter) {
861     if (bf::is_symlink(symlink_status(iter->path())) ||
862         (bf::is_directory(iter->path()) &&
863         (iter->path().filename() == ".mmc" ||
864             iter->path().filename() == ".pkg" ||
865             iter->path().filename() == "tep"))) {
866       // skip symlink or path which is related to
867       // mount or directory installer creates
868       continue;
869     } else if (bf::is_directory(iter->path())) {
870       // directories
871       if (!SetDirectoryOwnerAndPermissions(iter->path(), uid, *gid))
872         return false;
873     } else if (iter.level() == 1 &&
874         iter->path().parent_path().filename() == "bin") {
875       // bin files
876       if (!SetDirOwnershipAndPermissions(iter->path(), perms755, uid, *gid))
877         return false;
878     } else {
879       // other files
880       if (!SetDirOwnershipAndPermissions(iter->path(), perms644, uid, *gid))
881         return false;
882     }
883   }
884   return true;
885 }
886
887 bool ShouldSupportLegacySharedDataDir(const std::string& api_version) {
888   if (bf::exists(kDisableLegacySharedDataDirSupport))
889     return false;
890   utils::VersionNumber api_ver(api_version);
891   if (api_ver < ver30)
892     return true;
893   else
894     return false;
895 }
896
897 }  // namespace common_installer