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