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 "file_util.h"
17
18 #include <cstdint>
19 #include <cstdio>
20 #include <cstring>
21 #include <dirent.h>
22 #include <fcntl.h>
23 #include <fstream>
24 #include <istream>
25 #include <sys/sendfile.h>
26 #include <sys/stat.h>
27 #include <sys/xattr.h>
28 #include <unistd.h>
29 #include <vector>
30
31 #include "common_utils.h"
32 #include "directory_ex.h"
33 #include "file_ex.h"
34
35 namespace OHOS {
36 namespace HiviewDFX {
37 namespace FileUtil {
38 using namespace std;
LoadStringFromFile(const std::string & filePath,std::string & content)39 bool LoadStringFromFile(const std::string& filePath, std::string& content)
40 {
41 return OHOS::LoadStringFromFile(filePath, content);
42 }
43
LoadLinesFromFile(const std::string & filePath,std::vector<std::string> & lines)44 bool LoadLinesFromFile(const std::string& filePath, std::vector<std::string>& lines)
45 {
46 std::ifstream file(filePath);
47 if (file.is_open()) {
48 std::string line;
49 while (std::getline(file, line)) {
50 lines.emplace_back(line);
51 }
52 file.close();
53 return true;
54 }
55 return false;
56 }
57
LoadStringFromFd(int fd,std::string & content)58 bool LoadStringFromFd(int fd, std::string& content)
59 {
60 return OHOS::LoadStringFromFd(fd, content);
61 }
62
SaveStringToFile(const std::string & filePath,const std::string & content,bool truncated)63 bool SaveStringToFile(const std::string& filePath, const std::string& content, bool truncated)
64 {
65 return OHOS::SaveStringToFile(filePath, content, truncated);
66 }
67
SaveStringToFd(int fd,const std::string & content)68 bool SaveStringToFd(int fd, const std::string& content)
69 {
70 return OHOS::SaveStringToFd(fd, content);
71 }
72
LoadBufferFromFile(const std::string & filePath,std::vector<char> & content)73 bool LoadBufferFromFile(const std::string& filePath, std::vector<char>& content)
74 {
75 return OHOS::LoadBufferFromFile(filePath, content);
76 }
77
SaveBufferToFile(const std::string & filePath,const std::vector<char> & content,bool truncated)78 bool SaveBufferToFile(const std::string& filePath, const std::vector<char>& content, bool truncated)
79 {
80 return OHOS::SaveBufferToFile(filePath, content, truncated);
81 }
82
FileExists(const std::string & fileName)83 bool FileExists(const std::string& fileName)
84 {
85 return OHOS::FileExists(fileName);
86 }
87
ExtractFilePath(const std::string & fileFullName)88 std::string ExtractFilePath(const std::string& fileFullName)
89 {
90 return OHOS::ExtractFilePath(fileFullName);
91 }
92
ExtractFileName(const std::string & fileFullName)93 std::string ExtractFileName(const std::string& fileFullName)
94 {
95 return OHOS::ExtractFileName(fileFullName);
96 }
97
ExtractFileExt(const std::string & fileName)98 std::string ExtractFileExt(const std::string& fileName)
99 {
100 return OHOS::ExtractFileExt(fileName);
101 }
102
IncludeTrailingPathDelimiter(const std::string & path)103 std::string IncludeTrailingPathDelimiter(const std::string& path)
104 {
105 return OHOS::IncludeTrailingPathDelimiter(path);
106 }
107
ExcludeTrailingPathDelimiter(const std::string & path)108 std::string ExcludeTrailingPathDelimiter(const std::string& path)
109 {
110 return OHOS::ExcludeTrailingPathDelimiter(path);
111 }
112
GetDirFiles(const std::string & path,std::vector<std::string> & files,bool isRecursive)113 void GetDirFiles(const std::string& path, std::vector<std::string>& files, bool isRecursive)
114 {
115 DIR* dir = opendir(path.c_str());
116 if (dir == nullptr) {
117 return;
118 }
119
120 while (true) {
121 struct dirent* ptr = readdir(dir);
122 if (ptr == nullptr) {
123 break;
124 }
125
126 // current dir or parent dir
127 if ((strcmp(ptr->d_name, ".") == 0) || (strcmp(ptr->d_name, "..") == 0)) {
128 continue;
129 } else if (ptr->d_type == DT_DIR && isRecursive) {
130 std::string pathStringWithDelimiter = IncludeTrailingPathDelimiter(path) + string(ptr->d_name);
131 GetDirFiles(pathStringWithDelimiter, files);
132 } else {
133 files.push_back(IncludeTrailingPathDelimiter(path) + string(ptr->d_name));
134 }
135 }
136 closedir(dir);
137 }
138
GetDirDirs(const std::string & path,std::vector<std::string> & dirs)139 void GetDirDirs(const std::string& path, std::vector<std::string>& dirs)
140 {
141 DIR* dir = opendir(path.c_str());
142 if (dir == nullptr) {
143 return;
144 }
145
146 while (true) {
147 struct dirent *ptr = readdir(dir);
148 if (ptr == nullptr) {
149 break;
150 }
151 if (strcmp(ptr->d_name, ".") == 0 || strcmp(ptr->d_name, "..") == 0) {
152 continue;
153 } else if (ptr->d_type == DT_DIR) {
154 dirs.push_back(IncludeTrailingPathDelimiter(path) + string(ptr->d_name));
155 }
156 }
157 closedir(dir);
158 }
159
ForceCreateDirectory(const std::string & path)160 bool ForceCreateDirectory(const std::string& path)
161 {
162 return OHOS::ForceCreateDirectory(path);
163 }
164
ForceCreateDirectory(const string & path,mode_t mode)165 bool ForceCreateDirectory(const string& path, mode_t mode)
166 {
167 string::size_type index = 0;
168 do {
169 index = path.find('/', index + 1);
170 string subPath = (index == string::npos) ? path : path.substr(0, index);
171 if (access(subPath.c_str(), F_OK) != 0) {
172 if (mkdir(subPath.c_str(), mode) != 0) {
173 return false;
174 }
175 }
176 } while (index != string::npos);
177 return access(path.c_str(), F_OK) == 0;
178 }
179
ForceRemoveDirectory(const std::string & path,bool isNeedDeleteGivenDirSelf)180 bool ForceRemoveDirectory(const std::string& path, bool isNeedDeleteGivenDirSelf)
181 {
182 return OHOS::ForceRemoveDirectory(path);
183 }
184
GetFileSize(const std::string & path)185 uint64_t GetFileSize(const std::string& path)
186 {
187 struct stat st;
188 return stat(path.c_str(), &st) ? 0 : static_cast<uint64_t>(st.st_size);
189 }
190
RemoveFile(const std::string & fileName)191 bool RemoveFile(const std::string& fileName)
192 {
193 return OHOS::RemoveFile(fileName);
194 }
195
GetFolderSize(const std::string & path)196 uint64_t GetFolderSize(const std::string& path)
197 {
198 return OHOS::GetFolderSize(path);
199 }
200
201 // inner function, and param is legitimate
ChangeMode(const string & fileName,const mode_t & mode)202 bool ChangeMode(const string& fileName, const mode_t& mode)
203 {
204 return (chmod(fileName.c_str(), mode) == 0);
205 }
206
ChangeModeFile(const string & fileName,const mode_t & mode)207 bool ChangeModeFile(const string& fileName, const mode_t& mode)
208 {
209 if (access(fileName.c_str(), F_OK) != 0) {
210 return false;
211 }
212
213 return ChangeMode(fileName, mode);
214 }
215
ChangeModeDirectory(const std::string & path,const mode_t & mode)216 bool ChangeModeDirectory(const std::string& path, const mode_t& mode)
217 {
218 return OHOS::ChangeModeDirectory(path, mode);
219 }
220
PathToRealPath(const std::string & path,std::string & realPath)221 bool PathToRealPath(const std::string& path, std::string& realPath)
222 {
223 return OHOS::PathToRealPath(path, realPath);
224 }
225
Umask(const mode_t & mode)226 mode_t Umask(const mode_t& mode)
227 {
228 return umask(mode);
229 }
230
Open(const std::string & path,const int flags,const mode_t mode)231 int Open(const std::string& path, const int flags, const mode_t mode)
232 {
233 return open(path.c_str(), flags, mode);
234 }
235
CreateDirWithDefaultPerm(const std::string & path,uid_t aidRoot,uid_t aidSystem)236 void CreateDirWithDefaultPerm(const std::string& path, uid_t aidRoot, uid_t aidSystem)
237 {
238 FileUtil::ForceCreateDirectory(path);
239 chown(path.c_str(), aidRoot, aidSystem);
240 }
241
FormatPath2UnixStyle(std::string & path)242 void FormatPath2UnixStyle(std::string &path)
243 {
244 // unimplemented
245 }
246
RemoveFolderBeginWith(const std::string & path,const std::string & folderName)247 void RemoveFolderBeginWith(const std::string &path, const std::string &folderName)
248 {
249 // unimplemented
250 }
251
WriteBufferToFd(int fd,const char * buffer,size_t size)252 bool WriteBufferToFd(int fd, const char* buffer, size_t size)
253 {
254 if (fd < 0) {
255 return false;
256 }
257
258 if (buffer == nullptr) {
259 return false;
260 }
261
262 ssize_t writeSize = size;
263 if (writeSize != TEMP_FAILURE_RETRY(write(fd, buffer, size))) {
264 return false;
265 }
266
267 return true;
268 }
269
CreateFile(const std::string & path,mode_t mode)270 int CreateFile(const std::string &path, mode_t mode)
271 {
272 if (FileExists(path)) {
273 return 0;
274 } else {
275 std::ofstream fout(path);
276 if (!fout.is_open()) {
277 return -1;
278 }
279 fout.flush();
280 fout.close();
281 if (!ChangeMode(path, mode)) {
282 return -1;
283 }
284 }
285 return 0;
286 }
287
CopyFile(const std::string & src,const std::string & des)288 int CopyFile(const std::string &src, const std::string &des)
289 {
290 std::ifstream fin(src, ios::binary);
291 std::ofstream fout(des, ios::binary);
292 if (!fin.is_open()) {
293 return -1;
294 }
295 if (!fout.is_open()) {
296 return -1;
297 }
298 fout << fin.rdbuf();
299 if (fout.fail()) {
300 fout.clear();
301 }
302 fout.flush();
303 return 0;
304 }
305
CopyFileFast(const std::string & src,const std::string & des)306 int CopyFileFast(const std::string &src, const std::string &des)
307 {
308 int fdIn = open(src.c_str(), O_RDONLY);
309 if (fdIn < 0) {
310 return -1;
311 }
312 int fdOut = open(des.c_str(), O_CREAT | O_RDWR, 0664);
313 if (fdOut < 0) {
314 close(fdIn);
315 return -1;
316 }
317 struct stat st;
318 uint64_t totalLen = stat(src.c_str(), &st) ? 0 : static_cast<uint64_t>(st.st_size);
319 uint64_t copyTotalLen = 0;
320 while (copyTotalLen < totalLen) {
321 ssize_t copyLen = sendfile(fdOut, fdIn, nullptr, totalLen - copyTotalLen);
322 if (copyLen <= 0) {
323 break;
324 }
325 copyTotalLen += static_cast<uint64_t>(copyLen);
326 }
327 close(fdIn);
328 close(fdOut);
329 int ret = copyTotalLen == totalLen ? 0 : -1;
330 return ret;
331 }
332
IsDirectory(const std::string & path)333 bool IsDirectory(const std::string &path)
334 {
335 struct stat statBuffer;
336 if (stat(path.c_str(), &statBuffer) == 0 && S_ISDIR(statBuffer.st_mode)) {
337 return true;
338 }
339 return false;
340 }
341
GetLastLine(std::istream & fin,std::string & line,uint32_t maxLen)342 bool GetLastLine(std::istream &fin, std::string &line, uint32_t maxLen)
343 {
344 if (fin.tellg() <= 0) {
345 return false;
346 } else {
347 fin.seekg(-1, fin.cur);
348 }
349 uint32_t count = 0;
350 while (fin.good() && fin.peek() == fin.widen('\n') && fin.tellg() > 0 && count < maxLen) {
351 fin.seekg(-1, fin.cur);
352 count++;
353 }
354 if (!fin.good() || count >= maxLen) {
355 return false;
356 }
357 if (fin.tellg() == 0) {
358 return true;
359 }
360 count = 0;
361 while (fin.good() && fin.peek() != fin.widen('\n') && fin.tellg() > 0 && count < maxLen) {
362 fin.seekg(-1, fin.cur);
363 count++;
364 }
365 if (!fin.good() || count >= maxLen) {
366 return false;
367 }
368 if (fin.tellg() != 0) {
369 fin.seekg(1, fin.cur);
370 }
371 auto oldPos = fin.tellg();
372 getline(fin, line);
373 fin.seekg(oldPos);
374 return true;
375 }
376
GetFirstLine(const std::string & path)377 std::string GetFirstLine(const std::string& path)
378 {
379 std::ifstream inFile(path.c_str());
380 if (!inFile) {
381 return "";
382 }
383 std::string firstLine;
384 getline(inFile, firstLine);
385 inFile.close();
386 return firstLine;
387 }
388
GetParentDir(const std::string & path)389 std::string GetParentDir(const std::string &path)
390 {
391 string str = ExtractFilePath(path);
392 if (str.empty()) {
393 return "";
394 }
395 return str.substr(0, str.size() - 1);
396 }
397
IsLegalPath(const std::string & path)398 bool IsLegalPath(const std::string& path)
399 {
400 if (path.find("./") != std::string::npos ||
401 path.find("../") != std::string::npos) {
402 return false;
403 }
404 return true;
405 }
406
RenameFile(const std::string & src,const std::string & dest)407 bool RenameFile(const std::string& src, const std::string& dest)
408 {
409 if (std::rename(src.c_str(), dest.c_str()) == 0) {
410 return true;
411 }
412 return false;
413 }
414
GetDirXattr(const std::string & dir,const std::string & name,std::string & value)415 bool GetDirXattr(const std::string& dir, const std::string& name, std::string& value)
416 {
417 char buf[BUF_SIZE_256] = {0};
418 if (getxattr(dir.c_str(), name.c_str(), buf, BUF_SIZE_256) == -1) {
419 return false;
420 }
421 value = buf;
422 return true;
423 }
424 } // namespace FileUtil
425 } // namespace HiviewDFX
426 } // namespace OHOS
427