Fix variable shadowing
[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 <boost/range/iterator_range.hpp>
9
10 #include <unistd.h>
11 #include <sys/types.h>
12 #include <fcntl.h>
13 #include <pkgmgr-info.h>
14 #include <cassert>
15
16 #include <cstring>
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 bf = boost::filesystem;
28 namespace ci = common_installer;
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 bf::path& path) {
40   auto permission = bf::perms::owner_all |
41       bf::perms::group_read | bf::perms::group_exe |
42       bf::perms::others_read | bf::perms::others_exe;
43   if (!ci::SetDirPermissions(path, permission)) {
44     LOG(ERROR) << "Grant permission error" << " path: " << path
45                << " permission: " << permission;
46     return false;
47   }
48   return true;
49 }
50
51 bool GrantPermission644(const bf::path& path) {
52   auto permission = bf::perms::owner_read | bf::perms::owner_write |
53       bf::perms::group_read | bf::perms::others_read;
54   if (!ci::SetDirPermissions(path, permission)) {
55     LOG(ERROR) << "Grant permission error" << " path: " << path
56                << " permission: " << permission;
57     return false;
58   }
59   return true;
60 }
61
62 bool ChangeDataDir(const bf::path& pkg_path, uid_t uid) {
63   if (ci::GetRequestMode(uid) == ci::RequestMode::GLOBAL)
64     return true;
65   boost::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   bf::perms prms = bf::add_perms | bf::group_write | bf::set_gid_on_exe;
72   for (auto& entry : kDataDirEntries) {
73     bf::path path = pkg_path / entry;
74     if (!bf::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)) {
82       LOG(ERROR) << "Failed to change permission: " << path
83                  << std::oct << prms;
84       return false;
85     }
86   }
87
88   return true;
89 }
90
91 bool GrantDefaultPermissions(bf::path pkg_path, bool skip_symlink) {
92   if (bf::is_directory(pkg_path)) {
93     if (!GrantPermission755(pkg_path))
94       return false;
95   }
96   for (auto& entry :
97       boost::make_iterator_range(bf::directory_iterator(pkg_path), {})) {
98     auto path = entry.path();
99
100     if (skip_symlink && bf::is_symlink(symlink_status(path)))
101           continue;
102
103     // skip path, which is related to mount or directory installer creates
104     if (bf::is_directory(path) &&
105         (path.filename() == ".mmc" || path.filename() == ".pkg" ||
106         path.filename() == "tep"))
107       continue;
108
109     if (bf::is_directory(path) && path.filename() == "bin") {
110       if (!GrantPermission755(path))
111         return false;
112       for (auto& bin_entry :
113           boost::make_iterator_range(bf::directory_iterator(path), {})) {
114         auto bin_path = bin_entry.path();
115         if (bf::is_symlink(symlink_status(bin_path)))
116           continue;
117
118         if (bf::is_regular_file(bin_path)) {
119           if (!GrantPermission755(bin_path))
120             return false;
121         }
122       }
123       continue;
124     }
125
126     if (bf::is_directory(path) && path.filename() == "lib") {
127       if (!GrantPermission755(path))
128         return false;
129       for (auto& lib_entry :
130           boost::make_iterator_range(bf::directory_iterator(path), {})) {
131         auto lib_path = lib_entry.path();
132         if (bf::is_symlink(symlink_status(lib_path)))
133           continue;
134
135         if (bf::is_regular_file(lib_path)) {
136           if (!GrantPermission644(lib_path))
137             return false;
138         }
139       }
140       continue;
141     }
142
143     if (bf::is_directory(path)) {
144       if (!GrantPermission755(path))
145         return false;
146       continue;
147     }
148
149     if (bf::is_regular_file(path)) {
150       if (!GrantPermission644(path))
151         return false;
152       continue;
153     }
154   }
155
156   return true;
157 }
158
159 }  // namespace
160
161 namespace common_installer {
162 namespace filesystem {
163
164 StepChangeOwnershipAndPermission::StepChangeOwnershipAndPermission(
165     InstallerContext* context, bool skip_symlink = false)
166     : Step(context),
167       skip_symlink_(skip_symlink) {
168 }
169
170 Step::Status StepChangeOwnershipAndPermission::precheck() {
171   if (context_->root_application_path.get().empty()) {
172     LOG(ERROR) << "root_application_path attribute is empty";
173     return Step::Status::INVALID_VALUE;
174   }
175
176   if (!boost::filesystem::exists(context_->root_application_path.get())) {
177     LOG(ERROR) << "root_application_path ("
178                << context_->root_application_path.get()
179                << ") path does not exist";
180     return Step::Status::INVALID_VALUE;
181   }
182
183   if (context_->pkgid.get().empty()) {
184     LOG(ERROR) << "pkgid attribute is empty";
185     return Step::Status::PACKAGE_NOT_FOUND;
186   }
187
188   return Step::Status::OK;
189 }
190
191 Step::Status StepChangeOwnershipAndPermission::process() {
192   uid_t uid = context_->uid.get();
193   boost::optional<gid_t> gid = ci::GetGidByUid(uid);
194   if (!gid)
195     return Status::ERROR;
196
197   // Grant default permissions
198   if (!GrantDefaultPermissions(context_->GetPkgPath(), skip_symlink_))
199     return Status::GRANT_PERMISSION_ERROR;
200
201   // Change owner of files at root path
202   if (!ci::SetOwnershipAll(context_->GetPkgPath(), uid, *gid))
203     return Status::ERROR;
204
205   if (!ChangeDataDir(context_->GetPkgPath(), uid))
206     return Status::ERROR;
207
208   // For icon files
209   const char *iconpath = getIconPath(uid, context_->is_readonly_package.get());
210   if (iconpath) {
211     for (application_x* app :
212         GListRange<application_x*>(
213         context_->manifest_data.get()->application)) {
214       if (!app->icon)
215         continue;
216
217       icon_x* icon = reinterpret_cast<icon_x*>(app->icon->data);
218       bf::path icon_path = icon->text;
219       bf::path found_icon_path = GetIconPath(iconpath,
220           context_->pkgid.get(), icon_path.filename(),
221           context_->root_application_path.get());
222       if (!found_icon_path.empty()) {
223         if (!ci::SetOwnership(found_icon_path, uid, *gid))
224           return Status::ERROR;
225       }
226     }
227   }
228
229   // Manifest files for global apps
230   if (!context_->xml_path.get().empty()) {
231     if (!ci::SetOwnership(context_->xml_path.get(), uid, *gid))
232       return Status::ERROR;
233   }
234
235   return Status::OK;
236 }
237
238 }  // namespace filesystem
239 }  // namespace common_installer