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