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_manager.h"
17
18 #include <dirent.h>
19 #include <sys/stat.h>
20
21 #include <string>
22
23 #include "accesstoken_kit.h"
24 #include "log_print.h"
25 #include "types.h"
26 #include "unistd.h"
27 namespace OHOS::DistributedData {
28 using OHOS::DistributedKv::SecurityLevel;
29 using namespace OHOS::Security::AccessToken;
DirectoryManager()30 DirectoryManager::DirectoryManager()
31 : actions_({ { "{security}", &DirectoryManager::GetSecurity }, { "{store}", &DirectoryManager::GetStore },
32 { "{type}", &DirectoryManager::GetType }, { "{area}", &DirectoryManager::GetArea },
33 { "{userId}", &DirectoryManager::GetUserId }, { "{bundleName}", &DirectoryManager::GetBundleName },
34 { "{hapName}", &DirectoryManager::GetHapName } })
35 {
36 }
37
GetInstance()38 DirectoryManager &DirectoryManager::GetInstance()
39 {
40 static DirectoryManager instance;
41 return instance;
42 }
43
GetStorePath(const StoreMetaData & metaData,uint32_t version)44 std::string DirectoryManager::GetStorePath(const StoreMetaData &metaData, uint32_t version)
45 {
46 return GenPath(metaData, version, "");
47 }
48
GetStoreBackupPath(const StoreMetaData & metaData,uint32_t version)49 std::string DirectoryManager::GetStoreBackupPath(const StoreMetaData &metaData, uint32_t version)
50 {
51 auto rootBackupPath = GenPath(metaData, version, "backup");
52 return rootBackupPath + "/" + metaData.storeId;
53 }
54
GetSecretKeyPath(const StoreMetaData & metaData,uint32_t version)55 std::string DirectoryManager::GetSecretKeyPath(const StoreMetaData &metaData, uint32_t version)
56 {
57 return GenPath(metaData, version, "secret");
58 }
59
GetMetaStorePath(uint32_t version)60 std::string DirectoryManager::GetMetaStorePath(uint32_t version)
61 {
62 int32_t index = GetVersionIndex(version);
63 if (index < 0) {
64 return "";
65 }
66
67 auto &strategy = strategies_[index];
68 if (strategy.autoCreate) {
69 CreateDirectory(strategy.metaPath);
70 }
71 return strategy.metaPath;
72 }
73
GetMetaBackupPath(uint32_t version)74 std::string DirectoryManager::GetMetaBackupPath(uint32_t version)
75 {
76 int32_t index = GetVersionIndex(version);
77 if (index < 0) {
78 return "";
79 }
80
81 auto &strategy = strategies_[index];
82 std::string path = strategy.metaPath + "/backup";
83 if (strategy.autoCreate) {
84 CreateDirectory(path);
85 }
86 return path;
87 }
88
Initialize(const std::vector<Strategy> & strategies)89 void DirectoryManager::Initialize(const std::vector<Strategy> &strategies)
90 {
91 strategies_.resize(strategies.size());
92 for (size_t i = 0; i < strategies.size(); ++i) {
93 const Strategy &strategy = strategies[i];
94 StrategyImpl &impl = strategies_[i];
95 impl.autoCreate = strategy.autoCreate;
96 impl.version = strategy.version;
97 impl.metaPath = strategy.metaPath;
98 impl.path = Split(strategy.pattern, "/");
99 impl.pipes.clear();
100 for (auto &value : impl.path) {
101 auto it = actions_.find(value);
102 impl.pipes.push_back(it == actions_.end() ? nullptr : it->second);
103 }
104 }
105
106 std::sort(strategies_.begin(), strategies_.end(),
107 [](const StrategyImpl &curr, const StrategyImpl &prev) { return curr.version > prev.version; });
108 }
109
GetType(const StoreMetaData & metaData) const110 std::string DirectoryManager::GetType(const StoreMetaData &metaData) const
111 {
112 auto type = AccessTokenKit::GetTokenTypeFlag(metaData.tokenId);
113 if (type == TOKEN_NATIVE || type == TOKEN_SHELL) {
114 return "service";
115 }
116 return "app";
117 }
118
GetStore(const StoreMetaData & metaData) const119 std::string DirectoryManager::GetStore(const StoreMetaData &metaData) const
120 {
121 if (metaData.storeType >= StoreMetaData::StoreType::STORE_KV_BEGIN
122 && metaData.storeType <= StoreMetaData::StoreType::STORE_KV_END) {
123 return "kvdb";
124 }
125 // rdb use empty session
126 if (metaData.storeType >= StoreMetaData::StoreType::STORE_RELATIONAL_BEGIN
127 && metaData.storeType <= StoreMetaData::StoreType::STORE_RELATIONAL_END) {
128 return "rdb";
129 }
130 return "other";
131 }
132
GetSecurity(const StoreMetaData & metaData) const133 std::string DirectoryManager::GetSecurity(const StoreMetaData &metaData) const
134 {
135 switch (metaData.securityLevel) {
136 case SecurityLevel::NO_LABEL:
137 if ((metaData.bundleName != metaData.appId) || (metaData.appType != "harmony")) {
138 break;
139 }
140 [[fallthrough]];
141 case SecurityLevel::S0: [[fallthrough]];
142 case SecurityLevel::S1:
143 return "misc_de";
144 }
145 return "misc_ce";
146 }
147
GetArea(const StoreMetaData & metaData) const148 std::string DirectoryManager::GetArea(const StoreMetaData &metaData) const
149 {
150 return std::string("el") + std::to_string(metaData.area);
151 }
152
GetUserId(const StoreMetaData & metaData) const153 std::string DirectoryManager::GetUserId(const StoreMetaData &metaData) const
154 {
155 auto type = AccessTokenKit::GetTokenTypeFlag(metaData.tokenId);
156 if (type == TOKEN_NATIVE || type == TOKEN_SHELL) {
157 return "public";
158 }
159 return metaData.user;
160 }
161
GetBundleName(const StoreMetaData & metaData) const162 std::string DirectoryManager::GetBundleName(const StoreMetaData &metaData) const
163 {
164 if (metaData.instanceId == 0) {
165 return metaData.bundleName;
166 }
167 return metaData.bundleName + "_" + std::to_string(metaData.instanceId);
168 }
169
GetHapName(const StoreMetaData & metaData) const170 std::string DirectoryManager::GetHapName(const StoreMetaData &metaData) const
171 {
172 return metaData.hapName;
173 }
174
Split(const std::string & source,const std::string & pattern) const175 std::vector<std::string> DirectoryManager::Split(const std::string &source, const std::string &pattern) const
176 {
177 std::vector<std::string> values;
178 std::string::size_type pos = 0;
179 std::string::size_type nextPos = 0;
180 while (nextPos != std::string::npos) {
181 nextPos = source.find(pattern, pos);
182 if (nextPos == pos) {
183 pos = pos + pattern.size();
184 continue;
185 }
186 values.push_back(source.substr(pos, nextPos - pos));
187 pos = nextPos + pattern.size();
188 }
189 return values;
190 }
191
GetVersionIndex(uint32_t version) const192 int32_t DirectoryManager::GetVersionIndex(uint32_t version) const
193 {
194 for (size_t i = 0; i < strategies_.size(); ++i) {
195 if (version >= strategies_[i].version) {
196 return i;
197 }
198 }
199 return int32_t(strategies_.size()) - 1;
200 }
201
GetVersions()202 std::vector<uint32_t> DirectoryManager::GetVersions()
203 {
204 std::vector<uint32_t> versions;
205 for (size_t i = 0; i < strategies_.size(); ++i) {
206 versions[i] = strategies_[i].version;
207 }
208 return versions;
209 }
210
GenPath(const StoreMetaData & metaData,uint32_t version,const std::string & exPath) const211 std::string DirectoryManager::GenPath(const StoreMetaData &metaData, uint32_t version, const std::string &exPath) const
212 {
213 int32_t index = GetVersionIndex(version);
214 if (index < 0) {
215 return "";
216 }
217 std::string path;
218 auto &strategy = strategies_[index];
219 for (size_t i = 0; i < strategy.pipes.size(); ++i) {
220 std::string section;
221 if (strategy.pipes[i] == nullptr) {
222 section = strategy.path[i];
223 } else {
224 section = (this->*(strategy.pipes[i]))(metaData);
225 }
226 if (section.empty()) {
227 continue;
228 }
229 path += "/" + section;
230 }
231 if (!exPath.empty()) {
232 path += "/" + exPath;
233 }
234 if (strategy.autoCreate) {
235 CreateDirectory(path);
236 }
237 return path;
238 }
239
CreateDirectory(const std::string & path) const240 bool DirectoryManager::CreateDirectory(const std::string &path) const
241 {
242 if (access(path.c_str(), F_OK) == 0) {
243 return true;
244 }
245
246 std::string::size_type index = 0;
247 do {
248 std::string subPath;
249 index = path.find('/', index + 1);
250 if (index == std::string::npos) {
251 subPath = path;
252 } else {
253 subPath = path.substr(0, index);
254 }
255
256 if (access(subPath.c_str(), F_OK) != 0) {
257 if (mkdir(subPath.c_str(), (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)) != 0) {
258 return false;
259 }
260 }
261 } while (index != std::string::npos);
262
263 return access(path.c_str(), F_OK) == 0;
264 }
265 } // namespace OHOS::DistributedData
266