• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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)110 void DirectoryManager::Initialize(const std::vector<Strategy> &strategies)
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 
GetType(const StoreMetaData & metaData) const132 std::string DirectoryManager::GetType(const StoreMetaData &metaData) const
133 {
134     auto type = AccessTokenKit::GetTokenTypeFlag(metaData.tokenId);
135     if (type == TOKEN_NATIVE || type == TOKEN_SHELL) {
136         return "service";
137     }
138     return "app";
139 }
140 
GetStore(const StoreMetaData & metaData) const141 std::string DirectoryManager::GetStore(const StoreMetaData &metaData) const
142 {
143     if (metaData.storeType >= StoreMetaData::StoreType::STORE_KV_BEGIN &&
144         metaData.storeType <= StoreMetaData::StoreType::STORE_KV_END) {
145         return "kvdb";
146     }
147     // rdb use empty session
148     if (metaData.storeType >= StoreMetaData::StoreType::STORE_RELATIONAL_BEGIN &&
149         metaData.storeType <= StoreMetaData::StoreType::STORE_RELATIONAL_END) {
150         return "rdb";
151     }
152     // object use meta
153     if (metaData.storeType >= StoreMetaData::StoreType::STORE_OBJECT_BEGIN &&
154         metaData.storeType <= StoreMetaData::StoreType::STORE_OBJECT_END) {
155         return "kvdb";
156     }
157     return "other";
158 }
159 
GetSecurity(const StoreMetaData & metaData) const160 std::string DirectoryManager::GetSecurity(const StoreMetaData &metaData) const
161 {
162     switch (metaData.securityLevel) {
163         case SecurityLevel::NO_LABEL:
164             if ((metaData.bundleName != metaData.appId) || (metaData.appType != "harmony")) {
165                 break;
166             }
167             [[fallthrough]];
168         case SecurityLevel::S0:
169             [[fallthrough]];
170         case SecurityLevel::S1:
171             return "misc_de";
172     }
173     return "misc_ce";
174 }
175 
GetArea(const StoreMetaData & metaData) const176 std::string DirectoryManager::GetArea(const StoreMetaData &metaData) const
177 {
178     return std::string("el") + std::to_string(metaData.area);
179 }
180 
GetUserId(const StoreMetaData & metaData) const181 std::string DirectoryManager::GetUserId(const StoreMetaData &metaData) const
182 {
183     auto type = AccessTokenKit::GetTokenTypeFlag(metaData.tokenId);
184     if ((type == TOKEN_NATIVE || type == TOKEN_SHELL) && (metaData.user == StoreMetaData::ROOT_USER)) {
185         return "public";
186     }
187     return metaData.user;
188 }
189 
GetBundleName(const StoreMetaData & metaData) const190 std::string DirectoryManager::GetBundleName(const StoreMetaData &metaData) const
191 {
192     if (metaData.instanceId == 0) {
193         return metaData.bundleName;
194     }
195     return "+clone-" + std::to_string(metaData.instanceId) + "+" + metaData.bundleName;
196 }
197 
GetHapName(const StoreMetaData & metaData) const198 std::string DirectoryManager::GetHapName(const StoreMetaData &metaData) const
199 {
200     return metaData.hapName;
201 }
202 
GetCustomDir(const StoreMetaData & metaData) const203 std::string DirectoryManager::GetCustomDir(const StoreMetaData &metaData) const
204 {
205     return metaData.customDir;
206 }
207 
Split(const std::string & source,const std::string & pattern) const208 std::vector<std::string> DirectoryManager::Split(const std::string &source, const std::string &pattern) const
209 {
210     std::vector<std::string> values;
211     std::string::size_type pos = 0;
212     std::string::size_type nextPos = 0;
213     while (nextPos != std::string::npos) {
214         nextPos = source.find(pattern, pos);
215         if (nextPos == pos) {
216             pos = pos + pattern.size();
217             continue;
218         }
219         values.push_back(source.substr(pos, nextPos - pos));
220         pos = nextPos + pattern.size();
221     }
222     return values;
223 }
224 
GetVersionIndex(uint32_t version) const225 int32_t DirectoryManager::GetVersionIndex(uint32_t version) const
226 {
227     for (size_t i = 0; i < strategies_.size(); ++i) {
228         if (version >= strategies_[i].version) {
229             return i;
230         }
231     }
232     return int32_t(strategies_.size()) - 1;
233 }
234 
GetVersions()235 std::vector<uint32_t> DirectoryManager::GetVersions()
236 {
237     std::vector<uint32_t> versions;
238     for (size_t i = 0; i < strategies_.size(); ++i) {
239         versions.push_back(strategies_[i].version);
240     }
241     return versions;
242 }
243 
GenPath(const StoreMetaData & metaData,uint32_t version,const std::string & exPath) const244 std::string DirectoryManager::GenPath(const StoreMetaData &metaData, uint32_t version, const std::string &exPath) const
245 {
246     int32_t index = GetVersionIndex(version);
247     if (index < 0) {
248         return "";
249     }
250     std::string path;
251     auto &strategy = strategies_[index];
252     for (size_t i = 0; i < strategy.pipes.size(); ++i) {
253         std::string section;
254         if (strategy.pipes[i] == nullptr) {
255             section = strategy.path[i];
256         } else {
257             section = (this->*(strategy.pipes[i]))(metaData);
258         }
259         if (section.empty()) {
260             continue;
261         }
262         path += "/" + section;
263     }
264     if (!exPath.empty()) {
265         path += "/" + exPath;
266     }
267     if (strategy.autoCreate) {
268         CreateDirectory(path);
269     }
270     return path;
271 }
272 
CreateDirectory(const std::string & path) const273 bool DirectoryManager::CreateDirectory(const std::string &path) const
274 {
275     if (access(path.c_str(), F_OK) == 0) {
276         return true;
277     }
278 
279     std::string::size_type index = 0;
280     do {
281         std::string subPath;
282         index = path.find('/', index + 1);
283         if (index == std::string::npos) {
284             subPath = path;
285         } else {
286             subPath = path.substr(0, index);
287         }
288 
289         if (access(subPath.c_str(), F_OK) != 0) {
290             if (mkdir(subPath.c_str(), (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)) != 0) {
291                 return false;
292             }
293         }
294     } while (index != std::string::npos);
295 
296     return access(path.c_str(), F_OK) == 0;
297 }
298 
DeleteDirectory(const char * path)299 bool DirectoryManager::DeleteDirectory(const char* path)
300 {
301     if (path == nullptr) {
302         return false;
303     }
304     DIR* dir;
305     struct dirent* dirEntry;
306     struct stat buf;
307     char* curWorkDir = getcwd(nullptr, 0);
308     if ((dir = opendir(path)) == nullptr) {
309         return true;
310     }
311     if (chdir(path) == -1) {
312         closedir(dir);
313         return false;
314     }
315     while ((dirEntry = readdir(dir))) {
316         if ((strcmp(dirEntry->d_name, ".") == 0) || (strcmp(dirEntry->d_name, "..") == 0)) {
317             continue;
318         }
319         if (stat(dirEntry->d_name, &buf) == -1) {
320             closedir(dir);
321             return false;
322         }
323         if (S_ISDIR(buf.st_mode)) {
324             DeleteDirectory(dirEntry->d_name);
325             continue;
326         }
327         if (remove(dirEntry->d_name) == -1) {
328             closedir(dir);
329             return false;
330         }
331     }
332     closedir(dir);
333     if (chdir(curWorkDir) == -1 || rmdir(path) == -1) {
334         return false;
335     }
336     return true;
337 }
338 } // namespace OHOS::DistributedData
339