• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2025 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/statfs.h>
28 #include <sys/xattr.h>
29 #include <unistd.h>
30 #include <vector>
31 
32 #include "common_utils.h"
33 #include "directory_ex.h"
34 #include "file_ex.h"
35 
36 #define FDSAN_FILEUTIL_TAG 0xD002D10 // hiview domainid
37 
38 namespace OHOS {
39 namespace HiviewDFX {
40 namespace FileUtil {
41 using namespace std;
42 namespace {
43 constexpr int VALUE_MOD = 200000;
44 
CheckAndCreateDirectory(const std::string & tmpDirPath)45 bool CheckAndCreateDirectory(const std::string &tmpDirPath)
46 {
47     if (!FileExists(tmpDirPath)) {
48         return ForceCreateDirectory(tmpDirPath, FILE_PERM_775);
49     }
50     return true;
51 }
52 }
53 
LoadStringFromFile(const std::string & filePath,std::string & content)54 bool LoadStringFromFile(const std::string& filePath, std::string& content)
55 {
56     return OHOS::LoadStringFromFile(filePath, content);
57 }
58 
LoadLinesFromFile(const std::string & filePath,std::vector<std::string> & lines)59 bool LoadLinesFromFile(const std::string& filePath, std::vector<std::string>& lines)
60 {
61     std::ifstream file(filePath);
62     if (file.is_open()) {
63         std::string line;
64         while (std::getline(file, line)) {
65             lines.emplace_back(line);
66         }
67         file.close();
68         return true;
69     }
70     return false;
71 }
72 
LoadStringFromFd(int fd,std::string & content)73 bool LoadStringFromFd(int fd, std::string& content)
74 {
75     return OHOS::LoadStringFromFd(fd, content);
76 }
77 
SaveStringToFile(const std::string & filePath,const std::string & content,bool truncated)78 bool SaveStringToFile(const std::string& filePath, const std::string& content, bool truncated)
79 {
80     return OHOS::SaveStringToFile(filePath, content, truncated);
81 }
82 
SaveStringToFd(int fd,const std::string & content)83 bool SaveStringToFd(int fd, const std::string& content)
84 {
85     return OHOS::SaveStringToFd(fd, content);
86 }
87 
LoadBufferFromFile(const std::string & filePath,std::vector<char> & content)88 bool LoadBufferFromFile(const std::string& filePath, std::vector<char>& content)
89 {
90     return OHOS::LoadBufferFromFile(filePath, content);
91 }
92 
SaveBufferToFile(const std::string & filePath,const std::vector<char> & content,bool truncated)93 bool SaveBufferToFile(const std::string& filePath, const std::vector<char>& content, bool truncated)
94 {
95     return OHOS::SaveBufferToFile(filePath, content, truncated);
96 }
97 
FileExists(const std::string & fileName)98 bool FileExists(const std::string& fileName)
99 {
100     return OHOS::FileExists(fileName);
101 }
102 
ExtractFilePath(const std::string & fileFullName)103 std::string ExtractFilePath(const std::string& fileFullName)
104 {
105     return OHOS::ExtractFilePath(fileFullName);
106 }
107 
ExtractFileName(const std::string & fileFullName)108 std::string ExtractFileName(const std::string& fileFullName)
109 {
110     return OHOS::ExtractFileName(fileFullName);
111 }
112 
ExtractFileExt(const std::string & fileName)113 std::string ExtractFileExt(const std::string& fileName)
114 {
115     return OHOS::ExtractFileExt(fileName);
116 }
117 
IncludeTrailingPathDelimiter(const std::string & path)118 std::string IncludeTrailingPathDelimiter(const std::string& path)
119 {
120     return OHOS::IncludeTrailingPathDelimiter(path);
121 }
122 
ExcludeTrailingPathDelimiter(const std::string & path)123 std::string ExcludeTrailingPathDelimiter(const std::string& path)
124 {
125     return OHOS::ExcludeTrailingPathDelimiter(path);
126 }
127 
GetDirFiles(const std::string & path,std::vector<std::string> & files,bool isRecursive)128 void GetDirFiles(const std::string& path, std::vector<std::string>& files, bool isRecursive)
129 {
130     DIR* dir = opendir(path.c_str());
131     if (dir == nullptr) {
132         return;
133     }
134 
135     while (true) {
136         struct dirent* ptr = readdir(dir);
137         if (ptr == nullptr) {
138             break;
139         }
140 
141         // current dir or parent dir
142         if ((strcmp(ptr->d_name, ".") == 0) || (strcmp(ptr->d_name, "..") == 0)) {
143             continue;
144         } else if (ptr->d_type == DT_DIR && isRecursive) {
145             std::string pathStringWithDelimiter = IncludeTrailingPathDelimiter(path) + string(ptr->d_name);
146             GetDirFiles(pathStringWithDelimiter, files);
147         } else {
148             files.push_back(IncludeTrailingPathDelimiter(path) + string(ptr->d_name));
149         }
150     }
151     closedir(dir);
152 }
153 
GetDirDirs(const std::string & path,std::vector<std::string> & dirs)154 void GetDirDirs(const std::string& path, std::vector<std::string>& dirs)
155 {
156     DIR* dir = opendir(path.c_str());
157     if (dir == nullptr) {
158         return;
159     }
160 
161     while (true) {
162         struct dirent *ptr = readdir(dir);
163         if (ptr == nullptr) {
164             break;
165         }
166         if (strcmp(ptr->d_name, ".") == 0 || strcmp(ptr->d_name, "..") == 0) {
167             continue;
168         } else if (ptr->d_type == DT_DIR) {
169             dirs.push_back(IncludeTrailingPathDelimiter(path) + string(ptr->d_name));
170         }
171     }
172     closedir(dir);
173 }
174 
ForceCreateDirectory(const std::string & path)175 bool ForceCreateDirectory(const std::string& path)
176 {
177     return OHOS::ForceCreateDirectory(path);
178 }
179 
ForceCreateDirectory(const string & path,mode_t mode)180 bool ForceCreateDirectory(const string& path, mode_t mode)
181 {
182     string::size_type index = 0;
183     do {
184         index = path.find('/', index + 1);
185         string subPath = (index == string::npos) ? path : path.substr(0, index);
186         if (access(subPath.c_str(), F_OK) != 0) {
187             if (mkdir(subPath.c_str(), mode) != 0) {
188                 return false;
189             }
190         }
191     } while (index != string::npos);
192     return access(path.c_str(), F_OK) == 0;
193 }
194 
ForceRemoveDirectory(const std::string & path,bool isNeedDeleteGivenDirSelf)195 bool ForceRemoveDirectory(const std::string& path, bool isNeedDeleteGivenDirSelf)
196 {
197     return OHOS::ForceRemoveDirectory(path);
198 }
199 
GetFileSize(const std::string & path)200 uint64_t GetFileSize(const std::string& path)
201 {
202     struct stat st;
203     return stat(path.c_str(), &st) ? 0 : static_cast<uint64_t>(st.st_size);
204 }
205 
RemoveFile(const std::string & fileName)206 bool RemoveFile(const std::string& fileName)
207 {
208     return OHOS::RemoveFile(fileName);
209 }
210 
GetFolderSize(const std::string & path)211 uint64_t GetFolderSize(const std::string& path)
212 {
213     return OHOS::GetFolderSize(path);
214 }
215 
GetDeviceValidSize(const std::string & partitionName)216 double GetDeviceValidSize(const std::string& partitionName)
217 {
218     struct statfs stat;
219     int err = statfs(partitionName.c_str(), &stat);
220     if (err != 0) {
221         return 0;
222     }
223     return static_cast<double>(stat.f_bfree) * static_cast<double>(stat.f_bsize);
224 }
225 
226 // inner function, and param is legitimate
ChangeMode(const string & fileName,const mode_t & mode)227 bool ChangeMode(const string& fileName, const mode_t& mode)
228 {
229     return (chmod(fileName.c_str(), mode) == 0);
230 }
231 
ChangeModeFile(const string & fileName,const mode_t & mode)232 bool ChangeModeFile(const string& fileName, const mode_t& mode)
233 {
234     if (access(fileName.c_str(), F_OK) != 0) {
235         return false;
236     }
237 
238     return ChangeMode(fileName, mode);
239 }
240 
ChangeModeDirectory(const std::string & path,const mode_t & mode)241 bool ChangeModeDirectory(const std::string& path, const mode_t& mode)
242 {
243     return OHOS::ChangeModeDirectory(path, mode);
244 }
245 
PathToRealPath(const std::string & path,std::string & realPath)246 bool PathToRealPath(const std::string& path, std::string& realPath)
247 {
248     return OHOS::PathToRealPath(path, realPath);
249 }
250 
Umask(const mode_t & mode)251 mode_t Umask(const mode_t& mode)
252 {
253     return umask(mode);
254 }
255 
Open(const std::string & path,const int flags,const mode_t mode)256 int Open(const std::string& path, const int flags, const mode_t mode)
257 {
258     return open(path.c_str(), flags, mode);
259 }
260 
CreateDirWithDefaultPerm(const std::string & path,uid_t aidRoot,uid_t aidSystem)261 void CreateDirWithDefaultPerm(const std::string& path, uid_t aidRoot, uid_t aidSystem)
262 {
263     FileUtil::ForceCreateDirectory(path);
264     chown(path.c_str(), aidRoot, aidSystem);
265 }
266 
FormatPath2UnixStyle(std::string & path)267 void FormatPath2UnixStyle(std::string &path)
268 {
269     // unimplemented
270 }
271 
RemoveFolderBeginWith(const std::string & path,const std::string & folderName)272 void RemoveFolderBeginWith(const std::string &path, const std::string &folderName)
273 {
274     // unimplemented
275 }
276 
WriteBufferToFd(int fd,const char * buffer,size_t size)277 bool WriteBufferToFd(int fd, const char* buffer, size_t size)
278 {
279     if (fd < 0) {
280         return false;
281     }
282 
283     if (buffer == nullptr) {
284         return false;
285     }
286 
287     ssize_t writeSize = size;
288     if (writeSize != TEMP_FAILURE_RETRY(write(fd, buffer, size))) {
289         return false;
290     }
291 
292     return true;
293 }
294 
CreateFile(const std::string & path,mode_t mode)295 int CreateFile(const std::string &path, mode_t mode)
296 {
297     if (FileExists(path)) {
298         return 0;
299     } else {
300         std::ofstream fout(path);
301         if (!fout.is_open()) {
302             return -1;
303         }
304         fout.flush();
305         fout.close();
306         if (!ChangeMode(path, mode)) {
307             return -1;
308         }
309     }
310     return 0;
311 }
312 
CopyFile(const std::string & src,const std::string & des)313 int CopyFile(const std::string &src, const std::string &des)
314 {
315     std::ifstream fin(src, ios::binary);
316     std::ofstream fout(des, ios::binary);
317     if (!fin.is_open()) {
318         return -1;
319     }
320     if (!fout.is_open()) {
321         return -1;
322     }
323     fout << fin.rdbuf();
324     if (fout.fail()) {
325         fout.clear();
326     }
327     fout.flush();
328     return 0;
329 }
330 
CopyFileFast(const std::string & src,const std::string & des,uint32_t truncatedFileSize)331 int CopyFileFast(const std::string &src, const std::string &des, uint32_t truncatedFileSize)
332 {
333     int fdIn = open(src.c_str(), O_RDONLY);
334     if (fdIn < 0) {
335         return -1;
336     }
337     fdsan_exchange_owner_tag(fdIn, 0, FDSAN_FILEUTIL_TAG);
338     int fdOut = open(des.c_str(), O_CREAT | O_RDWR, 0664);
339     if (fdOut < 0) {
340         fdsan_close_with_tag(fdIn, FDSAN_FILEUTIL_TAG);
341         return -1;
342     }
343     fdsan_exchange_owner_tag(fdOut, 0, FDSAN_FILEUTIL_TAG);
344     struct stat st;
345     uint64_t totalLen = stat(src.c_str(), &st) ? 0 : static_cast<uint64_t>(st.st_size);
346     std::string truncateMsg = "";
347     if (truncatedFileSize != 0 && totalLen > truncatedFileSize) {
348         totalLen = truncatedFileSize;
349         truncateMsg = "\n[truncated]";
350     }
351     uint64_t copyTotalLen = 0;
352     while (copyTotalLen < totalLen) {
353         ssize_t copyLen = sendfile(fdOut, fdIn, nullptr, totalLen - copyTotalLen);
354         if (copyLen <= 0) {
355             break;
356         }
357         copyTotalLen += static_cast<uint64_t>(copyLen);
358     }
359     if (!truncateMsg.empty()) {
360         SaveStringToFd(fdOut, truncateMsg);
361     }
362     fdsan_close_with_tag(fdIn, FDSAN_FILEUTIL_TAG);
363     fdsan_close_with_tag(fdOut, FDSAN_FILEUTIL_TAG);
364     return copyTotalLen == totalLen ? 0 : -1;
365 }
366 
IsDirectory(const std::string & path)367 bool IsDirectory(const std::string &path)
368 {
369     struct stat statBuffer;
370     if (stat(path.c_str(), &statBuffer) == 0 && S_ISDIR(statBuffer.st_mode)) {
371         return true;
372     }
373     return false;
374 }
375 
GetLastLine(std::istream & fin,std::string & line,uint32_t maxLen)376 bool GetLastLine(std::istream &fin, std::string &line, uint32_t maxLen)
377 {
378     if (fin.tellg() <= 0) {
379         return false;
380     } else {
381         fin.seekg(-1, fin.cur);
382     }
383     uint32_t count = 0;
384     while (fin.good() && fin.peek() == fin.widen('\n') && fin.tellg() > 0 && count < maxLen) {
385         fin.seekg(-1, fin.cur);
386         count++;
387     }
388     if (!fin.good() || count >= maxLen) {
389         return false;
390     }
391     if (fin.tellg() == 0) {
392         return true;
393     }
394     count = 0;
395     while (fin.good() && fin.peek() != fin.widen('\n') && fin.tellg() > 0 && count < maxLen) {
396         fin.seekg(-1, fin.cur);
397         count++;
398     }
399     if (!fin.good() || count >= maxLen) {
400         return false;
401     }
402     if (fin.tellg() != 0) {
403         fin.seekg(1, fin.cur);
404     }
405     auto oldPos = fin.tellg();
406     getline(fin, line);
407     fin.seekg(oldPos);
408     return true;
409 }
410 
GetFirstLine(const std::string & path)411 std::string GetFirstLine(const std::string& path)
412 {
413     std::ifstream inFile(path.c_str());
414     if (!inFile) {
415         return "";
416     }
417     std::string firstLine;
418     getline(inFile, firstLine);
419     inFile.close();
420     return firstLine;
421 }
422 
GetParentDir(const std::string & path)423 std::string GetParentDir(const std::string &path)
424 {
425     string str = ExtractFilePath(path);
426     if (str.empty()) {
427         return "";
428     }
429     return str.substr(0, str.size() - 1);
430 }
431 
IsLegalPath(const std::string & path)432 bool IsLegalPath(const std::string& path)
433 {
434     if (path.find("./") != std::string::npos ||
435         path.find("../") != std::string::npos) {
436         return false;
437     }
438     return true;
439 }
440 
RenameFile(const std::string & src,const std::string & dest)441 bool RenameFile(const std::string& src, const std::string& dest)
442 {
443     if (std::rename(src.c_str(), dest.c_str()) == 0) {
444         return true;
445     }
446     return false;
447 }
448 
GetDirXattr(const std::string & dir,const std::string & name,std::string & value)449 bool GetDirXattr(const std::string& dir, const std::string& name, std::string& value)
450 {
451     char buf[BUF_SIZE_256] = {0};
452     if (getxattr(dir.c_str(), name.c_str(), buf, BUF_SIZE_256) == -1) {
453         return false;
454     }
455     value = buf;
456     return true;
457 }
458 
GetLastModifiedTimeStamp(const std::string & filePath)459 int64_t GetLastModifiedTimeStamp(const std::string& filePath)
460 {
461     struct stat fileInfo {0};
462     if (stat(filePath.c_str(), &fileInfo) != ERR_OK) {
463         return 0;
464     }
465     return fileInfo.st_mtime;
466 }
467 
GetUserId(int32_t uid)468 int GetUserId(int32_t uid)
469 {
470     return uid / VALUE_MOD;
471 }
472 
GetSandBoxLogPath(int32_t uid,const std::string & pathHolder,const std::string & subPath)473 std::string GetSandBoxLogPath(int32_t uid, const std::string& pathHolder, const std::string& subPath)
474 {
475     int userId = GetUserId(uid);
476     if (pathHolder.empty()) {
477         return "";
478     }
479     return "/data/app/el2/" + std::to_string(userId) + "/log/" + pathHolder + "/" + subPath;
480 }
481 
GetSandBoxBasePath(int32_t uid,const std::string & pathHolder)482 std::string GetSandBoxBasePath(int32_t uid, const std::string& pathHolder)
483 {
484     int userId = GetUserId(uid);
485     if (pathHolder.empty()) {
486         return "";
487     }
488     return "/data/app/el2/" + std::to_string(userId) + "/base/" + pathHolder + "/cache/hiappevent";
489 }
490 
CreateMultiDirectory(const std::string & dirPath)491 bool CreateMultiDirectory(const std::string &dirPath)
492 {
493     uint32_t dirPathLen = dirPath.length();
494     if (dirPathLen > PATH_MAX) {
495         return false;
496     }
497     char tmpDirPath[PATH_MAX] = { 0 };
498     for (uint32_t i = 0; i < dirPathLen; ++i) {
499         tmpDirPath[i] = dirPath[i];
500         if (tmpDirPath[i] == '/') {
501             if (!CheckAndCreateDirectory(tmpDirPath)) {
502                 return false;
503             }
504         }
505     }
506     return true;
507 }
508 } // namespace FileUtil
509 } // namespace HiviewDFX
510 } // namespace OHOS
511