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