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