1 /*
2 * Copyright (c) 2021 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 #define LOG_TAG "DirectoryUtils"
17
18 #include "directory_utils.h"
19 #include <dirent.h>
20 #include <cstring>
21 #include "log_print.h"
22 #include "unistd.h"
23
24 namespace OHOS {
25 namespace DistributedKv {
26 // change the mode of all files in the specified directory recursively.
ChangeModeFileOnly(const std::string & path,const mode_t & mode)27 bool DirectoryUtils::ChangeModeFileOnly(const std::string &path, const mode_t &mode)
28 {
29 ZLOGI("begin.");
30 std::string subPath;
31 bool ret = true;
32 DIR *dir = opendir(path.c_str());
33 if (dir == nullptr) {
34 return false;
35 }
36
37 while (true) {
38 struct dirent *ptr = readdir(dir);
39 if (ptr == nullptr) {
40 break;
41 }
42
43 // skip current directory and parent directory.
44 if (strcmp(ptr->d_name, ".") == 0 || strcmp(ptr->d_name, "..") == 0) {
45 continue;
46 }
47
48 subPath = IncludeDelimiterAtPathTail(path) + std::string(ptr->d_name);
49 if (ptr->d_type == DT_DIR) {
50 ret = ChangeModeFileOnly(subPath, mode);
51 continue;
52 }
53
54 // change the mode of file only.
55 if ((access(subPath.c_str(), F_OK) == 0) && (ptr->d_type == DT_REG)) {
56 ZLOGD("[Von-Debug]change the file[%s] to mode[%d].", subPath.c_str(), mode);
57 if (!ChangeMode(subPath, mode)) {
58 closedir(dir);
59 ZLOGD("[Von-Debug]change the file[%s] to mode[%d] failed.", subPath.c_str(), mode);
60 return false;
61 }
62 }
63 }
64 closedir(dir);
65 return ret;
66 }
67
68 // change the mode of all subdirectories in the specified directory recursively.
ChangeModeDirOnly(const std::string & path,const mode_t & mode)69 bool DirectoryUtils::ChangeModeDirOnly(const std::string &path, const mode_t &mode)
70 {
71 ZLOGI("begin.");
72 std::string subPath;
73 bool ret = true;
74 DIR *dir = opendir(path.c_str());
75 if (dir == nullptr) {
76 return false;
77 }
78
79 while (true) {
80 struct dirent *ptr = readdir(dir);
81 if (ptr == nullptr) {
82 break;
83 }
84
85 // skip current directory and parent directory.
86 if (strcmp(ptr->d_name, ".") == 0 || strcmp(ptr->d_name, "..") == 0) {
87 continue;
88 }
89
90 subPath = IncludeDelimiterAtPathTail(path) + std::string(ptr->d_name);
91 if (ptr->d_type == DT_DIR) {
92 ret = ChangeModeDirOnly(subPath, mode);
93 continue;
94 }
95
96 // change the mode of directory only.
97 if ((access(subPath.c_str(), F_OK) == 0) && (ptr->d_type == DT_DIR)) {
98 ZLOGD("[Von-Debug]change the dir[%s] to mode[%d].", subPath.c_str(), mode);
99 if (!ChangeMode(subPath, mode)) {
100 closedir(dir);
101 ZLOGD("[Von-Debug]change the dir[%s] to mode[%d] failed.", subPath.c_str(), mode);
102 return false;
103 }
104 }
105 }
106 closedir(dir);
107
108 std::string currentPath = ExcludeDelimiterAtPathTail(path);
109 if (access(currentPath.c_str(), F_OK) == 0) {
110 if (!ChangeMode(currentPath, mode)) {
111 return false;
112 }
113 }
114 return ret;
115 }
116
117 // create all subdirectories in the specified directory recursively.
CreateDirectory(const std::string & path)118 bool DirectoryUtils::CreateDirectory(const std::string &path)
119 {
120 std::string::size_type index = 0;
121 do {
122 std::string subPath;
123 index = path.find('/', index + 1);
124 if (index == std::string::npos) {
125 subPath = path;
126 } else {
127 subPath = path.substr(0, index);
128 }
129
130 if (access(subPath.c_str(), F_OK) != 0) {
131 if (mkdir(subPath.c_str(), (S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) != 0) {
132 return false;
133 }
134 }
135 } while (index != std::string::npos);
136
137 return access(path.c_str(), F_OK) == 0;
138 }
139
140 // exclude separators '/' at the end of the path.
ExcludeDelimiterAtPathTail(const std::string & path)141 std::string DirectoryUtils::ExcludeDelimiterAtPathTail(const std::string &path)
142 {
143 if (path.rfind('/') != path.size() - 1) {
144 return path;
145 }
146
147 if (!path.empty()) {
148 return path.substr(0, static_cast<int>(path.size()) - 1);
149 }
150
151 return path;
152 }
153
154 // include separators '/' at the end of the path.
IncludeDelimiterAtPathTail(const std::string & path)155 std::string DirectoryUtils::IncludeDelimiterAtPathTail(const std::string &path)
156 {
157 if (path.rfind('/') != path.size() - 1) {
158 return path + "/";
159 }
160
161 return path;
162 }
163 } // namespace DistributedKv
164 } // namespace OHOS
165