• 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 "file_util.h"
17 #include <algorithm>
18 #include <cstdio>
19 #include <cstring>
20 #ifdef __gnu_linux__
21 #include <experimental/filesystem>
22 #else
23 #include <filesystem>
24 #endif
25 #include <fstream>
26 #include <iostream>
27 #include <iterator>
28 namespace OHOS {
29 namespace HiviewDFX {
30 namespace FileUtil {
31 using namespace std;
32 #ifdef __gnu_linux__
33 namespace fs = experimental::filesystem;
34 #else
35 namespace fs = std::filesystem;
36 constexpr int PATH_MAX = 4096;
37 #endif
38 constexpr int MODE_MAX = 07777;
39 constexpr int MAX_FILE_LENGTH = 32 * 1024 * 1024; // 32MB
LoadStringFromFile(const string & filePath,string & content)40 bool LoadStringFromFile(const string& filePath, string& content)
41 {
42     ifstream file(filePath.c_str());
43     if (!file.is_open()) {
44         return false;
45     }
46 
47     file.seekg(0, ios::end);
48     const long fileLength = static_cast<long>(file.tellg());
49     if (fileLength > MAX_FILE_LENGTH) {
50         return false;
51     }
52 
53     content.clear();
54     file.seekg(0, ios::beg);
55     copy(istreambuf_iterator<char>(file), istreambuf_iterator<char>(), back_inserter(content));
56     return true;
57 }
58 
LoadBufferFromNodeFile(const string & filePath,vector<char> & content)59 bool LoadBufferFromNodeFile(const string& filePath, vector<char>& content)
60 {
61     string realPath;
62     if (!PathToRealPath(filePath, realPath)) {
63         return false;
64     }
65 
66     FILE* fp = fopen(realPath.c_str(), "r");
67     if (fp == nullptr) {
68         return false;
69     }
70 
71     char ch = fgetc(fp);
72     int byteCount = 1;
73     while (!feof(fp)) {
74         if (byteCount > MAX_FILE_LENGTH) {
75             fclose(fp);
76             fp = nullptr;
77             content.clear();
78             return false;
79         }
80 
81         content.push_back(ch);
82         ch = fgetc(fp);
83         byteCount++;
84     }
85 
86     fclose(fp);
87     fp = nullptr;
88     return true;
89 }
90 
LoadBufferFromFile(const std::string & filePath,std::vector<char> & content)91 bool LoadBufferFromFile(const std::string& filePath, std::vector<char>& content)
92 {
93     ifstream file;
94     file.open(filePath.c_str(), ios::in | ios::binary);
95     if (!file.is_open()) {
96         return false;
97     }
98 
99     file.seekg(0, std::ios::end);
100     const long fileLength = static_cast<long>(file.tellg());
101     if (fileLength > MAX_FILE_LENGTH) {
102         return false;
103     }
104 
105     // lseek is not support the linux file node
106     if (fileLength < 0) {
107         return LoadBufferFromNodeFile(filePath, content);
108     }
109 
110     if (fileLength == 0) {
111         content.clear();
112         return true;
113     }
114 
115     file.seekg(0, std::ios::beg);
116     if (file.fail()) {
117         return false;
118     }
119 
120     content.resize(fileLength);
121     file.read(&content[0], fileLength);
122     return true;
123 }
124 
SaveStringToFile(const std::string & filePath,const std::string & content,bool truncated)125 bool SaveStringToFile(const std::string& filePath, const std::string& content, bool truncated)
126 {
127     if (content.empty()) {
128         return true;
129     }
130 
131     ofstream file;
132     if (truncated) {
133         file.open(filePath.c_str(), ios::out | ios::trunc);
134     } else {
135         file.open(filePath.c_str(), ios::out | ios::app);
136     }
137 
138     if (!file.is_open()) {
139         return false;
140     }
141 
142     file.write(content.c_str(), content.length());
143     if (file.fail()) {
144         return false;
145     }
146 
147     return true;
148 }
149 
SaveBufferToFile(const string & filePath,const vector<char> & content,bool truncated)150 bool SaveBufferToFile(const string& filePath, const vector<char>& content, bool truncated)
151 {
152     // if the file is not exist,create it first!
153 
154     ios_base::openmode mode = truncated ? (ios::out | ios::binary | ios::trunc) : (ios::out | ios::binary | ios::app);
155     ofstream file;
156     file.open(filePath.c_str(), mode);
157     if (!file.is_open()) {
158         return false;
159     }
160 
161     if (content.empty()) {
162         return true;
163     }
164 
165     file.write(&content[0], content.size());
166     return true;
167 }
168 
FileExists(const std::string & fileName)169 bool FileExists(const std::string& fileName)
170 {
171     error_code ec;
172     bool ret = fs::exists(fileName, ec); // noexcept
173     if (ec) {
174         printf("%s\n", ec.message().c_str());
175     }
176     return ret;
177 }
178 
ExtractFilePath(const std::string & fileFullName)179 std::string ExtractFilePath(const std::string& fileFullName)
180 {
181     return fs::path(fileFullName).parent_path().string();
182 }
183 
ExtractFileName(const std::string & fileFullName)184 std::string ExtractFileName(const std::string& fileFullName)
185 {
186     return fs::path(fileFullName).filename().string();
187 }
188 
GetDirFiles(const std::string & path,std::vector<std::string> & files)189 void GetDirFiles(const std::string& path, std::vector<std::string>& files)
190 {
191     files.clear();
192     for (const auto& p : fs::directory_iterator(path)) {
193         files.push_back(p.path().string());
194     }
195     return;
196 }
197 
198 
ForceCreateDirectory(const std::string & path)199 bool ForceCreateDirectory(const std::string& path)
200 {
201     error_code ec;
202     if (fs::exists(path, ec)) {
203         return true;
204     }
205     if (!fs::create_directories(path, ec)) {
206         return false;
207     }
208     return fs::exists(path, ec);
209 }
210 
ForceCreateDirectory(const std::string & path,int mode)211 bool ForceCreateDirectory(const std::string& path, int mode)
212 {
213     if (!ForceCreateDirectory(path)) {
214         return false;
215     }
216     return ChangeModeDirectory(path, mode);
217 }
218 
ForceRemoveDirectory(const std::string & path,bool isNeedDeleteGivenDirSelf)219 bool ForceRemoveDirectory(const std::string& path, bool isNeedDeleteGivenDirSelf)
220 {
221     error_code ec;
222     fs::remove_all(path, ec);
223     return true;
224 }
225 
226 /* return true if file removed successfully, return false if file not exist. */
RemoveFile(const std::string & fileName)227 bool RemoveFile(const std::string& fileName)
228 {
229     error_code ec;
230     return fs::remove(fileName, ec);
231 }
232 
GetFileSize(const std::string & path)233 uint64_t GetFileSize(const std::string& path)
234 {
235     error_code ec;
236     return fs::file_size(path, ec);
237 }
238 
GetFolderSize(const std::string & path)239 uint64_t GetFolderSize(const std::string& path)
240 {
241     vector<string> files;
242     struct stat statbuf = {0};
243     GetDirFiles(path, files);
244     uint64_t totalSize = 0;
245     for (auto& file : files) {
246         if (stat(file.c_str(), &statbuf) == 0) {
247             totalSize += statbuf.st_size;
248         }
249     }
250 
251     return totalSize;
252 }
253 
CreateFile(const std::string & path,mode_t mode)254 int CreateFile(const std::string &path, mode_t mode)
255 {
256     if (FileExists(path)) {
257         return 0;
258     } else {
259         std::ofstream fout(path);
260         if (!fout.is_open()) {
261             return -1;
262         }
263         fout.flush();
264         fout.close();
265         if (ChangeMode(path, mode) != 0) {
266             return -1;
267         }
268     }
269     return 0;
270 }
271 
CopyFile(const std::string & src,const std::string & des)272 int CopyFile(const std::string &src, const std::string &des)
273 {
274     std::ifstream fin(src);
275     std::ofstream fout(des);
276     if (!fin.is_open()) {
277         return -1;
278     }
279     if (!fout.is_open()) {
280         return -1;
281     }
282     fout << fin.rdbuf();
283     if (fout.fail()) {
284         fout.clear();
285     }
286     fout.flush();
287     return 0;
288 }
289 
IsDirectory(const std::string & path)290 bool IsDirectory(const std::string &path)
291 {
292     return fs::is_directory(path);
293 }
294 
GetLastLine(std::istream & fin,std::string & line,uint32_t maxLen)295 bool GetLastLine(std::istream &fin, std::string &line, uint32_t maxLen)
296 {
297     if (fin.tellg() <= 0) {
298         return false;
299     } else {
300         fin.seekg(-1, fin.cur);
301     }
302     uint32_t count = 0;
303     while (fin.good() && fin.peek() == fin.widen('\n') && fin.tellg() > 0 && count < maxLen) {
304         fin.seekg(-1, fin.cur);
305         count++;
306     }
307     if (!fin.good() || count >= maxLen) {
308         return false;
309     }
310     if (fin.tellg() == 0) {
311         return true;
312     }
313     count = 0;
314     while (fin.good() && fin.peek() != fin.widen('\n') && fin.tellg() > 0 && count < maxLen) {
315         fin.seekg(-1, fin.cur);
316         count++;
317     }
318     if (!fin.good() || count >= maxLen) {
319         return false;
320     }
321     if (fin.tellg() != 0) {
322         fin.seekg(1, fin.cur);
323     }
324     auto oldPos = fin.tellg();
325     getline(fin, line);
326     fin.seekg(oldPos);
327     return true;
328 }
329 
GetParentDir(const std::string & path)330 std::string GetParentDir(const std::string &path)
331 {
332     string str = ExtractFilePath(path);
333     if (str.empty()) {
334         return "";
335     }
336     return str.substr(0, str.size() - 1);
337 }
338 
339 // inner function, and param is legitimate
ChangeMode(const string & fileName,const mode_t & mode)340 bool ChangeMode(const string& fileName, const mode_t& mode)
341 {
342     if (!FileExists(fileName)) {
343         return false;
344     }
345     if (mode > MODE_MAX) {
346         return false;
347     }
348     auto perm = static_cast<fs::perms>(mode);
349     fs::permissions(fileName, perm);
350     return true;
351 }
352 
ChangeModeDirectory(const string & path,const mode_t & mode)353 bool ChangeModeDirectory(const string& path, const mode_t& mode)
354 {
355     if (!FileExists(path)) {
356         return false;
357     }
358 
359     for (auto& p : fs::recursive_directory_iterator(path)) {
360         string tmpPath = p.path().string();
361         replace(tmpPath.begin(), tmpPath.end(), '\\', '/');
362         if (!ChangeMode(tmpPath, mode)) {
363             return false;
364         }
365     }
366     return ChangeMode(path, mode);
367 }
368 
PathToRealPath(const std::string & path,std::string & realPath)369 bool PathToRealPath(const std::string& path, std::string& realPath)
370 {
371     if (path.empty()) {
372         return false;
373     }
374 
375     if ((path.length() >= PATH_MAX)) {
376         return false;
377     }
378     if (!fs::exists(path)) {
379         return false;
380     }
381     fs::path absolutePath = fs::canonical(path);
382 
383     realPath = absolutePath.string();
384 #ifdef _WIN32
385     FormatPath2UnixStyle(realPath);
386 #endif
387     return true;
388 }
389 }
390 }
391 }
392