1 /*
2  * Copyright (c) 2024 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 "b_json/b_json_clear_data_config.h"
17 
18 #include <unistd.h>
19 #include <fcntl.h>
20 #include <sys/types.h>
21 #include <fstream>
22 #include "unique_fd.h"
23 #include "filemgmt_libhilog.h"
24 
25 #include "cJSON.h"
26 
27 namespace OHOS::FileManagement::Backup {
28 using namespace std;
29 
30 namespace {
31     const string PATH_BUNDLE_BACKUP_HOME = "/data/service/el2/100/backup/";
32     const string CONFIG_NAME = "ClearDataConfig.json";
33 }
34 
BJsonClearDataConfig()35 BJsonClearDataConfig::BJsonClearDataConfig()
36 {
37     string filePath = PATH_BUNDLE_BACKUP_HOME + CONFIG_NAME;
38     if (access(filePath.c_str(), F_OK) == 0) {
39         HILOGI("file exist filePath:%{public}s", filePath.c_str());
40         return;
41     }
42     HILOGI("Failed to access filePath :%{public}s", filePath.c_str());
43     UniqueFd fd(open(filePath.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR));
44     if (fd < 0) {
45         HILOGE("Failed to creat filePath :%{public}s", filePath.c_str());
46         return;
47     }
48     cJSON *jsonObjectDis = cJSON_CreateObject();
49     if (jsonObjectDis == nullptr) {
50         HILOGE("Creat json failed");
51         return;
52     }
53     cJSON *jsonArray = cJSON_CreateArray();
54     if (jsonArray == nullptr) {
55         HILOGE("Creat json failed");
56         cJSON_Delete(jsonObjectDis);
57         return;
58     }
59     cJSON_AddItemToObject(jsonObjectDis, "ClearDataConfigFile", jsonArray);
60 
61     char *newStr = cJSON_Print(jsonObjectDis);
62     if (newStr == nullptr) {
63         HILOGE("cJSON_Print json failed");
64         cJSON_Delete(jsonObjectDis);
65         return;
66     }
67     ofstream outFile(filePath);
68     if (!outFile.is_open()) {
69         HILOGE("open json failed");
70         cJSON_free(newStr);
71         cJSON_Delete(jsonObjectDis);
72         return;
73     }
74     outFile << newStr;
75     outFile.close();
76     cJSON_free(newStr);
77     cJSON_Delete(jsonObjectDis);
78     HILOGI("Creat filePath ok :%{public}s", filePath.c_str());
79 }
80 
HasClearBundleRecord()81 bool BJsonClearDataConfig::HasClearBundleRecord()
82 {
83     lock_guard<mutex> autoLock(fileMutex_);
84     string filePath = PATH_BUNDLE_BACKUP_HOME + CONFIG_NAME;
85     ifstream inFile(filePath);
86     if (!inFile.is_open()) {
87         HILOGE("open json failed");
88         return false;
89     }
90 
91     string jsonString((istreambuf_iterator<char>(inFile)), istreambuf_iterator<char>());
92     inFile.close();
93 
94     cJSON *jsonObjectDis = cJSON_Parse(jsonString.c_str());
95     if (jsonObjectDis == nullptr) {
96         HILOGE("parse json failed");
97         return false;
98     }
99 
100     cJSON *configArray = cJSON_GetObjectItem(jsonObjectDis, "ClearDataConfigFile");
101     if (configArray == nullptr) {
102         HILOGE("parse json failed");
103         cJSON_Delete(jsonObjectDis);
104         return false;
105     }
106 
107     int recordSize = cJSON_GetArraySize(configArray);
108     cJSON_Delete(jsonObjectDis);
109     return recordSize > 0;
110 }
111 
FindClearBundleRecord(const string & bundleName)112 bool BJsonClearDataConfig::FindClearBundleRecord(const string& bundleName)
113 {
114     lock_guard<mutex> autoLock(fileMutex_);
115     string filePath = PATH_BUNDLE_BACKUP_HOME + CONFIG_NAME;
116     ifstream inFile(filePath);
117     if (!inFile.is_open()) {
118         HILOGE("open json failed");
119         return false;
120     }
121 
122     string jsonString((istreambuf_iterator<char>(inFile)), istreambuf_iterator<char>());
123     inFile.close();
124 
125     cJSON *jsonObjectDis = cJSON_Parse(jsonString.c_str());
126     if (jsonObjectDis == nullptr) {
127         HILOGE("parse json failed");
128         return false;
129     }
130 
131     cJSON *configArray = cJSON_GetObjectItem(jsonObjectDis, "ClearDataConfigFile");
132     if (configArray == nullptr) {
133         HILOGE("parse json failed");
134         cJSON_Delete(jsonObjectDis);
135         return false;
136     }
137     bool ifBundlename = false;
138     for (int i = 0; i < cJSON_GetArraySize(configArray); ++i) {
139         cJSON *item = cJSON_GetArrayItem(configArray, i);
140         if (item != nullptr && cJSON_GetObjectItem(item, "bundleName") != nullptr &&
141             cJSON_GetObjectItem(item, "bundleName")->type == cJSON_String &&
142             cJSON_GetObjectItem(item, "bundleName")->valuestring == bundleName) {
143             ifBundlename = true;
144         }
145     }
146 
147     cJSON_Delete(jsonObjectDis);
148     return ifBundlename;
149 }
150 
InsertClearBundleRecord(const string & bundleName)151 bool BJsonClearDataConfig::InsertClearBundleRecord(const string& bundleName)
152 {
153     lock_guard<mutex> autoLock(fileMutex_);
154     string filePath = PATH_BUNDLE_BACKUP_HOME + CONFIG_NAME;
155     ifstream inFile(filePath);
156     if (!inFile.is_open()) {
157         HILOGE("open json failed");
158         return false;
159     }
160 
161     string jsonString((istreambuf_iterator<char>(inFile)), istreambuf_iterator<char>());
162     inFile.close();
163 
164     cJSON *jsonObjectDis = cJSON_Parse(jsonString.c_str());
165     if (jsonObjectDis == nullptr) {
166         HILOGE("parse json failed");
167         return false;
168     }
169 
170     cJSON *configArray = cJSON_GetObjectItem(jsonObjectDis, "ClearDataConfigFile");
171     if (configArray == nullptr) {
172         HILOGE("parse json failed");
173         cJSON_Delete(jsonObjectDis);
174         return false;
175     }
176 
177     for (int i = 0; i < cJSON_GetArraySize(configArray); ++i) {
178         cJSON *item = cJSON_GetArrayItem(configArray, i);
179         if (item != nullptr && cJSON_GetObjectItem(item, "bundleName") != nullptr &&
180             cJSON_GetObjectItem(item, "bundleName")->type == cJSON_String &&
181             cJSON_GetObjectItem(item, "bundleName")->valuestring == bundleName) {
182             HILOGI("record already exist, bundleName=%{public}s", bundleName.c_str());
183             cJSON_Delete(jsonObjectDis);
184             return true;
185         }
186     }
187 
188     if (!WriteClearBundleRecord(bundleName)) {
189         HILOGE("InsertClearBundleRecord Failed");
190         cJSON_Delete(jsonObjectDis);
191         return false;
192     }
193 
194     HILOGI("InsertClearBundleRecord Ok");
195     cJSON_Delete(jsonObjectDis);
196     return true;
197 }
198 
DeleteClearBundleRecord(const string & bundleName)199 bool BJsonClearDataConfig::DeleteClearBundleRecord(const string& bundleName)
200 {
201     lock_guard<mutex> autoLock(fileMutex_);
202     string filePath = PATH_BUNDLE_BACKUP_HOME + CONFIG_NAME;
203     ifstream input(filePath);
204     if (!input.is_open()) {
205         HILOGE("open json failed");
206         return false;
207     }
208 
209     string jsonString((istreambuf_iterator<char>(input)), istreambuf_iterator<char>());
210     input.close();
211 
212     cJSON *jsonObjectDis = cJSON_Parse(jsonString.c_str());
213     if (jsonObjectDis == nullptr) {
214         HILOGE("parse json failed");
215         return false;
216     }
217 
218     cJSON *configArray = cJSON_GetObjectItem(jsonObjectDis, "ClearDataConfigFile");
219     if (configArray == nullptr) {
220         cJSON_Delete(jsonObjectDis);
221         return false;
222     }
223     for (int i = 0; i < cJSON_GetArraySize(configArray); ++i) {
224         cJSON *item = cJSON_GetArrayItem(configArray, i);
225         if (item != nullptr && cJSON_GetObjectItem(item, "bundleName") != nullptr &&
226             cJSON_GetObjectItem(item, "bundleName")->type == cJSON_String &&
227             cJSON_GetObjectItem(item, "bundleName")->valuestring == bundleName) {
228             cJSON_DeleteItemFromArray(configArray, i);
229             break;
230         }
231     }
232     char *newStr = cJSON_Print(jsonObjectDis);
233     if (newStr == nullptr) {
234         HILOGE("cJSON_Print json failed");
235         cJSON_Delete(jsonObjectDis);
236         return false;
237     }
238     ofstream output(filePath);
239     if (!output.is_open()) {
240         HILOGE("open json failed");
241         cJSON_free(newStr);
242         cJSON_Delete(jsonObjectDis);
243         return false;
244     }
245     output << newStr;
246     output.close();
247 
248     cJSON_free(newStr);
249     cJSON_Delete(jsonObjectDis);
250     return true;
251 }
252 
GetAllClearBundleRecords()253 vector<string> BJsonClearDataConfig::GetAllClearBundleRecords()
254 {
255     lock_guard<mutex> autoLock(fileMutex_);
256     string filePath = PATH_BUNDLE_BACKUP_HOME + CONFIG_NAME;
257     vector<string> bundleNameList;
258     ifstream inFile(filePath);
259     if (!inFile.is_open()) {
260         HILOGE("open json failed");
261         return {};
262     }
263     string jsonString((istreambuf_iterator<char>(inFile)), istreambuf_iterator<char>());
264     inFile.close();
265 
266     cJSON *jsonObjectDis = cJSON_Parse(jsonString.c_str());
267     if (jsonObjectDis == nullptr) {
268         HILOGE("parse json failed");
269         return {};
270     }
271 
272     cJSON *configArray = cJSON_GetObjectItem(jsonObjectDis, "ClearDataConfigFile");
273     if (configArray == nullptr) {
274         HILOGE("parse json failed");
275         cJSON_Delete(jsonObjectDis);
276         return {};
277     }
278     for (int i = 0; i < cJSON_GetArraySize(configArray); ++i) {
279         cJSON *item = cJSON_GetArrayItem(configArray, i);
280         if (item != nullptr && cJSON_GetObjectItem(item, "bundleName") != nullptr &&
281             cJSON_GetObjectItem(item, "bundleName")->type == cJSON_String) {
282             bundleNameList.push_back(cJSON_GetObjectItem(item, "bundleName")->valuestring);
283         }
284     }
285     cJSON_Delete(jsonObjectDis);
286     return bundleNameList;
287 }
288 
DeleteConfigFile()289 bool BJsonClearDataConfig::DeleteConfigFile()
290 {
291     string filePath = PATH_BUNDLE_BACKUP_HOME + CONFIG_NAME;
292     if (access(filePath.c_str(), F_OK) != 0) {
293         HILOGE("File is not exist");
294         return false;
295     }
296     if (remove(filePath.c_str()) != 0) {
297         HILOGE("Delete ClearDataConfigFile failed");
298         return false;
299     }
300     HILOGI("All Restore Finished, Delete ClearDataConfigFile OK");
301     return true;
302 }
303 
WriteClearBundleRecord(const string & bundleName)304 bool BJsonClearDataConfig::WriteClearBundleRecord(const string& bundleName)
305 {
306     string filePath = PATH_BUNDLE_BACKUP_HOME + CONFIG_NAME;
307     ifstream inFile(filePath);
308     if (!inFile.is_open()) {
309         HILOGE("open json failed");
310         return false;
311     }
312     string jsonString((istreambuf_iterator<char>(inFile)), istreambuf_iterator<char>());
313     inFile.close();
314 
315     cJSON *jsonObjectDis = cJSON_Parse(jsonString.c_str());
316     if (jsonObjectDis == nullptr) {
317         HILOGE("parse json failed");
318         return false;
319     }
320 
321     cJSON *configArray = cJSON_GetObjectItem(jsonObjectDis, "ClearDataConfigFile");
322     if (configArray == nullptr) {
323         HILOGE("parse json failed");
324         cJSON_Delete(jsonObjectDis);
325         return false;
326     }
327     cJSON *newItem = cJSON_CreateObject();
328     if (configArray == nullptr || newItem == nullptr) {
329         HILOGE("parse json failed");
330         cJSON_Delete(jsonObjectDis);
331         return false;
332     }
333 
334     cJSON_AddStringToObject(newItem, "bundleName", bundleName.c_str());
335     cJSON_AddItemToArray(configArray, newItem);
336     char *newStr = cJSON_Print(jsonObjectDis);
337     if (newStr == nullptr) {
338         HILOGE("cJSON_Print json failed");
339         cJSON_Delete(jsonObjectDis);
340         return false;
341     }
342     ofstream outFile(filePath);
343     if (!outFile.is_open()) {
344         HILOGE("open json failed");
345         cJSON_free(newStr);
346         cJSON_Delete(jsonObjectDis);
347         return false;
348     }
349     outFile << newStr;
350     outFile.close();
351 
352     cJSON_free(newStr);
353     cJSON_Delete(jsonObjectDis);
354     return true;
355 }
356 } // namespace OHOS::FileManagement::Backup