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 "directory_ex.h"
17 #include <dirent.h>
18 #include <errno.h>
19 #include "securec.h"
20 #include "unistd.h"
21 #include "utils_log.h"
22 using namespace std;
23
24 namespace OHOS {
25
GetCurrentProcFullFileName()26 string GetCurrentProcFullFileName()
27 {
28 char procFile[PATH_MAX + 1] = {0};
29 int ret = readlink("/proc/self/exe", procFile, PATH_MAX);
30 if (ret < 0 || ret > PATH_MAX) {
31 UTILS_LOGE("Get proc name failed, ret is: %{public}d!", ret);
32 return string();
33 }
34 procFile[ret] = '\0';
35 return string(procFile);
36 }
37
GetCurrentProcPath()38 string GetCurrentProcPath()
39 {
40 return ExtractFilePath(GetCurrentProcFullFileName());
41 }
42
ExtractFilePath(const string & fileFullName)43 string ExtractFilePath(const string& fileFullName)
44 {
45 return string(fileFullName).substr(0, fileFullName.rfind("/") + 1);
46 }
47
ExtractFileName(const std::string & fileFullName)48 std::string ExtractFileName(const std::string& fileFullName)
49 {
50 return string(fileFullName).substr(fileFullName.rfind("/") + 1, fileFullName.size());
51 }
52
ExtractFileExt(const string & fileName)53 string ExtractFileExt(const string& fileName)
54 {
55 string::size_type pos = fileName.rfind(".");
56 if (pos == string::npos) {
57 return "";
58 }
59
60 return string(fileName).substr(pos + 1, fileName.size());
61 }
62
ExcludeTrailingPathDelimiter(const std::string & path)63 string ExcludeTrailingPathDelimiter(const std::string& path)
64 {
65 if (path.rfind("/") != path.size() - 1) {
66 return path;
67 }
68
69 if (!path.empty()) {
70 return path.substr(0, (int)path.size() - 1);
71 }
72
73 return path;
74 }
75
IncludeTrailingPathDelimiter(const std::string & path)76 string IncludeTrailingPathDelimiter(const std::string& path)
77 {
78 if (path.rfind("/") != path.size() - 1) {
79 return path + "/";
80 }
81
82 return path;
83 }
84
GetDirFiles(const string & path,vector<string> & files)85 void GetDirFiles(const string& path, vector<string>& files)
86 {
87 string pathStringWithDelimiter;
88 DIR *dir = opendir(path.c_str());
89 if (dir == nullptr) {
90 return;
91 }
92
93 while (true) {
94 struct dirent *ptr = readdir(dir);
95 if (ptr == nullptr) {
96 break;
97 }
98
99 // current dir OR parent dir
100 if ((strcmp(ptr->d_name, ".") == 0) || (strcmp(ptr->d_name, "..") == 0)) {
101 continue;
102 } else if (ptr->d_type == DT_DIR) {
103 pathStringWithDelimiter = IncludeTrailingPathDelimiter(path) + string(ptr->d_name);
104 GetDirFiles(pathStringWithDelimiter, files);
105 } else {
106 files.push_back(IncludeTrailingPathDelimiter(path) + string(ptr->d_name));
107 }
108 }
109 closedir(dir);
110 }
111
ForceCreateDirectory(const string & path)112 bool ForceCreateDirectory(const string& path)
113 {
114 string::size_type index = 0;
115 do {
116 string subPath;
117 index = path.find('/', index + 1);
118 if (index == string::npos) {
119 subPath = path;
120 } else {
121 subPath = path.substr(0, index);
122 }
123
124 if (access(subPath.c_str(), F_OK) != 0) {
125 if (mkdir(subPath.c_str(), (S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) != 0 && errno != EEXIST) {
126 return false;
127 }
128 }
129 } while (index != string::npos);
130
131 return access(path.c_str(), F_OK) == 0;
132 }
133
ForceRemoveDirectory(const string & path)134 bool ForceRemoveDirectory(const string& path)
135 {
136 string subPath;
137 bool ret = true;
138 DIR *dir = opendir(path.c_str());
139 if (dir == nullptr) {
140 return false;
141 }
142
143 while (true) {
144 struct dirent *ptr = readdir(dir);
145 if (ptr == nullptr) {
146 break;
147 }
148
149 // current dir OR parent dir
150 if (strcmp(ptr->d_name, ".") == 0 || strcmp(ptr->d_name, "..") == 0) {
151 continue;
152 }
153 subPath = IncludeTrailingPathDelimiter(path) + string(ptr->d_name);
154 if (ptr->d_type == DT_DIR) {
155 ret = ForceRemoveDirectory(subPath);
156 } else {
157 if (access(subPath.c_str(), F_OK) == 0) {
158 if (remove(subPath.c_str()) != 0) {
159 closedir(dir);
160 return false;
161 }
162 }
163 }
164 }
165 closedir(dir);
166
167 string currentPath = ExcludeTrailingPathDelimiter(path);
168 if (access(currentPath.c_str(), F_OK) == 0) {
169 if (remove(currentPath.c_str()) != 0) {
170 return false;
171 }
172 }
173
174 return ret && (access(path.c_str(), F_OK) != 0);
175 }
176
RemoveFile(const string & fileName)177 bool RemoveFile(const string& fileName)
178 {
179 if (access(fileName.c_str(), F_OK) == 0) {
180 return remove(fileName.c_str()) == 0;
181 }
182
183 return true;
184 }
185
IsEmptyFolder(const string & path)186 bool IsEmptyFolder(const string& path)
187 {
188 vector<string> files;
189 GetDirFiles(path, files);
190 return files.empty();
191 }
192
GetFolderSize(const string & path)193 uint64_t GetFolderSize(const string& path)
194 {
195 vector<string> files;
196 struct stat statbuf = {0};
197 GetDirFiles(path, files);
198 uint64_t totalSize = 0;
199 for (auto& file : files) {
200 if (stat(file.c_str(), &statbuf) == 0) {
201 totalSize += statbuf.st_size;
202 }
203 }
204
205 return totalSize;
206 }
207
208 // inner function, and param is legitimate
ChangeMode(const string & fileName,const mode_t & mode)209 bool ChangeMode(const string& fileName, const mode_t& mode)
210 {
211 return (chmod(fileName.c_str(), mode) == 0);
212 }
213
ChangeModeFile(const string & fileName,const mode_t & mode)214 bool ChangeModeFile(const string& fileName, const mode_t& mode)
215 {
216 if (access(fileName.c_str(), F_OK) != 0) {
217 return false;
218 }
219
220 return ChangeMode(fileName, mode);
221 }
222
ChangeModeDirectory(const string & path,const mode_t & mode)223 bool ChangeModeDirectory(const string& path, const mode_t& mode)
224 {
225 string subPath;
226 bool ret = true;
227 DIR *dir = opendir(path.c_str());
228 if (dir == nullptr) {
229 return false;
230 }
231
232 while (true) {
233 struct dirent *ptr = readdir(dir);
234 if (ptr == nullptr) {
235 break;
236 }
237
238 // current dir OR parent dir
239 if (strcmp(ptr->d_name, ".") == 0 || strcmp(ptr->d_name, "..") == 0) {
240 continue;
241 }
242 subPath = IncludeTrailingPathDelimiter(path) + string(ptr->d_name);
243 if (ptr->d_type == DT_DIR) {
244 ret = ChangeModeDirectory(subPath, mode);
245 } else {
246 if (access(subPath.c_str(), F_OK) == 0) {
247 if (!ChangeMode(subPath, mode)) {
248 UTILS_LOGE("Failed to exec ChangeMode");
249 closedir(dir);
250 return false;
251 }
252 }
253 }
254 }
255 closedir(dir);
256 string currentPath = ExcludeTrailingPathDelimiter(path);
257 if (access(currentPath.c_str(), F_OK) == 0) {
258 if (!ChangeMode(currentPath, mode)) {
259 UTILS_LOGE("Failed to exec ChangeMode");
260 return false;
261 }
262 }
263 return ret;
264 }
265
PathToRealPath(const string & path,string & realPath)266 bool PathToRealPath(const string& path, string& realPath)
267 {
268 if (path.empty()) {
269 UTILS_LOGE("path is empty!");
270 return false;
271 }
272
273 if ((path.length() >= PATH_MAX)) {
274 UTILS_LOGE("path len is error, the len is: [%{public}zu]", path.length());
275 return false;
276 }
277
278 char tmpPath[PATH_MAX] = {0};
279 if (realpath(path.c_str(), tmpPath) == nullptr) {
280 UTILS_LOGE("path to realpath error");
281 return false;
282 }
283
284 realPath = tmpPath;
285 if (access(realPath.c_str(), F_OK) != 0) {
286 UTILS_LOGE("check realpath (%{private}s) error", realPath.c_str());
287 return false;
288 }
289 return true;
290 }
291
292 } // OHOS
293