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 #define LOG_TAG "DirectoryManager"
16 #include "directory/directory_manager.h"
17
18 #include <dirent.h>
19 #include <string>
20 #include <sys/stat.h>
21
22 #include "accesstoken_kit.h"
23 #include "log_print.h"
24 #include "types.h"
25 #include "unistd.h"
26 namespace OHOS::DistributedData {
27 using OHOS::DistributedKv::SecurityLevel;
28 using namespace OHOS::Security::AccessToken;
DirectoryManager()29 DirectoryManager::DirectoryManager()
30 : actions_({ { "{security}", &DirectoryManager::GetSecurity }, { "{store}", &DirectoryManager::GetStore },
31 { "{type}", &DirectoryManager::GetType }, { "{area}", &DirectoryManager::GetArea },
32 { "{userId}", &DirectoryManager::GetUserId }, { "{bundleName}", &DirectoryManager::GetBundleName },
33 { "{hapName}", &DirectoryManager::GetHapName }, { "{customDir}", &DirectoryManager::GetCustomDir } })
34 {
35 }
36
GetInstance()37 DirectoryManager &DirectoryManager::GetInstance()
38 {
39 static DirectoryManager instance;
40 return instance;
41 }
42
GetStorePath(const StoreMetaData & metaData,uint32_t version)43 std::string DirectoryManager::GetStorePath(const StoreMetaData &metaData, uint32_t version)
44 {
45 return GenPath(metaData, version, "");
46 }
47
GetStoreBackupPath(const StoreMetaData & metaData,uint32_t version)48 std::string DirectoryManager::GetStoreBackupPath(const StoreMetaData &metaData, uint32_t version)
49 {
50 auto rootBackupPath = GenPath(metaData, version, "backup");
51 return rootBackupPath + "/" + metaData.storeId;
52 }
53
GetSecretKeyPath(const StoreMetaData & metaData,uint32_t version)54 std::string DirectoryManager::GetSecretKeyPath(const StoreMetaData &metaData, uint32_t version)
55 {
56 return GenPath(metaData, version, "secret");
57 }
58
GetMetaStorePath(uint32_t version)59 std::string DirectoryManager::GetMetaStorePath(uint32_t version)
60 {
61 int32_t index = GetVersionIndex(version);
62 if (index < 0) {
63 return "";
64 }
65
66 auto &strategy = strategies_[index];
67 if (strategy.autoCreate) {
68 CreateDirectory(strategy.metaPath);
69 }
70 return strategy.metaPath;
71 }
72
GetMetaBackupPath(uint32_t version)73 std::string DirectoryManager::GetMetaBackupPath(uint32_t version)
74 {
75 int32_t index = GetVersionIndex(version);
76 if (index < 0) {
77 return "";
78 }
79
80 auto &strategy = strategies_[index];
81 std::string path = strategy.metaPath + "/backup";
82 if (strategy.autoCreate) {
83 CreateDirectory(path);
84 }
85 return path;
86 }
87
GetClonePath(const std::string & userId,uint32_t version)88 std::string DirectoryManager::GetClonePath(const std::string &userId, uint32_t version)
89 {
90 int32_t index = GetVersionIndex(version);
91 if (index < 0) {
92 return "";
93 }
94
95 auto &strategy = strategies_[index];
96 auto path = strategy.clonePath;
97 std::string pattern = "{userId}";
98 size_t pos = path.find(pattern);
99 if (pos != std::string::npos) {
100 path.replace(pos, pattern.length(), userId);
101 if (CreateDirectory(path.substr(0, path.rfind('/')))) {
102 return path;
103 } else {
104 return "";
105 };
106 }
107 return "";
108 }
109
Initialize(const std::vector<Strategy> & strategies,const std::vector<StoreType> & storeTypes)110 void DirectoryManager::Initialize(const std::vector<Strategy> &strategies, const std::vector<StoreType> &storeTypes)
111 {
112 strategies_.resize(strategies.size());
113 for (size_t i = 0; i < strategies.size(); ++i) {
114 const Strategy &strategy = strategies[i];
115 StrategyImpl &impl = strategies_[i];
116 impl.autoCreate = strategy.autoCreate;
117 impl.version = strategy.version;
118 impl.metaPath = strategy.metaPath;
119 impl.path = Split(strategy.pattern, "/");
120 impl.clonePath = strategy.clonePath;
121 impl.pipes.clear();
122 for (auto &value : impl.path) {
123 auto it = actions_.find(value);
124 impl.pipes.push_back(it == actions_.end() ? nullptr : it->second);
125 }
126 }
127
128 std::sort(strategies_.begin(), strategies_.end(),
129 [](const StrategyImpl &curr, const StrategyImpl &prev) { return curr.version > prev.version; });
130
131 storeTypes_ = storeTypes;
132 }
133
GetType(const StoreMetaData & metaData) const134 std::string DirectoryManager::GetType(const StoreMetaData &metaData) const
135 {
136 auto type = AccessTokenKit::GetTokenTypeFlag(metaData.tokenId);
137 if (type == TOKEN_NATIVE || type == TOKEN_SHELL) {
138 return "service";
139 }
140 return "app";
141 }
142
GetStore(const StoreMetaData & metaData) const143 std::string DirectoryManager::GetStore(const StoreMetaData &metaData) const
144 {
145 for (const auto &storeType : storeTypes_) {
146 if (metaData.storeType >= storeType.range.front() && metaData.storeType <= storeType.range.back()) {
147 return storeType.type;
148 }
149 }
150 return "other";
151 }
152
GetSecurity(const StoreMetaData & metaData) const153 std::string DirectoryManager::GetSecurity(const StoreMetaData &metaData) const
154 {
155 switch (metaData.securityLevel) {
156 case SecurityLevel::NO_LABEL:
157 if ((metaData.bundleName != metaData.appId) || (metaData.appType != "harmony")) {
158 break;
159 }
160 [[fallthrough]];
161 case SecurityLevel::S0:
162 [[fallthrough]];
163 case SecurityLevel::S1:
164 return "misc_de";
165 }
166 return "misc_ce";
167 }
168
GetArea(const StoreMetaData & metaData) const169 std::string DirectoryManager::GetArea(const StoreMetaData &metaData) const
170 {
171 return std::string("el") + std::to_string(metaData.area);
172 }
173
GetUserId(const StoreMetaData & metaData) const174 std::string DirectoryManager::GetUserId(const StoreMetaData &metaData) const
175 {
176 auto type = AccessTokenKit::GetTokenTypeFlag(metaData.tokenId);
177 if ((type == TOKEN_NATIVE || type == TOKEN_SHELL) && (metaData.user == StoreMetaData::ROOT_USER)) {
178 return "public";
179 }
180 return metaData.user;
181 }
182
GetBundleName(const StoreMetaData & metaData) const183 std::string DirectoryManager::GetBundleName(const StoreMetaData &metaData) const
184 {
185 if (metaData.instanceId == 0) {
186 return metaData.bundleName;
187 }
188 return "+clone-" + std::to_string(metaData.instanceId) + "+" + metaData.bundleName;
189 }
190
GetHapName(const StoreMetaData & metaData) const191 std::string DirectoryManager::GetHapName(const StoreMetaData &metaData) const
192 {
193 return metaData.hapName;
194 }
195
GetCustomDir(const StoreMetaData & metaData) const196 std::string DirectoryManager::GetCustomDir(const StoreMetaData &metaData) const
197 {
198 return metaData.customDir;
199 }
200
Split(const std::string & source,const std::string & pattern) const201 std::vector<std::string> DirectoryManager::Split(const std::string &source, const std::string &pattern) const
202 {
203 std::vector<std::string> values;
204 std::string::size_type pos = 0;
205 std::string::size_type nextPos = 0;
206 while (nextPos != std::string::npos) {
207 nextPos = source.find(pattern, pos);
208 if (nextPos == pos) {
209 pos = pos + pattern.size();
210 continue;
211 }
212 values.push_back(source.substr(pos, nextPos - pos));
213 pos = nextPos + pattern.size();
214 }
215 return values;
216 }
217
GetVersionIndex(uint32_t version) const218 int32_t DirectoryManager::GetVersionIndex(uint32_t version) const
219 {
220 for (size_t i = 0; i < strategies_.size(); ++i) {
221 if (version >= strategies_[i].version) {
222 return i;
223 }
224 }
225 return int32_t(strategies_.size()) - 1;
226 }
227
GetVersions()228 std::vector<uint32_t> DirectoryManager::GetVersions()
229 {
230 std::vector<uint32_t> versions;
231 for (size_t i = 0; i < strategies_.size(); ++i) {
232 versions.push_back(strategies_[i].version);
233 }
234 return versions;
235 }
236
GenPath(const StoreMetaData & metaData,uint32_t version,const std::string & exPath) const237 std::string DirectoryManager::GenPath(const StoreMetaData &metaData, uint32_t version, const std::string &exPath) const
238 {
239 int32_t index = GetVersionIndex(version);
240 if (index < 0) {
241 return "";
242 }
243 std::string path;
244 auto &strategy = strategies_[index];
245 for (size_t i = 0; i < strategy.pipes.size(); ++i) {
246 std::string section;
247 if (strategy.pipes[i] == nullptr) {
248 section = strategy.path[i];
249 } else {
250 section = (this->*(strategy.pipes[i]))(metaData);
251 }
252 if (section.empty()) {
253 continue;
254 }
255 path += "/" + section;
256 }
257 if (!exPath.empty()) {
258 path += "/" + exPath;
259 }
260 if (strategy.autoCreate) {
261 CreateDirectory(path);
262 }
263 return path;
264 }
265
CreateDirectory(const std::string & path) const266 bool DirectoryManager::CreateDirectory(const std::string &path) const
267 {
268 if (access(path.c_str(), F_OK) == 0) {
269 return true;
270 }
271
272 std::string::size_type index = 0;
273 do {
274 std::string subPath;
275 index = path.find('/', index + 1);
276 if (index == std::string::npos) {
277 subPath = path;
278 } else {
279 subPath = path.substr(0, index);
280 }
281
282 if (access(subPath.c_str(), F_OK) != 0) {
283 if (mkdir(subPath.c_str(), (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)) != 0) {
284 ZLOGE("mkdir error:%{public}d", errno);
285 return false;
286 }
287 }
288 } while (index != std::string::npos);
289
290 return access(path.c_str(), F_OK) == 0;
291 }
292 } // namespace OHOS::DistributedData
293