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