1 /*
2  * Copyright (c) 2022-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 "ext_extension.h"
17 
18 #include <algorithm>
19 #include <chrono>
20 #include <fstream>
21 #include <iomanip>
22 #include <map>
23 #include <regex>
24 #include <string>
25 #include <thread>
26 #include <tuple>
27 #include <unordered_map>
28 #include <vector>
29 
30 #include <directory_ex.h>
31 #include <sys/stat.h>
32 #include <unistd.h>
33 
34 #include <directory_ex.h>
35 #include <unique_fd.h>
36 
37 #include "accesstoken_kit.h"
38 #include "bundle_mgr_client.h"
39 #include "errors.h"
40 #include "ipc_skeleton.h"
41 
42 #include "b_error/b_error.h"
43 #include "b_error/b_excep_utils.h"
44 #include "b_filesystem/b_dir.h"
45 #include "b_filesystem/b_file.h"
46 #include "b_filesystem/b_file_hash.h"
47 #include "b_json/b_json_cached_entity.h"
48 #include "b_jsonutil/b_jsonutil.h"
49 #include "b_ohos/startup/backup_para.h"
50 #include "b_tarball/b_tarball_factory.h"
51 #include "filemgmt_libhilog.h"
52 #include "hitrace_meter.h"
53 #include "i_service.h"
54 #include "sandbox_helper.h"
55 #include "service_proxy.h"
56 #include "tar_file.h"
57 #include "b_anony/b_anony.h"
58 
59 namespace OHOS::FileManagement::Backup {
60 const string INDEX_FILE_BACKUP = string(BConstants::PATH_BUNDLE_BACKUP_HOME).
61                                  append(BConstants::SA_BUNDLE_BACKUP_BACKUP).
62                                  append(BConstants::EXT_BACKUP_MANAGE);
63 const string INDEX_FILE_RESTORE = string(BConstants::PATH_BUNDLE_BACKUP_HOME).
64                                   append(BConstants::SA_BUNDLE_BACKUP_RESTORE).
65                                   append(BConstants::EXT_BACKUP_MANAGE);
66 const string INDEX_FILE_INCREMENTAL_BACKUP = string(BConstants::PATH_BUNDLE_BACKUP_HOME).
67                                              append(BConstants::SA_BUNDLE_BACKUP_BACKUP);
68 const string MEDIA_LIBRARY_BUNDLE_NAME = "com.ohos.medialibrary.medialibrarydata";
69 const string FILE_MANAGER_BUNDLE_NAME = "com.ohos.filepicker";
70 using namespace std;
71 
RecordDoRestoreRes(const std::string & bundleName,const std::string & func,AppRadar::DoRestoreInfo & restoreInfo)72 static void RecordDoRestoreRes(const std::string &bundleName, const std::string &func,
73     AppRadar::DoRestoreInfo &restoreInfo)
74 {
75     std::stringstream ss;
76     ss << R"("bigFileNums": )" << restoreInfo.bigFileNum << ", ";
77     ss << R"("bigFileSize": )" << restoreInfo.bigFileSize << ", ";
78     ss << R"("RestoreBigFileTime": )" << restoreInfo.bigFileSpendTime << ", ";
79     ss << R"("unTarFileNums": )" << restoreInfo.tarFileNum << ", ";
80     ss << R"("unTarFileSize": )" << restoreInfo.tarFileSize << ", ";
81     ss << R"("unTarTime": )" << restoreInfo.tarFileSpendTime << ", ";
82     ss << R"("totalFileNum": )" << restoreInfo.bigFileNum + restoreInfo.tarFileNum << ", ";
83     ss << R"("totalFileSize": )" << restoreInfo.bigFileSize + restoreInfo.tarFileSize << ", ";
84     ss << R"("restoreAllFileTime": )" << restoreInfo.totalFileSpendTime;
85     int32_t err = static_cast<int32_t>(BError::Codes::OK);
86     AppRadar::Info info (bundleName, "", ss.str());
87     AppRadar::GetInstance().RecordRestoreFuncRes(info, func, AppRadar::GetInstance().GetUserId(),
88         BizStageRestore::BIZ_STAGE_DO_RESTORE, err);
89 }
90 
RecordDoBackupRes(const std::string & bundleName,const ErrCode errCode,AppRadar::DoBackupInfo & backupInfo)91 static void RecordDoBackupRes(const std::string &bundleName, const ErrCode errCode, AppRadar::DoBackupInfo &backupInfo)
92 {
93     uint32_t inExcludeNum = backupInfo.includeNum + backupInfo.excludeNum;
94     if (inExcludeNum >= BConstants::MAX_INEXCLUDE_SIZE) {
95         AppRadar::Info infoInExclude(bundleName, "", string("\"total inExclude\":").append(to_string(inExcludeNum)));
96         AppRadar::GetInstance().RecordBackupFuncRes(infoInExclude, "BackupExtExtension::DoBackup",
97             AppRadar::GetInstance().GetUserId(), BizStageBackup::BIZ_STAGE_DO_BACKUP, ERR_OK);
98     }
99     if (errCode == ERR_OK && backupInfo.cost >= BConstants::MAX_TIME_COST) {
100         std::stringstream ss;
101         ss << R"("spendTime": )" << backupInfo.cost << "ms, ";
102         ss << R"("totalFilesNum": )" << backupInfo.allFileNum << ", ";
103         ss << R"("smallFilesNum": )" << backupInfo.smallFileNum << ", ";
104         ss << R"("bigFilesNum": )" << backupInfo.allFileNum - backupInfo.tarFileNum;
105         AppRadar::Info info(bundleName, "", ss.str());
106         AppRadar::GetInstance().RecordBackupFuncRes(info, "BackupExtExtension::DoBackup",
107             AppRadar::GetInstance().GetUserId(), BizStageBackup::BIZ_STAGE_DO_BACKUP, errCode);
108     }
109 }
110 
GetIndexFileRestorePath(const string & bundleName)111 static string GetIndexFileRestorePath(const string &bundleName)
112 {
113     if (BFile::EndsWith(bundleName, BConstants::BUNDLE_FILE_MANAGER) && bundleName.size() == BConstants::FM_LEN) {
114         return string(BConstants::PATH_FILEMANAGE_BACKUP_HOME).append(BConstants::SA_BUNDLE_BACKUP_RESTORE).
115                append(BConstants::EXT_BACKUP_MANAGE);
116     } else if (bundleName == BConstants::BUNDLE_MEDIAL_DATA) {
117         return string(BConstants::PATH_MEDIALDATA_BACKUP_HOME).append(BConstants::SA_BUNDLE_BACKUP_RESTORE).
118                append(BConstants::EXT_BACKUP_MANAGE);
119     }
120     return INDEX_FILE_RESTORE;
121 }
122 
GetRestoreTempPath(const string & bundleName)123 static string GetRestoreTempPath(const string &bundleName)
124 {
125     string path = string(BConstants::PATH_BUNDLE_BACKUP_HOME).append(BConstants::SA_BUNDLE_BACKUP_RESTORE);
126     if (BFile::EndsWith(bundleName, BConstants::BUNDLE_FILE_MANAGER) && bundleName.size() == BConstants::FM_LEN) {
127         if (mkdir(string(BConstants::PATH_FILEMANAGE_BACKUP_HOME).data(), S_IRWXU) && errno != EEXIST) {
128             string str = string("Failed to create .backup folder. ").append(std::generic_category().message(errno));
129             throw BError(BError::Codes::EXT_INVAL_ARG, str);
130         }
131         path = string(BConstants::PATH_FILEMANAGE_BACKUP_HOME).append(BConstants::SA_BUNDLE_BACKUP_RESTORE);
132     } else if (bundleName == BConstants::BUNDLE_MEDIAL_DATA) {
133         path = string(BConstants::PATH_MEDIALDATA_BACKUP_HOME).append(BConstants::SA_BUNDLE_BACKUP_RESTORE);
134     }
135     return path;
136 }
137 
GetIdxFileData(const string & bundleName)138 static std::set<std::string> GetIdxFileData(const string &bundleName)
139 {
140     string indexFileRestorePath = GetIndexFileRestorePath(bundleName);
141     UniqueFd idxFd(open(indexFileRestorePath.data(), O_RDONLY));
142     if (idxFd < 0) {
143         HILOGE("Failed to open idxFile = %{private}s, err = %{public}d", indexFileRestorePath.c_str(), errno);
144         return std::set<std::string>();
145     }
146     BJsonCachedEntity<BJsonEntityExtManage> cachedEntity(std::move(idxFd));
147     auto cache = cachedEntity.Structuralize();
148     return cache.GetExtManage();
149 }
150 
GetExtManageInfo()151 std::vector<ExtManageInfo> BackupExtExtension::GetExtManageInfo()
152 {
153     string indexFileRestorePath = GetIndexFileRestorePath(bundleName_);
154     string filePath = BExcepUltils::Canonicalize(indexFileRestorePath);
155     UniqueFd idxFd(open(filePath.data(), O_RDONLY));
156     if (idxFd < 0) {
157         HILOGE("Failed to open cano_idxFile = %{private}s, err = %{public}d", filePath.c_str(), errno);
158         return {};
159     }
160     BJsonCachedEntity<BJsonEntityExtManage> cachedEntity(std::move(idxFd));
161     auto cache = cachedEntity.Structuralize();
162     return cache.GetExtManageInfo();
163 }
164 
VerifyCaller()165 void BackupExtExtension::VerifyCaller()
166 {
167     uint32_t tokenCaller = IPCSkeleton::GetCallingTokenID();
168     int tokenType = Security::AccessToken::AccessTokenKit::GetTokenType(tokenCaller);
169     if (tokenType != Security::AccessToken::ATokenTypeEnum::TOKEN_NATIVE) {
170         AppRadar::Info info(bundleName_, "", "{\"reason\":\"Calling tokenType error\"}");
171         AppRadar::GetInstance().RecordDefaultFuncRes(
172             info, "BackupExtExtension::VerifyCaller", AppRadar::GetInstance().GetUserId(),
173             BizStageBackup::BIZ_STAGE_PERMISSION_CHECK_FAIL, BError(BError::Codes::EXT_BROKEN_IPC).GetCode());
174         throw BError(BError::Codes::EXT_BROKEN_IPC,
175             string("Calling tokenType is error, token type is ").append(to_string(tokenType)));
176     }
177     if (IPCSkeleton::GetCallingUid() != BConstants::BACKUP_UID) {
178         AppRadar::Info info(bundleName_, "", "{\"reason\":\"Calling uid invalid\"}");
179         AppRadar::GetInstance().RecordDefaultFuncRes(
180             info, "BackupExtExtension::VerifyCaller", AppRadar::GetInstance().GetUserId(),
181             BizStageBackup::BIZ_STAGE_PERMISSION_CHECK_FAIL, BError(BError::Codes::EXT_BROKEN_IPC).GetCode());
182         throw BError(BError::Codes::EXT_BROKEN_IPC,
183             string("Calling uid is invalid, calling uid is ").append(to_string(IPCSkeleton::GetCallingUid())));
184     }
185 }
186 
CheckAndCreateDirectory(const string & filePath)187 static bool CheckAndCreateDirectory(const string &filePath)
188 {
189     size_t pos = filePath.rfind('/');
190     if (pos == string::npos) {
191         return true;
192     }
193 
194     string folderPath = "/" + filePath.substr(0, pos);
195     if (access(folderPath.c_str(), F_OK) != 0) {
196         if (!ForceCreateDirectory(folderPath.data())) {
197             return false;
198         }
199     }
200     return true;
201 }
202 
GetFileHandleForSpecialCloneCloud(const string & fileName)203 static UniqueFd GetFileHandleForSpecialCloneCloud(const string &fileName)
204 {
205     HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
206     HILOGI("GetFileHandleForSpecialCloneCloud: fileName is %{public}s", GetAnonyPath(fileName).c_str());
207     string filePath = fileName;
208     if (fileName.front() != BConstants::FILE_SEPARATOR_CHAR) {
209         filePath = BConstants::FILE_SEPARATOR_CHAR + fileName;
210     }
211     size_t filePathPrefix = filePath.find_last_of(BConstants::FILE_SEPARATOR_CHAR);
212     if (filePathPrefix == string::npos) {
213         HILOGE("GetFileHandleForSpecialCloneCloud: Invalid fileName");
214         return UniqueFd(-1);
215     }
216     string path = filePath.substr(0, filePathPrefix);
217     if (access(path.c_str(), F_OK) != 0) {
218         bool created = ForceCreateDirectory(path.data());
219         if (!created) {
220             HILOGE("Failed to create restore folder.");
221             return UniqueFd(-1);
222         }
223     }
224     UniqueFd fd(open(fileName.data(), O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR));
225     if (fd < 0) {
226         HILOGE("Open file failed, file name is %{private}s, err = %{public}d", fileName.data(), errno);
227         return UniqueFd(-1);
228     }
229     return fd;
230 }
231 
GetFileHandle(const string & fileName,int32_t & errCode)232 UniqueFd BackupExtExtension::GetFileHandle(const string &fileName, int32_t &errCode)
233 {
234     HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
235     try {
236         if (extension_ == nullptr) {
237             HILOGE("Failed to get file handle, extension is nullptr");
238             throw BError(BError::Codes::EXT_INVAL_ARG, "Extension is nullptr");
239         }
240         if (extension_->GetExtensionAction() != BConstants::ExtensionAction::RESTORE) {
241             HILOGE("Failed to get file handle, because action is %{public}d invalid", extension_->GetExtensionAction());
242             throw BError(BError::Codes::EXT_INVAL_ARG, "Action is invalid");
243         }
244 
245         VerifyCaller();
246 
247         if (extension_->SpecialVersionForCloneAndCloud()) {
248             UniqueFd fd = GetFileHandleForSpecialCloneCloud(fileName);
249             if (fd < 0) {
250                 errCode = errno;
251             }
252             return fd;
253         }
254 
255         string path = GetRestoreTempPath(bundleName_);
256         if (mkdir(path.data(), S_IRWXU) && errno != EEXIST) {
257             string str = string("Failed to create restore folder. ").append(std::generic_category().message(errno));
258             throw BError(BError::Codes::EXT_INVAL_ARG, str);
259         }
260 
261         string tarName = path + fileName;
262         if (access(tarName.c_str(), F_OK) == 0) {
263             throw BError(BError::Codes::EXT_INVAL_ARG, string("The file already exists"));
264         }
265         UniqueFd tarFd(open(tarName.data(), O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR));
266         if (tarFd < 0) {
267             HILOGE("Open file failed, file name is %{private}s, err = %{public}d", tarName.data(), errno);
268             errCode = errno;
269         }
270         return tarFd;
271     } catch (...) {
272         HILOGE("Failed to get file handle");
273         DoClear();
274         errCode = -1;
275         return UniqueFd(-1);
276     }
277 }
278 
GetReportFileName(const string & fileName)279 static string GetReportFileName(const string &fileName)
280 {
281     string reportName = fileName + "." + string(BConstants::REPORT_FILE_EXT);
282     return reportName;
283 }
284 
GetIncreFileHandleForSpecialVersion(const string & fileName)285 static ErrCode GetIncreFileHandleForSpecialVersion(const string &fileName)
286 {
287     ErrCode errCode = ERR_OK;
288     UniqueFd fd = GetFileHandleForSpecialCloneCloud(fileName);
289     if (fd < 0) {
290         HILOGE("Failed to open file = %{private}s, err = %{public}d", fileName.c_str(), errno);
291         errCode = errno;
292     }
293 
294     string path = string(BConstants::PATH_BUNDLE_BACKUP_HOME).append(BConstants::SA_BUNDLE_BACKUP_RESTORE);
295     if (mkdir(path.data(), S_IRWXU) && errno != EEXIST) {
296         HILOGE("Failed to create restore folder : %{private}s, err = %{public}d", path.c_str(), errno);
297         errCode = errno;
298     }
299     string reportName = path + BConstants::BLANK_REPORT_NAME;
300     UniqueFd reportFd(open(reportName.data(), O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR));
301     if (reportFd < 0) {
302         HILOGE("Failed to open report file = %{private}s, err = %{public}d", reportName.c_str(), errno);
303         errCode = errno;
304     }
305 
306     auto proxy = ServiceProxy::GetInstance();
307     if (proxy == nullptr) {
308         HILOGE("Failed to get file handle for special version clone");
309         return BError(BError::Codes::EXT_BROKEN_BACKUP_SA).GetCode();
310     }
311     auto ret = proxy->AppIncrementalFileReady(fileName, move(fd), move(reportFd), errCode);
312     if (ret != ERR_OK) {
313         HILOGE("Failed to AppIncrementalFileReady %{public}d", ret);
314     }
315     return ERR_OK;
316 }
317 
GetIncrementalFileHandlePath(const string & fileName,const string & bundleName,std::string & tarName)318 static ErrCode GetIncrementalFileHandlePath(const string &fileName, const string &bundleName, std::string &tarName)
319 {
320     string path = string(BConstants::PATH_BUNDLE_BACKUP_HOME).append(BConstants::SA_BUNDLE_BACKUP_RESTORE);
321     if (BFile::EndsWith(bundleName, BConstants::BUNDLE_FILE_MANAGER) && bundleName.size() == BConstants::FM_LEN) {
322         if (mkdir(string(BConstants::PATH_FILEMANAGE_BACKUP_HOME).data(), S_IRWXU) && errno != EEXIST) {
323             string errMsg = string("Failed to create .backup folder. ").append(std::generic_category().message(errno));
324             HILOGE("%{public}s, errno = %{public}d", errMsg.c_str(), errno);
325             return errno;
326         }
327         path = string(BConstants::PATH_FILEMANAGE_BACKUP_HOME).append(BConstants::SA_BUNDLE_BACKUP_RESTORE);
328     } else if (bundleName == BConstants::BUNDLE_MEDIAL_DATA) {
329         path = string(BConstants::PATH_MEDIALDATA_BACKUP_HOME).append(BConstants::SA_BUNDLE_BACKUP_RESTORE);
330     }
331     if (mkdir(path.data(), S_IRWXU) && errno != EEXIST) {
332         string errMsg = string("Failed to create restore folder. ").append(std::generic_category().message(errno));
333         HILOGE("%{public}s, errno = %{public}d", errMsg.c_str(), errno);
334         return errno;
335     }
336     tarName = path + fileName;
337     return ERR_OK;
338 }
339 
GetIncreFileHandleForNormalVersion(const std::string & fileName)340 ErrCode BackupExtExtension::GetIncreFileHandleForNormalVersion(const std::string &fileName)
341 {
342     HILOGI("extension: GetIncrementalFileHandle single to single Name:%{public}s", GetAnonyPath(fileName).c_str());
343     auto proxy = ServiceProxy::GetInstance();
344     if (proxy == nullptr) {
345         throw BError(BError::Codes::EXT_BROKEN_IPC, string("Failed to AGetInstance"));
346     }
347     std::string tarName;
348     int32_t errCode = ERR_OK;
349     UniqueFd fd(-1);
350     UniqueFd reportFd(-1);
351     do {
352         errCode = GetIncrementalFileHandlePath(fileName, bundleName_, tarName);
353         if (errCode != ERR_OK) {
354             HILOGE("GetIncrementalFileHandlePath failed, err = %{public}d", errCode);
355             break;
356         }
357         if (access(tarName.c_str(), F_OK) == 0) {
358             HILOGE("The file already exists, tarname = %{public}s, err =%{public}d",
359                 GetAnonyPath(tarName).c_str(), errno);
360         }
361         fd = UniqueFd(open(tarName.data(), O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR));
362         if (fd < 0) {
363             HILOGE("Failed to open tar file = %{public}s, err = %{public}d", GetAnonyPath(tarName).c_str(), errno);
364             errCode = errno;
365             break;
366         }
367         // 对应的简报文件
368         string reportName = GetReportFileName(tarName);
369         if (access(reportName.c_str(), F_OK) == 0) {
370             HILOGE("The report file already exists, Name = %{private}s, err =%{public}d", reportName.c_str(), errno);
371         }
372         reportFd = UniqueFd(open(reportName.data(), O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR));
373         if (reportFd < 0) {
374             HILOGE("Failed to open report file = %{private}s, err = %{public}d", reportName.c_str(), errno);
375             errCode = errno;
376             break;
377         }
378     } while (0);
379     HILOGI("extension: Will notify AppIncrementalFileReady");
380     auto ret = proxy->AppIncrementalFileReady(fileName, move(fd), move(reportFd), errCode);
381     if (ret != ERR_OK) {
382         HILOGE("Failed to AppIncrementalFileReady %{public}d", ret);
383     }
384     return ERR_OK;
385 }
386 
GetIncrementalFileHandle(const string & fileName)387 ErrCode BackupExtExtension::GetIncrementalFileHandle(const string &fileName)
388 {
389     HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
390     try {
391         if ((extension_ == nullptr) || (extension_->GetExtensionAction() != BConstants::ExtensionAction::RESTORE)) {
392             HILOGE("Failed to get incremental file handle, extension or action is invalid, action %{public}d.",
393                 extension_->GetExtensionAction());
394             throw BError(BError::Codes::EXT_INVAL_ARG, "Action is invalid");
395         }
396         VerifyCaller();
397         if (BDir::CheckFilePathInvalid(fileName)) {
398             auto proxy = ServiceProxy::GetInstance();
399             if (proxy == nullptr) {
400                 throw BError(BError::Codes::EXT_BROKEN_IPC, string("Failed to AGetInstance"));
401             }
402             HILOGE("Check file path : %{public}s err, path is forbidden", GetAnonyPath(fileName).c_str());
403             auto ret = proxy->AppIncrementalDone(BError(BError::Codes::EXT_INVAL_ARG));
404             if (ret != ERR_OK) {
405                 HILOGE("Failed to notify app incre done. err = %{public}d", ret);
406             }
407             return BError(BError::Codes::EXT_INVAL_ARG).GetCode();
408         }
409         if (extension_->SpecialVersionForCloneAndCloud()) {
410             return GetIncreFileHandleForSpecialVersion(fileName);
411         }
412         return GetIncreFileHandleForNormalVersion(fileName);
413     } catch (...) {
414         HILOGE("Failed to get incremental file handle");
415         DoClear();
416         return BError(BError::Codes::EXT_BROKEN_IPC).GetCode();
417     }
418 }
419 
HandleClear()420 ErrCode BackupExtExtension::HandleClear()
421 {
422     HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
423     try {
424         HILOGI("begin clear");
425         if (extension_ == nullptr) {
426             HILOGE("Failed to handle clear, extension is nullptr");
427             return BError(BError::Codes::EXT_INVAL_ARG, "Extension is nullptr").GetCode();
428         }
429         if (extension_->GetExtensionAction() == BConstants::ExtensionAction::INVALID) {
430             return BError(BError::Codes::EXT_INVAL_ARG, "Action is invalid").GetCode();
431         }
432         VerifyCaller();
433         DoClear();
434         return ERR_OK;
435     } catch (...) {
436         HILOGE("Failed to handle clear");
437         return BError(BError::Codes::EXT_BROKEN_IPC).GetCode();
438     }
439 }
440 
IndexFileReady(const TarMap & pkgInfo,sptr<IService> proxy)441 static ErrCode IndexFileReady(const TarMap &pkgInfo, sptr<IService> proxy)
442 {
443     HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
444     UniqueFd fd(open(INDEX_FILE_BACKUP.data(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR));
445     if (fd < 0) {
446         HILOGE("Failed to open index json file = %{private}s, err = %{public}d", INDEX_FILE_BACKUP.c_str(), errno);
447         return BError::GetCodeByErrno(errno);
448     }
449     BJsonCachedEntity<BJsonEntityExtManage> cachedEntity(move(fd));
450     auto cache = cachedEntity.Structuralize();
451     cache.SetExtManage(pkgInfo);
452     cachedEntity.Persist();
453     close(cachedEntity.GetFd().Release());
454 
455     ErrCode ret =
456         proxy->AppFileReady(string(BConstants::EXT_BACKUP_MANAGE), UniqueFd(open(INDEX_FILE_BACKUP.data(), O_RDONLY)),
457             ERR_OK);
458     if (SUCCEEDED(ret)) {
459         HILOGI("The application is packaged successfully");
460     } else {
461         HILOGI(
462             "The application is packaged successfully but the AppFileReady interface fails to be invoked: "
463             "%{public}d",
464             ret);
465     }
466     HILOGI("End notify Appfile Ready");
467     return ret;
468 }
469 
ClearNoPermissionFiles(TarMap & pkgInfo,vector<std::string> & noPermissionFiles)470 void BackupExtExtension::ClearNoPermissionFiles(TarMap &pkgInfo, vector<std::string> &noPermissionFiles)
471 {
472     HILOGI("start ClearNoPermissionFiles;");
473     for (const auto &item : noPermissionFiles) {
474         auto it = pkgInfo.find(item);
475         if (it != pkgInfo.end()) {
476             HILOGI("noPermissionFile, don't need to backup, path = %{public}s",
477                 GetAnonyString(std::get<0>(it->second)).c_str());
478             pkgInfo.erase(it);
479         }
480     }
481 }
482 
BigFileReady(TarMap & bigFileInfo,sptr<IService> proxy)483 ErrCode BackupExtExtension::BigFileReady(TarMap &bigFileInfo, sptr<IService> proxy)
484 {
485     HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
486     HILOGI("BigFileReady Begin: bigFileInfo file size is: %{public}zu", bigFileInfo.size());
487     ErrCode ret {ERR_OK};
488     auto startTime = std::chrono::system_clock::now();
489     int fdNum = 0;
490     vector<string> noPermissionFiles;
491     for (auto &item : bigFileInfo) {
492         WaitToSendFd(startTime, fdNum);
493         int32_t errCode = ERR_OK;
494         string fllePath = std::get<0>(item.second);
495         UniqueFd fd(open(fllePath.data(), O_RDONLY));
496         if (fd < 0) {
497             HILOGE("open file failed, file name is %{public}s, err = %{public}d", fllePath.c_str(), errno);
498             errCode = errno;
499             if (errCode == ERR_NO_PERMISSION) {
500                 noPermissionFiles.emplace_back(item.first.c_str());
501                 continue;
502             }
503         }
504         ret = proxy->AppFileReady(item.first, std::move(fd), errCode);
505         if (SUCCEEDED(ret)) {
506             HILOGI("The application is packaged successfully, package name is %{public}s", item.first.c_str());
507         } else {
508             HILOGW("Current file execute app file ready interface failed, ret is:%{public}d", ret);
509         }
510         fdNum++;
511         RefreshTimeInfo(startTime, fdNum);
512     }
513     ClearNoPermissionFiles(bigFileInfo, noPermissionFiles);
514     HILOGI("BigFileReady End");
515     return ret;
516 }
517 
PublishFile(const std::string & fileName)518 ErrCode BackupExtExtension::PublishFile(const std::string &fileName)
519 {
520     HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
521     HILOGI("Begin publish file. fileName is %{public}s", GetAnonyPath(fileName).c_str());
522     try {
523         if (extension_ == nullptr) {
524             throw BError(BError::Codes::EXT_INVAL_ARG, "Extension is nullptr");
525         }
526         if (extension_->GetExtensionAction() != BConstants::ExtensionAction::RESTORE) {
527             throw BError(BError::Codes::EXT_INVAL_ARG, "Action is invalid");
528         }
529         VerifyCaller();
530         // 异步执行解压操作
531         if (extension_->AllowToBackupRestore()) {
532             AsyncTaskRestore(GetIdxFileData(bundleName_), GetExtManageInfo());
533         }
534         HILOGI("End publish file");
535         return ERR_OK;
536     } catch (const BError &e) {
537         DoClear();
538         return e.GetCode();
539     } catch (const exception &e) {
540         HILOGE("Catched an unexpected low-level exception %{public}s", e.what());
541         DoClear();
542         return BError(BError::Codes::EXT_BROKEN_FRAMEWORK).GetCode();
543     } catch (...) {
544         HILOGE("Unexpected exception");
545         DoClear();
546         return BError(BError::Codes::EXT_BROKEN_FRAMEWORK).GetCode();
547     }
548 }
549 
PublishIncrementalFile(const string & fileName)550 ErrCode BackupExtExtension::PublishIncrementalFile(const string &fileName)
551 {
552     HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
553     HILOGI("begin publish incremental file. fileName is %{private}s", fileName.data());
554     try {
555         if (extension_ == nullptr) {
556             throw BError(BError::Codes::EXT_INVAL_ARG, "Extension is nullptr");
557         }
558         if (extension_->GetExtensionAction() != BConstants::ExtensionAction::RESTORE) {
559             throw BError(BError::Codes::EXT_INVAL_ARG, "Action is invalid");
560         }
561         VerifyCaller();
562         // 异步执行解压操作
563         if (BackupPara::GetBackupDebugState()) {
564             isDebug_ = true;
565         }
566         if (extension_->AllowToBackupRestore()) {
567             if (extension_->SpecialVersionForCloneAndCloud()) {
568                 HILOGI("Create task for Incremental SpecialVersion");
569                 AsyncTaskIncreRestoreSpecialVersion();
570             } else {
571                 HILOGI("Create task for Incremental Restore");
572                 AsyncTaskIncrementalRestore();
573             }
574         }
575         HILOGI("End publish incremental file");
576         return ERR_OK;
577     } catch (const BError &e) {
578         DoClear();
579         return e.GetCode();
580     } catch (const exception &e) {
581         HILOGE("Catched an unexpected low-level exception %{public}s", e.what());
582         DoClear();
583         return BError(BError::Codes::EXT_BROKEN_FRAMEWORK).GetCode();
584     } catch (...) {
585         HILOGE("Unexpected exception");
586         DoClear();
587         return BError(BError::Codes::EXT_BROKEN_FRAMEWORK).GetCode();
588     }
589 }
590 
HandleBackup(bool isClearData)591 ErrCode BackupExtExtension::HandleBackup(bool isClearData)
592 {
593     HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
594     SetClearDataFlag(isClearData);
595     if (!IfAllowToBackupRestore()) {
596         return BError(BError::Codes::EXT_FORBID_BACKUP_RESTORE, "Application does not allow backup or restore")
597             .GetCode();
598     }
599     AsyncTaskOnBackup();
600     return ERR_OK;
601 }
602 
IsUserTar(const string & tarFile,const std::vector<ExtManageInfo> & extManageInfo,off_t & tarFileSize)603 static bool IsUserTar(const string &tarFile, const std::vector<ExtManageInfo> &extManageInfo, off_t &tarFileSize)
604 {
605     HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
606     if (tarFile.empty()) {
607         return false;
608     }
609     auto iter = find_if(extManageInfo.begin(), extManageInfo.end(),
610         [&tarFile](const auto &item) { return item.hashName == tarFile; });
611     if (iter != extManageInfo.end()) {
612         HILOGI("tarFile:%{public}s isUserTar:%{public}d", tarFile.data(), iter->isUserTar);
613         tarFileSize = iter->sta.st_size;
614         return iter->isUserTar;
615     }
616     HILOGE("Can not find tarFile %{public}s", tarFile.data());
617     return false;
618 }
619 
GetFileInfos(const vector<string> & includes,const vector<string> & excludes)620 static pair<TarMap, map<string, size_t>> GetFileInfos(const vector<string> &includes, const vector<string> &excludes)
621 {
622     HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
623     auto [errCode, files, smallFiles] = BDir::GetBigFiles(includes, excludes);
624     if (errCode != 0) {
625         return {};
626     }
627 
628     auto getStringHash = [](const TarMap &m, const string &str) -> string {
629         ostringstream strHex;
630         strHex << hex;
631 
632         hash<string> strHash;
633         size_t szHash = strHash(str);
634         strHex << setfill('0') << setw(BConstants::BIG_FILE_NAME_SIZE) << szHash;
635         string name = strHex.str();
636         for (int i = 0; m.find(name) != m.end(); ++i, strHex.str("")) {
637             szHash = strHash(str + to_string(i));
638             strHex << setfill('0') << setw(BConstants::BIG_FILE_NAME_SIZE) << szHash;
639             name = strHex.str();
640         }
641 
642         return name;
643     };
644 
645     TarMap bigFiles;
646     for (const auto &item : files) {
647         string md5Name = getStringHash(bigFiles, item.first);
648         if (!md5Name.empty()) {
649             bigFiles.emplace(md5Name, make_tuple(item.first, item.second, true));
650         }
651     }
652 
653     return {bigFiles, smallFiles};
654 }
655 
656 /**
657  * 全量tar包回传
658  */
TarFileReady(const TarMap & tarFileInfo,sptr<IService> proxy)659 static ErrCode TarFileReady(const TarMap &tarFileInfo, sptr<IService> proxy)
660 {
661     if (tarFileInfo.empty()) {
662         HILOGI("TarFileReady: No tar file found");
663         return ERR_OK;
664     }
665     string tarName = tarFileInfo.begin()->first;
666     string path = string(BConstants::PATH_BUNDLE_BACKUP_HOME).append(BConstants::SA_BUNDLE_BACKUP_BACKUP);
667     string tarPath = path + tarName;
668     int32_t errCode = ERR_OK;
669     UniqueFd fd(open(tarPath.data(), O_RDONLY));
670     if (fd < 0) {
671         HILOGE("TarFileReady open file failed, file name is %{public}s, err = %{public}d", tarName.c_str(), errno);
672         errCode = errno;
673     }
674     int ret = proxy->AppFileReady(tarName, std::move(fd), errCode);
675     if (SUCCEEDED(ret)) {
676         HILOGI("TarFileReady: AppFileReady success for %{public}s", tarName.c_str());
677         // 删除文件
678         RemoveFile(tarPath);
679     } else {
680         HILOGE("TarFileReady AppFileReady fail to be invoked for %{public}s: ret = %{public}d", tarName.c_str(), ret);
681     }
682     return ret;
683 }
684 
ReportErrFileByProc(wptr<BackupExtExtension> obj,BackupRestoreScenario scenario)685 std::function<void(std::string, int)> BackupExtExtension::ReportErrFileByProc(wptr<BackupExtExtension> obj,
686     BackupRestoreScenario scenario)
687 {
688     return [obj, scenario](std::string msg, int err) {
689         auto extPtr = obj.promote();
690         if (extPtr == nullptr) {
691             HILOGE("ReportErr ExtPtr is empty.");
692             return;
693         }
694         string jsonInfo;
695         BJsonUtil::BuildOnProcessErrInfo(jsonInfo, msg, err);
696         HILOGI("ReportErr Will notify err info.");
697         extPtr->ReportAppProcessInfo(jsonInfo, scenario);
698     };
699 }
700 
DoPacket(const map<string,size_t> & srcFiles,TarMap & tar,sptr<IService> proxy)701 void BackupExtExtension::DoPacket(const map<string, size_t> &srcFiles, TarMap &tar, sptr<IService> proxy)
702 {
703     HILOGI("DoPacket begin, infos count: %{public}zu", srcFiles.size());
704     string path = string(BConstants::PATH_BUNDLE_BACKUP_HOME).append(BConstants::SA_BUNDLE_BACKUP_BACKUP);
705     uint64_t totalSize = 0;
706     uint32_t fileCount = 0;
707     vector<string> packFiles;
708     TarFile::GetInstance().SetPacketMode(true); // 设置下打包模式
709     auto startTime = std::chrono::system_clock::now();
710     int fdNum = 0;
711     auto reportCb = ReportErrFileByProc(wptr<BackupExtExtension> {this}, curScenario_);
712     for (auto small : srcFiles) {
713         totalSize += small.second;
714         fileCount += 1;
715         packFiles.emplace_back(small.first);
716         if (totalSize >= BConstants::DEFAULT_SLICE_SIZE || fileCount >= BConstants::MAX_FILE_COUNT) {
717             TarMap tarMap {};
718             TarFile::GetInstance().Packet(packFiles, "part", path, tarMap, reportCb);
719             tar.insert(tarMap.begin(), tarMap.end());
720             // 执行tar包回传功能
721             WaitToSendFd(startTime, fdNum);
722             TarFileReady(tarMap, proxy);
723             totalSize = 0;
724             fileCount = 0;
725             packFiles.clear();
726             fdNum += BConstants::FILE_AND_MANIFEST_FD_COUNT;
727             RefreshTimeInfo(startTime, fdNum);
728         }
729     }
730     if (fileCount > 0) {
731         // 打包回传
732         TarMap tarMap {};
733         TarFile::GetInstance().Packet(packFiles, "part", path, tarMap, reportCb);
734         TarFileReady(tarMap, proxy);
735         fdNum = 1;
736         WaitToSendFd(startTime, fdNum);
737         tar.insert(tarMap.begin(), tarMap.end());
738         packFiles.clear();
739         RefreshTimeInfo(startTime, fdNum);
740     }
741 }
742 
DoBackup(const BJsonEntityExtensionConfig & usrConfig)743 int BackupExtExtension::DoBackup(const BJsonEntityExtensionConfig &usrConfig)
744 {
745     HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
746     HILOGI("Start Do backup");
747     auto start = std::chrono::system_clock::now();
748     if (extension_ == nullptr) {
749         throw BError(BError::Codes::EXT_INVAL_ARG, "Extension is nullptr");
750     }
751     if (extension_->GetExtensionAction() != BConstants::ExtensionAction::BACKUP) {
752         return EPERM;
753     }
754 
755     string path = string(BConstants::PATH_BUNDLE_BACKUP_HOME).append(BConstants::SA_BUNDLE_BACKUP_BACKUP);
756     if (mkdir(path.data(), S_IRWXU) && errno != EEXIST) {
757         throw BError(errno);
758     }
759 
760     vector<string> includes = usrConfig.GetIncludes();
761     vector<string> excludes = usrConfig.GetExcludes();
762     auto proxy = ServiceProxy::GetInstance();
763     if (proxy == nullptr) {
764         throw BError(BError::Codes::EXT_BROKEN_BACKUP_SA, std::generic_category().message(errno));
765     }
766 
767     // 大文件处理
768     HILOGI("Start packet bigfiles and small files");
769     auto [bigFileInfo, smallFiles] = GetFileInfos(includes, excludes);
770     for (const auto &item : bigFileInfo) {
771         auto filePath = std::get<0>(item.second);
772         if (!filePath.empty()) {
773             excludes.push_back(filePath);
774         }
775     }
776 
777     // 回传大文件
778     HILOGI("Will notify BigFileReady");
779     auto res = BigFileReady(bigFileInfo, proxy);
780 
781     HILOGI("Start packet Tar files");
782     // 分片打包, 回传tar包
783     TarMap tarMap {};
784     DoPacket(smallFiles, tarMap, proxy);
785     bigFileInfo.insert(tarMap.begin(), tarMap.end());
786     HILOGI("Do backup, DoPacket end");
787 
788     HILOGI("Will notify IndexFileReady");
789     if (auto ret = IndexFileReady(bigFileInfo, proxy); ret) {
790         return ret;
791     }
792 
793     HILOGI("HandleBackup finish, ret = %{public}d", res);
794     auto end = std::chrono::system_clock::now();
795     auto cost = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
796     AppRadar::DoBackupInfo doBackupInfo = {cost, bigFileInfo.size(), smallFiles.size(), tarMap.size(),
797                                            includes.size(), excludes.size()};
798     RecordDoBackupRes(bundleName_, res, doBackupInfo);
799     return res;
800 }
801 
DoRestore(const string & fileName,const off_t fileSize)802 int BackupExtExtension::DoRestore(const string &fileName, const off_t fileSize)
803 {
804     HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
805     HILOGI("Do restore");
806     if (extension_ == nullptr) {
807         throw BError(BError::Codes::EXT_INVAL_ARG, "Extension is nullptr");
808     }
809     if (extension_->GetExtensionAction() != BConstants::ExtensionAction::RESTORE) {
810         return EPERM;
811     }
812     // REM: 给定version
813     // REM: 解压启动Extension时即挂载好的备份目录中的数据
814     string path = GetRestoreTempPath(bundleName_);
815     string tarName = path + fileName;
816 
817     // 当用户指定fullBackupOnly字段或指定版本的恢复,解压目录当前在/backup/restore
818     if (!extension_->SpecialVersionForCloneAndCloud() && !extension_->UseFullBackupOnly()) {
819         path = "/";
820     }
821     auto [ret, fileInfos, errInfos] = UntarFile::GetInstance().UnPacket(tarName, path);
822     if (isDebug_) {
823         if (ret != 0) {
824             endFileInfos_[tarName] = fileSize;
825             errFileInfos_[tarName] = { ret };
826         }
827         endFileInfos_.merge(fileInfos);
828         errFileInfos_.merge(errInfos);
829     }
830     if (ret != 0) {
831         HILOGE("Failed to untar file = %{public}s, err = %{public}d", tarName.c_str(), ret);
832         return ret;
833     }
834     HILOGI("Application recovered successfully, package path is %{public}s", tarName.c_str());
835     if (!isClearData_) {
836         HILOGI("configured not clear data");
837         return ERR_OK;
838     }
839     if (!RemoveFile(tarName)) {
840         HILOGE("Failed to delete the backup tar %{public}s", tarName.c_str());
841     }
842     return ERR_OK;
843 }
844 
GetTarIncludes(const string & tarName)845 static unordered_map<string, struct ReportFileInfo> GetTarIncludes(const string &tarName)
846 {
847     // 获取简报文件内容
848     string reportName = GetReportFileName(tarName);
849 
850     UniqueFd fd(open(reportName.data(), O_RDONLY));
851     if (fd < 0) {
852         HILOGE("Failed to open report file = %{private}s, err = %{public}d", reportName.c_str(), errno);
853         return {};
854     }
855 
856     // 获取简报内容
857     BReportEntity rp(move(fd));
858     return rp.GetReportInfos();
859 }
860 
DealIncreUnPacketResult(const off_t tarFileSize,const std::string & tarFileName,const std::tuple<int,EndFileInfo,ErrFileInfo> & result)861 void BackupExtExtension::DealIncreUnPacketResult(const off_t tarFileSize, const std::string &tarFileName,
862     const std::tuple<int, EndFileInfo, ErrFileInfo> &result)
863 {
864     if (!isDebug_) {
865         return;
866     }
867     int err = std::get<FIRST_PARAM>(result);
868     if (!isRpValid_) {
869         if (err != ERR_OK) {
870             endFileInfos_[tarFileName] = tarFileSize;
871             errFileInfos_[tarFileName] = {err};
872         } else {
873             EndFileInfo tmpEndInfo = std::get<SECOND_PARAM>(result);
874             endFileInfos_.merge(tmpEndInfo);
875         }
876     }
877     ErrFileInfo tmpErrInfo = std::get<THIRD_PARAM>(result);
878     errFileInfos_.merge(tmpErrInfo);
879 }
880 
DoIncrementalRestore()881 int BackupExtExtension::DoIncrementalRestore()
882 {
883     HILOGI("Do incremental restore");
884     if (extension_ == nullptr) {
885         HILOGE("Failed to do incremental restore, extension is nullptr");
886         throw BError(BError::Codes::EXT_INVAL_ARG, "Extension is nullptr");
887     }
888     auto fileSet = GetIdxFileData(bundleName_);
889     auto extManageInfo = GetExtManageInfo();
890     std::tuple<int, EndFileInfo, ErrFileInfo> unPacketRes;
891     ErrCode err = ERR_OK;
892     auto startTime = std::chrono::system_clock::now();
893     for (auto item : fileSet) { // 处理要解压的tar文件
894         off_t tarFileSize = 0;
895         if (ExtractFileExt(item) == "tar" && !IsUserTar(item, extManageInfo, tarFileSize)) {
896             if (extension_->GetExtensionAction() != BConstants::ExtensionAction::RESTORE) {
897                 return EPERM;
898             }
899             auto iter = find_if(extManageInfo.begin(), extManageInfo.end(),
900                 [&item](const auto &itemManage) { return itemManage.hashName == item; });
901             if (iter != extManageInfo.end()) {
902                 tarFileSize = iter->sta.st_size;
903             }
904             radarRestoreInfo_.tarFileNum++;
905             radarRestoreInfo_.tarFileSize += static_cast<uint64_t>(tarFileSize);
906             // REM: 给定version
907             // REM: 解压启动Extension时即挂载好的备份目录中的数据
908             string path = GetRestoreTempPath(bundleName_);
909             string tarName = path + item;
910 
911             // 当用户指定fullBackupOnly字段或指定版本的恢复,解压目录当前在/backup/restore
912             if (BDir::CheckFilePathInvalid(tarName)) {
913                 HILOGE("Check incre tarfile path : %{public}s err, path is forbidden", GetAnonyPath(tarName).c_str());
914                 return ERR_INVALID_VALUE;
915             }
916             unordered_map<string, struct ReportFileInfo> result = GetTarIncludes(tarName);
917             if ((!extension_->SpecialVersionForCloneAndCloud()) && (!extension_->UseFullBackupOnly())) {
918                 path = "/";
919             }
920             if (isDebug_) {
921                 FillEndFileInfos(path, result);
922             }
923             unPacketRes = UntarFile::GetInstance().IncrementalUnPacket(tarName, path, result);
924             err = std::get<FIRST_PARAM>(unPacketRes);
925             DealIncreUnPacketResult(tarFileSize, item, unPacketRes);
926             HILOGI("Application recovered successfully, package path is %{public}s", tarName.c_str());
927             DeleteBackupIncrementalTars(tarName);
928         }
929     }
930     auto endTime = std::chrono::system_clock::now();
931     radarRestoreInfo_.tarFileSpendTime =
932         std::chrono::duration_cast<std::chrono::milliseconds>(endTime - startTime).count();
933     return err;
934 }
935 
AsyncTaskBackup(const string config)936 void BackupExtExtension::AsyncTaskBackup(const string config)
937 {
938     HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
939     auto task = [obj {wptr<BackupExtExtension>(this)}, config]() {
940         auto ptr = obj.promote();
941         BExcepUltils::BAssert(ptr, BError::Codes::EXT_BROKEN_FRAMEWORK, "Ext extension handle have been released");
942         try {
943             HILOGI("Do backup, start fwk timer begin.");
944             bool isFwkStart;
945             ptr->StartFwkTimer(isFwkStart);
946             if (!isFwkStart) {
947                 HILOGE("Do backup, start fwk timer fail.");
948                 return;
949             }
950             HILOGI("Do backup, start fwk timer end.");
951             BJsonCachedEntity<BJsonEntityExtensionConfig> cachedEntity(config);
952             auto cache = cachedEntity.Structuralize();
953             auto ret = ptr->DoBackup(cache);
954             // REM: 处理返回结果 ret
955             ptr->AppDone(ret);
956             HILOGI("backup app done %{public}d", ret);
957         } catch (const BError &e) {
958             HILOGE("extension: AsyncTaskBackup error, err code:%{public}d", e.GetCode());
959             ptr->AppDone(e.GetCode());
960         } catch (const exception &e) {
961             HILOGE("Catched an unexpected low-level exception %{public}s", e.what());
962             ptr->AppDone(BError(BError::Codes::EXT_INVAL_ARG).GetCode());
963         } catch (...) {
964             HILOGE("Failed to restore the ext bundle");
965             ptr->AppDone(BError(BError::Codes::EXT_INVAL_ARG).GetCode());
966         }
967         // 清空备份目录
968         ptr->DoClear();
969     };
970 
971     // REM: 这里异步化了,需要做并发控制
972     // 在往线程池中投入任务之前将需要的数据拷贝副本到参数中,保证不发生读写竞争,
973     // 由于拷贝参数时尚运行在主线程中,故在参数拷贝过程中是线程安全的。
974     threadPool_.AddTask([task]() {
975         try {
976             task();
977         } catch (...) {
978             HILOGE("Failed to add task to thread pool");
979         }
980     });
981 }
982 
RestoreBigFilesForSpecialCloneCloud(const ExtManageInfo & item)983 void BackupExtExtension::RestoreBigFilesForSpecialCloneCloud(const ExtManageInfo &item)
984 {
985     HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
986     if (isDebug_) {
987         endFileInfos_[item.hashName] = item.sta.st_size;
988     }
989     const struct stat &sta = item.sta;
990     string fileName = item.hashName;
991     if (BDir::CheckFilePathInvalid(fileName)) {
992         HILOGE("Check big spec file path : %{public}s err, path is forbidden", GetAnonyPath(fileName).c_str());
993         errFileInfos_[fileName].push_back(DEFAULT_INVAL_VALUE);
994         return;
995     }
996     if (chmod(fileName.c_str(), sta.st_mode) != 0) {
997         HILOGE("Failed to chmod filePath, err = %{public}d", errno);
998         errFileInfos_[fileName].push_back(errno);
999     }
1000 
1001     struct timespec tv[2] = {sta.st_atim, sta.st_mtim};
1002     UniqueFd fd(open(fileName.data(), O_RDONLY));
1003     if (fd < 0) {
1004         HILOGE("Failed to open file = %{public}s, err = %{public}d", GetAnonyPath(fileName).c_str(), errno);
1005         errFileInfos_[fileName].push_back(errno);
1006         return;
1007     }
1008     if (futimens(fd.Get(), tv) != 0) {
1009         errFileInfos_[fileName].push_back(errno);
1010         HILOGE("Failed to change the file time. %{public}s , %{public}d", GetAnonyPath(fileName).c_str(), errno);
1011     }
1012 }
1013 
RestoreTarForSpecialCloneCloud(const ExtManageInfo & item)1014 ErrCode BackupExtExtension::RestoreTarForSpecialCloneCloud(const ExtManageInfo &item)
1015 {
1016     HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
1017     string tarName = item.hashName;
1018     if (item.fileName.empty()) {
1019         HILOGE("Invalid untar path info for tar %{public}s", tarName.c_str());
1020         return ERR_INVALID_VALUE;
1021     }
1022     string untarPath = item.fileName;
1023     if (untarPath.back() != BConstants::FILE_SEPARATOR_CHAR) {
1024         untarPath += BConstants::FILE_SEPARATOR_CHAR;
1025     }
1026     HILOGI("Start to untar file = %{public}s, untarPath = %{public}s", GetAnonyPath(item.hashName).c_str(),
1027         GetAnonyPath(untarPath).c_str());
1028     if (BDir::CheckFilePathInvalid(tarName)) {
1029         HILOGE("Check spec tarfile hash path : %{public}s err, path is forbidden", GetAnonyPath(tarName).c_str());
1030         return ERR_INVALID_VALUE;
1031     }
1032     if (BDir::CheckFilePathInvalid(untarPath)) {
1033         HILOGE("Check spec tarfile path : %{public}s err, path is forbidden", GetAnonyPath(untarPath).c_str());
1034         return ERR_INVALID_VALUE;
1035     }
1036     auto [err, fileInfos, errInfos] = UntarFile::GetInstance().UnPacket(tarName, untarPath);
1037     if (isDebug_) {
1038         if (err != 0) {
1039             endFileInfos_[tarName] = item.sta.st_size;
1040             errFileInfos_[tarName] = { err };
1041         }
1042         endFileInfos_.merge(fileInfos);
1043         errFileInfos_.merge(errInfos);
1044     }
1045     if (err != ERR_OK) {
1046         HILOGE("Failed to untar file = %{public}s, err = %{public}d", tarName.c_str(), err);
1047         return err;
1048     }
1049     if (!RemoveFile(tarName)) {
1050         HILOGE("Failed to delete the backup tar %{public}s", tarName.c_str());
1051     }
1052     return ERR_OK;
1053 }
1054 
RestoreFilesForSpecialCloneCloud()1055 ErrCode BackupExtExtension::RestoreFilesForSpecialCloneCloud()
1056 {
1057     HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
1058     // 获取索引文件内容
1059     UniqueFd fd(open(INDEX_FILE_RESTORE.data(), O_RDONLY));
1060     if (fd < 0) {
1061         HILOGE("Failed to open index json file = %{private}s, err = %{public}d", INDEX_FILE_RESTORE.c_str(), errno);
1062         return BError::GetCodeByErrno(errno);
1063     }
1064     BJsonCachedEntity<BJsonEntityExtManage> cachedEntity(move(fd));
1065     auto cache = cachedEntity.Structuralize();
1066     auto info = cache.GetExtManageInfo();
1067     HILOGI("Start do restore for SpecialCloneCloud.");
1068     auto startTime = std::chrono::system_clock::now();
1069     for (auto &item : info) {
1070         if (item.hashName.empty()) {
1071             HILOGE("Hash name empty");
1072             continue;
1073         }
1074         if (item.isUserTar || item.isBigFile) {
1075             // 大文件处理
1076             radarRestoreInfo_.bigFileNum++;
1077             radarRestoreInfo_.bigFileSize += static_cast<uint64_t>(item.sta.st_size);
1078             RestoreBigFilesForSpecialCloneCloud(item);
1079         } else {
1080             // 待解压tar文件处理
1081             radarRestoreInfo_.tarFileNum++;
1082             radarRestoreInfo_.tarFileSize += static_cast<uint64_t>(item.sta.st_size);
1083             int ret = RestoreTarForSpecialCloneCloud(item);
1084             if (isDebug_ && ret != ERR_OK) {
1085                 errFileInfos_[item.hashName].push_back(ret);
1086                 endFileInfos_[item.hashName] = item.sta.st_size;
1087             }
1088             if (ret != ERR_OK) {
1089                 HILOGE("Failed to restore tar file %{public}s", item.hashName.c_str());
1090                 return ERR_INVALID_VALUE;
1091             }
1092         }
1093     }
1094     if (!RemoveFile(INDEX_FILE_RESTORE)) {
1095         HILOGE("Failed to delete the backup index %{public}s", INDEX_FILE_RESTORE.c_str());
1096     }
1097     auto endTime = std::chrono::system_clock::now();
1098     radarRestoreInfo_.totalFileSpendTime =
1099         std::chrono::duration_cast<std::chrono::milliseconds>(endTime - startTime).count();
1100     RecordDoRestoreRes(bundleName_, "BackupExtExtension::RestoreFilesForSpecialCloneCloud", radarRestoreInfo_);
1101     HILOGI("End do restore for SpecialCloneCloud.");
1102     return ERR_OK;
1103 }
1104 
RestoreBigFilePrecheck(string & fileName,const string & path,const string & hashName,const string & filePath)1105 static bool RestoreBigFilePrecheck(string &fileName, const string &path, const string &hashName, const string &filePath)
1106 {
1107     if (filePath.empty()) {
1108         HILOGE("file path is empty. %{public}s", filePath.c_str());
1109         return false;
1110     }
1111 
1112     // 不带路径的文件名
1113     if (access(fileName.data(), F_OK) != 0) {
1114         HILOGE("file does not exist");
1115         return false;
1116     }
1117 
1118     // 目录不存在且只有大文件时,不能通过untar创建,需要检查并创建
1119     if (!CheckAndCreateDirectory(filePath)) {
1120         HILOGE("failed to create directory %{public}s", filePath.c_str());
1121         return false;
1122     }
1123     return true;
1124 }
1125 
RestoreBigFileAfter(const string & filePath,const struct stat & sta)1126 void BackupExtExtension::RestoreBigFileAfter(const string &filePath, const struct stat &sta)
1127 {
1128     if (chmod(filePath.c_str(), sta.st_mode) != 0) {
1129         errFileInfos_[filePath].push_back(errno);
1130         HILOGE("Failed to chmod filePath, err = %{public}d", errno);
1131     }
1132     struct timespec tv[2] = {sta.st_atim, sta.st_mtim};
1133     UniqueFd fd(open(filePath.data(), O_RDONLY));
1134     if (fd < 0) {
1135         errFileInfos_[filePath].push_back(errno);
1136         HILOGE("Failed to open file = %{public}s, err = %{public}d", GetAnonyPath(filePath).c_str(), errno);
1137         return;
1138     }
1139     if (futimens(fd.Get(), tv) != 0) {
1140         errFileInfos_[filePath].push_back(errno);
1141         HILOGE("failed to change the file time. %{public}s , %{public}d", GetAnonyPath(filePath).c_str(), errno);
1142     }
1143 }
1144 
RestoreOneBigFile(const std::string & path,const ExtManageInfo & item,const bool appendTargetPath)1145 void BackupExtExtension::RestoreOneBigFile(const std::string &path,
1146     const ExtManageInfo &item, const bool appendTargetPath)
1147 {
1148     radarRestoreInfo_.bigFileNum++;
1149     radarRestoreInfo_.bigFileSize += static_cast<uint64_t>(item.sta.st_size);
1150     string itemHashName = item.hashName;
1151     string itemFileName = item.fileName;
1152     // check if item.hasName and fileName need decode by report item attribute
1153     string reportPath = GetReportFileName(path + item.hashName);
1154     UniqueFd fd(open(reportPath.data(), O_RDONLY));
1155     if (fd < 0) {
1156         HILOGE("Failed to open report file = %{public}s, err = %{public}d", reportPath.c_str(), errno);
1157         errFileInfos_[item.hashName].push_back(errno);
1158         throw BError(BError::Codes::EXT_INVAL_ARG, string("open report file failed"));
1159     }
1160     BReportEntity rp(move(fd));
1161     rp.CheckAndUpdateIfReportLineEncoded(itemFileName);
1162 
1163     string fileName = path + itemHashName;
1164     string filePath = appendTargetPath ? (path + itemFileName) : itemFileName;
1165     if (BDir::CheckFilePathInvalid(filePath)) {
1166         HILOGE("Check big file path : %{public}s err, path is forbidden", GetAnonyPath(filePath).c_str());
1167         return;
1168     }
1169     if (isDebug_) {
1170         endFileInfos_[filePath] = item.sta.st_size;
1171     }
1172 
1173     if (!RestoreBigFilePrecheck(fileName, path, item.hashName, filePath)) {
1174         return;
1175     }
1176     if (!BFile::MoveFile(fileName, filePath)) {
1177         errFileInfos_[filePath].push_back(errno);
1178         HILOGE("failed to move the file. err = %{public}d", errno);
1179         return;
1180     }
1181 
1182     RestoreBigFileAfter(filePath, item.sta);
1183 }
1184 
RestoreBigFiles(bool appendTargetPath)1185 void BackupExtExtension::RestoreBigFiles(bool appendTargetPath)
1186 {
1187     HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
1188     // 获取索引文件内容
1189     string path = GetRestoreTempPath(bundleName_);
1190     string indexFileRestorePath = GetIndexFileRestorePath(bundleName_);
1191     UniqueFd fd(open(indexFileRestorePath.data(), O_RDONLY));
1192     if (fd < 0) {
1193         HILOGE("Failed to open index json file = %{private}s, err = %{public}d", indexFileRestorePath.c_str(), errno);
1194         return;
1195     }
1196     BJsonCachedEntity<BJsonEntityExtManage> cachedEntity(move(fd));
1197     auto cache = cachedEntity.Structuralize();
1198     auto info = cache.GetExtManageInfo();
1199     HILOGI("Start Restore Big Files");
1200     auto start = std::chrono::system_clock::now();
1201     for (auto &item : info) {
1202         if (item.hashName.empty() || (!item.isUserTar && !item.isBigFile)) {
1203             continue;
1204         }
1205         RestoreOneBigFile(path, item, appendTargetPath);
1206     }
1207     auto end = std::chrono::system_clock::now();
1208     radarRestoreInfo_.bigFileSpendTime = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
1209     HILOGI("End Restore Big Files");
1210 }
1211 
FillEndFileInfos(const std::string & path,const unordered_map<string,struct ReportFileInfo> & result)1212 void BackupExtExtension::FillEndFileInfos(const std::string &path,
1213     const unordered_map<string, struct ReportFileInfo> &result)
1214 {
1215     isRpValid_ = result.size() > 0;
1216     if (!isRpValid_) {
1217         return;
1218     }
1219     for (const auto &it : result) {
1220         std::string filePath = it.first;
1221         if (!filePath.empty() && filePath.size() <= PATH_MAX) {
1222             endFileInfos_[path + filePath] = it.second.size;
1223         } else {
1224             HILOGE("File name : %{public}s check error", GetAnonyPath(path + filePath).c_str());
1225         }
1226     }
1227 }
1228 
DeleteBackupIdxFile()1229 void BackupExtExtension::DeleteBackupIdxFile()
1230 {
1231     if (!isClearData_) {
1232         HILOGI("configured not clear data.");
1233         return;
1234     }
1235     HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
1236     string indexFileRestorePath = GetIndexFileRestorePath(bundleName_);
1237     if (!RemoveFile(indexFileRestorePath)) {
1238         HILOGE("Failed to delete the backup index %{public}s", indexFileRestorePath.c_str());
1239     }
1240     HILOGI("End execute DeleteBackupIdxFile");
1241 }
1242 
DeleteBackupIncrementalIdxFile()1243 void BackupExtExtension::DeleteBackupIncrementalIdxFile()
1244 {
1245     if (!isClearData_) {
1246         HILOGI("configured not clear data.");
1247         return;
1248     }
1249     string indexFileRestorePath = GetIndexFileRestorePath(bundleName_);
1250     if (!RemoveFile(indexFileRestorePath)) {
1251         HILOGE("Failed to delete the backup index %{public}s", indexFileRestorePath.c_str());
1252     }
1253     string reportManagePath = GetReportFileName(indexFileRestorePath); // GetIncrementalFileHandle创建的空fd
1254     if (!RemoveFile(reportManagePath)) {
1255         HILOGE("Failed to delete the backup report index %{public}s", reportManagePath.c_str());
1256     }
1257 }
1258 
DeleteBackupIncrementalTars(const string & tarName)1259 void BackupExtExtension::DeleteBackupIncrementalTars(const string &tarName)
1260 {
1261     if (!isClearData_) {
1262         HILOGI("configured not need clear data");
1263         return;
1264     }
1265     if (!RemoveFile(tarName)) {
1266         HILOGE("Failed to delete the backup tar %{private}s, err = %{public}d", tarName.c_str(), errno);
1267     }
1268     // 删除简报文件
1269     string reportPath = GetReportFileName(tarName);
1270     if (!RemoveFile(reportPath)) {
1271         HILOGE("Failed to delete backup report %{private}s, err = %{public}d", reportPath.c_str(), errno);
1272     }
1273 }
1274 
HandleSpecialVersionRestore()1275 void BackupExtExtension::HandleSpecialVersionRestore()
1276 {
1277     auto ret = RestoreFilesForSpecialCloneCloud();
1278     if (ret == ERR_OK) {
1279         AsyncTaskRestoreForUpgrade();
1280     } else {
1281         AppDone(ret);
1282         DoClear();
1283     }
1284 }
1285 
AsyncTaskRestore(std::set<std::string> fileSet,const std::vector<ExtManageInfo> extManageInfo)1286 void BackupExtExtension::AsyncTaskRestore(std::set<std::string> fileSet,
1287     const std::vector<ExtManageInfo> extManageInfo)
1288 {
1289     auto task = [obj {wptr<BackupExtExtension>(this)}, fileSet {fileSet}, extManageInfo {extManageInfo}]() {
1290         auto ptr = obj.promote();
1291         BExcepUltils::BAssert(ptr, BError::Codes::EXT_BROKEN_FRAMEWORK, "Ext extension handle have been released");
1292         BExcepUltils::BAssert(ptr->extension_, BError::Codes::EXT_INVAL_ARG, "Extension handle have been released");
1293         try {
1294             int ret = ERR_OK;
1295             if (ptr->extension_->SpecialVersionForCloneAndCloud()) {
1296                 ptr->HandleSpecialVersionRestore();
1297                 return;
1298             }
1299             // 解压
1300             for (auto item : fileSet) { // 处理要解压的tar文件
1301                 off_t tarFileSize = 0;
1302                 if (ExtractFileExt(item) == "tar" && !IsUserTar(item, extManageInfo, tarFileSize)) {
1303                     ret = ptr->DoRestore(item, tarFileSize);
1304                 }
1305             }
1306             // 恢复用户tar包以及大文件
1307             // 目的地址是否需要拼接path(临时目录),FullBackupOnly为true并且非特殊场景
1308             bool appendTargetPath =
1309                 ptr->extension_->UseFullBackupOnly() && !ptr->extension_->SpecialVersionForCloneAndCloud();
1310             ptr->RestoreBigFiles(appendTargetPath);
1311             ptr->DeleteBackupIdxFile();
1312             if (ret == ERR_OK) {
1313                 ptr->AsyncTaskRestoreForUpgrade();
1314             } else {
1315                 ptr->AppDone(ret);
1316                 ptr->DoClear();
1317             }
1318         } catch (const BError &e) {
1319             ptr->AppDone(e.GetCode());
1320         } catch (const exception &e) {
1321             HILOGE("Catched an unexpected low-level exception %{public}s", e.what());
1322             ptr->AppDone(BError(BError::Codes::EXT_INVAL_ARG).GetCode());
1323         } catch (...) {
1324             HILOGE("Failed to restore the ext bundle");
1325             ptr->AppDone(BError(BError::Codes::EXT_INVAL_ARG).GetCode());
1326         }
1327     };
1328     // REM: 这里异步化了,需要做并发控制
1329     // 在往线程池中投入任务之前将需要的数据拷贝副本到参数中,保证不发生读写竞争,
1330     // 由于拷贝参数时尚运行在主线程中,故在参数拷贝过程中是线程安全的。
1331     threadPool_.AddTask([task]() {
1332         try {
1333             task();
1334         } catch (...) {
1335             HILOGE("Failed to add task to thread pool");
1336         }
1337     });
1338 }
1339 
DealIncreRestoreBigAndTarFile()1340 int BackupExtExtension::DealIncreRestoreBigAndTarFile()
1341 {
1342     if (isDebug_) {
1343         CheckTmpDirFileInfos();
1344     }
1345     auto startTime = std::chrono::system_clock::now();
1346     // 解压
1347     int ret = ERR_OK;
1348     ret = DoIncrementalRestore();
1349     if (ret != ERR_OK) {
1350         HILOGE("Do incremental restore err");
1351         return ret;
1352     }
1353     // 恢复用户tar包以及大文件
1354     // 目的地址是否需要拼接path(临时目录),FullBackupOnly为true并且非特殊场景
1355     bool appendTargetPath =
1356         extension_->UseFullBackupOnly() && !extension_->SpecialVersionForCloneAndCloud();
1357     RestoreBigFiles(appendTargetPath);
1358     // delete 1.tar/manage.json
1359     DeleteBackupIncrementalIdxFile();
1360     if (isDebug_) {
1361         CheckRestoreFileInfos();
1362     }
1363     auto endTime = std::chrono::system_clock::now();
1364     radarRestoreInfo_.totalFileSpendTime =
1365         std::chrono::duration_cast<std::chrono::milliseconds>(endTime - startTime).count();
1366     RecordDoRestoreRes(bundleName_, "BackupExtExtension::AsyncTaskIncrementalRestore",
1367         radarRestoreInfo_);
1368     return ret;
1369 }
1370 
AsyncTaskIncrementalRestore()1371 void BackupExtExtension::AsyncTaskIncrementalRestore()
1372 {
1373     auto task = [obj {wptr<BackupExtExtension>(this)}]() {
1374         auto ptr = obj.promote();
1375         BExcepUltils::BAssert(ptr, BError::Codes::EXT_BROKEN_FRAMEWORK, "Ext extension handle have been released");
1376         BExcepUltils::BAssert(ptr->extension_, BError::Codes::EXT_INVAL_ARG, "Extension handle have been released");
1377         try {
1378             int ret = ptr->DealIncreRestoreBigAndTarFile();
1379             if (ret == ERR_OK) {
1380                 HILOGI("after extra, do incremental restore.");
1381                 ptr->AsyncTaskIncrementalRestoreForUpgrade();
1382             } else {
1383                 ptr->AppIncrementalDone(ret);
1384                 ptr->DoClear();
1385             }
1386         } catch (const BError &e) {
1387             ptr->AppIncrementalDone(e.GetCode());
1388         } catch (const exception &e) {
1389             HILOGE("Catched an unexpected low-level exception %{public}s", e.what());
1390             ptr->AppIncrementalDone(BError(BError::Codes::EXT_INVAL_ARG).GetCode());
1391         } catch (...) {
1392             HILOGE("Failed to restore the ext bundle");
1393             ptr->AppIncrementalDone(BError(BError::Codes::EXT_INVAL_ARG).GetCode());
1394         }
1395     };
1396 
1397     // REM: 这里异步化了,需要做并发控制
1398     // 在往线程池中投入任务之前将需要的数据拷贝副本到参数中,保证不发生读写竞争,
1399     // 由于拷贝参数时尚运行在主线程中,故在参数拷贝过程中是线程安全的。
1400     threadPool_.AddTask([task]() {
1401         try {
1402             task();
1403         } catch (...) {
1404             HILOGE("Failed to add task to thread pool");
1405         }
1406     });
1407 }
1408 
AsyncTaskIncreRestoreSpecialVersion()1409 void BackupExtExtension::AsyncTaskIncreRestoreSpecialVersion()
1410 {
1411     auto task = [obj {wptr<BackupExtExtension>(this)}]() {
1412         auto ptr = obj.promote();
1413         BExcepUltils::BAssert(ptr, BError::Codes::EXT_BROKEN_FRAMEWORK, "Ext extension handle have been released");
1414         try {
1415             if (ptr != nullptr && ptr->isDebug_) {
1416                 ptr->CheckTmpDirFileInfos(true);
1417             }
1418             int ret = ptr->RestoreFilesForSpecialCloneCloud();
1419             if (ptr != nullptr && ptr->isDebug_) {
1420                 ptr->CheckRestoreFileInfos();
1421             }
1422             if (ret == ERR_OK) {
1423                 ptr->AsyncTaskIncrementalRestoreForUpgrade();
1424             } else {
1425                 ptr->AppIncrementalDone(ret);
1426                 ptr->DoClear();
1427             }
1428         } catch (const BError &e) {
1429             ptr->AppIncrementalDone(e.GetCode());
1430         } catch (const exception &e) {
1431             HILOGE("Catched an unexpected low-level exception %{public}s", e.what());
1432             ptr->AppIncrementalDone(BError(BError::Codes::EXT_INVAL_ARG).GetCode());
1433         } catch (...) {
1434             HILOGE("Failed to restore the ext bundle");
1435             ptr->AppIncrementalDone(BError(BError::Codes::EXT_INVAL_ARG).GetCode());
1436         }
1437     };
1438 
1439     // REM: 这里异步化了,需要做并发控制
1440     // 在往线程池中投入任务之前将需要的数据拷贝副本到参数中,保证不发生读写竞争,
1441     // 由于拷贝参数时尚运行在主线程中,故在参数拷贝过程中是线程安全的。
1442     threadPool_.AddTask([task]() {
1443         try {
1444             task();
1445         } catch (...) {
1446             HILOGE("Failed to add task to thread pool");
1447         }
1448     });
1449 }
1450 
AsyncTaskRestoreForUpgrade()1451 void BackupExtExtension::AsyncTaskRestoreForUpgrade()
1452 {
1453     HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
1454     auto task = [obj {wptr<BackupExtExtension>(this)}]() {
1455         auto ptr = obj.promote();
1456         BExcepUltils::BAssert(ptr, BError::Codes::EXT_BROKEN_FRAMEWORK, "Ext extension handle have been released");
1457         BExcepUltils::BAssert(ptr->extension_, BError::Codes::EXT_INVAL_ARG, "Extension handle have been released");
1458         try {
1459             HILOGI("On restore, start ext timer begin.");
1460             bool isExtStart;
1461             ptr->StartExtTimer(isExtStart);
1462             if (!isExtStart) {
1463                 HILOGE("On restore, start ext timer fail.");
1464                 return;
1465             }
1466             HILOGI("On restore, start ext timer end.");
1467             ptr->curScenario_ = BackupRestoreScenario::FULL_RESTORE;
1468             ptr->StartOnProcessTaskThread(obj, BackupRestoreScenario::FULL_RESTORE);
1469             auto callBackup = ptr->OnRestoreCallback(obj);
1470             auto callBackupEx = ptr->OnRestoreExCallback(obj);
1471             ptr->UpdateOnStartTime();
1472             ErrCode err = ptr->extension_->OnRestore(callBackup, callBackupEx);
1473             if (err != ERR_OK) {
1474                 ptr->AppDone(BError::GetCodeByErrno(err));
1475                 ptr->DoClear();
1476             }
1477         } catch (const BError &e) {
1478             ptr->AppDone(e.GetCode());
1479             ptr->DoClear();
1480         } catch (const exception &e) {
1481             HILOGE("Catched an unexpected low-level exception %{public}s", e.what());
1482             ptr->AppDone(BError(BError::Codes::EXT_INVAL_ARG).GetCode());
1483             ptr->DoClear();
1484         } catch (...) {
1485             HILOGE("Failed to restore the ext bundle");
1486             ptr->AppDone(BError(BError::Codes::EXT_INVAL_ARG).GetCode());
1487             ptr->DoClear();
1488         }
1489     };
1490     threadPool_.AddTask([task]() {
1491         try {
1492             task();
1493         } catch (...) {
1494             HILOGE("Failed to add task to thread pool");
1495         }
1496     });
1497 }
1498 
ExtClear()1499 void BackupExtExtension::ExtClear()
1500 {
1501     HILOGI("ext begin clear");
1502     DoClear();
1503 }
1504 
AsyncTaskIncrementalRestoreForUpgrade()1505 void BackupExtExtension::AsyncTaskIncrementalRestoreForUpgrade()
1506 {
1507     auto task = [obj {wptr<BackupExtExtension>(this)}]() {
1508         auto ptr = obj.promote();
1509         BExcepUltils::BAssert(ptr, BError::Codes::EXT_BROKEN_FRAMEWORK, "Ext extension handle have been released");
1510         BExcepUltils::BAssert(ptr->extension_, BError::Codes::EXT_INVAL_ARG, "Extension handle have been released");
1511         try {
1512             HILOGI("On incrementalRestore, start ext timer begin.");
1513             bool isExtStart;
1514             ptr->StartExtTimer(isExtStart);
1515             if (!isExtStart) {
1516                 HILOGE("On incrementalRestore, start ext timer fail.");
1517                 return;
1518             }
1519             HILOGI("On incrementalRestore, start ext timer end.");
1520             ptr->curScenario_ = BackupRestoreScenario::INCREMENTAL_RESTORE;
1521             ptr->StartOnProcessTaskThread(obj, BackupRestoreScenario::INCREMENTAL_RESTORE);
1522             auto callBackup = ptr->IncreOnRestoreCallback(obj);
1523             auto callBackupEx = ptr->IncreOnRestoreExCallback(obj);
1524             ptr->UpdateOnStartTime();
1525             ErrCode err = ptr->extension_->OnRestore(callBackup, callBackupEx);
1526             if (err != ERR_OK) {
1527                 HILOGE("OnRestore done, err = %{pubilc}d", err);
1528                 ptr->AppIncrementalDone(BError::GetCodeByErrno(err));
1529                 ptr->DoClear();
1530             }
1531         } catch (const BError &e) {
1532             ptr->AppIncrementalDone(e.GetCode());
1533             ptr->DoClear();
1534         } catch (const exception &e) {
1535             HILOGE("Catched an unexpected low-level exception %{public}s", e.what());
1536             ptr->AppIncrementalDone(BError(BError::Codes::EXT_INVAL_ARG).GetCode());
1537             ptr->DoClear();
1538         } catch (...) {
1539             HILOGE("Failed to restore the ext bundle");
1540             ptr->AppIncrementalDone(BError(BError::Codes::EXT_INVAL_ARG).GetCode());
1541             ptr->DoClear();
1542         }
1543     };
1544 
1545     // REM: 这里异步化了,需要做并发控制
1546     // 在往线程池中投入任务之前将需要的数据拷贝副本到参数中,保证不发生读写竞争,
1547     // 由于拷贝参数时尚运行在主线程中,故在参数拷贝过程中是线程安全的。
1548     threadPool_.AddTask([task]() {
1549         try {
1550             task();
1551         } catch (...) {
1552             HILOGE("Failed to add task to thread pool");
1553         }
1554     });
1555 }
1556 
DoClear()1557 void BackupExtExtension::DoClear()
1558 {
1559     HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
1560     try {
1561         if (!isClearData_) {
1562             HILOGI("configured not clear data.");
1563             return;
1564         }
1565         string backupCache = string(BConstants::PATH_BUNDLE_BACKUP_HOME).append(BConstants::SA_BUNDLE_BACKUP_BACKUP);
1566         string restoreCache = string(BConstants::PATH_BUNDLE_BACKUP_HOME).append(BConstants::SA_BUNDLE_BACKUP_RESTORE);
1567         string specialRestoreCache = GetRestoreTempPath(bundleName_);
1568 
1569         if (!ForceRemoveDirectory(backupCache)) {
1570             HILOGI("Failed to delete the backup cache %{public}s", backupCache.c_str());
1571         }
1572 
1573         if (!ForceRemoveDirectory(restoreCache)) {
1574             HILOGI("Failed to delete the restore cache %{public}s", restoreCache.c_str());
1575         }
1576 
1577         if (!ForceRemoveDirectory(specialRestoreCache)) {
1578             HILOGI("Failed to delete cache for filemanager or medialibrary %{public}s", specialRestoreCache.c_str());
1579         }
1580         // delete el1 backup/restore
1581         ForceRemoveDirectory(
1582             string(BConstants::PATH_BUNDLE_BACKUP_HOME_EL1).append(BConstants::SA_BUNDLE_BACKUP_BACKUP));
1583         ForceRemoveDirectory(
1584             string(BConstants::PATH_BUNDLE_BACKUP_HOME_EL1).append(BConstants::SA_BUNDLE_BACKUP_RESTORE));
1585         // delete special directory
1586         if (bundleName_.compare(MEDIA_LIBRARY_BUNDLE_NAME) == 0) {
1587             ForceRemoveDirectory(
1588                 string(BConstants::PATH_MEDIALDATA_BACKUP_HOME).append(BConstants::SA_BUNDLE_BACKUP_BACKUP));
1589             ForceRemoveDirectory(
1590                 string(BConstants::PATH_MEDIALDATA_BACKUP_HOME).append(BConstants::SA_BUNDLE_BACKUP_RESTORE));
1591         }
1592         if (bundleName_.compare(FILE_MANAGER_BUNDLE_NAME) == 0) {
1593             ForceRemoveDirectory(
1594                 string(BConstants::PATH_FILEMANAGE_BACKUP_HOME).append(BConstants::SA_BUNDLE_BACKUP_BACKUP));
1595             ForceRemoveDirectory(
1596                 string(BConstants::PATH_FILEMANAGE_BACKUP_HOME).append(BConstants::SA_BUNDLE_BACKUP_RESTORE));
1597         }
1598         unique_lock<shared_mutex> lock(lock_);
1599     } catch (...) {
1600         HILOGE("Failed to clear");
1601     }
1602 }
1603 
AppDone(ErrCode errCode)1604 void BackupExtExtension::AppDone(ErrCode errCode)
1605 {
1606     HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
1607     HILOGI("AppDone Begin.");
1608     auto proxy = ServiceProxy::GetInstance();
1609     if (proxy == nullptr) {
1610         HILOGE("Failed to obtain the ServiceProxy handle");
1611         DoClear();
1612         return;
1613     }
1614     auto ret = proxy->AppDone(errCode);
1615     if (ret != ERR_OK) {
1616         HILOGE("Failed to notify the app done. err = %{public}d", ret);
1617     }
1618 }
1619 
AppResultReport(const std::string restoreRetInfo,BackupRestoreScenario scenario,ErrCode errCode)1620 void BackupExtExtension::AppResultReport(const std::string restoreRetInfo,
1621     BackupRestoreScenario scenario, ErrCode errCode)
1622 {
1623     auto proxy = ServiceProxy::GetInstance();
1624     BExcepUltils::BAssert(proxy, BError::Codes::EXT_BROKEN_IPC, "Failed to obtain the ServiceProxy handle");
1625     HILOGI("restoreRetInfo is %{public}s", restoreRetInfo.c_str());
1626     auto ret = proxy->ServiceResultReport(restoreRetInfo, scenario, errCode);
1627     if (ret != ERR_OK) {
1628         HILOGE("Failed notify app restoreResultReport, errCode: %{public}d", ret);
1629     }
1630 }
1631 
StartExtTimer(bool & isExtStart)1632 void BackupExtExtension::StartExtTimer(bool &isExtStart)
1633 {
1634     auto proxy = ServiceProxy::GetInstance();
1635     BExcepUltils::BAssert(proxy, BError::Codes::EXT_BROKEN_IPC, "Failed to obtain the ServiceProxy handle");
1636     HILOGI("Start ext timer by ipc.");
1637     auto ret = proxy->StartExtTimer(isExtStart);
1638     if (ret != ERR_OK) {
1639         HILOGE("Start ext timer failed, errCode: %{public}d", ret);
1640     }
1641 }
1642 
StartFwkTimer(bool & isFwkStart)1643 void BackupExtExtension::StartFwkTimer(bool &isFwkStart)
1644 {
1645     auto proxy = ServiceProxy::GetInstance();
1646     BExcepUltils::BAssert(proxy, BError::Codes::EXT_BROKEN_IPC, "Failed to obtain the ServiceProxy handle");
1647     HILOGI("Start fwk timer by ipc.");
1648     auto ret = proxy->StartFwkTimer(isFwkStart);
1649     if (ret != ERR_OK) {
1650         HILOGE("Start fwk timer failed, errCode: %{public}d", ret);
1651     }
1652 }
1653 
UpdateOnStartTime()1654 void BackupExtExtension::UpdateOnStartTime()
1655 {
1656     std::lock_guard<std::mutex> lock(onStartTimeLock_);
1657     g_onStart = std::chrono::system_clock::now();
1658 }
1659 
AsyncTaskOnBackup()1660 void BackupExtExtension::AsyncTaskOnBackup()
1661 {
1662     HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
1663     auto task = [obj {wptr<BackupExtExtension>(this)}]() {
1664         auto ptr = obj.promote();
1665         BExcepUltils::BAssert(ptr, BError::Codes::EXT_BROKEN_FRAMEWORK, "Ext extension handle have been released");
1666         BExcepUltils::BAssert(ptr->extension_, BError::Codes::EXT_INVAL_ARG, "Extension handle have been released");
1667         try {
1668             ptr->curScenario_ = BackupRestoreScenario::FULL_BACKUP;
1669             ptr->StartOnProcessTaskThread(obj, BackupRestoreScenario::FULL_BACKUP);
1670             auto callBackup = ptr->OnBackupCallback(obj);
1671             auto callBackupEx = ptr->OnBackupExCallback(obj);
1672             ptr->UpdateOnStartTime();
1673             ErrCode err = ptr->extension_->OnBackup(callBackup, callBackupEx);
1674             if (err != ERR_OK) {
1675                 HILOGE("OnBackup done, err = %{pubilc}d", err);
1676                 ptr->AppDone(BError::GetCodeByErrno(err));
1677             }
1678         } catch (const BError &e) {
1679             ptr->AppDone(e.GetCode());
1680         } catch (const exception &e) {
1681             HILOGE("Catched an unexpected low-level exception %{public}s", e.what());
1682             ptr->AppDone(BError(BError::Codes::EXT_INVAL_ARG).GetCode());
1683         } catch (...) {
1684             HILOGE("Failed to restore the ext bundle");
1685             ptr->AppDone(BError(BError::Codes::EXT_INVAL_ARG).GetCode());
1686         }
1687     };
1688 
1689     threadPool_.AddTask([task]() {
1690         try {
1691             task();
1692         } catch (...) {
1693             HILOGE("Failed to add task to thread pool");
1694         }
1695     });
1696 }
1697 
HandleRestore(bool isClearData)1698 ErrCode BackupExtExtension::HandleRestore(bool isClearData)
1699 {
1700     HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
1701     try {
1702         VerifyCaller();
1703         SetClearDataFlag(isClearData);
1704         if (extension_ == nullptr) {
1705             HILOGE("Failed to handle restore, extension is nullptr");
1706             return BError(BError::Codes::EXT_INVAL_ARG, "Extension is nullptr").GetCode();
1707         }
1708         if (extension_->GetExtensionAction() != BConstants::ExtensionAction::RESTORE) {
1709             HILOGE("Failed to get file handle, because action is %{public}d invalid", extension_->GetExtensionAction());
1710             return BError(BError::Codes::EXT_INVAL_ARG, "Action is invalid").GetCode();
1711         }
1712         // read backup_config is allow to backup or restore
1713         if (!extension_->AllowToBackupRestore()) {
1714             HILOGE("Application does not allow backup or restore");
1715             return BError(BError::Codes::EXT_FORBID_BACKUP_RESTORE, "Application does not allow backup or restore")
1716                 .GetCode();
1717         }
1718 
1719         // async do restore.
1720         if (extension_->WasFromSpecialVersion() && extension_->RestoreDataReady()) {
1721             HILOGI("Restore directly when upgrading.");
1722             AsyncTaskRestoreForUpgrade();
1723         }
1724         return ERR_OK;
1725     } catch (...) {
1726         HILOGE("Failed to handle restore");
1727         return BError(BError::Codes::EXT_BROKEN_IPC).GetCode();
1728     }
1729 }
1730 
CheckTar(const string & fileName)1731 static bool CheckTar(const string &fileName)
1732 {
1733     return ExtractFileExt(fileName) == "tar";
1734 }
1735 
IfEquality(const ReportFileInfo & info,const ReportFileInfo & infoAd)1736 static bool IfEquality(const ReportFileInfo &info, const ReportFileInfo &infoAd)
1737 {
1738     return info.filePath < infoAd.filePath;
1739 }
1740 
AdDeduplication(vector<struct ReportFileInfo> & FilesList)1741 static void AdDeduplication(vector<struct ReportFileInfo> &FilesList)
1742 {
1743     sort(FilesList.begin(), FilesList.end(), IfEquality);
1744     auto it = unique(FilesList.begin(), FilesList.end(), [](const ReportFileInfo &info, const ReportFileInfo &infoAd) {
1745         return info.filePath == infoAd.filePath;
1746         });
1747     FilesList.erase(it, FilesList.end());
1748 }
1749 
CompareFiles(UniqueFd incrementalFd,UniqueFd manifestFd,vector<struct ReportFileInfo> & allFiles,vector<struct ReportFileInfo> & smallFiles,vector<struct ReportFileInfo> & bigFiles)1750 void BackupExtExtension::CompareFiles(UniqueFd incrementalFd,
1751                                       UniqueFd manifestFd,
1752                                       vector<struct ReportFileInfo> &allFiles,
1753                                       vector<struct ReportFileInfo> &smallFiles,
1754                                       vector<struct ReportFileInfo> &bigFiles)
1755 {
1756     HILOGI("Begin Compare");
1757     struct ReportFileInfo storageFiles;
1758     BReportEntity cloudRp(move(manifestFd));
1759     unordered_map<string, struct ReportFileInfo> cloudFiles = cloudRp.GetReportInfos();
1760     BReportEntity storageRp(move(incrementalFd));
1761 
1762     while (storageRp.GetStorageReportInfos(storageFiles)) {
1763         // 进行文件对比
1764         const string &path = storageFiles.filePath;
1765         if (path.empty()) {
1766             HILOGD("GetStorageReportInfos failed");
1767             continue;
1768         }
1769         auto it = cloudFiles.find(path);
1770         bool isExist = (it != cloudFiles.end()) ? true : false;
1771         if (storageFiles.isIncremental == true && storageFiles.isDir == true && !isExist) {
1772             smallFiles.push_back(storageFiles);
1773         }
1774         bool isChange = (isExist && storageFiles.size == it->second.size &&
1775             storageFiles.mtime == it->second.mtime) ? false : true;
1776         if (storageFiles.isDir == false && isChange) {
1777             auto [res, fileHash] = BackupFileHash::HashWithSHA256(path);
1778             if (fileHash.empty()) {
1779                 continue;
1780             }
1781             storageFiles.hash = fileHash;
1782         } else if (storageFiles.isDir == false) {
1783             storageFiles.hash = it->second.hash;
1784         }
1785 
1786         if (storageFiles.isDir == false && CheckTar(path)) {
1787             storageFiles.userTar = 1;
1788         }
1789 
1790         allFiles.push_back(storageFiles);
1791         if (storageFiles.isDir == false && storageFiles.isIncremental == true && (!isExist ||
1792              cloudFiles.find(path)->second.hash != storageFiles.hash)) {
1793             // 在云空间简报里不存在或者hash不一致
1794             if (storageFiles.size <= BConstants::BIG_FILE_BOUNDARY) {
1795                 smallFiles.push_back(storageFiles);
1796                 continue;
1797             }
1798             bigFiles.push_back(storageFiles);
1799         }
1800     }
1801     AdDeduplication(allFiles);
1802     AdDeduplication(smallFiles);
1803     AdDeduplication(bigFiles);
1804     HILOGI("End Compare, allfile is %{public}zu, samllfile is %{public}zu, bigfile is %{public}zu",
1805         allFiles.size(), smallFiles.size(), bigFiles.size());
1806 }
1807 
HandleIncrementalBackup(UniqueFd incrementalFd,UniqueFd manifestFd)1808 ErrCode BackupExtExtension::HandleIncrementalBackup(UniqueFd incrementalFd, UniqueFd manifestFd)
1809 {
1810     HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
1811     try {
1812         HILOGI("Start HandleIncrementalBackup");
1813         if (!IfAllowToBackupRestore()) {
1814             return BError(BError::Codes::EXT_FORBID_BACKUP_RESTORE, "Application does not allow backup or restore")
1815                 .GetCode();
1816         }
1817         AsyncTaskDoIncrementalBackup(move(incrementalFd), move(manifestFd));
1818         return ERR_OK;
1819     } catch (...) {
1820         HILOGE("Failed to handle incremental backup");
1821         return BError(BError::Codes::EXT_INVAL_ARG).GetCode();
1822     }
1823 }
1824 
IncrementalOnBackup(bool isClearData)1825 ErrCode BackupExtExtension::IncrementalOnBackup(bool isClearData)
1826 {
1827     HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
1828     SetClearDataFlag(isClearData);
1829     if (!IfAllowToBackupRestore()) {
1830         return BError(BError::Codes::EXT_FORBID_BACKUP_RESTORE, "Application does not allow backup or restore")
1831             .GetCode();
1832     }
1833     AsyncTaskOnIncrementalBackup();
1834     return ERR_OK;
1835 }
1836 
GetIncrementalBackupFileHandle()1837 tuple<UniqueFd, UniqueFd> BackupExtExtension::GetIncrementalBackupFileHandle()
1838 {
1839     HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
1840     return {UniqueFd(-1), UniqueFd(-1)};
1841 }
1842 
WriteFile(const string & filename,const vector<struct ReportFileInfo> & srcFiles)1843 static void WriteFile(const string &filename, const vector<struct ReportFileInfo> &srcFiles)
1844 {
1845     fstream f;
1846     f.open(filename.data(), ios::out);
1847     if (!f) {
1848         HILOGE("Failed to open file = %{private}s", filename.c_str());
1849         return;
1850     }
1851 
1852     // 前面2行先填充进去
1853     f << "version=1.0&attrNum=8" << endl;
1854     f << "path;mode;dir;size;mtime;hash;usertar;encodeFlag" << endl;
1855     for (auto item : srcFiles) {
1856         string path = BReportEntity::EncodeReportItem(item.filePath, item.encodeFlag);
1857         string str = path + ";" + item.mode + ";" + to_string(item.isDir) + ";" + to_string(item.size);
1858         str += ";" + to_string(item.mtime) + ";" + item.hash + ";" + to_string(item.userTar)+ ";";
1859         if (item.encodeFlag) {
1860             str += std::to_string(1);
1861         } else {
1862             str += std::to_string(0);
1863         }
1864         f << str << endl;
1865     }
1866     f.close();
1867 }
1868 
1869 /**
1870  * 获取增量的大文件的信息
1871  */
GetIncrmentBigInfos(const vector<struct ReportFileInfo> & files)1872 static TarMap GetIncrmentBigInfos(const vector<struct ReportFileInfo> &files)
1873 {
1874     auto getStringHash = [](const TarMap &tarMap, const string &str) -> string {
1875         ostringstream strHex;
1876         strHex << hex;
1877 
1878         hash<string> strHash;
1879         size_t szHash = strHash(str);
1880         strHex << setfill('0') << setw(BConstants::BIG_FILE_NAME_SIZE) << szHash;
1881         string name = strHex.str();
1882         for (int i = 0; tarMap.find(name) != tarMap.end(); ++i, strHex.str("")) {
1883             szHash = strHash(str + to_string(i));
1884             strHex << setfill('0') << setw(BConstants::BIG_FILE_NAME_SIZE) << szHash;
1885             name = strHex.str();
1886         }
1887 
1888         return name;
1889     };
1890 
1891     TarMap bigFiles;
1892     for (const auto &item : files) {
1893         struct stat sta = {};
1894         if (stat(item.filePath.c_str(), &sta) != 0) {
1895             HILOGE("Failed to stat file %{public}s, err = %{public}d", item.filePath.c_str(), errno);
1896             throw BError(BError::Codes::EXT_INVAL_ARG, "Get file stat failed");
1897         }
1898         string md5Name = getStringHash(bigFiles, item.filePath);
1899         if (!md5Name.empty()) {
1900             bigFiles.emplace(md5Name, make_tuple(item.filePath, sta, true));
1901         }
1902     }
1903 
1904     return bigFiles;
1905 }
1906 
1907 /**
1908  * 增量tar包和简报信息回传
1909  */
IncrementalTarFileReady(const TarMap & bigFileInfo,const vector<struct ReportFileInfo> & srcFiles,sptr<IService> proxy)1910 static ErrCode IncrementalTarFileReady(const TarMap &bigFileInfo,
1911                                        const vector<struct ReportFileInfo> &srcFiles,
1912                                        sptr<IService> proxy)
1913 {
1914     string tarFile = bigFileInfo.begin()->first;
1915     string manageFile = GetReportFileName(tarFile);
1916     string file = string(INDEX_FILE_INCREMENTAL_BACKUP).append(manageFile);
1917     WriteFile(file, srcFiles);
1918 
1919     string tarName = string(INDEX_FILE_INCREMENTAL_BACKUP).append(tarFile);
1920     ErrCode ret = proxy->AppIncrementalFileReady(tarFile, UniqueFd(open(tarName.data(), O_RDONLY)),
1921                                                  UniqueFd(open(file.data(), O_RDONLY)), ERR_OK);
1922     if (SUCCEEDED(ret)) {
1923         HILOGI("IncrementalTarFileReady: The application is packaged successfully");
1924         // 删除文件
1925         RemoveFile(file);
1926         RemoveFile(tarName);
1927     } else {
1928         HILOGE("IncrementalTarFileReady interface fails to be invoked: %{public}d", ret);
1929     }
1930     return ret;
1931 }
1932 
1933 /**
1934  * 增量大文件和简报信息回传
1935  */
IncrementalBigFileReady(TarMap & pkgInfo,const vector<struct ReportFileInfo> & bigInfos,sptr<IService> proxy)1936 ErrCode BackupExtExtension::IncrementalBigFileReady(TarMap &pkgInfo,
1937     const vector<struct ReportFileInfo> &bigInfos, sptr<IService> proxy)
1938 {
1939     ErrCode ret {ERR_OK};
1940     HILOGI("IncrementalBigFileReady Begin, pkgInfo size:%{public}zu", pkgInfo.size());
1941     auto startTime = std::chrono::system_clock::now();
1942     int fdNum = 0;
1943     vector<string> noPermissionFiles;
1944     for (auto &item : pkgInfo) {
1945         if (item.first.empty()) {
1946             continue;
1947         }
1948         auto [path, sta, isBeforeTar] = item.second;
1949         int32_t errCode = ERR_OK;
1950         WaitToSendFd(startTime, fdNum);
1951         UniqueFd fd(open(path.data(), O_RDONLY));
1952         if (fd < 0) {
1953             HILOGE("IncrementalBigFileReady open file failed, file name is %{public}s, err = %{public}d", path.c_str(),
1954                    errno);
1955             errCode = errno;
1956             if (errCode == ERR_NO_PERMISSION) {
1957                 noPermissionFiles.emplace_back(item.first.c_str());
1958                 continue;
1959             }
1960         }
1961         vector<struct ReportFileInfo> bigInfo;
1962         for (const auto &tempFile : bigInfos) {
1963             if (tempFile.filePath == path) {
1964                 bigInfo.emplace_back(tempFile);
1965                 break;
1966             }
1967         }
1968         string file = GetReportFileName(string(INDEX_FILE_INCREMENTAL_BACKUP).append(item.first));
1969         WriteFile(file, bigInfo);
1970         ret = proxy->AppIncrementalFileReady(item.first, std::move(fd), UniqueFd(open(file.data(), O_RDONLY)), errCode);
1971         if (SUCCEEDED(ret)) {
1972             HILOGI("IncrementalBigFileReady: The application is packaged successfully, package name is %{public}s",
1973                    item.first.c_str());
1974             RemoveFile(file);
1975         } else {
1976             HILOGE("IncrementalBigFileReady interface fails to be invoked: %{public}d", ret);
1977         }
1978         fdNum += BConstants::FILE_AND_MANIFEST_FD_COUNT;
1979         RefreshTimeInfo(startTime, fdNum);
1980     }
1981     ClearNoPermissionFiles(pkgInfo, noPermissionFiles);
1982     HILOGI("IncrementalBigFileReady End");
1983     return ret;
1984 }
1985 
DoIncrementalBackupTask(UniqueFd incrementalFd,UniqueFd manifestFd)1986 int BackupExtExtension::DoIncrementalBackupTask(UniqueFd incrementalFd, UniqueFd manifestFd)
1987 {
1988     auto start = std::chrono::system_clock::now();
1989     vector<struct ReportFileInfo> allFiles;
1990     vector<struct ReportFileInfo> smallFiles;
1991     vector<struct ReportFileInfo> bigFiles;
1992     CompareFiles(move(incrementalFd), move(manifestFd), allFiles, smallFiles, bigFiles);
1993     auto ret = DoIncrementalBackup(allFiles, smallFiles, bigFiles);
1994     if (ret == ERR_OK) {
1995         auto end = std::chrono::system_clock::now();
1996         auto cost = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
1997         if (cost >= BConstants::MAX_TIME_COST) {
1998             std::stringstream ss;
1999             ss << R"("spendTime": )"<< cost << R"(ms, "totalFiles": )" << allFiles.size() << R"(, "smallFiles": )"
2000                 << smallFiles.size() << R"(, "bigFiles": )" << bigFiles.size();
2001             AppRadar::Info info(bundleName_, "", ss.str());
2002             AppRadar::GetInstance().RecordBackupFuncRes(info, "BackupExtExtension::DoIncrementalBackupTask",
2003                 AppRadar::GetInstance().GetUserId(), BizStageBackup::BIZ_STAGE_DO_BACKUP, static_cast<int32_t>(ret));
2004         }
2005     }
2006     return ret;
2007 }
2008 
AsyncTaskDoIncrementalBackup(UniqueFd incrementalFd,UniqueFd manifestFd)2009 void BackupExtExtension::AsyncTaskDoIncrementalBackup(UniqueFd incrementalFd, UniqueFd manifestFd)
2010 {
2011     HILOGI("Do IncrementalBackup, start fwk timer begin.");
2012     bool isFwkStart;
2013     StartFwkTimer(isFwkStart);
2014     if (!isFwkStart) {
2015         HILOGE("Do IncrementalBackup, start fwk timer fail.");
2016         return;
2017     }
2018     HILOGI("Do IncrementalBackup, start fwk timer end.");
2019     int incrementalFdDup = dup(incrementalFd);
2020     int manifestFdDup = dup(manifestFd);
2021     if (incrementalFdDup < 0) {
2022         throw BError(BError::Codes::EXT_INVAL_ARG, "dup failed");
2023     }
2024     auto task = [obj {wptr<BackupExtExtension>(this)}, manifestFdDup, incrementalFdDup]() {
2025         auto ptr = obj.promote();
2026         BExcepUltils::BAssert(ptr, BError::Codes::EXT_BROKEN_FRAMEWORK, "Ext extension handle have been released");
2027         try {
2028             UniqueFd incrementalDupFd(dup(incrementalFdDup));
2029             UniqueFd manifestDupFd(dup(manifestFdDup));
2030             if (incrementalDupFd < 0) {
2031                 throw BError(BError::Codes::EXT_INVAL_ARG, "dup failed");
2032             }
2033             close(incrementalFdDup);
2034             close(manifestFdDup);
2035             auto ret = ptr->DoIncrementalBackupTask(move(incrementalDupFd), move(manifestDupFd));
2036             ptr->AppIncrementalDone(ret);
2037             HILOGI("Incremental backup app done %{public}d", ret);
2038         } catch (const BError &e) {
2039             ptr->AppIncrementalDone(e.GetCode());
2040         } catch (const exception &e) {
2041             HILOGE("Catched an unexpected low-level exception %{public}s", e.what());
2042             ptr->AppIncrementalDone(BError(BError::Codes::EXT_INVAL_ARG).GetCode());
2043         } catch (...) {
2044             HILOGE("Failed to restore the ext bundle");
2045             ptr->AppIncrementalDone(BError(BError::Codes::EXT_INVAL_ARG).GetCode());
2046         }
2047     };
2048 
2049     threadPool_.AddTask([task]() {
2050         try {
2051             task();
2052         } catch (...) {
2053             HILOGE("Failed to add task to thread pool");
2054         }
2055     });
2056 }
2057 
AsyncTaskOnIncrementalBackup()2058 void BackupExtExtension::AsyncTaskOnIncrementalBackup()
2059 {
2060     auto task = [obj {wptr<BackupExtExtension>(this)}]() {
2061         auto ptr = obj.promote();
2062         BExcepUltils::BAssert(ptr, BError::Codes::EXT_BROKEN_FRAMEWORK, "Ext extension handle have been released");
2063         BExcepUltils::BAssert(ptr->extension_, BError::Codes::EXT_INVAL_ARG, "Extension handle have been released");
2064         try {
2065             ptr->curScenario_ = BackupRestoreScenario::INCREMENTAL_BACKUP;
2066             ptr->StartOnProcessTaskThread(obj, BackupRestoreScenario::INCREMENTAL_BACKUP);
2067             auto callBackup = ptr->IncOnBackupCallback(obj);
2068             auto callBackupEx = ptr->IncOnBackupExCallback(obj);
2069             ptr->UpdateOnStartTime();
2070             ErrCode err = ptr->extension_->OnBackup(callBackup, callBackupEx);
2071             if (err != ERR_OK) {
2072                 HILOGE("OnBackup done, err = %{pubilc}d", err);
2073                 ptr->AppIncrementalDone(BError::GetCodeByErrno(err));
2074             }
2075         } catch (const BError &e) {
2076             ptr->AppIncrementalDone(e.GetCode());
2077         } catch (const exception &e) {
2078             HILOGE("Catched an unexpected low-level exception %{public}s", e.what());
2079             ptr->AppIncrementalDone(BError(BError::Codes::EXT_INVAL_ARG).GetCode());
2080         } catch (...) {
2081             HILOGE("Failed to restore the ext bundle");
2082             ptr->AppIncrementalDone(BError(BError::Codes::EXT_INVAL_ARG).GetCode());
2083         }
2084     };
2085 
2086     threadPool_.AddTask([task]() {
2087         try {
2088             task();
2089         } catch (...) {
2090             HILOGE("Failed to add task to thread pool");
2091         }
2092     });
2093 }
2094 
GetIncrmentPartName()2095 static string GetIncrmentPartName()
2096 {
2097     auto now = chrono::system_clock::now();
2098     auto duration = now.time_since_epoch();
2099     auto milliseconds = chrono::duration_cast<chrono::milliseconds>(duration);
2100 
2101     return to_string(milliseconds.count()) + "_part";
2102 }
2103 
IncrementalPacket(const vector<struct ReportFileInfo> & infos,TarMap & tar,sptr<IService> proxy)2104 void BackupExtExtension::IncrementalPacket(const vector<struct ReportFileInfo> &infos, TarMap &tar,
2105     sptr<IService> proxy)
2106 {
2107     HILOGI("IncrementalPacket begin, infos count: %{public}zu", infos.size());
2108     string path = string(BConstants::PATH_BUNDLE_BACKUP_HOME).append(BConstants::SA_BUNDLE_BACKUP_BACKUP);
2109     uint64_t totalSize = 0;
2110     uint32_t fileCount = 0;
2111     vector<string> packFiles;
2112     vector<struct ReportFileInfo> tarInfos;
2113     TarFile::GetInstance().SetPacketMode(true); // 设置下打包模式
2114     auto startTime = std::chrono::system_clock::now();
2115     int fdNum = 0;
2116     string partName = GetIncrmentPartName();
2117     auto reportCb = ReportErrFileByProc(wptr<BackupExtExtension> {this}, curScenario_);
2118     for (auto small : infos) {
2119         totalSize += static_cast<uint64_t>(small.size);
2120         fileCount += 1;
2121         packFiles.emplace_back(small.filePath);
2122         tarInfos.emplace_back(small);
2123         if (totalSize >= BConstants::DEFAULT_SLICE_SIZE || fileCount >= BConstants::MAX_FILE_COUNT) {
2124             TarMap tarMap {};
2125             TarFile::GetInstance().Packet(packFiles, partName, path, tarMap, reportCb);
2126             tar.insert(tarMap.begin(), tarMap.end());
2127             // 执行tar包回传功能
2128             WaitToSendFd(startTime, fdNum);
2129             IncrementalTarFileReady(tarMap, tarInfos, proxy);
2130             totalSize = 0;
2131             fileCount = 0;
2132             packFiles.clear();
2133             tarInfos.clear();
2134             fdNum += BConstants::FILE_AND_MANIFEST_FD_COUNT;
2135             RefreshTimeInfo(startTime, fdNum);
2136         }
2137     }
2138     if (fileCount > 0) {
2139         // 打包回传
2140         TarMap tarMap {};
2141         TarFile::GetInstance().Packet(packFiles, partName, path, tarMap, reportCb);
2142         IncrementalTarFileReady(tarMap, tarInfos, proxy);
2143         fdNum = 1;
2144         WaitToSendFd(startTime, fdNum);
2145         tar.insert(tarMap.begin(), tarMap.end());
2146         packFiles.clear();
2147         tarInfos.clear();
2148         RefreshTimeInfo(startTime, fdNum);
2149     }
2150 }
2151 
IncrementalAllFileReady(const TarMap & pkgInfo,const vector<struct ReportFileInfo> & srcFiles,sptr<IService> proxy)2152 static ErrCode IncrementalAllFileReady(const TarMap &pkgInfo,
2153                                        const vector<struct ReportFileInfo> &srcFiles,
2154                                        sptr<IService> proxy)
2155 {
2156     UniqueFd fdIndex(open(INDEX_FILE_BACKUP.data(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR));
2157     if (fdIndex < 0) {
2158         HILOGE("Failed to open index json file = %{private}s, err = %{public}d", INDEX_FILE_BACKUP.c_str(), errno);
2159         return BError::GetCodeByErrno(errno);
2160     }
2161     BJsonCachedEntity<BJsonEntityExtManage> cachedEntity(std::move(fdIndex));
2162     auto cache = cachedEntity.Structuralize();
2163     cache.SetExtManage(pkgInfo);
2164     cachedEntity.Persist();
2165     close(cachedEntity.GetFd().Release());
2166 
2167     string file = GetReportFileName(string(INDEX_FILE_INCREMENTAL_BACKUP).append("all"));
2168     WriteFile(file, srcFiles);
2169     UniqueFd fd(open(INDEX_FILE_BACKUP.data(), O_RDONLY));
2170     UniqueFd manifestFd(open(file.data(), O_RDONLY));
2171     ErrCode ret =
2172         proxy->AppIncrementalFileReady(string(BConstants::EXT_BACKUP_MANAGE), std::move(fd), std::move(manifestFd),
2173             ERR_OK);
2174     if (SUCCEEDED(ret)) {
2175         HILOGI("IncrementalAllFileReady successfully");
2176         RemoveFile(file);
2177     } else {
2178         HILOGI("successfully but the IncrementalAllFileReady interface fails to be invoked: %{public}d", ret);
2179     }
2180     return ret;
2181 }
2182 
DoIncrementalBackup(const vector<struct ReportFileInfo> & allFiles,const vector<struct ReportFileInfo> & smallFiles,const vector<struct ReportFileInfo> & bigFiles)2183 int BackupExtExtension::DoIncrementalBackup(const vector<struct ReportFileInfo> &allFiles,
2184                                             const vector<struct ReportFileInfo> &smallFiles,
2185                                             const vector<struct ReportFileInfo> &bigFiles)
2186 {
2187     HILOGI("Do increment backup begin");
2188     if (extension_ == nullptr) {
2189         HILOGE("Failed to do incremental backup, extension is nullptr");
2190         throw BError(BError::Codes::EXT_INVAL_ARG, "Extension is nullptr");
2191     }
2192     if (extension_->GetExtensionAction() != BConstants::ExtensionAction::BACKUP) {
2193         return EPERM;
2194     }
2195     string path = string(BConstants::PATH_BUNDLE_BACKUP_HOME).append(BConstants::SA_BUNDLE_BACKUP_BACKUP);
2196     if (mkdir(path.data(), S_IRWXU) && errno != EEXIST) {
2197         throw BError(errno);
2198     }
2199     auto proxy = ServiceProxy::GetInstance();
2200     if (proxy == nullptr) {
2201         throw BError(BError::Codes::EXT_BROKEN_BACKUP_SA, std::generic_category().message(errno));
2202     }
2203     // 获取增量文件和全量数据
2204     if (smallFiles.size() == 0 && bigFiles.size() == 0) {
2205         // 没有增量,则不需要上传
2206         TarMap tMap;
2207         ErrCode err = IncrementalAllFileReady(tMap, allFiles, proxy);
2208         HILOGI("Do increment backup, IncrementalAllFileReady end, file empty");
2209         return err;
2210     }
2211     // tar包数据
2212     TarMap tarMap;
2213     IncrementalPacket(smallFiles, tarMap, proxy);
2214     HILOGI("Do increment backup, IncrementalPacket end");
2215     // 最后回传大文件
2216     TarMap bigMap = GetIncrmentBigInfos(bigFiles);
2217     IncrementalBigFileReady(bigMap, bigFiles, proxy);
2218     HILOGI("Do increment backup, IncrementalBigFileReady end");
2219     bigMap.insert(tarMap.begin(), tarMap.end());
2220     // 回传manage.json和全量文件
2221     ErrCode err = IncrementalAllFileReady(bigMap, allFiles, proxy);
2222     HILOGI("End, bigFiles num:%{public}zu, smallFiles num:%{public}zu, allFiles num:%{public}zu", bigFiles.size(),
2223         smallFiles.size(), allFiles.size());
2224     return err;
2225 }
2226 } // namespace OHOS::FileManagement::Backup
2227