1 /*
2 * Copyright (c) 2020 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "bundle_daemon_handler.h"
17
18 #include <climits>
19 #include <cstring>
20 #include <dirent.h>
21
22 #include "bundle_daemon_log.h"
23 #include "bundle_file_utils.h"
24 #include "extractor_util.h"
25 #include "ohos_errno.h"
26
27 namespace OHOS {
28 namespace {
29 const char *PERMISSIONS_PATH = "/storage/app/etc/permissions/";
30 constexpr pid_t PMS_UID = 7;
31 constexpr pid_t PMS_GID = 7;
32 const std::string JSON_PATH = "/app/etc/";
33 const std::string HAP_CODE_PATH = "/app/run/";
34 const std::string HAP_DATA_PATH = "/app/data/";
35 const std::string SYSTEM_HAP_PATH = "/system/internal";
36 const std::string THIRD_HAP_PATH = "/system/external";
37 const std::string SDCARD = "/sdcard";
38 const std::string STORAGE = "/storage";
39 }
40
ExtractHap(const char * hapPath,const char * codePath)41 int32_t BundleDaemonHandler::ExtractHap(const char *hapPath, const char *codePath)
42 {
43 char realHapPath[PATH_MAX + 1] = { '\0' };
44 if (hapPath == nullptr || realpath(hapPath, realHapPath) == nullptr) {
45 PRINTE("BundleDaemonHandler", "realPath fail!");
46 return EC_INVALID;
47 }
48 ExtractorUtil extractorUtil(realHapPath);
49 if (!extractorUtil.Init()) {
50 PRINTE("BundleDaemonHandler", "init fail!");
51 return EC_NOINIT;
52 }
53
54 // check and mkdir code path
55 if (!IsValideCodePath(codePath)) {
56 return EC_INVALID;
57 }
58 if (!BundleFileUtils::RemoveFile(codePath)) {
59 PRINTE("BundleDaemonHandler", "remove codePath fail!");
60 return EC_NODIR;
61 }
62 std::string codeDir = std::string(codePath);
63 if (codeDir.back() != PATH_SEPARATOR) {
64 codeDir += PATH_SEPARATOR;
65 }
66
67 if (!BundleFileUtils::MkRecursiveDir(codeDir.c_str(), true)) {
68 PRINTE("BundleDaemonHandler", "create codePath fail!");
69 return EC_NODIR;
70 }
71
72 // unzip one by one
73 const std::vector<std::string> &fileNames = extractorUtil.GetZipFileNames();
74 for (const auto &fileName : fileNames) {
75 if (fileName.find("..") != std::string::npos) {
76 PRINTE("BundleDaemonHandler", "zip file is invalid!");
77 return EC_NODIR;
78 }
79 if (fileName.back() == PATH_SEPARATOR) {
80 continue;
81 }
82 const std::string dir = BundleFileUtils::GetPathDir(fileName);
83 if (!dir.empty()) {
84 std::string fileDir = codeDir + dir;
85 if (!BundleFileUtils::MkRecursiveDir(fileDir.c_str(), false)) {
86 PRINTE("BundleDaemonHandler", "create other dir fail!");
87 return EC_NODIR;
88 }
89 }
90 std::string filePath = codeDir + fileName;
91 if (!extractorUtil.ExtractFileToPath(filePath, fileName)) {
92 PRINTE("BundleDaemonHandler", "ExtractFileToPath fail!");
93 return EC_NODIR;
94 }
95 }
96 return EC_SUCCESS;
97 }
98
RenameFile(const char * oldFile,const char * newFile)99 int32_t BundleDaemonHandler::RenameFile(const char *oldFile, const char *newFile)
100 {
101 char realOldPath[PATH_MAX + 1] = { '\0' };
102 if (oldFile == nullptr || realpath(oldFile, realOldPath) == nullptr) {
103 PRINTE("BundleDaemonHandler", "realPath fail!");
104 return EC_INVALID;
105 }
106 if (!(IsValideCodePath(realOldPath) && IsValideCodePath(newFile)) &&
107 !(IsValideJsonPath(realOldPath) && IsValideJsonPath(newFile))) {
108 PRINTE("BundleDaemonHandler", "file path is invalid");
109 return EC_INVALID;
110 }
111 if (!BundleFileUtils::RenameFile(realOldPath, newFile)) {
112 PRINTE("BundleDaemonHandler", "rename dir fail");
113 return EC_NODIR;
114 }
115 return EC_SUCCESS;
116 }
117
CreatePermissionDir()118 int32_t BundleDaemonHandler::CreatePermissionDir()
119 {
120 if (!BundleFileUtils::MkRecursiveDir(PERMISSIONS_PATH, false)) {
121 PRINTE("BundleDaemonHandler", "mk dir fail");
122 return EC_NODIR;
123 }
124 if (!BundleFileUtils::ChownFile(PERMISSIONS_PATH, PMS_UID, PMS_GID)) {
125 PRINTE("BundleDaemonHandler", "chown permission path fail");
126 return EC_PERMISSION;
127 }
128 return EC_SUCCESS;
129 }
130
CreateDataDirectory(const char * dataPath,int32_t uid,int32_t gid,bool isChown)131 int32_t BundleDaemonHandler::CreateDataDirectory(const char *dataPath, int32_t uid, int32_t gid, bool isChown)
132 {
133 if (!IsValideDataPath(dataPath)) {
134 PRINTE("BundleDaemonHandler", "bundleName is nullptr");
135 return EC_INVALID;
136 }
137 std::string dataDir = std::string(dataPath);
138 if (dataDir.back() != PATH_SEPARATOR) {
139 dataDir += PATH_SEPARATOR;
140 }
141
142 if (!BundleFileUtils::IsExistDir(dataDir.c_str())) {
143 if (!BundleFileUtils::MkOwnerDir(dataDir.c_str())) {
144 PRINTE("BundleDaemonHandler", "create dataPath fail");
145 return EC_NODIR;
146 }
147 }
148 PRINTI("BundleDaemonClient", "uid is %{public}d, isChown is %{public}d", uid, isChown);
149 if (isChown && !BundleFileUtils::ChownFile(dataDir.c_str(), uid, gid)) {
150 PRINTE("BundleDaemonHandler", "chown file fail");
151 return EC_NOFILE;
152 }
153 return EC_SUCCESS;
154 }
155
RemoveInstallDirectory(const char * codePath,const char * dataPath,bool keepData)156 int32_t BundleDaemonHandler::RemoveInstallDirectory(const char *codePath, const char *dataPath, bool keepData)
157 {
158 bool result = IsValideCodePath(codePath) && BundleFileUtils::RemoveFile(codePath);
159 if (!keepData) {
160 result = IsValideDataPath(dataPath) && BundleFileUtils::RemoveFile(dataPath) && result;
161 }
162 return result ? EC_SUCCESS : EC_NODIR;
163 }
164
StoreContentToFile(const char * filePath,const void * buffer,uint32_t size)165 int32_t BundleDaemonHandler::StoreContentToFile(const char *filePath, const void *buffer, uint32_t size)
166 {
167 if (!IsValideJsonPath(filePath)) {
168 PRINTE("BundleDaemonHandler", "store content file path invalid");
169 return EC_NOFILE;
170 }
171 // mkdir root dir
172 const std::string dir = BundleFileUtils::GetPathDir(filePath);
173 if (dir.empty()) {
174 PRINTE("BundleDaemonHandler", "store content file dir invalid");
175 return EC_NODIR;
176 }
177 if (!BundleFileUtils::IsExistDir(dir.c_str())) {
178 if (!BundleFileUtils::MkRecursiveDir(dir.c_str(), true)) {
179 PRINTE("BundleDaemonHandler", "mkdir content json path fail");
180 return EC_NODIR;
181 }
182 }
183
184 if (!BundleFileUtils::WriteFile(filePath, buffer, size)) {
185 PRINTE("BundleDaemonHandler", "save content to file fail");
186 BundleFileUtils::RemoveFile(filePath);
187 return EC_NODIR;
188 }
189 return EC_SUCCESS;
190 }
191
MoveFile(const char * oldFile,const char * newFile)192 int32_t BundleDaemonHandler::MoveFile(const char *oldFile, const char *newFile)
193 {
194 char realOldPath[PATH_MAX + 1] = { '\0' };
195 if (oldFile == nullptr || realpath(oldFile, static_cast<char *>(realOldPath)) == nullptr) {
196 PRINTE("BundleDaemonHandler", "realPath oldFile fail!");
197 return EC_INVALID;
198 }
199
200 if (BundleFileUtils::IsExistFile(static_cast<char *>(realOldPath))) {
201 if (!BundleFileUtils::RenameFile(static_cast<char *>(realOldPath), newFile)) {
202 PRINTE("BundleDaemonHandler", "RenameFile fail!");
203 return EC_FAILURE;
204 }
205 return EC_SUCCESS;
206 }
207 if (BundleFileUtils::IsExistFile(newFile)) {
208 PRINTE("BundleDaemonHandler", "target file exist!");
209 return EC_INVALID;
210 }
211 if (!BundleFileUtils::IsExistDir(newFile)) {
212 BundleFileUtils::MkRecursiveDir(newFile, true);
213 }
214
215 DIR *dir = opendir(static_cast<char *>(realOldPath));
216 if (dir == nullptr) {
217 return EC_FAILURE;
218 }
219
220 dirent *ent;
221 while ((ent = readdir(dir)) != nullptr) {
222 if ((strcmp(ent->d_name, ".") == 0) || (strcmp(ent->d_name, "..")) == 0) {
223 continue;
224 }
225 std::string oldFileName = std::string(realOldPath) + PATH_SEPARATOR + ent->d_name;
226 if (BundleFileUtils::IsExistDir(oldFileName.c_str())) {
227 continue;
228 }
229 std::string newFileName = std::string(newFile) + PATH_SEPARATOR + ent->d_name;
230 if (!BundleFileUtils::RenameFile(oldFileName.c_str(), newFileName.c_str())) {
231 PRINTW("BundleDaemonHandler", "RenameFile fail!");
232 }
233 }
234 closedir(dir);
235 BundleFileUtils::RemoveFile(static_cast<char *>(realOldPath));
236
237 return EC_SUCCESS;
238 }
239
RemoveFile(const char * filePath)240 int32_t BundleDaemonHandler::RemoveFile(const char *filePath)
241 {
242 char realFilePath[PATH_MAX + 1] = { '\0' };
243 if (filePath == nullptr || realpath(filePath, realFilePath) == nullptr) {
244 PRINTE("BundleDaemonHandler", "realPath fail!");
245 return EC_INVALID;
246 }
247 if (!IsValideJsonPath(realFilePath) && !IsValideSystemPath(realFilePath) &&
248 !IsValideCodePath(realFilePath)) {
249 PRINTE("BundleDaemonHandler", "file path is invalid");
250 return EC_INVALID;
251 }
252 if (!BundleFileUtils::RemoveFile(realFilePath)) {
253 PRINTE("BundleDaemonHandler", "clear content to file fail");
254 return EC_NODIR;
255 }
256 return EC_SUCCESS;
257 }
258
IsValideCodePath(const char * codePath)259 bool BundleDaemonHandler::IsValideCodePath(const char *codePath)
260 {
261 if (codePath == nullptr) {
262 return false;
263 }
264 return BundleFileUtils::IsValidPath(STORAGE + HAP_CODE_PATH, codePath) ||
265 BundleFileUtils::IsValidPath(SDCARD + HAP_CODE_PATH, codePath);
266 }
267
IsValideDataPath(const char * dataPath)268 bool BundleDaemonHandler::IsValideDataPath(const char *dataPath)
269 {
270 if (dataPath == nullptr) {
271 return false;
272 }
273 return BundleFileUtils::IsValidPath(STORAGE + HAP_DATA_PATH, dataPath) ||
274 BundleFileUtils::IsValidPath(SDCARD + HAP_DATA_PATH, dataPath);
275 }
276
IsValideJsonPath(const char * jsonPath)277 bool BundleDaemonHandler::IsValideJsonPath(const char *jsonPath)
278 {
279 if (jsonPath == nullptr) {
280 return false;
281 }
282 return BundleFileUtils::IsValidPath(STORAGE + JSON_PATH, jsonPath);
283 }
284
IsValideSystemPath(const char * path)285 bool BundleDaemonHandler::IsValideSystemPath(const char *path)
286 {
287 if (path == nullptr) {
288 return false;
289 }
290 return BundleFileUtils::IsValidPath(SYSTEM_HAP_PATH, path) ||
291 BundleFileUtils::IsValidPath(THIRD_HAP_PATH, path);
292 }
293 } // OHOS
294