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