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