• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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_state_storage.h"
17 
18 #include <fstream>
19 #include <sys/stat.h>
20 #include <unistd.h>
21 
22 #include "app_log_wrapper.h"
23 #include "bundle_constants.h"
24 #include "bundle_util.h"
25 #include "installd_client.h"
26 #include "string_ex.h"
27 
28 namespace OHOS {
29 namespace AppExecFwk {
30 namespace {
31 const std::string::size_type EXPECT_SPLIT_SIZE = 2;
32 constexpr const char* BUNDLE_USER_INFO_PATH =
33     "/data/service/el1/public/bms/bundle_manager_service/bundle_user_info.json";
34 
NameAndUserIdToKey(const std::string & bundleName,int32_t userId,std::string & key)35 void NameAndUserIdToKey(
36     const std::string &bundleName, int32_t userId, std::string &key)
37 {
38     key.append(bundleName);
39     key.append(Constants::FILE_UNDERLINE);
40     key.append(std::to_string(userId));
41     APP_LOGD("bundleName = %{public}s", bundleName.c_str());
42 }
43 
KeyToNameAndUserId(const std::string & key,std::string & bundleName,int32_t & userId)44 bool KeyToNameAndUserId(
45     const std::string &key, std::string &bundleName, int32_t &userId)
46 {
47     bool ret = false;
48     std::vector<std::string> splitStrs;
49     OHOS::SplitStr(key, Constants::FILE_UNDERLINE, splitStrs);
50     if (splitStrs.size() == EXPECT_SPLIT_SIZE) {
51         bundleName = splitStrs[0];
52         userId = atoi(splitStrs[1].c_str());
53         ret = true;
54     }
55 
56     APP_LOGD("bundleName = %{public}s", bundleName.c_str());
57     return ret;
58 }
59 }
60 
HasBundleUserInfoJsonDb()61 bool BundleStateStorage::HasBundleUserInfoJsonDb()
62 {
63     APP_LOGD("HasBundleUserInfoJsonDb start");
64     if (BundleUtil::IsExistFile(BUNDLE_USER_INFO_PATH)) {
65         APP_LOGD("Json db exist");
66         return true;
67     }
68 
69     APP_LOGD("Json db not exist, and create it");
70     bool isDirExist = BundleUtil::IsExistDir(Constants::BUNDLE_MANAGER_SERVICE_PATH);
71     if (!isDirExist) {
72         mode_t mode = S_IRWXU | S_IXGRP | S_IXOTH;
73         ErrCode result = InstalldClient::GetInstance()->Mkdir(
74             Constants::BUNDLE_MANAGER_SERVICE_PATH, mode, getuid(), getgid());
75         if (result != ERR_OK) {
76             APP_LOGE("fail to create dir, error is %{public}d", result);
77             return false;
78         }
79     }
80 
81     auto file = fopen(BUNDLE_USER_INFO_PATH, "at++");
82     if (file == nullptr) {
83         APP_LOGE("create json db failed");
84         return false;
85     }
86 
87     auto ret = fclose(file);
88     if (ret != 0) {
89         APP_LOGE("ret: %{public}d", ret);
90     }
91 
92     return false;
93 }
94 
LoadAllBundleStateData(std::map<std::string,std::map<int32_t,BundleUserInfo>> & infos)95 bool BundleStateStorage::LoadAllBundleStateData(
96     std::map<std::string, std::map<int32_t, BundleUserInfo>> &infos)
97 {
98     APP_LOGD("load all bundle state data to map");
99     std::lock_guard<std::mutex> lock(bundleStateMutex_);
100     std::fstream i(BUNDLE_USER_INFO_PATH);
101     nlohmann::json jParse;
102     if (!i.is_open()) {
103         APP_LOGE("failed to open bundle database file");
104         return false;
105     }
106 
107     APP_LOGD("Open bundle state db file success");
108     i.seekg(0, std::ios::end);
109     int len = static_cast<int>(i.tellg());
110     if (len <= 0) {
111         APP_LOGD("Tellg failed.");
112         i.close();
113         return false;
114     }
115 
116     i.seekg(0, std::ios::beg);
117     jParse = nlohmann::json::parse(i, nullptr, false);
118     i.close();
119     return LoadAllBundleStateDataFromJson(jParse, infos);
120 }
121 
LoadAllBundleStateDataFromJson(nlohmann::json & jParse,std::map<std::string,std::map<int32_t,BundleUserInfo>> & infos)122 bool BundleStateStorage::LoadAllBundleStateDataFromJson(
123     nlohmann::json &jParse, std::map<std::string, std::map<int32_t, BundleUserInfo>> &infos)
124 {
125     if (jParse.is_discarded()) {
126         APP_LOGE("Bad json due to jParse is discarded");
127         return false;
128     }
129 
130     for (auto &item : jParse.items()) {
131         std::string bundleName;
132         int32_t userId;
133         if (!KeyToNameAndUserId(item.key(), bundleName, userId)) {
134             continue;
135         }
136 
137         BundleUserInfo bundleUserInfo;
138         nlohmann::json& jsonObject = item.value();
139         if (jsonObject.is_discarded()) {
140             APP_LOGE("Load failed due to data is discarded");
141             continue;
142         }
143 
144         bundleUserInfo = jsonObject.get<BundleUserInfo>();
145         if (infos.find(bundleName) == infos.end()) {
146             std::map<int32_t, BundleUserInfo> tempUser;
147             tempUser.try_emplace(userId, bundleUserInfo);
148             infos.try_emplace(bundleName, tempUser);
149             continue;
150         }
151 
152         auto& bundleUserInfoMaps = infos.at(bundleName);
153         if (bundleUserInfoMaps.find(userId) == bundleUserInfoMaps.end()) {
154             bundleUserInfoMaps.try_emplace(userId, bundleUserInfo);
155             continue;
156         }
157 
158         bundleUserInfoMaps.at(userId) = bundleUserInfo;
159     }
160 
161     return !infos.empty();
162 }
163 
SaveBundleStateStorage(const std::string bundleName,int32_t userId,const BundleUserInfo & bundleUserInfo)164 bool BundleStateStorage::SaveBundleStateStorage(
165     const std::string bundleName, int32_t userId, const BundleUserInfo &bundleUserInfo)
166 {
167     APP_LOGD("Save bundle state to json db");
168     if (bundleName.empty() || userId < 0) {
169         APP_LOGE("Save bundle state failed due to param invalid.");
170         return false;
171     }
172 
173     std::lock_guard<std::mutex> lock(bundleStateMutex_);
174     std::string appName;
175     NameAndUserIdToKey(bundleName, userId, appName);
176     std::fstream f(BUNDLE_USER_INFO_PATH);
177     if (!f.is_open()) {
178         APP_LOGE("failed to open bundle database file");
179         return false;
180     }
181 
182     f.seekg(0, std::ios::end);
183     int len = static_cast<int>(f.tellg());
184     if (len == 0) {
185         nlohmann::json appRoot;
186         appRoot[appName] = bundleUserInfo;
187         f << std::setw(Constants::DUMP_INDENT) << appRoot << std::endl;
188     } else {
189         f.seekg(0, std::ios::beg);
190         nlohmann::json jsonFile;
191         f >> jsonFile;
192         jsonFile[appName] = bundleUserInfo;
193         f.seekp(0, std::ios::beg);
194         f << std::setw(Constants::DUMP_INDENT) << jsonFile << std::endl;
195     }
196 
197     f.close();
198     return true;
199 }
200 
GetBundleStateStorage(const std::string bundleName,int32_t userId,BundleUserInfo & bundleUserInfo)201 bool BundleStateStorage::GetBundleStateStorage(
202     const std::string bundleName, int32_t userId, BundleUserInfo &bundleUserInfo)
203 {
204     if (bundleName.empty() || userId < 0) {
205         APP_LOGE("Get bundle state data failed due to param invalid.");
206         return false;
207     }
208 
209     std::lock_guard<std::mutex> lock(bundleStateMutex_);
210     std::string appName;
211     NameAndUserIdToKey(bundleName, userId, appName);
212     std::fstream f(BUNDLE_USER_INFO_PATH);
213     if (!f.is_open()) {
214         APP_LOGE("failed to open bundle database file");
215         return false;
216     }
217 
218     f.seekg(0, std::ios::end);
219     int len = static_cast<int>(f.tellg());
220     if (len == 0) {
221         f.close();
222         APP_LOGE("failed to open bundle database file due to tellg invalid");
223         return false;
224     }
225 
226     f.seekg(0, std::ios::beg);
227     nlohmann::json jsonFile;
228     f >> jsonFile;
229     if (jsonFile.is_discarded()) {
230         f.close();
231         APP_LOGE("Get failed due to data is discarded");
232         return false;
233     }
234 
235     bundleUserInfo = jsonFile.get<BundleUserInfo>();
236     f.close();
237     return true;
238 }
239 
DeleteBundleState(const std::string bundleName,int32_t userId)240 bool BundleStateStorage::DeleteBundleState(
241     const std::string bundleName, int32_t userId)
242 {
243     APP_LOGD("Delete bundle state data");
244     if (bundleName.empty() || userId < 0) {
245         APP_LOGE("Delete bundle state data failed due to param invalid.");
246         return false;
247     }
248 
249     std::lock_guard<std::mutex> lock(bundleStateMutex_);
250     bool isEmpty = false;
251     std::string appName;
252     NameAndUserIdToKey(bundleName, userId, appName);
253     std::ifstream i(BUNDLE_USER_INFO_PATH);
254     nlohmann::json jParse;
255     if (!i.is_open()) {
256         APP_LOGE("failed to open bundle database file");
257         return false;
258     }
259 
260     i.seekg(0, std::ios::end);
261     int len = static_cast<int>(i.tellg());
262     if (len == 0) {
263         i.close();
264         APP_LOGE("file is empty appName = %{private}s", appName.c_str());
265         return true;
266     }
267 
268     i.seekg(0, std::ios::beg);
269     i >> jParse;
270     if (jParse.find(appName) == jParse.end()) {
271         i.close();
272         APP_LOGD("not find appName = %{public}s", appName.c_str());
273         return true;
274     }
275 
276     jParse.erase(appName);
277     isEmpty = (jParse.size() == 0) ? true : false;
278     i.close();
279     std::ofstream o(BUNDLE_USER_INFO_PATH);
280     if (!o.is_open()) {
281         APP_LOGE("failed to open bundle database file");
282         return false;
283     }
284 
285     if (!isEmpty) {
286         o << std::setw(Constants::DUMP_INDENT) << jParse;
287     }
288 
289     o.close();
290     return true;
291 }
292 }  // namespace AppExecFwk
293 }  // namespace OHOS
294