1 /*
2 * Copyright (c) 2021-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 "utils/file_utils.h"
17
18 #include <dirent.h>
19 #include <fcntl.h>
20 #include <fstream>
21 #include <sys/stat.h>
22 #include <sys/wait.h>
23 #include <unistd.h>
24 #include "securec.h"
25 #include "storage_service_errno.h"
26 #include "storage_service_log.h"
27 #include "string_ex.h"
28 #ifdef USE_LIBRESTORECON
29 #include "policycoreutils.h"
30 #endif
31 #ifdef EXTERNAL_STORAGE_QOS_TRANS
32 #include "concurrent_task_client.h"
33 #endif
34 namespace OHOS {
35 namespace StorageDaemon {
36 constexpr uint32_t ALL_PERMS = (S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO);
37 #ifdef EXTERNAL_STORAGE_QOS_TRANS
38 constexpr int SET_SCHED_LOAD_TRANS_TYPE = 10001;
39 #endif
40 constexpr int BUF_LEN = 1024;
41 constexpr uint8_t KILL_RETRY_TIME = 5;
42 constexpr uint32_t KILL_RETRY_INTERVAL_MS = 100 * 1000;
43 constexpr const char *MOUNT_POINT_INFO = "/proc/mounts";
44
ChMod(const std::string & path,mode_t mode)45 int32_t ChMod(const std::string &path, mode_t mode)
46 {
47 return TEMP_FAILURE_RETRY(chmod(path.c_str(), mode));
48 }
49
ChOwn(const std::string & path,uid_t uid,gid_t gid)50 int32_t ChOwn(const std::string &path, uid_t uid, gid_t gid)
51 {
52 return TEMP_FAILURE_RETRY(chown(path.c_str(), uid, gid));
53 }
54
MkDir(const std::string & path,mode_t mode)55 int32_t MkDir(const std::string &path, mode_t mode)
56 {
57 return TEMP_FAILURE_RETRY(mkdir(path.c_str(), mode));
58 }
59
RmDir(const std::string & path)60 int32_t RmDir(const std::string &path)
61 {
62 return TEMP_FAILURE_RETRY(rmdir(path.c_str()));
63 }
64
Mount(const std::string & source,const std::string & target,const char * type,unsigned long flags,const void * data)65 int32_t Mount(const std::string &source, const std::string &target, const char *type,
66 unsigned long flags, const void *data)
67 {
68 return TEMP_FAILURE_RETRY(mount(source.c_str(), target.c_str(), type, flags, data));
69 }
70
UMount(const std::string & path)71 int32_t UMount(const std::string &path)
72 {
73 return TEMP_FAILURE_RETRY(umount(path.c_str()));
74 }
75
UMount2(const std::string & path,int flag)76 int32_t UMount2(const std::string &path, int flag)
77 {
78 return TEMP_FAILURE_RETRY(umount2(path.c_str(), flag));
79 }
80
IsDir(const std::string & path)81 bool IsDir(const std::string &path)
82 {
83 // check whether the path exists
84 struct stat st;
85 int ret = TEMP_FAILURE_RETRY(lstat(path.c_str(), &st));
86 if (ret) {
87 return false;
88 }
89
90 return S_ISDIR(st.st_mode);
91 }
92
IsFile(const std::string & path)93 bool IsFile(const std::string &path)
94 {
95 // check whether the path exists
96 struct stat buf = {};
97 if (stat(path.c_str(), &buf) != 0) {
98 return false;
99 }
100 return S_ISREG(buf.st_mode);
101 }
102
MkDirRecurse(const std::string & path,mode_t mode)103 bool MkDirRecurse(const std::string& path, mode_t mode)
104 {
105 std::string::size_type index = 0;
106 do {
107 std::string subPath = path;
108 index = path.find('/', index + 1);
109 if (index != std::string::npos) {
110 subPath = path.substr(0, index);
111 }
112
113 if (TEMP_FAILURE_RETRY(access(subPath.c_str(), F_OK)) != 0) {
114 if (MkDir(subPath, mode) != 0 && errno != EEXIST) {
115 return false;
116 }
117 }
118 } while (index != std::string::npos);
119
120 return TEMP_FAILURE_RETRY(access(path.c_str(), F_OK)) == 0;
121 }
122
123 // On success, true is returned. On error, false is returned, and errno is set appropriately.
PrepareDir(const std::string & path,mode_t mode,uid_t uid,gid_t gid)124 bool PrepareDir(const std::string &path, mode_t mode, uid_t uid, gid_t gid)
125 {
126 LOGI("prepare for %{public}s", path.c_str());
127
128 // check whether the path exists
129 struct stat st;
130 if (TEMP_FAILURE_RETRY(lstat(path.c_str(), &st)) == E_ERR) {
131 if (errno != ENOENT) {
132 LOGE("failed to lstat, errno %{public}d", errno);
133 return false;
134 }
135 } else {
136 if (!S_ISDIR(st.st_mode)) {
137 LOGE("%{public}s exists and is not a directory", path.c_str());
138 return false;
139 }
140
141 if (((st.st_mode & ALL_PERMS) != mode) && ChMod(path, mode)) {
142 LOGE("dir exists and failed to chmod, errno %{public}d", errno);
143 return false;
144 }
145
146 if (((st.st_uid != uid) || (st.st_gid != gid)) && ChOwn(path, uid, gid)) {
147 LOGE("dir exists and failed to chown, errno %{public}d", errno);
148 return false;
149 }
150
151 return true;
152 }
153
154 mode_t mask = umask(0);
155 if (MkDir(path, mode)) {
156 LOGE("failed to mkdir, errno %{public}d", errno);
157 umask(mask);
158 return false;
159 }
160 umask(mask);
161
162 if (ChMod(path, mode)) {
163 LOGE("failed to chmod, errno %{public}d", errno);
164 return false;
165 }
166
167 if (ChOwn(path, uid, gid)) {
168 LOGE("failed to chown, errno %{public}d", errno);
169 return false;
170 }
171
172 #ifdef USE_LIBRESTORECON
173 int err = Restorecon(path.c_str());
174 if (err) {
175 LOGE("failed to restorecon, err:%{public}d", err);
176 return false;
177 }
178 #endif
179
180 return true;
181 }
182
RmDirRecurse(const std::string & path)183 bool RmDirRecurse(const std::string &path)
184 {
185 LOGD("rm dir %{public}s", path.c_str());
186 DIR *dir = opendir(path.c_str());
187 if (!dir) {
188 if (errno == ENOENT) {
189 return true;
190 }
191
192 LOGE("failed to open dir %{public}s, errno %{public}d", path.c_str(), errno);
193 return false;
194 }
195
196 for (struct dirent *ent = readdir(dir); ent != nullptr; ent = readdir(dir)) {
197 if (ent->d_type == DT_DIR) {
198 if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) {
199 continue;
200 }
201
202 if (!RmDirRecurse(path + "/" + ent->d_name)) {
203 LOGE("failed to RmDirRecurse %{public}s, errno %{public}d", path.c_str(), errno);
204 (void)closedir(dir);
205 return false;
206 }
207 } else {
208 if (unlink((path + "/" + ent->d_name).c_str())) {
209 LOGE("failed to unlink file %{public}s, errno %{public}d", ent->d_name, errno);
210 (void)closedir(dir);
211 return false;
212 }
213 }
214 }
215
216 (void)closedir(dir);
217 if (rmdir(path.c_str())) {
218 LOGE("failed to rm dir %{public}s, errno %{public}d", path.c_str(), errno);
219 return false;
220 }
221 return true;
222 }
223
TravelChmod(const std::string & path,mode_t mode)224 void TravelChmod(const std::string &path, mode_t mode)
225 {
226 struct stat st;
227 DIR *d = nullptr;
228 struct dirent *dp = nullptr;
229 const char *skip1 = ".";
230 const char *skip2 = "..";
231
232 if (stat(path.c_str(), &st) < 0 || !S_ISDIR(st.st_mode)) {
233 LOGE("invalid path");
234 return;
235 }
236
237 (void)ChMod(path, mode);
238 if (!(d = opendir(path.c_str()))) {
239 LOGE("opendir failed");
240 return;
241 }
242
243 while ((dp = readdir(d)) != nullptr) {
244 if ((!strncmp(dp->d_name, skip1, strlen(skip1))) || (!strncmp(dp->d_name, skip2, strlen(skip2)))) {
245 continue;
246 }
247 std::string subpath = path + "/" + dp->d_name;
248 stat(subpath.c_str(), &st);
249 (void)ChMod(subpath, mode);
250 if (S_ISDIR(st.st_mode)) {
251 TravelChmod(subpath, mode);
252 }
253 }
254 (void)closedir(d);
255 }
256
StringToUint32(const std::string & str,uint32_t & num)257 bool StringToUint32(const std::string &str, uint32_t &num)
258 {
259 if (str.empty()) {
260 return false;
261 }
262 if (!IsNumericStr(str)) {
263 LOGE("Not numeric entry");
264 return false;
265 }
266
267 int value;
268 if (!StrToInt(str, value)) {
269 LOGE("String to int convert failed");
270 return false;
271 }
272 num = static_cast<uint32_t>(value);
273
274 return true;
275 }
276
StringToBool(const std::string & str,bool & result)277 bool StringToBool(const std::string &str, bool &result)
278 {
279 if (str.empty()) {
280 return false;
281 }
282
283 if (str == "true") {
284 result = true;
285 } else if (str == "false") {
286 result = false;
287 } else {
288 LOGE("Invalid boolean string: %{public}s", str.c_str());
289 return false;
290 }
291
292 return true;
293 }
294
GetSubDirs(const std::string & path,std::vector<std::string> & dirList)295 void GetSubDirs(const std::string &path, std::vector<std::string> &dirList)
296 {
297 dirList.clear();
298
299 struct stat st;
300 int ret = TEMP_FAILURE_RETRY(lstat(path.c_str(), &st));
301 if (ret != 0 || ((st.st_mode & S_IFDIR) != S_IFDIR)) {
302 LOGE("path is not dir");
303 return;
304 }
305
306 DIR *dir = opendir(path.c_str());
307 if (!dir) {
308 LOGE("failed to open dir %{public}s, errno %{public}d", path.c_str(), errno);
309 return;
310 }
311
312 for (struct dirent *ent = readdir(dir); ent != nullptr; ent = readdir(dir)) {
313 if ((ent->d_type != DT_DIR) ||
314 (strcmp(ent->d_name, ".") == 0) ||
315 (strcmp(ent->d_name, "..") == 0)) {
316 continue;
317 }
318 dirList.push_back(ent->d_name);
319 }
320
321 (void)closedir(dir);
322 }
323
ReadDigitDir(const std::string & path,std::vector<FileList> & dirInfo)324 void ReadDigitDir(const std::string &path, std::vector<FileList> &dirInfo)
325 {
326 struct stat st;
327 int ret = TEMP_FAILURE_RETRY(lstat(path.c_str(), &st));
328 if (ret != 0 || ((st.st_mode & S_IFDIR) != S_IFDIR)) {
329 LOGE("path is not dir");
330 return;
331 }
332
333 DIR *dir = opendir(path.c_str());
334 if (!dir) {
335 LOGE("failed to open dir %{public}s, errno %{public}d", path.c_str(), errno);
336 return;
337 }
338
339 for (struct dirent *ent = readdir(dir); ent != nullptr; ent = readdir(dir)) {
340 if ((ent->d_type != DT_DIR) ||
341 (strcmp(ent->d_name, ".") == 0) ||
342 (strcmp(ent->d_name, "..") == 0)) {
343 continue;
344 }
345
346 uint32_t userId;
347 std::string name(ent->d_name);
348 if (!StringToUint32(name, userId)) {
349 continue;
350 }
351 FileList entry = {
352 .userId = userId,
353 .path = path + "/" + name
354 };
355 dirInfo.push_back(entry);
356 }
357
358 (void)closedir(dir);
359 }
360
OpenSubFile(const std::string & path,std::vector<std::string> & file)361 void OpenSubFile(const std::string &path, std::vector<std::string> &file)
362 {
363 struct stat st;
364 int ret = TEMP_FAILURE_RETRY(lstat(path.c_str(), &st));
365 if (ret != 0 || ((st.st_mode & S_IFDIR) != S_IFDIR)) {
366 LOGI("path is not dir");
367 return;
368 }
369
370 DIR *dir = opendir(path.c_str());
371 if (!dir) {
372 LOGI("failed to open dir %{public}s, errno %{public}d", path.c_str(), errno);
373 return;
374 }
375 for (struct dirent *ent = readdir(dir); ent != nullptr; ent = readdir(dir)) {
376 if ((ent->d_type != DT_DIR)) {
377 std::string name(ent->d_name);
378 std::string filePath = path + "/" + name;
379 LOGI("filePath is %{public}s", filePath.c_str());
380 file.push_back(filePath);
381 continue;
382 } else {
383 if ((strcmp(ent->d_name, ".") == 0) || (strcmp(ent->d_name, "..") == 0)) {
384 continue;
385 }
386 std::string name(ent->d_name);
387 std::string filePath = path + "/" + name;
388 OpenSubFile(filePath, file);
389 }
390 }
391 (void)closedir(dir);
392 }
393
ReadFile(const std::string & path,std::string * str)394 bool ReadFile(const std::string &path, std::string *str)
395 {
396 std::ifstream infile;
397 int cnt = 0;
398
399 std::string rpath(PATH_MAX + 1, '\0');
400 if ((path.length() > PATH_MAX) || (realpath(path.c_str(), rpath.data()) == nullptr)) {
401 LOGE("realpath failed");
402 return false;
403 }
404
405 infile.open(rpath.c_str());
406 if (!infile) {
407 LOGE("Cannot open file");
408 return false;
409 }
410
411 while (1) {
412 std::string subStr;
413 infile >> subStr;
414 if (subStr == "") {
415 break;
416 }
417 cnt++;
418 *str = *str + subStr + '\n';
419 }
420
421 infile.close();
422 return cnt == 0 ? false : true;
423 }
424
FromatCmd(std::vector<std::string> & cmd)425 static std::vector<char*> FromatCmd(std::vector<std::string> &cmd)
426 {
427 std::vector<char*>res;
428 res.reserve(cmd.size() + 1);
429
430 for (auto& line : cmd) {
431 LOGI("cmd %{public}s", line.c_str());
432 res.emplace_back(const_cast<char*>(line.c_str()));
433 }
434 res.emplace_back(nullptr);
435
436 return res;
437 }
438
ForkExec(std::vector<std::string> & cmd,std::vector<std::string> * output)439 int ForkExec(std::vector<std::string> &cmd, std::vector<std::string> *output)
440 {
441 int pipe_fd[2];
442 pid_t pid;
443 int status;
444 auto args = FromatCmd(cmd);
445
446 if (pipe(pipe_fd) < 0) {
447 LOGE("creat pipe failed");
448 return E_CREATE_PIPE;
449 }
450
451 pid = fork();
452 if (pid == -1) {
453 LOGE("fork failed");
454 return E_FORK;
455 } else if (pid == 0) {
456 (void)close(pipe_fd[0]);
457 if (dup2(pipe_fd[1], STDOUT_FILENO) == -1) {
458 LOGE("dup2 failed");
459 _exit(1);
460 }
461 (void)close(pipe_fd[1]);
462 execvp(args[0], const_cast<char **>(args.data()));
463 LOGE("execvp failed errno: %{public}d", errno);
464 _exit(1);
465 } else {
466 (void)close(pipe_fd[1]);
467 if (output) {
468 char buf[BUF_LEN] = { 0 };
469 (void)memset_s(buf, sizeof(buf), 0, sizeof(buf));
470 output->clear();
471 while (read(pipe_fd[0], buf, BUF_LEN - 1) > 0) {
472 LOGI("get result %{public}s", buf);
473 output->push_back(buf);
474 }
475 }
476
477 (void)close(pipe_fd[0]);
478 waitpid(pid, &status, 0);
479 if (errno == ECHILD) {
480 return E_NO_CHILD;
481 }
482 if (!WIFEXITED(status)) {
483 LOGE("Process exits abnormally");
484 return E_WIFEXITED;
485 }
486 if (WEXITSTATUS(status) != 0) {
487 LOGE("Process exited with an error");
488 return E_WEXITSTATUS;
489 }
490 }
491 return E_OK;
492 }
493 #ifdef EXTERNAL_STORAGE_QOS_TRANS
ReportExecutorPidEvent(std::vector<std::string> & cmd,int32_t pid)494 static void ReportExecutorPidEvent(std::vector<std::string> &cmd, int32_t pid)
495 {
496 std::unordered_map<std::string, std::string> payloads;
497 if (!cmd.empty() && (cmd[0] == "mount.ntfs" || cmd[0] == "mount.exfat")) {
498 payloads["value"] = std::to_string(1);
499 payloads["pid"] = std::to_string(pid);
500 OHOS::ConcurrentTask::ConcurrentTaskClient::GetInstance().ReportSceneInfo(
501 SET_SCHED_LOAD_TRANS_TYPE, payloads);
502 }
503 }
504
ExtStorageMountForkExec(std::vector<std::string> & cmd)505 int ExtStorageMountForkExec(std::vector<std::string> &cmd)
506 {
507 int pipe_fd[2];
508 pid_t pid;
509 int status;
510 auto args = FromatCmd(cmd);
511
512 if (pipe(pipe_fd) < 0) {
513 LOGE("creat pipe failed");
514 return E_ERR;
515 }
516
517 pid = fork();
518 if (pid == -1) {
519 LOGE("fork failed");
520 return E_ERR;
521 } else if (pid == 0) {
522 (void)close(pipe_fd[0]);
523 int send_pid = (int)getpid();
524 if (write(pipe_fd[1], &send_pid, sizeof(int)) == -1) {
525 LOGE("write pipe failed");
526 _exit(1);
527 }
528 (void)close(pipe_fd[1]);
529 execvp(args[0], const_cast<char **>(args.data()));
530 LOGE("execvp failed errno: %{public}d", errno);
531 _exit(1);
532 } else {
533 (void)close(pipe_fd[1]);
534 int recv_pid;
535 while (read(pipe_fd[0], &recv_pid, sizeof(int)) > 0) {
536 LOGI("read child pid: %{public}d", recv_pid);
537 }
538
539 (void)close(pipe_fd[0]);
540 ReportExecutorPidEvent(cmd, recv_pid);
541
542 waitpid(pid, &status, 0);
543 if (errno == ECHILD) {
544 return E_NO_CHILD;
545 }
546 if (!WIFEXITED(status)) {
547 LOGE("Process exits abnormally");
548 return E_ERR;
549 }
550 if (WEXITSTATUS(status) != 0) {
551 LOGE("Process exited with an error");
552 return E_ERR;
553 }
554 }
555 return E_OK;
556 }
557 #endif
558
TraverseDirUevent(const std::string & path,bool flag)559 void TraverseDirUevent(const std::string &path, bool flag)
560 {
561 DIR *dir = opendir(path.c_str());
562 if (dir == nullptr) {
563 return;
564 }
565
566 int dirFd = dirfd(dir);
567 int fd = openat(dirFd, "uevent", O_WRONLY | O_CLOEXEC);
568 if (fd >= 0) {
569 std::string writeStr = "add\n";
570 write(fd, writeStr.c_str(), writeStr.length());
571 (void)close(fd);
572 }
573
574 for (struct dirent *ent = readdir(dir); ent != nullptr; ent = readdir(dir)) {
575 if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) {
576 continue;
577 }
578
579 if (ent->d_type != DT_DIR && !flag) {
580 continue;
581 }
582
583 TraverseDirUevent(path + "/" + ent->d_name, false);
584 }
585
586 (void)closedir(dir);
587 }
588
IsSameGidUid(const std::string & dir,uid_t uid,gid_t gid)589 int IsSameGidUid(const std::string &dir, uid_t uid, gid_t gid)
590 {
591 struct stat st;
592 if (TEMP_FAILURE_RETRY(lstat(dir.c_str(), &st)) == E_ERR) {
593 LOGE("failed to lstat, errno %{public}d", errno);
594 if (errno == ENOENT) {
595 return E_NON_EXIST;
596 }
597 return E_SYS_KERNEL_ERR;
598 }
599 return (st.st_uid == uid) && (st.st_gid == gid) ? E_OK : E_DIFF_UID_GID;
600 }
601
MoveDataShell(const std::string & from,const std::string & to)602 bool MoveDataShell(const std::string &from, const std::string &to)
603 {
604 LOGI("MoveDataShell start");
605 if (TEMP_FAILURE_RETRY(access(from.c_str(), F_OK)) != 0) {
606 return true;
607 }
608 std::vector<std::string> cmd = {
609 "/system/bin/mv",
610 from,
611 to
612 };
613 std::vector<std::string> out;
614 int32_t err = ForkExec(cmd, &out);
615 if (err != 0) {
616 LOGE("MoveDataShell failed err:%{public}d", err);
617 }
618 return true;
619 }
620
MoveFileManagerData(const std::string & filesPath)621 void MoveFileManagerData(const std::string &filesPath)
622 {
623 std::string docsPath = filesPath + "Docs/";
624 MoveDataShell(filesPath + "Download/", docsPath);
625 MoveDataShell(filesPath + "Documents/", docsPath);
626 MoveDataShell(filesPath + "Desktop/", docsPath);
627 MoveDataShell(filesPath + ".Trash/", docsPath);
628 }
629
ChownRecursion(const std::string & dir,uid_t uid,gid_t gid)630 void ChownRecursion(const std::string &dir, uid_t uid, gid_t gid)
631 {
632 std::vector<std::string> cmd = {
633 "/system/bin/chown",
634 "-R",
635 std::to_string(uid) + ":" + std::to_string(gid),
636 dir
637 };
638 std::vector<std::string> out;
639 int32_t err = ForkExec(cmd, &out);
640 if (err != 0) {
641 LOGE("path: %{public}s chown failed err:%{public}d", cmd.back().c_str(), err);
642 }
643 }
644
Split(std::string str,const std::string & pattern)645 std::vector<std::string> Split(std::string str, const std::string &pattern)
646 {
647 std::vector<std::string> result;
648 str += pattern;
649 size_t size = str.size();
650 for (size_t i = 0; i < size; i++) {
651 size_t pos = str.find(pattern, i);
652 if (pos < size) {
653 std::string s = str.substr(i, pos - i);
654 result.push_back(s);
655 i = pos + pattern.size() - 1;
656 }
657 }
658 return result;
659 }
660
DeleteFile(const std::string & path)661 bool DeleteFile(const std::string &path)
662 {
663 DIR *dir;
664 struct dirent *dirinfo;
665 struct stat statbuf;
666 lstat(path.c_str(), &statbuf);
667
668 if (S_ISREG(statbuf.st_mode)) {
669 remove(path.c_str());
670 } else if (S_ISDIR(statbuf.st_mode)) {
671 if ((dir = opendir(path.c_str())) == NULL)
672 return 1;
673 while ((dirinfo = readdir(dir)) != NULL) {
674 std::string filepath;
675 filepath.append(path).append("/").append(dirinfo->d_name);
676 if (strcmp(dirinfo->d_name, ".") == 0 || strcmp(dirinfo->d_name, "..") == 0) {
677 continue;
678 }
679 DeleteFile(filepath);
680 rmdir(filepath.c_str());
681 }
682 closedir(dir);
683 }
684 return 0;
685 }
686
IsTempFolder(const std::string & path,const std::string & sub)687 bool IsTempFolder(const std::string &path, const std::string &sub)
688 {
689 bool result = false;
690 if (IsDir(path)) {
691 std::vector<std::string> paths = Split(path, "/");
692 std::string filePath = paths.back();
693 if (filePath.find(sub) == 0) {
694 result = true;
695 }
696 }
697 return result;
698 }
699
DelTemp(const std::string & path)700 void DelTemp(const std::string &path)
701 {
702 DIR *dir;
703 if (!IsDir(path)) {
704 return;
705 }
706 if ((dir = opendir(path.c_str())) != NULL) {
707 {
708 struct dirent *dirinfo;
709 while ((dirinfo = readdir(dir)) != NULL) {
710 if (strcmp(dirinfo->d_name, ".") == 0 || strcmp(dirinfo->d_name, "..") == 0) {
711 continue;
712 }
713 std::string filePath;
714 filePath.append(path).append("/").append(dirinfo->d_name);
715 if (IsTempFolder(filePath, "simple-mtpfs")) {
716 DeleteFile(filePath.c_str());
717 rmdir(filePath.c_str());
718 }
719 }
720 closedir(dir);
721 }
722 }
723 }
724
IsPathMounted(std::string & path)725 bool IsPathMounted(std::string &path)
726 {
727 if (path.empty()) {
728 return true;
729 }
730 if (path.back() == '/') {
731 path.pop_back();
732 }
733 std::ifstream inputStream(MOUNT_POINT_INFO, std::ios::in);
734 if (!inputStream.is_open()) {
735 LOGE("unable to open /proc/mounts, errno is %{public}d", errno);
736 return false;
737 }
738 std::string tmpLine;
739 while (std::getline(inputStream, tmpLine)) {
740 std::stringstream ss(tmpLine);
741 std::string dst;
742 ss >> dst;
743 ss >> dst;
744 if (path == dst) {
745 inputStream.close();
746 return true;
747 }
748 }
749 inputStream.close();
750 return false;
751 }
752
CreateFolder(const std::string & path)753 bool CreateFolder(const std::string &path)
754 {
755 if (!access(path.c_str(), F_OK) || path == "") {
756 return true;
757 }
758
759 size_t pos = path.rfind("/");
760 if (pos == std::string::npos) {
761 return false;
762 }
763
764 std::string upperPath = path.substr(0, pos);
765 if (CreateFolder(upperPath)) {
766 if (mkdir(path.c_str(), S_IRWXU | S_IRWXG | S_IRWXO)) {
767 if (errno != EEXIST) {
768 return false;
769 }
770 }
771 return true;
772 }
773 return false;
774 }
775
DelFolder(const std::string & path)776 bool DelFolder(const std::string &path)
777 {
778 if (rmdir(path.c_str()) == 0) {
779 return true;
780 }
781 return false;
782 }
783
KillProcess(const std::vector<ProcessInfo> & processList,std::vector<ProcessInfo> & killFailList)784 void KillProcess(const std::vector<ProcessInfo> &processList, std::vector<ProcessInfo> &killFailList)
785 {
786 if (processList.empty()) {
787 return;
788 }
789 for (const auto &item: processList) {
790 int pid = item.pid;
791 LOGI("kill pid %{public}d", pid);
792 kill(pid, SIGKILL);
793 bool isAlive = true;
794 for (int i = 0; i < KILL_RETRY_TIME; i++) {
795 if (!IsProcessAlive(pid)) {
796 LOGI("kill pid %{public}d success.", pid);
797 isAlive = false;
798 break;
799 }
800 usleep(KILL_RETRY_INTERVAL_MS);
801 }
802 if (isAlive) {
803 LOGE("kill pid %{public}d failed.", pid);
804 killFailList.push_back(item);
805 }
806 }
807 }
808
IsProcessAlive(int pid)809 bool IsProcessAlive(int pid)
810 {
811 std::stringstream procPath;
812 procPath << "/proc/" << pid << "/stat";
813 std::ifstream statFile(procPath.str());
814 if (!statFile) {
815 statFile.close();
816 return false;
817 }
818 statFile.close();
819 return true;
820 }
821
ProcessToString(std::vector<ProcessInfo> & processList)822 std::string ProcessToString(std::vector<ProcessInfo> &processList)
823 {
824 if (processList.empty()) {
825 return "";
826 }
827 std::string result;
828 for (auto &iter : processList) {
829 result += std::to_string(iter.pid) + "_" + iter.name + ",";
830 }
831 return result.empty() ? "" : result.substr(0, result.length() -1);
832 }
833 } // STORAGE_DAEMON
834 } // OHOS
835