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