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