• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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