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