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