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