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