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 "utils_fs.h"
17 #include <algorithm>
18 #include <cerrno>
19 #include <cstdint>
20 #include <cstdlib>
21 #include <dirent.h>
22 #include <fcntl.h>
23 #include <limits>
24 #include <linux/reboot.h>
25 #include <string>
26 #include <sys/reboot.h>
27 #include <sys/stat.h>
28 #include <sys/syscall.h>
29 #include <unistd.h>
30 #include <vector>
31 #include "log/log.h"
32 
33 namespace Updater {
34 namespace Utils {
35 
MkdirRecursive(const std::string & pathName,mode_t mode)36 int MkdirRecursive(const std::string &pathName, mode_t mode)
37 {
38     size_t slashPos = 0;
39     struct stat info {};
40     while (true) {
41         slashPos = pathName.find_first_of("/", slashPos);
42         if (slashPos == std::string::npos) {
43             break;
44         }
45         if (slashPos == 0) {
46             slashPos++;
47             continue;
48         }
49         if (slashPos > PATH_MAX) {
50             LOG(ERROR) << "path too long for mkdir";
51             return -1;
52         }
53         auto subDir = pathName.substr(0, slashPos);
54         LOG(INFO) << "subDir : " << subDir;
55         if (stat(subDir.c_str(), &info) != 0) {
56             int ret = mkdir(subDir.c_str(), mode);
57             if (ret && errno != EEXIST) {
58                 return ret;
59             }
60         }
61         slashPos++;
62     }
63     int ret = mkdir(pathName.c_str(), mode);
64     if (ret && errno != EEXIST) {
65         return ret;
66     }
67     return 0;
68 }
69 
GetFilesFromDirectory(const std::string & path,std::vector<std::string> & files,bool isRecursive)70 int64_t GetFilesFromDirectory(const std::string &path, std::vector<std::string> &files,
71     bool isRecursive)
72 {
73     struct stat sb {};
74     if (stat(path.c_str(), &sb) == -1) {
75         LOG(ERROR) << "Failed to stat";
76         return -1;
77     }
78     DIR *dirp = opendir(path.c_str());
79     struct dirent *dp;
80     int64_t totalSize = 0;
81     while ((dp = readdir(dirp)) != nullptr) {
82         std::string fileName = path + "/" + dp->d_name;
83         struct stat st {};
84         if (stat(fileName.c_str(), &st) == 0) {
85             std::string tmpName = dp->d_name;
86             if (tmpName == "." || tmpName == "..") {
87                 continue;
88             }
89             if (isRecursive && S_ISDIR(st.st_mode)) {
90                 totalSize += GetFilesFromDirectory(fileName, files, isRecursive);
91             }
92             files.push_back(fileName);
93             totalSize += st.st_size;
94         }
95     }
96     closedir(dirp);
97     return totalSize;
98 }
99 
RemoveDir(const std::string & path)100 bool RemoveDir(const std::string &path)
101 {
102     if (path.empty()) {
103         LOG(ERROR) << "input path is empty.";
104         return false;
105     }
106     std::string strPath = path;
107     if (strPath.at(strPath.length() - 1) != '/') {
108         strPath.append("/");
109     }
110     DIR *d = opendir(strPath.c_str());
111     if (d != nullptr) {
112         struct dirent *dt = nullptr;
113         dt = readdir(d);
114         while (dt != nullptr) {
115             if (strcmp(dt->d_name, "..") == 0 || strcmp(dt->d_name, ".") == 0) {
116                 dt = readdir(d);
117                 continue;
118             }
119             struct stat st {};
120             auto file_name = strPath + std::string(dt->d_name);
121             stat(file_name.c_str(), &st);
122             if (S_ISDIR(st.st_mode)) {
123                 RemoveDir(file_name);
124             } else {
125                 remove(file_name.c_str());
126             }
127             dt = readdir(d);
128         }
129         closedir(d);
130     }
131     return rmdir(strPath.c_str()) == 0 ? true : false;
132 }
133 
IsFileExist(const std::string & path)134 bool IsFileExist(const std::string &path)
135 {
136     struct stat st {};
137     if (stat(path.c_str(), &st) == 0 && S_ISREG(st.st_mode)) {
138         return true;
139     }
140     return false;
141 }
142 
IsDirExist(const std::string & path)143 bool IsDirExist(const std::string &path)
144 {
145     struct stat st {};
146     if (stat(path.c_str(), &st) == 0 && S_ISDIR(st.st_mode)) {
147         return true;
148     }
149     return false;
150 }
151 } // Utils
152 } // updater
153