Remove boost dependency
[platform/core/appfw/app-installers.git] / src / common / step / filesystem / step_change_ownership_and_permission.cc
1 /* 2016, Copyright © Intel Coporation, license APACHE-2.0, see LICENSE file */
2 // Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
3 // Use of this source code is governed by a apache 2.0 license that can be
4 // found in the LICENSE file.
5
6 #include "common/step/filesystem/step_change_ownership_and_permission.h"
7
8 #include <unistd.h>
9 #include <sys/types.h>
10 #include <fcntl.h>
11 #include <pkgmgr-info.h>
12
13 #include <cassert>
14 #include <cstring>
15 #include <filesystem>
16 #include <optional>
17 #include <string>
18 #include <vector>
19
20 #include "common/utils/paths.h"
21 #include "common/shared_dirs.h"
22 #include "common/utils/file_util.h"
23 #include "common/utils/glist_range.h"
24 #include "common/utils/user_util.h"
25 #include "common/utils/request.h"
26
27 namespace ci = common_installer;
28 namespace fs = std::filesystem;
29
30 namespace {
31
32 const char kSystemShareGroupName[] = "system_share";
33 const std::vector<const char*> kDataDirEntries = {
34   {"data"},
35   {"shared/data"},
36   {"cache"},
37 };
38
39 bool GrantPermission755(const fs::path& path) {
40   auto permission = fs::perms::owner_all |
41       fs::perms::group_read | fs::perms::group_exec |
42       fs::perms::others_read | fs::perms::others_exec;
43   if (!ci::SetDirPermissions(path, permission)) {
44     LOG(ERROR) << "Grant permission error" << " path: " << path
45                << " permission: 755";
46     return false;
47   }
48   return true;
49 }
50
51 bool GrantPermission644(const fs::path& path) {
52   auto permission = fs::perms::owner_read | fs::perms::owner_write |
53       fs::perms::group_read | fs::perms::others_read;
54   if (!ci::SetDirPermissions(path, permission)) {
55     LOG(ERROR) << "Grant permission error" << " path: " << path
56                << " permission: 644";
57     return false;
58   }
59   return true;
60 }
61
62 bool ChangeDataDir(const fs::path& pkg_path, uid_t uid) {
63   if (ci::GetRequestMode(uid) == ci::RequestMode::GLOBAL)
64     return true;
65   std::optional<gid_t> gid = ci::GetGidByGroupName(kSystemShareGroupName);
66   if (!gid) {
67     LOG(ERROR) << "Failed to get gid of " << kSystemShareGroupName;
68     return false;
69   }
70
71   fs::perms prms = fs::perms::group_write | fs::perms::set_gid;
72   for (auto& entry : kDataDirEntries) {
73     fs::path path = pkg_path / entry;
74     if (!fs::exists(path))
75       continue;
76     if (!ci::SetOwnership(path, uid, *gid)) {
77       LOG(ERROR) << "Failed to change owner: " << path
78                  << "(" << uid << ", " << *gid << ")";
79       return false;
80     }
81     if (!ci::SetDirPermissions(path, prms, true)) {
82       LOG(ERROR) << "Failed to add data dir permission: " << path;
83       return false;
84     }
85   }
86
87   return true;
88 }
89
90 bool GrantDefaultPermissions(fs::path pkg_path, bool skip_symlink) {
91   if (fs::is_directory(pkg_path)) {
92     if (!GrantPermission755(pkg_path))
93       return false;
94   }
95   for (auto& entry : fs::directory_iterator(pkg_path)) {
96     if (skip_symlink && fs::is_symlink(symlink_status(entry)))
97       continue;
98
99     // skip path, which is related to mount or directory installer creates
100     if (fs::is_directory(entry) &&
101         (entry.path().filename() == ".mmc" || entry.path().filename() == ".pkg" ||
102         entry.path().filename() == "tep"))
103       continue;
104
105     if (fs::is_directory(entry) && entry.path().filename() == "bin") {
106       if (!GrantPermission755(entry))
107         return false;
108       for (auto& bin_entry : fs::directory_iterator(entry)) {
109         if (fs::is_symlink(symlink_status(bin_entry)))
110           continue;
111
112         if (fs::is_regular_file(bin_entry)) {
113           if (!GrantPermission755(bin_entry))
114             return false;
115         }
116       }
117       continue;
118     }
119
120     if (fs::is_directory(entry) && entry.path().filename() == "lib") {
121       if (!GrantPermission755(entry))
122         return false;
123       for (auto& lib_entry : fs::directory_iterator(entry)) {
124         if (fs::is_symlink(fs::symlink_status(lib_entry)))
125           continue;
126
127         if (fs::is_regular_file(lib_entry)) {
128           if (!GrantPermission644(lib_entry))
129             return false;
130         }
131       }
132       continue;
133     }
134
135     if (fs::is_directory(entry)) {
136       if (!GrantPermission755(entry))
137         return false;
138       continue;
139     }
140
141     if (fs::is_regular_file(entry)) {
142       if (!GrantPermission644(entry))
143         return false;
144       continue;
145     }
146   }
147
148   return true;
149 }
150
151 }  // namespace
152
153 namespace common_installer {
154 namespace filesystem {
155
156 StepChangeOwnershipAndPermission::StepChangeOwnershipAndPermission(
157     InstallerContext* context, bool skip_symlink = false)
158     : Step(context),
159       skip_symlink_(skip_symlink) {
160 }
161
162 Step::Status StepChangeOwnershipAndPermission::precheck() {
163   if (context_->root_application_path.get().empty()) {
164     LOG(ERROR) << "root_application_path attribute is empty";
165     return Step::Status::INVALID_VALUE;
166   }
167
168   if (!std::filesystem::exists(context_->root_application_path.get())) {
169     LOG(ERROR) << "root_application_path ("
170                << context_->root_application_path.get()
171                << ") path does not exist";
172     return Step::Status::INVALID_VALUE;
173   }
174
175   if (context_->pkgid.get().empty()) {
176     LOG(ERROR) << "pkgid attribute is empty";
177     return Step::Status::PACKAGE_NOT_FOUND;
178   }
179
180   return Step::Status::OK;
181 }
182
183 Step::Status StepChangeOwnershipAndPermission::process() {
184   uid_t uid = context_->uid.get();
185   std::optional<gid_t> gid = ci::GetGidByUid(uid);
186   if (!gid)
187     return Status::ERROR;
188
189   // Grant default permissions
190   if (!GrantDefaultPermissions(context_->GetPkgPath(), skip_symlink_))
191     return Status::GRANT_PERMISSION_ERROR;
192
193   // Change owner of files at root path
194   if (!ci::SetOwnershipAll(context_->GetPkgPath(), uid, *gid))
195     return Status::ERROR;
196
197   if (!ChangeDataDir(context_->GetPkgPath(), uid))
198     return Status::ERROR;
199
200   // For icon files
201   const char *iconpath = getIconPath(uid, context_->is_readonly_package.get());
202   if (iconpath) {
203     for (application_x* app :
204         GListRange<application_x*>(
205         context_->manifest_data.get()->application)) {
206       if (!app->icon)
207         continue;
208
209       icon_x* icon = reinterpret_cast<icon_x*>(app->icon->data);
210       fs::path icon_path = icon->text;
211       fs::path found_icon_path = GetIconPath(iconpath,
212           context_->pkgid.get(), icon_path.filename(),
213           context_->root_application_path.get());
214       if (!found_icon_path.empty()) {
215         if (!ci::SetOwnership(found_icon_path, uid, *gid))
216           return Status::ERROR;
217       }
218     }
219   }
220
221   // Manifest files for global apps
222   if (!context_->xml_path.get().empty()) {
223     if (!ci::SetOwnership(context_->xml_path.get(), uid, *gid))
224       return Status::ERROR;
225   }
226
227   return Status::OK;
228 }
229
230 }  // namespace filesystem
231 }  // namespace common_installer