Fix codes for efficiency
[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
69 const char kSharedResDir[] = "shared/res";
70 const char kSharedCacheDir[] = "shared/cache";
71 const char kSharedDataDir[] = "shared/data";
72 const char kSharedTrustedDir[] = "shared/trusted";
73 const char kSkelAppDir[] = "skel/apps_rw";
74 const char kExternalStoragePrivilege[] =
75     "http://tizen.org/privilege/externalstorage.appdata";
76 const char kSystemShareGroupName[] = "system_share";
77
78 bool SetDirectoryOwnerAndPermissions(const bf::path& subpath, uid_t uid,
79                                      gid_t gid) {
80   // symlink and non directory will be skipped
81   if (bf::is_symlink(symlink_status(subpath)) || !bf::is_directory(subpath))
82     return true;
83
84   bf::perms perms = bf::all_all ^ bf::group_write ^ bf::others_write;
85   if (subpath.filename() == "data" || subpath.filename() == "cache") {
86     perms |= bf::group_write | bf::set_gid_on_exe;
87     boost::optional<gid_t> system_share =
88         ci::GetGidByGroupName(kSystemShareGroupName);
89     if (!system_share)
90       return false;
91     gid = *system_share;
92   }
93   return common_installer::SetDirOwnershipAndPermissions(subpath, perms,
94                                                          uid, gid);
95 }
96
97 bool CreateDirectories(const bf::path& app_dir, const std::string& pkgid,
98                        uid_t uid, gid_t gid, const bool set_permissions,
99                        const std::vector<const char*>
100                        additional_dirs = std::vector<const char*>()) {
101   bf::path base_dir = app_dir / pkgid;
102   if (bf::exists(base_dir)) {
103     LOG(DEBUG) << "Directory for user already exist: " << base_dir;
104     return true;
105   } else {
106     bs::error_code error;
107     bf::create_directories(base_dir, error);
108     if (error) {
109       LOG(ERROR) << "Failed to create directory: " << base_dir;
110       return false;
111     }
112   }
113
114   bs::error_code error;
115   std::vector<const char*> dirs(kEntries);
116   dirs.insert(dirs.end(), additional_dirs.begin(), additional_dirs.end());
117   // always trusted
118   dirs.push_back(kSharedTrustedDir);
119   for (auto& entry : dirs) {
120     bf::path subpath = base_dir / entry;
121     bf::create_directories(subpath, error);
122     if (error) {
123       LOG(ERROR) << "Failed to create directory: " << subpath;
124       return false;
125     }
126
127     if (set_permissions) {
128       if (!SetDirectoryOwnerAndPermissions(subpath, uid, gid))
129         return false;
130
131       // for content
132       for (bf::recursive_directory_iterator iter(subpath);
133            iter != bf::recursive_directory_iterator(); ++iter) {
134         if (!SetDirectoryOwnerAndPermissions(iter->path(), uid, gid))
135           return false;
136       }
137     }
138   }
139
140   return true;
141 }
142
143 bf::path GetDirectoryPathForStorage(uid_t user, std::string apps_prefix) {
144   std::string username = ci::GetUsernameByUid(user);
145   if (username.empty())
146     return {};
147
148   bf::path apps_rw;
149   apps_rw = bf::path(apps_prefix.c_str()) / username / "apps_rw";
150   return apps_rw;
151 }
152
153 bool CreateUserDirectories(uid_t user, const std::string& pkgid,
154     const std::string& apps_prefix, const bool set_permissions) {
155   boost::optional<gid_t> gid = ci::GetGidByUid(user);
156   if (!gid)
157     return false;
158
159   std::string group_name = ci::GetGroupNameByGid(*gid);
160   if (group_name != tzplatform_getenv(TZ_SYS_USER_GROUP))
161     return false;
162
163   LOG(DEBUG) << "Creating directories for uid: " << user << ", gid: "
164              << *gid;
165
166   bf::path apps_rw = GetDirectoryPathForStorage(user, apps_prefix);
167   if (apps_rw.empty()) {
168     LOG(DEBUG) << "Directory not exists: " << apps_rw;
169     return false;
170   }
171
172   if (!CreateDirectories(apps_rw, pkgid,
173      user, *gid, set_permissions)) {
174     return false;
175   }
176   return true;
177 }
178
179 bool DeleteDirectories(const bf::path& app_dir, const std::string& pkgid) {
180   bf::path base_dir = app_dir / pkgid;
181   return ci::RemoveAll(base_dir);
182 }
183
184
185 bool CreateSymlinkFiles(const bf::path& src_dir, const bf::path& dst_dir) {
186   std::vector<std::string> rofiles(kReadOnlyEntries);
187   for (bf::directory_iterator file(src_dir);
188       file != bf::directory_iterator();
189       ++file) {
190     if (bf::is_regular_file(file->path())) {
191       bf::path current(file->path());
192       bf::path file_name = current.filename();
193       LOG(DEBUG) << "file_name: " << file_name;
194       rofiles.push_back(file_name.string());
195     }
196   }
197
198   bs::error_code error;
199   for (auto& entry : rofiles) {
200     bf::path src_path = src_dir / entry;
201     bf::path dst_path = dst_dir / entry;
202     if (!bf::exists(src_path)) {
203       // check if symlink for .mmc/bin,lib,res, then do not skip
204       if (!bf::is_symlink(symlink_status(src_path))) {
205         LOG(INFO) << "src_path not exist : " << src_path;
206         continue;
207       }
208     }
209     if (bf::exists(dst_path) || bf::is_symlink(symlink_status(dst_path))) {
210       LOG(WARNING) << "dst_path exist, skip : " << dst_path;
211       continue;
212     }
213     bf::create_symlink(src_path, dst_path, error);
214     if (error) {
215       LOG(ERROR) << "Symlink creation failure src_path: " << src_path
216                  << " dst_path: " << dst_path;
217       LOG(ERROR) << "error: " << error.message();
218       return false;
219     }
220   }
221   return true;
222 }
223
224 bool DeleteSymlinkFiles(const bf::path& src_dir, const bf::path& dst_dir) {
225   bs::error_code error;
226   for (bf::directory_iterator file(dst_dir);
227       file != bf::directory_iterator();
228       ++file) {
229     bf::path current(file->path());
230     if (bf::is_symlink(symlink_status(current))) {
231       bf::path resolved_path = bf::read_symlink(current, error);
232       if (error) {
233         LOG(ERROR) << "Getting resolved path of symlink: " << current;
234         LOG(ERROR) << "resolved_path: " << resolved_path;
235         LOG(ERROR) << "error: " << error.message();
236         return false;
237       }
238       LOG(DEBUG) << "resolved_path: " << resolved_path;
239       bf::path parent = resolved_path.parent_path();
240       if (!parent.empty() && (parent == src_dir)) {
241         bf::remove(current, error);
242         if (error) {
243           LOG(ERROR) << "Symlink deletion failure for: " << current
244                      << ", error: " << error.message();
245           return false;
246         }
247         LOG(DEBUG) << "removed: " << current;
248       } else {
249         LOG(WARNING) << "Parent is empty or not equal to src, parenet: ("
250                    << parent << ")";
251       }
252     }
253   }
254   bf::path shared_res = dst_dir / kSharedResDir;
255   if (bf::is_symlink(symlink_status(shared_res))) {
256       bf::remove(shared_res, error);
257       if (error) {
258           LOG(ERROR) << "Symlink deletion failure for: " << shared_res
259                      << ", error: " << error.message();
260           return false;
261       }
262   }
263   return true;
264 }
265
266 bool CreateStorageDirectories(const boost::filesystem::path& path,
267                               bool trusted, bool shareddata,
268                               const std::vector<const char*> additional_dirs) {
269   if (!bf::exists(path)) {
270     LOG(DEBUG) << "Creating directories in: " << path;
271     bs::error_code error;
272     bf::create_directories(path, error);
273     if (error) {
274       LOG(ERROR) << "Failed to create directory: " << path;
275       return false;
276     }
277   }
278
279   std::vector<const char*> dirs(kEntries);
280   dirs.insert(dirs.end(), additional_dirs.begin(), additional_dirs.end());
281   if (trusted)
282     dirs.push_back(kSharedTrustedDir);
283   if (shareddata) {
284     dirs.push_back(kSharedDataDir);
285   } else {
286     bf::path shared_data_path = path / kSharedDataDir;
287     // remove shared/data (deprecated)
288     if (!ci::RemoveAll(shared_data_path))
289       return false;
290   }
291   for (auto& entry : dirs) {
292     bs::error_code error;
293     bf::path subpath = path / entry;
294     bf::create_directories(subpath, error);
295     if (error && !bf::exists(subpath)) {
296       LOG(ERROR) << "Failed to create directory: " << subpath;
297       return false;
298     }
299   }
300
301   bf::path shared_cache_path = path / kSharedCacheDir;
302   // remove shared/cache (do not support)
303   if (!ci::RemoveAll(shared_cache_path))
304     return false;
305
306   return true;
307 }
308
309 }  // namespace
310
311 namespace common_installer {
312
313 std::string GetDirectoryPathForInternalStorage() {
314   const char* internal_storage_prefix = tzplatform_getenv(TZ_SYS_HOME);
315   if (internal_storage_prefix)
316     return std::string(internal_storage_prefix);
317   return tzplatform_getenv(TZ_SYS_HOME);
318 }
319
320 std::string GetDirectoryPathForExternalStorage() {
321   return GetExternalCardPath().string();
322 }
323
324 bool PerformExternalDirectoryCreationForUser(uid_t user,
325                                              const std::string& pkgid) {
326   bf::path storage_path = GetExternalCardPath();
327
328   const bool set_permissions = false;
329   if (!bf::exists(storage_path)) {
330     LOG(WARNING) << "External storage (SD Card) is not mounted.";
331     return false;
332   }
333
334   bf::path storage_apps_path = storage_path / "apps";
335   if (!bf::exists(storage_apps_path)) {
336     bs::error_code error;
337     bf::create_directories(storage_apps_path, error);
338     if (error) {
339       LOG(ERROR) << "Failed to create directory: "
340           << storage_apps_path.c_str();
341       return false;
342     }
343   }
344
345   CreateUserDirectories(user, pkgid,
346                             storage_apps_path.c_str(), set_permissions);
347   return true;
348 }
349
350 bool PerformExternalDirectoryDeletionForUser(uid_t user,
351                                              const std::string& pkgid) {
352   bf::path storage_path = GetExternalCardPath();
353   if (!bf::exists(storage_path)) {
354     LOG(WARNING) << "External storage (SD Card) is not mounted. "
355         << "It will be ignored";
356     return true;
357   }
358
359   bf::path storage_apps_path = bf::path(storage_path) / "apps";
360   return DeleteDirectories(
361       GetDirectoryPathForStorage(user, storage_apps_path.string()), pkgid);
362 }
363
364 bool PerformExternalDirectoryCreationForAllUsers(const std::string& pkgid) {
365   UserList list = ci::GetUserList();
366   for (auto l : list) {
367     if (!PerformExternalDirectoryCreationForUser(std::get<0>(l),
368                                                  pkgid))
369       LOG(WARNING) << "Could not create external storage directories for user: "
370                    << std::get<0>(l);
371   }
372   return true;
373 }
374
375 bool PerformExternalDirectoryCreationForAllPkgs() {
376   UserList list = ci::GetUserList();
377   for (auto l  : list) {
378     uid_t uid = std::get<0>(l);
379     pkgmgrinfo_pkginfo_filter_h filter_handle = nullptr;
380     int ret = pkgmgrinfo_pkginfo_filter_create(&filter_handle);
381     if (ret != PMINFO_R_OK)
382       return false;
383     ret = pkgmgrinfo_pkginfo_filter_add_string(filter_handle,
384         PMINFO_PKGINFO_PROP_PACKAGE_PRIVILEGE, kExternalStoragePrivilege);
385     if (ret != PMINFO_R_OK) {
386       pkgmgrinfo_pkginfo_filter_destroy(filter_handle);
387       return false;
388     }
389
390     ret = pkgmgrinfo_pkginfo_filter_foreach_pkginfo(filter_handle,
391         [](const pkgmgrinfo_pkginfo_h handle, void* user_data) -> int {
392           uid_t uid =
393               static_cast<uid_t>(reinterpret_cast<uintptr_t>(user_data));
394           char* pkgid = nullptr;
395
396           int ret = pkgmgrinfo_pkginfo_get_pkgid(handle, &pkgid);
397           if (ret != PMINFO_R_OK)
398             return -1;
399           if (!PerformExternalDirectoryCreationForUser(uid, pkgid))
400             return -1;
401
402           return 0;
403         },
404         reinterpret_cast<void*>(static_cast<uintptr_t>(uid)));
405     if (ret != PMINFO_R_OK) {
406       LOG(DEBUG) << "Failed to create external directoy";
407       pkgmgrinfo_pkginfo_filter_destroy(filter_handle);
408       return false;
409     }
410     pkgmgrinfo_pkginfo_filter_destroy(filter_handle);
411   }
412
413   return true;
414 }
415
416 bool PerformExternalDirectoryDeletionForAllUsers(const std::string& pkgid) {
417   UserList list = ci::GetUserList();
418   for (auto l : list) {
419     uid_t uid = std::get<0>(l);
420     ci::PkgQueryInterface pkg_query(pkgid, uid);
421     LOG(DEBUG) << "Deleting directories for user: " << uid;
422     if (pkg_query.IsPackageInstalled()) {
423       LOG(DEBUG) << "Package: " << pkgid << " for uid: " << uid
424                  << " still exists. Skipping";
425       continue;
426     }
427
428     if (!PerformExternalDirectoryDeletionForUser(uid, pkgid))
429       LOG(WARNING) << "Could not delete external storage directories for user: "
430                    << uid;
431   }
432   return true;
433 }
434
435 bool CreateStorageDirectories(const boost::filesystem::path& path,
436                               const std::string& pkgid, uid_t uid,
437                               bool trusted, bool shareddata) {
438   if (!::CreateStorageDirectories(path, trusted, shareddata,
439                                   std::vector<const char*>())) {
440     LOG(ERROR) << "Failed to create storage directory for path: " << path;
441     return false;
442   }
443
444   std::string error_message;
445   if (!RegisterSecurityContextForPath(pkgid, path, uid, false,
446                                       &error_message)) {
447     LOG(ERROR) << "Failed to register security context for path: " << path
448                << ", error_message: " << error_message;
449     return false;
450   }
451
452   return true;
453 }
454
455 bool DeleteStorageDirectories(const boost::filesystem::path& path) {
456   std::vector<const char*> dirs;
457   dirs.assign(kEntries.begin() + 1, kEntries.end());
458   dirs.push_back(kSharedTrustedDir);
459   dirs.push_back(kSharedDataDir);
460   dirs.push_back(kSharedCacheDir);
461   for (auto& entry : dirs) {
462     bf::path subpath = path / entry;
463     if (!ci::RemoveAll(subpath))
464       return false;
465   }
466   return true;
467 }
468
469 bool CreateSkelDirectories(const std::string& pkgid,
470                            bool trusted, bool shareddata, bool is_readonly,
471                            const std::vector<const char*> additional_dirs) {
472   bf::path path = bf::path(tzplatform_getenv(TZ_SYS_ETC)) /
473                   bf::path(kSkelAppDir) / pkgid;
474   LOG(DEBUG) << "Creating directories in: " << path;
475
476   if (!::CreateStorageDirectories(path, trusted, shareddata,
477                                   additional_dirs)) {
478     LOG(ERROR) << "Failed to create storage directory for path: " << path;
479     return false;
480   }
481
482   std::string error_message;
483   if (!RegisterSecurityContextForPath(pkgid, path, kGlobalUserUid,
484                                       is_readonly, &error_message)) {
485     LOG(ERROR) << "Failed to register security context for path: " << path
486                << ", error_message: " << error_message;
487     return false;
488   }
489
490   bool result = true;
491   if (!is_readonly) {
492     bf::path src_dir = bf::path(tzplatform_getenv(TZ_SYS_RW_APP)) / pkgid;
493     result = CreateSymlinkFiles(src_dir, path);
494   }
495
496   return result;
497 }
498
499 bool UpdateSkelDirectories(const std::string& pkgid,
500                            bool is_remove_shareddata) {
501   bf::path path = bf::path(tzplatform_getenv(TZ_SYS_ETC)) /
502                   bf::path(kSkelAppDir) / pkgid;
503   bf::path shared_data_path = path / kSharedDataDir;
504   LOG(DEBUG) << ((is_remove_shareddata) ? "Removing" : "Creating")
505              << " directory : " << shared_data_path;
506
507   if (!is_remove_shareddata) {
508     if (!CreateDir(shared_data_path))
509       return false;
510
511     std::string error_message;
512     if (!RegisterSecurityContextForPath(pkgid, path, kGlobalUserUid,
513                                         false, &error_message)) {
514       LOG(ERROR) << "Failed to register security context for path: " << path
515                  << ", error_message: " << error_message;
516       return false;
517     }
518   } else {
519     return ci::RemoveAll(shared_data_path);
520   }
521   return true;
522 }
523
524 bool DeleteSkelDirectories(const std::string& pkgid) {
525   bf::path path = bf::path(tzplatform_getenv(TZ_SYS_ETC)) /
526                   bf::path(kSkelAppDir);
527   return DeleteDirectories(path, pkgid);
528 }
529
530
531 bool DeleteUserDirectories(const std::string& pkgid) {
532   UserList list = ci::GetUserList();
533   for (auto l : list) {
534     uid_t uid = std::get<0>(l);
535     ci::PkgQueryInterface pkg_query(pkgid, uid);
536     if (pkg_query.IsPackageInstalled()) {
537       LOG(INFO) << pkgid << " is installed for user " << std::get<0>(l);
538       continue;
539     }
540
541     LOG(DEBUG) << "Deleting directories of " << pkgid
542                << ", for uid: " << std::get<0>(l);
543     bf::path apps_rw(std::get<2>(l) / "apps_rw");
544     if (!DeleteDirectories(apps_rw, pkgid)) {
545       return false;
546     }
547   }
548   return true;
549 }
550
551 bool DeleteUserExternalDirectories(const std::string& pkgid) {
552   UserList list = ci::GetUserList();
553   for (auto l : list) {
554     uid_t uid = std::get<0>(l);
555     ci::PkgQueryInterface pkg_query(pkgid, uid);
556     if (pkg_query.IsPackageInstalled()) {
557       LOG(INFO) << pkgid << " is installed for user " << uid;
558       continue;
559     }
560
561     LOG(DEBUG) << "Deleting external directories of " << pkgid
562                << ", for uid: " << uid;
563     bf::path apps_rw(std::get<2>(l) / "apps_rw");
564     if (!DeleteDirectories(apps_rw, pkgid)) {
565       return false;
566     }
567   }
568   return true;
569 }
570
571 bool CopyUserDirectories(const std::string& pkgid) {
572   UserList list = ci::GetUserList();
573   for (auto l : list) {
574     uid_t uid = std::get<0>(l);
575     LOG(DEBUG) << "Copying directories for uid: " << uid;
576     bf::path apps_rw(std::get<2>(l) / "apps_rw");
577     bf::path src = bf::path(tzplatform_getenv(TZ_SYS_ETC)) /
578                    bf::path(kSkelAppDir) / pkgid;
579     bf::path dst = apps_rw / pkgid;
580     if (!ci::CopyDir(src, dst, FSFlag::FS_NONE, true))
581       continue;
582     gid_t gid = std::get<1>(l);
583     if (!SetDirectoryOwnerAndPermissions(dst, uid, gid))
584       return false;
585     for (bf::recursive_directory_iterator iter(dst);
586         iter != bf::recursive_directory_iterator(); ++iter) {
587       if (!SetDirectoryOwnerAndPermissions(iter->path(),
588           uid, gid))
589         return false;
590     }
591     std::string error_message;
592     if (!RegisterSecurityContextForPath(pkgid, dst, uid,
593         false, &error_message)) {
594       LOG(ERROR) << "Failed to register security context for path: " << dst
595                  << ", error_message: " << error_message;
596       return false;
597     }
598   }
599   return true;
600 }
601
602 bool UpdateUserDirectory(const std::string& pkgid, bool is_remove_shareddata) {
603   UserList list = ci::GetUserList();
604   for (auto l : list) {
605     bf::path apps_rw(std::get<2>(l) / "apps_rw");
606     bf::path root_dst = apps_rw / pkgid;
607     bf::path shareddir_dst = root_dst / kSharedDataDir;
608     uid_t uid = std::get<0>(l);
609     LOG(DEBUG) << ((is_remove_shareddata) ? "Deleting" : "Adding")
610                << " shareddata directory for uid: " << uid;
611
612     if (!is_remove_shareddata) {
613       bs::error_code error;
614       bf::create_directories(shareddir_dst, error);
615       if (error && !bf::exists(shareddir_dst)) {
616         LOG(ERROR) << "Failed to create directory: " << shareddir_dst;
617         return false;
618       }
619
620       gid_t gid = std::get<1>(l);
621       if (!SetDirectoryOwnerAndPermissions(root_dst, uid, gid))
622         return false;
623       for (bf::recursive_directory_iterator iter(root_dst);
624           iter != bf::recursive_directory_iterator(); ++iter) {
625         if (!SetDirectoryOwnerAndPermissions(iter->path(),
626             uid, gid))
627           return false;
628       }
629
630       std::string error_message;
631       if (!RegisterSecurityContextForPath(pkgid, root_dst, uid,
632           false, &error_message)) {
633         LOG(ERROR) << "Failed to register security context for path: "
634                    << root_dst << ", error_message: " << error_message;
635         return false;
636       }
637     } else {
638       return ci::RemoveAll(shareddir_dst);
639     }
640   }
641   return true;
642 }
643
644 bool CreateGlobalAppSymlinksForAllUsers(const std::string& pkgid) {
645   bf::path src_dir = bf::path(tzplatform_getenv(TZ_SYS_RW_APP)) / pkgid;
646   if (!bf::exists(src_dir)) {
647     LOG(ERROR) << "src_dir not exists";
648     return false;
649   }
650
651   bool result = true;
652   UserList list = ci::GetUserList();
653   for (auto l : list) {
654     uid_t uid = std::get<0>(l);
655     LOG(DEBUG) << "Creating symlinks for uid: " << uid;
656     // check installed user private app.
657     ci::PkgQueryInterface pkg_query(pkgid, uid);
658     if (pkg_query.IsPackageInstalled())
659       continue;
660     bf::path apps_rw(std::get<2>(l) / "apps_rw");
661     bf::path dst_dir = apps_rw / pkgid;
662     if (!bf::exists(dst_dir)) {
663       LOG(WARNING) << "dst_dir not exists";
664       continue;
665     }
666     result = CreateSymlinkFiles(src_dir, dst_dir);
667   }
668   return result;
669 }
670
671 bool CreateGlobalAppSymlinksForUser(const std::string& pkgid, uid_t uid) {
672   bf::path src_dir = bf::path(tzplatform_getenv(TZ_SYS_RW_APP)) / pkgid;
673   if (!bf::exists(src_dir)) {
674     LOG(WARNING) << "src_dir(" << src_dir << ") not exists";
675     return true;
676   }
677
678   tzplatform_set_user(uid);
679   bf::path dst_dir = bf::path(tzplatform_getenv(TZ_USER_APP)) / pkgid;
680   tzplatform_reset_user();
681   if (!bf::exists(dst_dir)) {
682     LOG(WARNING) << "dst_dir not exists";
683     return true;
684   }
685   bool result = CreateSymlinkFiles(src_dir, dst_dir);
686
687   return result;
688 }
689
690 bool DeleteGlobalAppSymlinksForAllUsers(const std::string& pkgid) {
691   bf::path src_dir = bf::path(tzplatform_getenv(TZ_SYS_RW_APP)) / pkgid;
692   if (!bf::exists(src_dir)) {
693     LOG(WARNING) << "src_dir(" << src_dir << ") not exists";
694     return true;
695   }
696
697   bool result = true;
698   UserList list = ci::GetUserList();
699   for (auto l : list) {
700     uid_t uid = std::get<0>(l);
701     LOG(DEBUG) << "Deleting symlinks for uid: " << uid;
702     // check installed user private app.
703     ci::PkgQueryInterface pkg_query(pkgid, uid);
704     if (pkg_query.IsPackageInstalled())
705       continue;
706     bf::path apps_rw(std::get<2>(l) / "apps_rw");
707     bf::path dst_dir = apps_rw / pkgid;
708     if (!bf::exists(dst_dir)) {
709       LOG(WARNING) << "dst_dir not exists";
710       continue;
711     }
712     result = DeleteSymlinkFiles(src_dir, dst_dir);
713   }
714   return result;
715 }
716
717 bool DeleteGlobalAppSymlinksForUser(const std::string& pkgid, uid_t uid) {
718   bf::path src_dir = bf::path(tzplatform_getenv(TZ_SYS_RW_APP)) / pkgid;
719   if (!bf::exists(src_dir)) {
720     LOG(ERROR) << "src_dir not exists";
721     return false;
722   }
723
724   tzplatform_set_user(uid);
725   bf::path dst_dir = bf::path(tzplatform_getenv(TZ_USER_APP)) / pkgid;
726   tzplatform_reset_user();
727   if (!bf::exists(dst_dir)) {
728     LOG(WARNING) << "dst_dir not exists";
729     return true;
730   }
731   bool result = DeleteSymlinkFiles(src_dir, dst_dir);
732   return result;
733 }
734
735 bool SetPackageDirectoryOwnerAndPermissions(const bf::path& path, uid_t uid) {
736   boost::optional<gid_t> gid = ci::GetGidByUid(uid);
737   if (!gid)
738     return false;
739   bf::perms perms644 =
740       bf::owner_read | bf::owner_write | bf::group_read | bf::others_read;
741   bf::perms perms755 =
742       perms644 | bf::owner_exe | bf::group_exe | bf::others_exe;
743   for (bf::recursive_directory_iterator iter(path);
744       iter != bf::recursive_directory_iterator(); ++iter) {
745     if (bf::is_symlink(symlink_status(iter->path())) ||
746         (bf::is_directory(iter->path()) &&
747         (iter->path().filename() == ".mmc" ||
748             iter->path().filename() == ".pkg" ||
749             iter->path().filename() == "tep"))) {
750       // skip symlink or path which is related to
751       // mount or directory installer creates
752       continue;
753     } else if (bf::is_directory(iter->path())) {
754       // directories
755       if (!SetDirectoryOwnerAndPermissions(iter->path(), uid, *gid))
756         return false;
757     } else if (iter.level() == 1 &&
758         iter->path().parent_path().filename() == "bin") {
759       // bin files
760       if (!SetDirOwnershipAndPermissions(iter->path(), perms755, uid, *gid))
761         return false;
762     } else {
763       // other files
764       if (!SetDirOwnershipAndPermissions(iter->path(), perms644, uid, *gid))
765         return false;
766     }
767   }
768   return true;
769 }
770
771 bool ShouldSupportLegacySharedDataDir(const std::string& api_version) {
772   if (bf::exists(kDisableLegacySharedDataDirSupport))
773     return false;
774   utils::VersionNumber api_ver(api_version);
775   if (api_ver < ver30)
776     return true;
777   else
778     return false;
779 }
780
781 }  // namespace common_installer