1 /*
2 * Copyright (c) 2022 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 "file_util.h"
16
17 #include <dirent.h>
18 #include <fstream>
19 #include <iostream>
20 #include <sys/stat.h>
21 #include <sys/types.h>
22 #include <sys/xattr.h>
23 #include <unistd.h>
24
25 namespace OHOS {
26 namespace HiviewDFX {
27 namespace FileUtil {
28 namespace {
29 const char PATH_DELIMITER = '/';
30 constexpr mode_t FILE_PERM_600 = S_IRUSR | S_IWUSR;
31 }
IsFileExists(const std::string & file)32 bool IsFileExists(const std::string& file)
33 {
34 return access(file.c_str(), F_OK) == 0;
35 }
36
IsFile(const std::string & file)37 bool IsFile(const std::string& file)
38 {
39 struct stat statBuf {};
40 return lstat(file.c_str(), &statBuf) == 0 ? S_ISREG(statBuf.st_mode) : false;
41 }
42
IsDirectory(const std::string & dir)43 bool IsDirectory(const std::string& dir)
44 {
45 struct stat statBuf {};
46 return lstat(dir.c_str(), &statBuf) == 0 ? S_ISDIR(statBuf.st_mode) : false;
47 }
48
RemoveFile(const std::string & file)49 bool RemoveFile(const std::string& file)
50 {
51 return !IsFileExists(file) || (remove(file.c_str()) == 0);
52 }
53
RemoveDirectory(const std::string & dir)54 bool RemoveDirectory(const std::string& dir)
55 {
56 return !IsFileExists(dir) || (rmdir(dir.c_str()) == 0);
57 }
58
ForceCreateDirectory(const std::string & dir)59 bool ForceCreateDirectory(const std::string& dir)
60 {
61 std::string::size_type index = 0;
62 do {
63 std::string subPath;
64 index = dir.find('/', index + 1); // (index + 1) means the next char traversed
65 if (index == std::string::npos) {
66 subPath = dir;
67 } else {
68 subPath = dir.substr(0, index);
69 }
70
71 if (!IsFileExists(subPath) && mkdir(subPath.c_str(), S_IRWXU) != 0) {
72 return false;
73 }
74 } while (index != std::string::npos);
75 return IsFileExists(dir);
76 }
77
ForceRemoveDirectory(const std::string & dir,bool isDeleteSelf)78 bool ForceRemoveDirectory(const std::string& dir, bool isDeleteSelf)
79 {
80 if (IsFile(dir)) {
81 return RemoveFile(dir);
82 } else if (IsDirectory(dir)) {
83 DIR* dirPtr = opendir(dir.c_str());
84 if (dirPtr == nullptr) {
85 return false;
86 }
87 struct dirent* dirInfo = nullptr;
88 while ((dirInfo = readdir(dirPtr)) != nullptr) {
89 // do not process the special dir
90 if (strcmp(dirInfo->d_name, ".") == 0 || strcmp(dirInfo->d_name, "..") == 0) {
91 continue;
92 }
93 std::string filePath = GetFilePathByDir(dir, dirInfo->d_name);
94 if (!ForceRemoveDirectory(filePath)) {
95 closedir(dirPtr);
96 return false;
97 }
98 }
99 closedir(dirPtr);
100 if (isDeleteSelf && !RemoveDirectory(dir)) {
101 return false;
102 }
103 } else {
104 return false;
105 }
106 return true;
107 }
108
GetDirFiles(const std::string & dir,std::vector<std::string> & files)109 void GetDirFiles(const std::string& dir, std::vector<std::string>& files)
110 {
111 DIR* dirPtr = opendir(dir.c_str());
112 if (dirPtr == nullptr) {
113 return;
114 }
115
116 struct dirent* ent = nullptr;
117 while ((ent = readdir(dirPtr)) != nullptr) {
118 if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) {
119 continue;
120 }
121 std::string filePath = GetFilePathByDir(dir, ent->d_name);
122 if (IsFile(filePath)) { // do not process subdirectory
123 files.push_back(filePath);
124 }
125 }
126 closedir(dirPtr);
127 }
128
GetDirSize(const std::string & dir)129 uint64_t GetDirSize(const std::string& dir)
130 {
131 std::vector<std::string> files;
132 GetDirFiles(dir, files);
133 uint64_t totalSize = 0;
134 struct stat statBuf {};
135 for (auto& file : files) {
136 if (stat(file.c_str(), &statBuf) == 0) {
137 totalSize += static_cast<uint64_t>(statBuf.st_size);
138 }
139 }
140 return totalSize;
141 }
142
GetFileSize(const std::string & file)143 uint64_t GetFileSize(const std::string& file)
144 {
145 struct stat statBuf {};
146 return stat(file.c_str(), &statBuf) == 0 ? static_cast<uint64_t>(statBuf.st_size) : 0;
147 }
148
ChangeMode(const std::string & file,const mode_t & mode)149 bool ChangeMode(const std::string& file, const mode_t& mode)
150 {
151 return (chmod(file.c_str(), mode) == 0);
152 }
153
CreateFile(const std::string & file,const mode_t & mode)154 bool CreateFile(const std::string& file, const mode_t& mode)
155 {
156 if (IsFileExists(file)) {
157 return true;
158 }
159 std::ofstream fout(file);
160 if (!fout.is_open()) {
161 return false;
162 }
163 fout.flush();
164 fout.close();
165 return ChangeMode(file, mode);
166 }
167
SaveStringToFile(const std::string & file,const std::string & content,bool isTrunc)168 bool SaveStringToFile(const std::string& file, const std::string& content, bool isTrunc)
169 {
170 if (content.empty()) {
171 return true;
172 }
173
174 if (!CreateFile(file, FILE_PERM_600)) {
175 return false;
176 }
177 std::ofstream os;
178 if (isTrunc) {
179 os.open(file.c_str(), std::ios::out | std::ios::trunc);
180 } else {
181 os.open(file.c_str(), std::ios::out | std::ios::app);
182 }
183 if (!os.is_open()) {
184 return false;
185 }
186
187 os.write(content.c_str(), content.length());
188 if (os.fail()) {
189 os.close();
190 return false;
191 }
192 os.close();
193 return true;
194 }
195
GetFilePathByDir(const std::string & dir,const std::string & fileName)196 std::string GetFilePathByDir(const std::string& dir, const std::string& fileName)
197 {
198 if (dir.empty()) {
199 return fileName;
200 }
201 std::string filePath = dir;
202 if (filePath.back() != '/') {
203 filePath.push_back(PATH_DELIMITER);
204 }
205 filePath.append(fileName);
206 return filePath;
207 }
208
LoadLinesFromFile(const std::string & filePath,std::vector<std::string> & lines)209 bool LoadLinesFromFile(const std::string& filePath, std::vector<std::string>& lines)
210 {
211 std::ifstream file(filePath);
212 if (file.is_open()) {
213 std::string line;
214 while (std::getline(file, line)) {
215 lines.emplace_back(line);
216 }
217 file.close();
218 return true;
219 }
220 return false;
221 }
222
SetDirXattr(const std::string & dir,const std::string & name,const std::string & value)223 bool SetDirXattr(const std::string& dir, const std::string& name, const std::string& value)
224 {
225 return setxattr(dir.c_str(), name.c_str(), value.c_str(), strlen(value.c_str()), 0) == 0;
226 }
227 } // namespace FileUtil
228 } // namespace HiviewDFX
229 } // namespace OHOS
230