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