• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 "installd/installd_operator.h"
17 
18 #include <cstdio>
19 #include <fstream>
20 #include <map>
21 #include <sstream>
22 #include <dirent.h>
23 #include <string.h>
24 #include <sys/stat.h>
25 #include <sys/types.h>
26 #include <unistd.h>
27 
28 #include "directory_ex.h"
29 #include "app_log_wrapper.h"
30 #include "bundle_constants.h"
31 #include "bundle_extractor.h"
32 
33 namespace OHOS {
34 namespace AppExecFwk {
35 namespace {}  // namespace
36 
IsExistFile(const std::string & path)37 bool InstalldOperator::IsExistFile(const std::string &path)
38 {
39     if (path.empty()) {
40         return false;
41     }
42 
43     struct stat buf = {};
44     if (stat(path.c_str(), &buf) != 0) {
45         return false;
46     }
47     return S_ISREG(buf.st_mode);
48 }
49 
IsExistDir(const std::string & path)50 bool InstalldOperator::IsExistDir(const std::string &path)
51 {
52     if (path.empty()) {
53         return false;
54     }
55 
56     struct stat buf = {};
57     if (stat(path.c_str(), &buf) != 0) {
58         return false;
59     }
60     return S_ISDIR(buf.st_mode);
61 }
62 
MkRecursiveDir(const std::string & path,bool isReadByOthers)63 bool InstalldOperator::MkRecursiveDir(const std::string &path, bool isReadByOthers)
64 {
65     if (!OHOS::ForceCreateDirectory(path)) {
66         APP_LOGE("mkdir failed");
67         return false;
68     }
69     mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IXOTH;
70     mode |= (isReadByOthers ? S_IROTH : 0);
71     return OHOS::ChangeModeDirectory(path, mode);
72 }
73 
DeleteDir(const std::string & path)74 bool InstalldOperator::DeleteDir(const std::string &path)
75 {
76     if (IsExistFile(path)) {
77         return OHOS::RemoveFile(path);
78     }
79     if (IsExistDir(path)) {
80         return OHOS::ForceRemoveDirectory(path);
81     }
82     return true;
83 }
84 
ExtractFiles(const std::string & sourcePath,const std::string & targetPath)85 bool InstalldOperator::ExtractFiles(const std::string &sourcePath, const std::string &targetPath)
86 {
87     BundleExtractor extractor(sourcePath);
88     if (!extractor.Init()) {
89         return false;
90     }
91     std::vector<std::string> entryNames;
92     if (!extractor.GetZipFileNames(entryNames)) {
93         return false;
94     }
95     if (entryNames.empty()) {
96         return false;
97     }
98 
99     std::string targetDir = targetPath;
100     if (targetPath.back() != Constants::PATH_SEPARATOR[0]) {
101         targetDir = targetPath + Constants::PATH_SEPARATOR;
102     }
103     for (const auto &entryName : entryNames) {
104         if (entryName.find("..") != std::string::npos) {
105             return false;
106         }
107         if (entryName.back() == Constants::PATH_SEPARATOR[0]) {
108             continue;
109         }
110         const std::string dir = GetPathDir(entryName);
111         std::string filePath = targetDir + dir;
112         if (!dir.empty()) {
113             if (!MkRecursiveDir(filePath, true)) {
114                 return false;
115             }
116         }
117         filePath = targetDir + entryName;
118         if (!extractor.ExtractFile(entryName, filePath)) {
119             return false;
120         }
121         mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
122         if (!OHOS::ChangeModeFile(filePath, mode)) {
123             APP_LOGE("change mode failed");
124         }
125         filePath.clear();
126     }
127     return true;
128 }
129 
RenameDir(const std::string & oldPath,const std::string & newPath)130 bool InstalldOperator::RenameDir(const std::string &oldPath, const std::string &newPath)
131 {
132     if (oldPath.empty() || oldPath.size() > PATH_MAX) {
133         APP_LOGE("oldpath error");
134         return false;
135     }
136     std::string realOldPath;
137     realOldPath.reserve(PATH_MAX);
138     realOldPath.resize(PATH_MAX - 1);
139     if (realpath(oldPath.c_str(), &(realOldPath[0])) == nullptr) {
140         APP_LOGE("realOldPath %{public}s", realOldPath.c_str());
141         return false;
142     }
143     if (!(IsValideCodePath(realOldPath) && IsValideCodePath(newPath))) {
144         APP_LOGE("IsValideCodePath failed");
145         return false;
146     }
147     return RenameFile(realOldPath, newPath);
148 }
149 
GetPathDir(const std::string & path)150 std::string InstalldOperator::GetPathDir(const std::string &path)
151 {
152     std::size_t pos = path.rfind(Constants::PATH_SEPARATOR);
153     if (pos == std::string::npos) {
154         return std::string();
155     }
156     return path.substr(0, pos + 1);
157 }
158 
ChangeFileAttr(const std::string & filePath,const int uid,const int gid)159 bool InstalldOperator::ChangeFileAttr(const std::string &filePath, const int uid, const int gid)
160 {
161     APP_LOGD("begin to change %{private}s file attribute", filePath.c_str());
162     if (chown(filePath.c_str(), uid, gid) != 0) {
163         APP_LOGE("fail to change %{private}s ownership", filePath.c_str());
164         return false;
165     }
166     APP_LOGD("change %{private}s file attribute successfully", filePath.c_str());
167     return true;
168 }
169 
RenameFile(const std::string & oldPath,const std::string & newPath)170 bool InstalldOperator::RenameFile(const std::string &oldPath, const std::string &newPath)
171 {
172     if (oldPath.empty() || newPath.empty()) {
173         return false;
174     }
175     if (!DeleteDir(newPath)) {
176         return false;
177     }
178     return rename(oldPath.c_str(), newPath.c_str()) == 0;
179 }
180 
IsValidPath(const std::string & rootDir,const std::string & path)181 bool InstalldOperator::IsValidPath(const std::string &rootDir, const std::string &path)
182 {
183     if (rootDir.find(Constants::PATH_SEPARATOR) != 0 ||
184         rootDir.rfind(Constants::PATH_SEPARATOR) != (rootDir.size() - 1) || rootDir.find("..") != std::string::npos) {
185         return false;
186     }
187     if (path.find("..") != std::string::npos) {
188         return false;
189     }
190     return path.compare(0, rootDir.size(), rootDir) == 0;
191 }
192 
IsValideCodePath(const std::string & codePath)193 bool InstalldOperator::IsValideCodePath(const std::string &codePath)
194 {
195     if (codePath.empty()) {
196         return false;
197     }
198     return IsValidPath(Constants::THIRD_PARTY_APP_INSTALL_PATH + Constants::PATH_SEPARATOR, codePath) ||
199            IsValidPath(Constants::SYSTEM_APP_INSTALL_PATH + Constants::PATH_SEPARATOR, codePath);
200 }
201 
DeleteFiles(const std::string & dataPath)202 bool InstalldOperator::DeleteFiles(const std::string &dataPath)
203 {
204     std::string subPath;
205     bool ret = true;
206     DIR *dir = opendir(dataPath.c_str());
207     if (dir == nullptr) {
208         return false;
209     }
210     while (true) {
211         struct dirent *ptr = readdir(dir);
212         if (ptr == nullptr) {
213             break;
214         }
215         if (strcmp(ptr->d_name, ".") == 0 || strcmp(ptr->d_name, "..") == 0) {
216             continue;
217         }
218         subPath = OHOS::IncludeTrailingPathDelimiter(dataPath) + std::string(ptr->d_name);
219         if (ptr->d_type == DT_DIR) {
220             ret = OHOS::ForceRemoveDirectory(subPath);
221         } else {
222             if (access(subPath.c_str(), F_OK) == 0) {
223                 ret = OHOS::RemoveFile(subPath);
224             }
225         }
226     }
227     closedir(dir);
228     return ret;
229 }
230 
MkOwnerDir(const std::string & path,bool isReadByOthers,const int uid,const int gid)231 bool InstalldOperator::MkOwnerDir(const std::string &path, bool isReadByOthers, const int uid, const int gid)
232 {
233     if (!MkRecursiveDir(path, isReadByOthers)) {
234         return false;
235     }
236     return ChangeFileAttr(path, uid, gid);
237 }
238 
239 }  // namespace AppExecFwk
240 }  // namespace OHOS