1 /*
2 * Copyright (c) 2023 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 "CustomUtdStore"
16 #include "custom_utd_store.h"
17 #include <fstream>
18 #include <sys/stat.h>
19 #include "logger.h"
20 #include "preset_type_descriptors.h"
21 #include "unistd.h"
22 #include "utd_cfgs_checker.h"
23 #include "utd_graph.h"
24 #ifdef WITH_SELINUX
25 #include <policycoreutils.h>
26 #endif
27 namespace OHOS {
28 namespace UDMF {
29 constexpr const char* UTD_CFG_FILE = "utd-adt.json";
30 constexpr const char* CUSTOM_UTD_HAP_DIR = "/data/utd/utd-adt.json";
31 constexpr const char* CUSTOM_UTD_SA_DIR = "/data/service/el1/";
32 constexpr const char* OLD_CUSTOM_UTD_SA_SUB_DIR = "/distributeddata/utd/";
33 constexpr const char* CUSTOM_UTD_SA_SUB_DIR = "/utdtypes/utd/";
34
CustomUtdStore()35 CustomUtdStore::CustomUtdStore()
36 {
37 }
38
~CustomUtdStore()39 CustomUtdStore::~CustomUtdStore()
40 {
41 }
42
GetInstance()43 CustomUtdStore &CustomUtdStore::GetInstance()
44 {
45 static CustomUtdStore utdCustomPersistence;
46 return utdCustomPersistence;
47 }
48
GetHapTypeCfgs()49 std::vector<TypeDescriptorCfg> CustomUtdStore::GetHapTypeCfgs()
50 {
51 LOG_DEBUG(UDMF_CLIENT, "get utdcustom from cfg, Path:%{public}s.", CUSTOM_UTD_HAP_DIR);
52 std::string jsonStr;
53 std::ifstream fin(CUSTOM_UTD_HAP_DIR);
54 while (fin.good()) {
55 std::string line;
56 std::getline(fin, line);
57 jsonStr += line;
58 }
59 std::vector<TypeDescriptorCfg> customUtdTypes;
60 utdJsonParser_.ParseStoredCustomUtdJson(jsonStr, customUtdTypes);
61 LOG_DEBUG(UDMF_CLIENT, "GetTypeCfgs, customUtdTypes total:%{public}zu.", customUtdTypes.size());
62 return customUtdTypes;
63 }
64
GetTypeCfgs(int32_t userId)65 std::vector<TypeDescriptorCfg> CustomUtdStore::GetTypeCfgs(int32_t userId)
66 {
67 std::string path = CUSTOM_UTD_SA_DIR + std::to_string(userId) + CUSTOM_UTD_SA_SUB_DIR;
68 std::string old_path = CUSTOM_UTD_SA_DIR + std::to_string(userId) + OLD_CUSTOM_UTD_SA_SUB_DIR;
69 std::string cfgFilePath = path;
70 if (access(path.c_str(), F_OK) != 0 && access(old_path.c_str(), F_OK) == 0) {
71 cfgFilePath = old_path;
72 }
73 cfgFilePath.append(UTD_CFG_FILE);
74 LOG_DEBUG(UDMF_CLIENT, "get utdcustom from cfg, Path:%{public}s.", cfgFilePath.c_str());
75 std::string jsonStr;
76 std::ifstream fin(cfgFilePath);
77 while (fin.good()) {
78 std::string line;
79 std::getline(fin, line);
80 jsonStr += line;
81 }
82 std::vector<TypeDescriptorCfg> customUtdTypes;
83 utdJsonParser_.ParseStoredCustomUtdJson(jsonStr, customUtdTypes);
84 LOG_DEBUG(UDMF_CLIENT, "GetTypeCfgs, customUtdTypes total:%{public}zu.", customUtdTypes.size());
85 return customUtdTypes;
86 }
87
SaveTypeCfgs(const std::vector<TypeDescriptorCfg> & customUtdTypes,int32_t user)88 int32_t CustomUtdStore::SaveTypeCfgs(const std::vector<TypeDescriptorCfg> &customUtdTypes, int32_t user)
89 {
90 LOG_DEBUG(UDMF_CLIENT, "customUtdTypes total:%{public}zu.", customUtdTypes.size());
91 std::string jsonData;
92 std::string cfgFileDir = CUSTOM_UTD_SA_DIR + std::to_string(user) + CUSTOM_UTD_SA_SUB_DIR;
93 if (utdJsonParser_.ConvertUtdCfgsToJson(customUtdTypes, jsonData) && CreateDirectory(cfgFileDir)) {
94 SavaCfgFile(jsonData, cfgFileDir.append(UTD_CFG_FILE));
95 }
96 return 0;
97 }
98
SavaCfgFile(const std::string & jsonData,const std::string & cfgFilePath)99 int32_t CustomUtdStore::SavaCfgFile(const std::string &jsonData, const std::string &cfgFilePath)
100 {
101 std::ofstream ofs;
102 LOG_DEBUG(UDMF_CLIENT, "set cfg start, path:%{public}s ", cfgFilePath.c_str());
103 ofs.open(cfgFilePath, 0x02);
104 if (!ofs.is_open()) {
105 LOG_ERROR(UDMF_CLIENT, "open cfg failed, path:%{public}s", cfgFilePath.c_str());
106 }
107 ofs << jsonData << std::endl;
108 ofs.close();
109 LOG_DEBUG(UDMF_CLIENT, "set cfg end.");
110 return 0;
111 }
112
CreateDirectory(const std::string & path) const113 bool CustomUtdStore::CreateDirectory(const std::string &path) const
114 {
115 LOG_DEBUG(UDMF_CLIENT, "CreateDirectory start, path:%{public}s ", path.c_str());
116 if (access(path.c_str(), F_OK) == 0) {
117 return true;
118 }
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_IRWXG | S_IROTH | S_IXOTH)) != 0) {
132 LOG_WARN(UDMF_CLIENT, "CreateDirectory, fail. path:%{public}s, subPath:%{public}s.",
133 path.c_str(), subPath.c_str());
134 return false;
135 }
136 }
137 } while (index != std::string::npos);
138
139 if (access(path.c_str(), F_OK) == 0) {
140 #ifdef WITH_SELINUX
141 Restorecon(path.c_str());
142 #endif
143 return true;
144 }
145
146 return false;
147 }
148
InstallCustomUtds(const std::string & bundleName,const std::string & jsonStr,int32_t user,std::vector<TypeDescriptorCfg> & customTyepCfgs)149 bool CustomUtdStore::InstallCustomUtds(const std::string &bundleName, const std::string &jsonStr,
150 int32_t user, std::vector<TypeDescriptorCfg> &customTyepCfgs)
151 {
152 CustomUtdCfgs typeCfgs;
153 if (!utdJsonParser_.ParseUserCustomUtdJson(jsonStr, typeCfgs.first, typeCfgs.second)) {
154 LOG_ERROR(UDMF_CLIENT, "Parse json failed. bundleName:%{public}s", bundleName.c_str());
155 return false;
156 }
157 std::vector<TypeDescriptorCfg> presetTypes = PresetTypeDescriptors::GetInstance().GetPresetTypes();
158
159 if (!UtdCfgsChecker::GetInstance().CheckTypeDescriptors(
160 typeCfgs, presetTypes, customTyepCfgs, bundleName)) {
161 LOG_ERROR(UDMF_CLIENT, "check type descriptors failed, bundleName:%{public}s", bundleName.c_str());
162 return false;
163 }
164
165 ProcessUtdForSave(typeCfgs, customTyepCfgs, bundleName);
166 if (CustomUtdStore::GetInstance().SaveTypeCfgs(customTyepCfgs, user) != E_OK) {
167 LOG_ERROR(UDMF_CLIENT, "Save failed, bundleName: %{public}s", bundleName.c_str());
168 return false;
169 }
170 return true;
171 }
172
UninstallCustomUtds(const std::string & bundleName,int32_t user,std::vector<TypeDescriptorCfg> & customTyepCfgs)173 bool CustomUtdStore::UninstallCustomUtds(const std::string &bundleName, int32_t user,
174 std::vector<TypeDescriptorCfg> &customTyepCfgs)
175 {
176 for (auto iter = customTyepCfgs.begin(); iter != customTyepCfgs.end();) {
177 auto it = find(iter->installerBundles.begin(), iter->installerBundles.end(), bundleName);
178 if (it != iter->installerBundles.end()) {
179 iter->installerBundles.erase(it);
180 }
181 if (iter->installerBundles.empty()) {
182 iter = customTyepCfgs.erase(iter);
183 } else {
184 iter++;
185 }
186 }
187 std::vector<TypeDescriptorCfg> presetTypes = PresetTypeDescriptors::GetInstance().GetPresetTypes();
188 if (!UtdCfgsChecker::GetInstance().CheckBelongingToTypes(customTyepCfgs, presetTypes)) {
189 LOG_ERROR(UDMF_CLIENT, "belongingToTypes check failed. bundleName:%{public}s", bundleName.c_str());
190 return false;
191 }
192 if (CustomUtdStore::GetInstance().SaveTypeCfgs(customTyepCfgs, user) != E_OK) {
193 LOG_ERROR(UDMF_CLIENT, "Save type cfgs failed, bundleName: %{public}s", bundleName.c_str());
194 return false;
195 }
196 return true;
197 }
198
ProcessUtdForSave(const CustomUtdCfgs & utdTypes,std::vector<TypeDescriptorCfg> & customTyepCfgs,const std::string & bundleName)199 void CustomUtdStore::ProcessUtdForSave(const CustomUtdCfgs &utdTypes, std::vector<TypeDescriptorCfg> &customTyepCfgs,
200 const std::string &bundleName)
201 {
202 for (TypeDescriptorCfg declarationType : utdTypes.first) {
203 for (auto iter = customTyepCfgs.begin(); iter != customTyepCfgs.end();) {
204 if (iter->typeId == declarationType.typeId) {
205 declarationType.installerBundles = iter->installerBundles;
206 iter = customTyepCfgs.erase(iter);
207 } else {
208 iter++;
209 }
210 }
211 declarationType.installerBundles.emplace(bundleName);
212 declarationType.ownerBundle = bundleName;
213 customTyepCfgs.push_back(declarationType);
214 }
215 for (TypeDescriptorCfg referenceType : utdTypes.second) {
216 bool found = false;
217 for (auto &typeCfg : customTyepCfgs) {
218 if (typeCfg.typeId == referenceType.typeId) {
219 typeCfg.installerBundles.emplace(bundleName);
220 found = true;
221 break;
222 }
223 }
224 if (!found) {
225 referenceType.installerBundles.emplace(bundleName);
226 customTyepCfgs.push_back(referenceType);
227 }
228 }
229 }
230 } // namespace UDMF
231 } // namespace OHOS