1 /*
2  * Copyright (c) 2020 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 "bundle_file_utils.h"
17 
18 #include <climits>
19 #include <dirent.h>
20 #include <fcntl.h>
21 #include <sys/stat.h>
22 #include <unistd.h>
23 
24 #include "bundle_daemon_log.h"
25 #include "securec.h"
26 
27 namespace OHOS {
IsExistDir(const char * path)28 bool BundleFileUtils::IsExistDir(const char *path)
29 {
30     if (path == nullptr) {
31         return false;
32     }
33 
34     struct stat buf = {};
35     if (stat(path, &buf) != 0) {
36         return false;
37     }
38     return S_ISDIR(buf.st_mode);
39 }
40 
IsExistFile(const char * file)41 bool BundleFileUtils::IsExistFile(const char *file)
42 {
43     if (file == nullptr) {
44         return false;
45     }
46 
47     struct stat buf = {};
48     if (stat(file, &buf) != 0) {
49         return false;
50     }
51     return S_ISREG(buf.st_mode);
52 }
53 
MkRecursiveDir(const char * dir,bool isReadOthers)54 bool BundleFileUtils::MkRecursiveDir(const char *dir, bool isReadOthers)
55 {
56     if (dir == nullptr) {
57         return false;
58     }
59     if (IsExistDir(dir)) {
60         return true;
61     }
62     size_t len = strlen(dir);
63     if (len == 0 || len > PATH_MAX) {
64         return false;
65     }
66     // Create directories level by level
67     char rootDir[PATH_MAX] = { '\0' };
68     for (size_t i = 0; i < len; ++i) {
69         rootDir[i] = dir[i];
70         if ((rootDir[i] == PATH_SEPARATOR || i == (len - 1)) && !IsExistDir(rootDir)) {
71             mode_t mode = S_IRWXU | S_IRWXG | S_IXOTH;
72             mode |= (isReadOthers ? S_IROTH : 0);
73             if (mkdir(rootDir, mode) < 0) {
74                 return false;
75             }
76         }
77     }
78     return true;
79 }
80 
MkOwnerDir(const char * dir)81 bool BundleFileUtils::MkOwnerDir(const char *dir)
82 {
83     if (dir == nullptr) {
84         return false;
85     }
86     if (IsExistDir(dir)) {
87         return true;
88     }
89     size_t len = strlen(dir);
90     if (len == 0 || len > PATH_MAX) {
91         return false;
92     }
93     // Create directories level by level
94     char rootDir[PATH_MAX] = { '\0' };
95     for (size_t i = 0; i < len; ++i) {
96         rootDir[i] = dir[i];
97         if ((rootDir[i] == PATH_SEPARATOR || i == (len - 1)) && !IsExistDir(rootDir)) {
98             mode_t mode = S_IRWXU | S_IRWXG;
99             if (mkdir(rootDir, mode) < 0) {
100                 return false;
101             }
102         }
103     }
104     return true;
105 }
106 
RemoveFile(const char * path)107 bool BundleFileUtils::RemoveFile(const char *path)
108 {
109     if (IsExistFile(path)) {
110         return remove(path) == 0;
111     } else if (IsExistDir(path)) {
112         DIR *dir = opendir(path);
113         if (dir == nullptr) {
114             return false;
115         }
116         struct dirent *dp = nullptr;
117         // Remove file before delete the directory
118         while ((dp = readdir(dir)) != nullptr) {
119             if ((strcmp(dp->d_name, ".") == 0) || (strcmp(dp->d_name, "..")) == 0) {
120                 continue;
121             }
122             std::string dirName = std::string(path) + "/" + dp->d_name;
123             if (dirName.length() >= PATH_MAX || !RemoveFile(dirName.c_str())) {
124                 closedir(dir);
125                 return false;
126             }
127         }
128         closedir(dir);
129         return remove(path) == 0;
130     } else {
131         return true;
132     }
133 }
134 
RenameFile(const char * oldFile,const char * newFile)135 bool BundleFileUtils::RenameFile(const char *oldFile, const char *newFile)
136 {
137     if (oldFile == nullptr || newFile == nullptr) {
138         return false;
139     }
140     if (!RemoveFile(newFile)) {
141         return false;
142     }
143 
144     return rename(oldFile, newFile) == 0;
145 }
146 
ChownFile(const char * file,int32_t uid,int32_t gid)147 bool BundleFileUtils::ChownFile(const char *file, int32_t uid, int32_t gid)
148 {
149     if (file == nullptr) {
150         return false;
151     }
152     return chown(file, uid, gid) == 0;
153 }
154 
WriteFile(const char * file,const void * buffer,uint32_t size)155 bool BundleFileUtils::WriteFile(const char *file, const void *buffer, uint32_t size)
156 {
157     if (file == nullptr || buffer == nullptr || size == 0) {
158         return false;
159     }
160 
161     int32_t fp = open(file, O_RDWR | O_CREAT | O_TRUNC, S_IREAD | S_IWUSR | S_IRGRP | S_IROTH);
162     if (fp < 0) {
163         return false;
164     }
165 
166     if (write(fp, buffer, size) != static_cast<int32_t>(size)) {
167         close(fp);
168         return false;
169     }
170 
171     fsync(fp);
172     close(fp);
173     return true;
174 }
175 
IsValidPath(const std::string & rootDir,const std::string & path)176 bool BundleFileUtils::IsValidPath(const std::string &rootDir, const std::string &path)
177 {
178     if (rootDir.find(PATH_SEPARATOR) != 0 || rootDir.rfind(PATH_SEPARATOR) != (rootDir.size() - 1) ||
179         rootDir.find("..") != std::string::npos) {
180         return false;
181     }
182     if (path.find("..") != std::string::npos) {
183         return false;
184     }
185     return path.compare(0, rootDir.size(), rootDir) == 0;
186 }
187 
GetPathDir(const std::string & path)188 std::string BundleFileUtils::GetPathDir(const std::string &path)
189 {
190     std::size_t pos = path.rfind(PATH_SEPARATOR);
191     if (pos == std::string::npos) {
192         return std::string();
193     }
194     return path.substr(0, pos + 1);
195 }
196 } // OHOS
197