• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <sstream>
19 #include <sys/stat.h>
20 #include "logger.h"
21 #include "preset_type_descriptors.h"
22 #include "unistd.h"
23 #include "utd_cfgs_checker.h"
24 #include "utd_graph.h"
25 #ifdef WITH_SELINUX
26 #include <policycoreutils.h>
27 #endif
28 namespace OHOS {
29 namespace UDMF {
30 constexpr const char* UTD_CFG_FILE = "utd-adt.json";
31 constexpr const char* CUSTOM_UTD_HAP_DIR = "/data/utd/utd-adt.json";
32 constexpr const char* CUSTOM_UTD_SA_DIR = "/data/service/el1/";
33 constexpr const char* OLD_CUSTOM_UTD_SA_SUB_DIR = "/distributeddata/utd/";
34 constexpr const char* CUSTOM_UTD_SA_SUB_DIR = "/utdtypes/utd/";
35 
CustomUtdStore()36 CustomUtdStore::CustomUtdStore()
37 {
38 }
39 
~CustomUtdStore()40 CustomUtdStore::~CustomUtdStore()
41 {
42 }
43 
GetInstance()44 CustomUtdStore &CustomUtdStore::GetInstance()
45 {
46     static CustomUtdStore utdCustomPersistence;
47     return utdCustomPersistence;
48 }
49 
GetCustomUtd(bool isHap,int32_t userId)50 std::vector<TypeDescriptorCfg> CustomUtdStore::GetCustomUtd(bool isHap, int32_t userId)
51 {
52     std::string path = GetCustomUtdPath(isHap, userId);
53     LOG_DEBUG(UDMF_CLIENT, "get utdcustom from cfg");
54 
55     std::vector<TypeDescriptorCfg> customUtd;
56     std::ifstream fin(path);
57     if (!fin.is_open()) {
58         LOG_ERROR(UDMF_CLIENT, "Failed to open custom utd file, errno=%{public}d", errno);
59         return customUtd;
60     }
61 
62     std::ostringstream buffer;
63     buffer << fin.rdbuf();
64     if (fin.fail() && !fin.eof()) {
65         LOG_ERROR(UDMF_CLIENT, "Error reading file, errno=%{public}d", errno);
66         return customUtd;
67     }
68 
69     std::string jsonStr = buffer.str();
70     if (!utdJsonParser_.ParseStoredCustomUtdJson(jsonStr, customUtd)) {
71         LOG_ERROR(UDMF_CLIENT, "Failed to parse custom utd json");
72         customUtd.clear();
73     }
74     LOG_DEBUG(UDMF_CLIENT, "CustomUtd total:%{public}zu.", customUtd.size());
75     return customUtd;
76 }
77 
GetCustomUtdPath(bool isHap,int32_t userId)78 std::string CustomUtdStore::GetCustomUtdPath(bool isHap, int32_t userId)
79 {
80     if (isHap) {
81         return CUSTOM_UTD_HAP_DIR;
82     }
83     std::string userIdStr = std::to_string(userId);
84     std::string path = std::string(CUSTOM_UTD_SA_DIR).append(userIdStr).append(CUSTOM_UTD_SA_SUB_DIR);
85     std::string oldPath = std::string(CUSTOM_UTD_SA_DIR).append(userIdStr).append(OLD_CUSTOM_UTD_SA_SUB_DIR);
86     path = (access(path.c_str(), F_OK) != 0 && access(oldPath.c_str(), F_OK) == 0) ? oldPath : path;
87     path.append(UTD_CFG_FILE);
88     return path;
89 }
90 
SaveTypeCfgs(const std::vector<TypeDescriptorCfg> & customUtdTypes,int32_t user)91 int32_t CustomUtdStore::SaveTypeCfgs(const std::vector<TypeDescriptorCfg> &customUtdTypes, int32_t user)
92 {
93     LOG_DEBUG(UDMF_CLIENT, "customUtdTypes total:%{public}zu.", customUtdTypes.size());
94     std::string jsonData;
95     if (!utdJsonParser_.ConvertUtdCfgsToJson(customUtdTypes, jsonData)) {
96         LOG_ERROR(UDMF_CLIENT, "ConvertUtdCfgsToJson failed");
97         return E_JSON_CONVERT_FAILED;
98     }
99     std::string cfgFileDir = CUSTOM_UTD_SA_DIR + std::to_string(user) + CUSTOM_UTD_SA_SUB_DIR;
100     if (!CreateDirectory(cfgFileDir)) {
101         LOG_ERROR(UDMF_CLIENT, "CreateDirectory failed");
102         return E_FS_ERROR;
103     }
104     return SaveCfgFile(jsonData, cfgFileDir + UTD_CFG_FILE);
105 }
106 
SaveCfgFile(const std::string & jsonData,const std::string & cfgFilePath)107 int32_t CustomUtdStore::SaveCfgFile(const std::string &jsonData, const std::string &cfgFilePath)
108 {
109     std::ofstream ofs;
110     ofs.open(cfgFilePath, 0x02);
111     if (!ofs.is_open()) {
112         LOG_ERROR(UDMF_CLIENT, "open cfg failed");
113         return E_FS_ERROR;
114     }
115     ofs << jsonData << std::endl;
116     if (!ofs.good()) {
117         LOG_ERROR(UDMF_CLIENT, "write cfg failed");
118         return E_FS_ERROR;
119     }
120     ofs.close();
121     LOG_DEBUG(UDMF_CLIENT, "set cfg end.");
122     return E_OK;
123 }
124 
CreateDirectory(const std::string & path) const125 bool CustomUtdStore::CreateDirectory(const std::string &path) const
126 {
127     if (access(path.c_str(), F_OK) == 0) {
128         return true;
129     }
130 
131     std::string::size_type index = 0;
132     do {
133         std::string subPath;
134         index = path.find('/', index + 1);
135         if (index == std::string::npos) {
136             subPath = path;
137         } else {
138             subPath = path.substr(0, index);
139         }
140 
141         if (access(subPath.c_str(), F_OK) != 0) {
142             if (mkdir(subPath.c_str(), (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)) != 0) {
143                 LOG_WARN(UDMF_CLIENT, "CreateDirectory, fail.");
144                 return false;
145             }
146         }
147     } while (index != std::string::npos);
148 
149     if (access(path.c_str(), F_OK) == 0) {
150 #ifdef WITH_SELINUX
151         Restorecon(path.c_str());
152 #endif
153         return true;
154     }
155     LOG_ERROR(UDMF_CLIENT, "CreateDirectory fail.");
156     return false;
157 }
158 
InstallCustomUtds(const std::string & bundleName,const std::string & jsonStr,int32_t user,std::vector<TypeDescriptorCfg> & customTyepCfgs)159 bool CustomUtdStore::InstallCustomUtds(const std::string &bundleName, const std::string &jsonStr,
160     int32_t user, std::vector<TypeDescriptorCfg> &customTyepCfgs)
161 {
162     CustomUtdCfgs typeCfgs;
163     if (!utdJsonParser_.ParseUserCustomUtdJson(jsonStr, typeCfgs.first, typeCfgs.second)) {
164         LOG_ERROR(UDMF_CLIENT, "Parse json failed. bundleName:%{public}s", bundleName.c_str());
165         return false;
166     }
167     std::vector<TypeDescriptorCfg> presetTypes = PresetTypeDescriptors::GetInstance().GetPresetTypes();
168 
169     if (!UtdCfgsChecker::GetInstance().CheckTypeDescriptors(
170         typeCfgs, presetTypes, customTyepCfgs, bundleName)) {
171         LOG_ERROR(UDMF_CLIENT, "check type descriptors failed, bundleName:%{public}s", bundleName.c_str());
172         return false;
173     }
174 
175     ProcessUtdForSave(typeCfgs, customTyepCfgs, bundleName);
176     if (CustomUtdStore::GetInstance().SaveTypeCfgs(customTyepCfgs, user) != E_OK) {
177         LOG_ERROR(UDMF_CLIENT, "Save failed, bundleName: %{public}s", bundleName.c_str());
178         return false;
179     }
180     return true;
181 }
182 
UninstallCustomUtds(const std::string & bundleName,int32_t user,std::vector<TypeDescriptorCfg> & customTyepCfgs)183 bool CustomUtdStore::UninstallCustomUtds(const std::string &bundleName, int32_t user,
184     std::vector<TypeDescriptorCfg> &customTyepCfgs)
185 {
186     for (auto iter = customTyepCfgs.begin(); iter != customTyepCfgs.end();) {
187         auto it = find(iter->installerBundles.begin(), iter->installerBundles.end(), bundleName);
188         if (it != iter->installerBundles.end()) {
189             iter->installerBundles.erase(it);
190         }
191         if (iter->installerBundles.empty()) {
192             iter = customTyepCfgs.erase(iter);
193         } else {
194             iter++;
195         }
196     }
197     std::vector<TypeDescriptorCfg> presetTypes = PresetTypeDescriptors::GetInstance().GetPresetTypes();
198     if (!UtdCfgsChecker::GetInstance().CheckBelongingToTypes(customTyepCfgs, presetTypes)) {
199         LOG_ERROR(UDMF_CLIENT, "belongingToTypes check failed. bundleName:%{public}s", bundleName.c_str());
200         return false;
201     }
202     if (CustomUtdStore::GetInstance().SaveTypeCfgs(customTyepCfgs, user) != E_OK) {
203         LOG_ERROR(UDMF_CLIENT, "Save type cfgs failed, bundleName: %{public}s", bundleName.c_str());
204         return false;
205     }
206     return true;
207 }
208 
ProcessUtdForSave(const CustomUtdCfgs & utdTypes,std::vector<TypeDescriptorCfg> & customTyepCfgs,const std::string & bundleName)209 void CustomUtdStore::ProcessUtdForSave(const CustomUtdCfgs &utdTypes, std::vector<TypeDescriptorCfg> &customTyepCfgs,
210     const std::string &bundleName)
211 {
212     for (TypeDescriptorCfg declarationType : utdTypes.first) {
213         for (auto iter = customTyepCfgs.begin(); iter != customTyepCfgs.end();) {
214             if (iter->typeId == declarationType.typeId) {
215                 declarationType.installerBundles = iter->installerBundles;
216                 iter = customTyepCfgs.erase(iter);
217             } else {
218                 iter++;
219             }
220         }
221         declarationType.installerBundles.emplace(bundleName);
222         declarationType.ownerBundle = bundleName;
223         customTyepCfgs.push_back(declarationType);
224     }
225     for (TypeDescriptorCfg referenceType : utdTypes.second) {
226         bool found = false;
227         for (auto &typeCfg : customTyepCfgs) {
228             if (typeCfg.typeId == referenceType.typeId) {
229                 typeCfg.installerBundles.emplace(bundleName);
230                 found = true;
231                 break;
232             }
233         }
234         if (!found) {
235             referenceType.installerBundles.emplace(bundleName);
236             customTyepCfgs.push_back(referenceType);
237         }
238     }
239 }
240 
GetCustomUtdInfo(bool isHap,int32_t userId)241 UtdFileInfo CustomUtdStore::GetCustomUtdInfo(bool isHap, int32_t userId)
242 {
243     UtdFileInfo info = {0};
244     std::string path = GetCustomUtdPath(isHap, userId);
245     struct stat fileStat;
246     if (stat(path.c_str(), &fileStat) != 0) {
247         LOG_WARN(UDMF_CLIENT, "custom utd file not exist");
248         return info;
249     }
250 
251     info.lastTime = fileStat.st_mtime;
252     info.size = static_cast<uint64_t>(fileStat.st_size);
253     return info;
254 }
255 } // namespace UDMF
256 } // namespace OHOS