• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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 "res_sched_file_util.h"
17 
18 #include <system_error>
19 #include <cstring>
20 #include <dirent.h>
21 #include <fstream>
22 #include <filesystem>
23 #include <sys/statfs.h>
24 
25 #include "config_policy_utils.h"
26 #include "directory_ex.h"
27 #include "file_ex.h"
28 #include "res_sched_log.h"
29 
30 namespace OHOS {
31 namespace ResourceSchedule {
32 namespace ResCommonUtil {
WriteFileReclaim(int32_t pid)33 void WriteFileReclaim(int32_t pid)
34 {
35     std::string path = "/proc/" + std::to_string(pid) + "/reclaim";
36     std::string contentStr = "1";
37     int fd = open(path.c_str(), O_WRONLY);
38     // judge whether open failed
39     if (fd < 0) {
40         RESSCHED_LOGE("%{public}s: open failed.", __func__);
41         return;
42     }
43     // write content to fd
44     write(fd, contentStr.c_str(), contentStr.length());
45     close(fd);
46 }
47 
GetRealPath(const std::string & filePath,std::string & realPath)48 bool GetRealPath(const std::string& filePath, std::string& realPath)
49 {
50     if (!OHOS::PathToRealPath(filePath, realPath)) {
51         RESSCHED_LOGE("%{public}s: get real path failed.", __func__);
52         return false;
53     }
54     return true;
55 }
56 
PathOrFileExists(const std::string & path)57 bool PathOrFileExists(const std::string& path)
58 {
59     if (access(path.c_str(), F_OK) != 0) {
60         RESSCHED_LOGE("%{public}s: access failed.", __func__);
61         return false;
62     }
63     return true;
64 }
65 
DirIterator(const std::string & filePath,std::vector<std::string> & iters)66 bool DirIterator(const std::string& filePath, std::vector<std::string>& iters)
67 {
68     DIR *dir = opendir(filePath.c_str());
69     // input invaild, open failed
70     if (dir == nullptr) {
71         RESSCHED_LOGE("%{public}s: open failed.", __func__);
72         return false;
73     }
74     struct dirent *ptr;
75     while ((ptr = readdir(dir)) != nullptr) {
76         // current dir is path of '.' or '..'
77         if ((strcmp(ptr->d_name, ".") == 0) || (strcmp(ptr->d_name, "..") == 0)) {
78             RESSCHED_LOGD("%{public}s: skip current and pre path", __func__);
79             continue;
80         }
81         iters.emplace_back(IncludeTrailingPathDelimiter(filePath) + std::string(ptr->d_name));
82     }
83     closedir(dir);
84     return true;
85 }
86 
IsEmptyDir(const std::string & filePath)87 bool IsEmptyDir(const std::string& filePath)
88 {
89     return OHOS::IsEmptyFolder(filePath);
90 }
91 
IsDir(const std::string & filePath)92 bool IsDir(const std::string& filePath)
93 {
94     struct stat info{};
95     // dose not exist
96     if (stat(filePath.c_str(), &info) != 0) {
97         RESSCHED_LOGE("%{public}s: file path not exist.", __func__);
98         return false;
99     }
100     // is not directory
101     if (!(info.st_mode & S_IFDIR)) {
102         return false;
103     }
104     return true;
105 }
106 
CreateDir(const std::string & dir,const mode_t & mode)107 bool CreateDir(const std::string& dir, const mode_t& mode)
108 {
109     // create directory
110     if (!OHOS::ForceCreateDirectory(dir)) {
111         RESSCHED_LOGE("%{public}s: Failed to create dir", __func__);
112         return false;
113     }
114     // change directory's mode.
115     if (!OHOS::ChangeModeDirectory(dir, mode)) {
116         RESSCHED_LOGE("%{public}s: Failed to change dir mode to %{public}ud", __func__,
117             mode);
118         // if change failed, remove it.
119         RemoveDirs(dir);
120         return false;
121     }
122     return true;
123 }
124 
CreateFile(const std::string & filePath,const mode_t & mode)125 bool CreateFile(const std::string& filePath, const mode_t& mode)
126 {
127     std::ofstream fd;
128     // create and open file.
129     fd.open(filePath);
130     if (!fd.is_open()) {
131         //create filed
132         RESSCHED_LOGE("%{public}s: Failed to create file", __func__);
133         return false;
134     }
135     fd.close();
136 
137     //change file mode
138     if (!OHOS::ChangeModeFile(filePath, mode)) {
139         //change failed
140         RESSCHED_LOGE("%{public}s: Failed to change file mode to %{public}ud", __func__,
141             mode);
142         RemoveFile(filePath);
143         return false;
144     }
145     return true;
146 }
147 
RemoveDirs(const std::string & dir)148 bool RemoveDirs(const std::string& dir)
149 {
150     if (!OHOS::ForceRemoveDirectory(dir)) {
151         RESSCHED_LOGE("%{public}s: Failed to remove dir", __func__);
152         return false;
153     }
154     return true;
155 }
156 
RemoveFile(const std::string & filePath)157 bool RemoveFile(const std::string& filePath)
158 {
159     if (!OHOS::RemoveFile(filePath)) {
160         RESSCHED_LOGE("%{public}s: Failed to remove file", __func__);
161         return false;
162     }
163     return true;
164 }
165 
ExtractFileName(const std::string & filePath)166 std::string ExtractFileName(const std::string& filePath)
167 {
168     return OHOS::ExtractFileName(filePath);
169 }
170 
IsBLKPath(const std::string & filePath)171 bool IsBLKPath(const std::string& filePath)
172 {
173     struct stat sb;
174     if (stat(filePath.c_str(), &sb) == 0 && S_ISBLK(sb.st_mode)) {
175         return true;
176     }
177     return false;
178 }
179 
SaveStringToFile(const std::string & filePath,const std::string & content,bool truncated)180 bool SaveStringToFile(const std::string& filePath, const std::string& content, bool truncated)
181 {
182     return OHOS::SaveStringToFile(filePath, content, truncated);
183 }
184 
ReadLinesFromFile(const std::string & filePath,std::vector<std::string> & lines)185 bool ReadLinesFromFile(const std::string& filePath, std::vector<std::string>& lines)
186 {
187     std::string line;
188     char tmpPath[PATH_MAX + 1] = {0};
189     auto len = filePath.length();
190     if (len == 0 || len > PATH_MAX || !realpath(filePath.c_str(), tmpPath)) {
191         RESSCHED_LOGE("%{public}s: file path invalid", __func__);
192         return false;
193     }
194     std::string realConfigPath(tmpPath);
195     std::ifstream fin(realConfigPath, std::ifstream::in);
196     // judge whether open failed.
197     if (!fin) {
198         RESSCHED_LOGE("%{public}s: open file failed.", __func__);
199         return false;
200     }
201     // clear container and read lines
202     lines.clear();
203     while (fin.peek() != EOF) {
204         getline(fin, line);
205         lines.emplace_back(line);
206     }
207     fin.close();
208     return true;
209 }
210 
DoCopy(const std::string & src,const std::string & des)211 bool DoCopy(const std::string& src, const std::string& des)
212 {
213     std::filesystem::path sPath(src);
214     std::filesystem::path dPath(des);
215     std::error_code errNo;
216 
217     const auto copyOptions = std::filesystem::copy_options::overwrite_existing |
218         std::filesystem::copy_options::recursive |
219         std::filesystem::copy_options::skip_symlinks;
220     std::filesystem::copy(sPath, dPath, copyOptions, errNo);
221     // if has some error in copy, record errno
222     if (errNo.value()) {
223         RESSCHED_LOGE("copy failed errno:%{public}d", errNo.value());
224         return false;
225     }
226     RESSCHED_LOGD("copy success");
227     return true;
228 }
229 
CopyFile(const std::string & src,const std::string & des)230 bool CopyFile(const std::string& src, const std::string& des)
231 {
232     // judge src exist.
233     if (!PathOrFileExists(src)) {
234         RESSCHED_LOGE("%{public}s: src path invalid!", __func__);
235         return false;
236     }
237     if (PathOrFileExists(des)) {
238         // target path is exist, remove it before copy.
239         if (!RemoveDirs(des)) {
240             RESSCHED_LOGE("%{public}s: target path is exist and remove failed!", __func__);
241             return false;
242         }
243     }
244     errno = 0;
245     // create target directory.
246     if (mkdir(des.c_str(), S_IRWXU) != 0 && errno != EEXIST) {
247         RESSCHED_LOGE("%{public}s: create target path failed!", __func__);
248         return false;
249     }
250     // do real copy action.
251     return DoCopy(src, des);
252 }
253 
GetRealConfigPath(const std::string & configPath,std::string & realConfigPath)254 bool GetRealConfigPath(const std::string& configPath, std::string& realConfigPath)
255 {
256     // judge input path vaild.
257     if (configPath.empty()) {
258         RESSCHED_LOGE("%{public}s:the input config path is empty", __func__);
259         return false;
260     }
261     char buf[PATH_MAX];
262     char* tmpPath = GetOneCfgFile(configPath.c_str(), buf, PATH_MAX);
263     char absolutePath[PATH_MAX] = {0};
264     // if config path is vaild, obtain real path.
265     if (!tmpPath || strlen(tmpPath) > PATH_MAX || !realpath(tmpPath, absolutePath)) {
266         RESSCHED_LOGE("%{public}s:get one config file failed", __func__);
267         return false;
268     }
269     realConfigPath = std::string(absolutePath);
270     return true;
271 }
272 
IsValidPath(const std::string & path)273 bool IsValidPath(const std::string& path)
274 {
275     return !(path.empty() || path.find('\0') != std::string::npos);
276 }
277 
GetFileSize(const std::string & path)278 uint64_t GetFileSize(const std::string& path)
279 {
280     struct stat st;
281     return stat(path.c_str(), &st) ? 0 : static_cast<uint64_t>(st.st_size);
282 }
283 
GetPartitionName(const std::string & path)284 std::string GetPartitionName(const std::string& path)
285 {
286     std::string partition;
287     std::size_t first = path.find_first_of("/");
288     if (first == std::string::npos) {
289         partition = "/" + path;
290         return partition;
291     }
292     std::size_t second = path.find_first_of("/", first + 1);
293     if (second == std::string::npos) {
294         if (path.at(0) != '/') {
295             partition = "/" + path.substr(0, first);
296         } else {
297             partition = path;
298         }
299         return partition;
300     }
301     partition = path.substr(0, second - first);
302     return partition;
303 }
304 
GetDeviceVailidSize(const std::string & path)305 double GetDeviceVailidSize(const std::string& path)
306 {
307     std::string partitionName = GetPartitionName(path);
308     struct statfs stat;
309     if (statfs(partitionName.c_str(), &stat) != 0) {
310         return 0;
311     }
312     constexpr double units = 1024.0;
313     return (static_cast<double>(stat.f_bfree) / units) * (static_cast<double>(stat.f_bsize) / units);
314 }
315 } // namespace ResCommonUtil
316 } // namespace ResourceSchedule
317 } // namespace OHOS
318