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