1 /*
2 * Copyright (c) 2024-2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "ext_extension.h"
17
18 #include <algorithm>
19 #include <chrono>
20 #include <cinttypes>
21 #include <fstream>
22 #include <fnmatch.h>
23 #include <iomanip>
24 #include <map>
25 #include <regex>
26 #include <string>
27 #include <thread>
28 #include <tuple>
29 #include <unordered_map>
30 #include <vector>
31
32 #include <directory_ex.h>
33 #include <sys/stat.h>
34 #include <unistd.h>
35
36 #include <directory_ex.h>
37 #include <unique_fd.h>
38
39 #include "accesstoken_kit.h"
40 #include "bundle_mgr_client.h"
41 #include "errors.h"
42 #include "ipc_skeleton.h"
43
44 #include "b_error/b_error.h"
45 #include "b_error/b_excep_utils.h"
46 #include "b_filesystem/b_dir.h"
47 #include "b_filesystem/b_file.h"
48 #include "b_filesystem/b_file_hash.h"
49 #include "b_json/b_json_cached_entity.h"
50 #include "b_jsonutil/b_jsonutil.h"
51 #include "b_ohos/startup/backup_para.h"
52 #include "b_radar/b_radar.h"
53 #include "b_tarball/b_tarball_factory.h"
54 #include "b_utils/scan_file_singleton.h"
55 #include "filemgmt_libhilog.h"
56 #include "hitrace_meter.h"
57 #include "sandbox_helper.h"
58 #include "service_client.h"
59 #include "tar_file.h"
60 #include "b_anony/b_anony.h"
61
62 namespace OHOS::FileManagement::Backup {
63 const uint32_t MAX_FD_GROUP_USE_TIME = 1000; // 每组打开最大时间1000ms
64
HandleIncrementalBackup(int incrementalFd,int manifestFd)65 ErrCode BackupExtExtension::HandleIncrementalBackup(int incrementalFd, int manifestFd)
66 {
67 HILOGI("Start HandleIncrementalBackup. incrementalFd:%{public}d, manifestFd:%{public}d", incrementalFd, manifestFd);
68 UniqueFd incrementalFdUnique(dup(incrementalFd));
69 UniqueFd manifestFdUnique(dup(manifestFd));
70 ErrCode ret = HandleIncrementalBackup(std::move(incrementalFdUnique), std::move(manifestFdUnique));
71 close(incrementalFd);
72 close(manifestFd);
73 return ret;
74 }
75
HandleIncrementalBackup(UniqueFd incrementalFd,UniqueFd manifestFd)76 ErrCode BackupExtExtension::HandleIncrementalBackup(UniqueFd incrementalFd, UniqueFd manifestFd)
77 {
78 HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
79 try {
80 HILOGI("Start HandleIncrementalBackup");
81 if (!IfAllowToBackupRestore()) {
82 return BError(BError::Codes::EXT_FORBID_BACKUP_RESTORE, "Application does not allow backup or restore")
83 .GetCode();
84 }
85 AsyncTaskDoIncrementalBackup(move(incrementalFd), move(manifestFd));
86 return ERR_OK;
87 } catch (...) {
88 HILOGE("Failed to handle incremental backup");
89 return BError(BError::Codes::EXT_INVAL_ARG).GetCode();
90 }
91 }
92
IncrementalOnBackup(bool isClearData)93 ErrCode BackupExtExtension::IncrementalOnBackup(bool isClearData)
94 {
95 HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
96 SetClearDataFlag(isClearData);
97 if (!IfAllowToBackupRestore()) {
98 return BError(BError::Codes::EXT_FORBID_BACKUP_RESTORE, "Application does not allow backup or restore")
99 .GetCode();
100 }
101 curScenario_ = BackupRestoreScenario::INCREMENTAL_BACKUP;
102 AsyncTaskOnIncrementalBackup();
103 return ERR_OK;
104 }
105
WaitToSendFd(std::chrono::system_clock::time_point & startTime,int & fdSendNum)106 void BackupExtExtension::WaitToSendFd(std::chrono::system_clock::time_point &startTime, int &fdSendNum)
107 {
108 HILOGD("WaitToSendFd Begin");
109 std::unique_lock<std::mutex> lock(startSendMutex_);
110 startSendFdRateCon_.wait(lock, [this] { return sendRate_ > 0; });
111 if (fdSendNum >= sendRate_) {
112 HILOGI("current time fd num is max rate, bundle name:%{public}s, rate:%{public}d", bundleName_.c_str(),
113 sendRate_);
114 auto curTime = std::chrono::system_clock::now();
115 auto useTimeMs = std::chrono::duration_cast<std::chrono::milliseconds>(curTime - startTime).count();
116 if (useTimeMs < MAX_FD_GROUP_USE_TIME) {
117 int32_t sleepTime = MAX_FD_GROUP_USE_TIME - useTimeMs;
118 HILOGI("will wait time:%{public}d ms", sleepTime);
119 std::this_thread::sleep_for(std::chrono::milliseconds(sleepTime));
120 } else {
121 HILOGW("current fd send num exceeds one second");
122 }
123 fdSendNum = 0;
124 startTime = std::chrono::system_clock::now();
125 }
126 HILOGD("WaitToSendFd End");
127 }
128
RefreshTimeInfo(std::chrono::system_clock::time_point & startTime,int & fdSendNum)129 void BackupExtExtension::RefreshTimeInfo(std::chrono::system_clock::time_point &startTime, int &fdSendNum)
130 {
131 auto currentTime = std::chrono::system_clock::now();
132 auto useTime = std::chrono::duration_cast<std::chrono::milliseconds>(currentTime - startTime).count();
133 if (useTime >= MAX_FD_GROUP_USE_TIME) {
134 HILOGI("RefreshTimeInfo Begin, fdSendNum is:%{public}d", fdSendNum);
135 startTime = std::chrono::system_clock::now();
136 fdSendNum = 0;
137 }
138 }
139
SetClearDataFlag(bool isClearData)140 void BackupExtExtension::SetClearDataFlag(bool isClearData)
141 {
142 isClearData_ = isClearData;
143 HILOGI("set clear data flag:%{public}d", isClearData);
144 if (extension_ == nullptr) {
145 HILOGE("Extension handle have been released");
146 return;
147 }
148 if (!extension_->WasFromSpecialVersion() && !extension_->RestoreDataReady()) {
149 DoClear();
150 }
151 }
152
GetBundlePath()153 string BackupExtExtension::GetBundlePath()
154 {
155 if (bundleName_ == BConstants::BUNDLE_FILE_MANAGER) {
156 return string(BConstants::PATH_FILEMANAGE_BACKUP_HOME).append(BConstants::SA_BUNDLE_BACKUP_RESTORE);
157 } else if (bundleName_ == BConstants::BUNDLE_MEDIAL_DATA) {
158 return string(BConstants::PATH_MEDIALDATA_BACKUP_HOME).append(BConstants::SA_BUNDLE_BACKUP_RESTORE);
159 }
160 return string(BConstants::PATH_BUNDLE_BACKUP_HOME).append(BConstants::SA_BUNDLE_BACKUP_RESTORE);
161 }
162
GetIdxFileInfos(bool isSpecialVersion)163 std::map<std::string, off_t> BackupExtExtension::GetIdxFileInfos(bool isSpecialVersion)
164 {
165 string restoreDir = isSpecialVersion ? "" : GetBundlePath();
166 auto extManageInfo = GetExtManageInfo(isSpecialVersion);
167 std::map<std::string, off_t> idxFileInfos;
168 for (size_t i = 0; i < extManageInfo.size(); ++i) {
169 std::string realPath = restoreDir + extManageInfo[i].hashName;
170 idxFileInfos[realPath] = extManageInfo[i].sta.st_size;
171 }
172 return idxFileInfos;
173 }
174
CheckTmpDirFileInfos(bool isSpecialVersion)175 void BackupExtExtension::CheckTmpDirFileInfos(bool isSpecialVersion)
176 {
177 ErrFileInfo errFiles;
178 auto idxFileInfos = GetIdxFileInfos(isSpecialVersion);
179 struct stat attr;
180 for (const auto &it : idxFileInfos) {
181 if (it.first.size() >= PATH_MAX || stat(it.first.data(), &attr) == -1) {
182 HILOGE("(Debug) Failed to get stat of %{public}s, errno = %{public}d", GetAnonyPath(it.first).c_str(),
183 errno);
184 errFiles[it.first].emplace_back(errno);
185 } else if (it.second != attr.st_size) {
186 HILOGE("(Debug) RecFile:%{public}s size err, recSize: %{public}" PRId64 ", idxSize: %{public}" PRId64 "",
187 GetAnonyPath(it.first).c_str(), attr.st_size, it.second);
188 errFiles[it.first] = std::vector<int>();
189 }
190 }
191 HILOGE("(Debug) Temp file check result: Total file: %{public}zu, err file: %{public}zu", idxFileInfos.size(),
192 errFiles.size());
193 if (!errFiles.empty()) {
194 HILOGE("(Debug) The received file and idx is not same");
195 std::stringstream ss;
196 ss << R"("totalFile": )" << idxFileInfos.size() << R"(, "restoreFile": )"
197 << idxFileInfos.size() - errFiles.size() << R"(, "info": "different received file and idx")";
198 AppRadar::Info info (bundleName_, "", ss.str());
199 AppRadar::GetInstance().RecordRestoreFuncRes(info, "BackupExtExtension::CheckTmpDirFileInfos",
200 AppRadar::GetInstance().GetUserId(), BizStageRestore::BIZ_STAGE_CHECK_DATA_FAIL,
201 static_cast<int32_t>(BError::BackupErrorCode::E_UKERR));
202 } else {
203 HILOGI("(Debug) The received file and idx is same");
204 }
205 }
206
CheckRestoreFileInfos()207 tuple<bool, vector<string>> BackupExtExtension::CheckRestoreFileInfos()
208 {
209 vector<string> errFiles;
210 struct stat curFileStat {};
211 for (const auto &it : endFileInfos_) {
212 if (lstat(it.first.c_str(), &curFileStat) != 0) {
213 HILOGE("Failed to lstat %{public}s, err = %{public}d", GetAnonyPath(it.first).c_str(), errno);
214 errFiles.emplace_back(it.first);
215 errFileInfos_[it.first].emplace_back(errno);
216 } else if (curFileStat.st_size != it.second) {
217 HILOGE("File size error, file: %{public}s, idx: %{public}" PRId64 ", act: %{public}" PRId64 "",
218 GetAnonyPath(it.first).c_str(), it.second, curFileStat.st_size);
219 errFiles.emplace_back(it.first);
220 errFileInfos_[it.first].emplace_back(errno);
221 }
222 }
223 for (const auto &it : errFileInfos_) {
224 for (const auto &codeIt : it.second) {
225 HILOGE("(Debug) errfileInfos file = %{public}s -> %{public}d", GetAnonyPath(it.first).c_str(), codeIt);
226 }
227 }
228 HILOGE("(Debug) End file check result Total file: %{public}zu, err file: %{public}zu", endFileInfos_.size(),
229 errFileInfos_.size());
230 if (errFiles.size()) {
231 std::stringstream ss;
232 ss << R"("totalFile": )" << endFileInfos_.size() << R"(, "restoreFile": )"
233 << endFileInfos_.size() - errFileInfos_.size();
234 AppRadar::Info info (bundleName_, "", ss.str());
235 AppRadar::GetInstance().RecordRestoreFuncRes(info, "BackupExtExtension::CheckRestoreFileInfos",
236 AppRadar::GetInstance().GetUserId(), BizStageRestore::BIZ_STAGE_CHECK_DATA_FAIL,
237 static_cast<int32_t>(BError::BackupErrorCode::E_UKERR));
238 return { false, errFiles };
239 }
240 return { true, errFiles };
241 }
242
OnRestoreCallback(wptr<BackupExtExtension> obj)243 std::function<void(ErrCode, std::string)> BackupExtExtension::OnRestoreCallback(wptr<BackupExtExtension> obj)
244 {
245 HILOGI("Begin get full restore onRestore callback");
246 return [obj](ErrCode errCode, std::string errMsg) {
247 auto extensionPtr = obj.promote();
248 if (extensionPtr == nullptr) {
249 HILOGE("Ext extension handle have been released");
250 return;
251 }
252 extensionPtr->OnRestoreFinish();
253 if (extensionPtr->isExecAppDone_.load()) {
254 HILOGE("Appdone has been executed for the current application");
255 return;
256 }
257 HILOGI("Current bundle will execute app done");
258 if (errCode == ERR_OK) {
259 auto spendTime = extensionPtr->GetOnStartTimeCost();
260 if (spendTime >= BConstants::MAX_TIME_COST) {
261 std::stringstream ss;
262 ss << R"("spendTime": )"<< spendTime << "ms";
263 AppRadar::Info info (extensionPtr->bundleName_, "", ss.str());
264 AppRadar::GetInstance().RecordRestoreFuncRes(info, "BackupExtExtension::OnRestoreCallback",
265 AppRadar::GetInstance().GetUserId(), BizStageRestore::BIZ_STAGE_ON_RESTORE, ERR_OK);
266 }
267 }
268 extensionPtr->FinishOnProcessTask();
269 if (errMsg.empty()) {
270 extensionPtr->AppDone(errCode);
271 } else {
272 std::string errInfo;
273 BJsonUtil::BuildExtensionErrInfo(errInfo, errCode, errMsg);
274 extensionPtr->ReportAppStatistic("OnRestoreCallback", errCode);
275 extensionPtr->AppResultReport(errInfo, BackupRestoreScenario::FULL_RESTORE, errCode);
276 }
277 extensionPtr->DoClear();
278 };
279 }
280
OnRestoreExCallback(wptr<BackupExtExtension> obj)281 std::function<void(ErrCode, std::string)> BackupExtExtension::OnRestoreExCallback(wptr<BackupExtExtension> obj)
282 {
283 HILOGI("Begin get full restore onRestoreEx callback");
284 return [obj](ErrCode errCode, const std::string restoreRetInfo) {
285 auto extensionPtr = obj.promote();
286 if (extensionPtr == nullptr) {
287 HILOGE("Ext extension handle have been released");
288 return;
289 }
290 extensionPtr->OnRestoreExFinish();
291 if (extensionPtr->extension_ == nullptr) {
292 HILOGE("Extension handle have been released");
293 return;
294 }
295 if (extensionPtr->isExecAppDone_.load()) {
296 HILOGE("Appdone has been executed for the current application");
297 return;
298 }
299 if (errCode == ERR_OK && !restoreRetInfo.empty()) {
300 auto spendTime = extensionPtr->GetOnStartTimeCost();
301 if (spendTime >= BConstants::MAX_TIME_COST) {
302 std::stringstream ss;
303 ss << R"("spendTime": )"<< spendTime << "ms";
304 AppRadar::Info info (extensionPtr->bundleName_, "", ss.str());
305 AppRadar::GetInstance().RecordRestoreFuncRes(info, "BackupExtExtension::OnRestoreExCallback",
306 AppRadar::GetInstance().GetUserId(), BizStageRestore::BIZ_STAGE_ON_RESTORE, ERR_OK);
307 }
308 }
309 extensionPtr->FinishOnProcessTask();
310 extensionPtr->extension_->InvokeAppExtMethod(errCode, restoreRetInfo);
311 if (errCode == ERR_OK) {
312 if (restoreRetInfo.size()) {
313 HILOGI("Will notify restore result report");
314 extensionPtr->ReportAppStatistic("OnRestoreExCallback1", errCode);
315 extensionPtr->AppResultReport(restoreRetInfo, BackupRestoreScenario::FULL_RESTORE);
316 }
317 return;
318 }
319 if (restoreRetInfo.empty()) {
320 extensionPtr->AppDone(errCode);
321 extensionPtr->DoClear();
322 } else {
323 std::string errInfo;
324 BJsonUtil::BuildExtensionErrInfo(errInfo, errCode, restoreRetInfo);
325 extensionPtr->ReportAppStatistic("OnRestoreExCallback2", errCode);
326 extensionPtr->AppResultReport(errInfo, BackupRestoreScenario::FULL_RESTORE, errCode);
327 extensionPtr->DoClear();
328 }
329 };
330 }
331
AppDoneCallbackEx(wptr<BackupExtExtension> obj)332 std::function<void(ErrCode, std::string)> BackupExtExtension::AppDoneCallbackEx(wptr<BackupExtExtension> obj)
333 {
334 HILOGI("Begin get callback for appDone");
335 return [obj](ErrCode errCode, std::string errMsg) {
336 HILOGI("begin call callBackupExAppDone");
337 auto extensionPtr = obj.promote();
338 if (extensionPtr == nullptr) {
339 HILOGE("Ext extension handle have been released");
340 return;
341 }
342 extensionPtr->AppDone(errCode);
343 extensionPtr->DoClear();
344 };
345 }
346
IncreOnRestoreExCallback(wptr<BackupExtExtension> obj)347 std::function<void(ErrCode, std::string)> BackupExtExtension::IncreOnRestoreExCallback(wptr<BackupExtExtension> obj)
348 {
349 HILOGI("Begin get callback for increment onRestoreEx");
350 return [obj](ErrCode errCode, const std::string restoreRetInfo) {
351 HILOGI("begin call increment restoreEx");
352 auto extensionPtr = obj.promote();
353 if (extensionPtr == nullptr) {
354 HILOGE("Ext extension handle have been released");
355 return;
356 }
357 extensionPtr->OnRestoreExFinish();
358 if (extensionPtr->extension_ == nullptr) {
359 HILOGE("Extension handle have been released");
360 return;
361 }
362 if (extensionPtr->isExecAppDone_.load()) {
363 HILOGE("Appdone has been executed for the current application");
364 return;
365 }
366 if (errCode == ERR_OK && !restoreRetInfo.empty()) {
367 auto spendTime = extensionPtr->GetOnStartTimeCost();
368 if (spendTime >= BConstants::MAX_TIME_COST) {
369 std::stringstream ss;
370 ss << R"("spendTime": )"<< spendTime << "ms";
371 AppRadar::Info info (extensionPtr->bundleName_, "", ss.str());
372 AppRadar::GetInstance().RecordRestoreFuncRes(info, "BackupExtExtension::IncreOnRestoreExCallback",
373 AppRadar::GetInstance().GetUserId(), BizStageRestore::BIZ_STAGE_ON_RESTORE, ERR_OK);
374 }
375 }
376 extensionPtr->FinishOnProcessTask();
377 extensionPtr->extension_->InvokeAppExtMethod(errCode, restoreRetInfo);
378 if (errCode == ERR_OK) {
379 if (restoreRetInfo.size()) {
380 extensionPtr->ReportAppStatistic("IncreOnRestoreExCallback1", errCode);
381 extensionPtr->AppResultReport(restoreRetInfo, BackupRestoreScenario::INCREMENTAL_RESTORE);
382 }
383 return;
384 }
385 if (restoreRetInfo.empty()) {
386 extensionPtr->AppIncrementalDone(errCode);
387 extensionPtr->DoClear();
388 } else {
389 std::string errInfo;
390 BJsonUtil::BuildExtensionErrInfo(errInfo, errCode, restoreRetInfo);
391 extensionPtr->ReportAppStatistic("IncreOnRestoreExCallback2", errCode);
392 extensionPtr->AppResultReport(errInfo, BackupRestoreScenario::INCREMENTAL_RESTORE, errCode);
393 extensionPtr->DoClear();
394 }
395 };
396 }
397
IncreOnRestoreCallback(wptr<BackupExtExtension> obj)398 std::function<void(ErrCode, std::string)> BackupExtExtension::IncreOnRestoreCallback(wptr<BackupExtExtension> obj)
399 {
400 return [obj](ErrCode errCode, std::string errMsg) {
401 auto extensionPtr = obj.promote();
402 if (extensionPtr == nullptr) {
403 HILOGE("Ext extension handle have been released");
404 return;
405 }
406 extensionPtr->OnRestoreFinish();
407 if (extensionPtr->isExecAppDone_.load()) {
408 HILOGE("Appdone has been executed for the current application");
409 return;
410 }
411 HILOGI("Current bundle will execute app done");
412 if (errCode == ERR_OK) {
413 auto spendTime = extensionPtr->GetOnStartTimeCost();
414 if (spendTime >= BConstants::MAX_TIME_COST) {
415 std::stringstream ss;
416 ss << R"("spendTime": )"<< spendTime << "ms";
417 AppRadar::Info info (extensionPtr->bundleName_, "", ss.str());
418 AppRadar::GetInstance().RecordRestoreFuncRes(info, "BackupExtExtension::IncreOnRestoreCallback",
419 AppRadar::GetInstance().GetUserId(), BizStageRestore::BIZ_STAGE_ON_RESTORE, ERR_OK);
420 }
421 }
422 extensionPtr->FinishOnProcessTask();
423 if (errMsg.empty()) {
424 extensionPtr->AppIncrementalDone(errCode);
425 } else {
426 std::string errInfo;
427 BJsonUtil::BuildExtensionErrInfo(errInfo, errCode, errMsg);
428 extensionPtr->ReportAppStatistic("IncreOnRestoreCallback", errCode);
429 extensionPtr->AppResultReport(errInfo, BackupRestoreScenario::INCREMENTAL_RESTORE, errCode);
430 }
431 extensionPtr->DoClear();
432 };
433 }
434
GetOnStartTimeCost()435 int32_t BackupExtExtension::GetOnStartTimeCost()
436 {
437 auto onBackupRestoreEnd = std::chrono::system_clock::now();
438 std::lock_guard<std::mutex> lock(onStartTimeLock_);
439 auto spendTime = std::chrono::duration_cast<std::chrono::milliseconds>(onBackupRestoreEnd - g_onStart).count();
440 return spendTime;
441 }
442
OnBackupCallback(wptr<BackupExtExtension> obj)443 std::function<void(ErrCode, const std::string)> BackupExtExtension::OnBackupCallback(wptr<BackupExtExtension> obj)
444 {
445 HILOGI("Begin get HandleFullBackupCallbackEx");
446 return [obj](ErrCode errCode, std::string errMsg) {
447 HILOGI("begin call backup");
448 auto extensionPtr = obj.promote();
449 if (extensionPtr == nullptr) {
450 HILOGE("Ext extension handle have been released");
451 return;
452 }
453 extensionPtr->OnBackupFinish();
454 if (extensionPtr->extension_ == nullptr) {
455 HILOGE("Extension handle have been released");
456 return;
457 }
458 if (extensionPtr->isExecAppDone_.load()) {
459 HILOGE("Appdone has been executed for the current application");
460 return;
461 }
462 extensionPtr->FinishOnProcessTask();
463 if (errCode == ERR_OK) {
464 auto spendTime = extensionPtr->GetOnStartTimeCost();
465 if (spendTime >= BConstants::MAX_TIME_COST) {
466 AppRadar::Info info(extensionPtr->bundleName_, "", string("\"spend_time\":\" ").
467 append(to_string(spendTime)).append(string("ms\"")));
468 AppRadar::GetInstance().RecordBackupFuncRes(info, "BackupExtExtension::OnBackupCallback",
469 AppRadar::GetInstance().GetUserId(), BizStageBackup::BIZ_STAGE_ON_BACKUP,
470 static_cast<int32_t>(ERR_OK));
471 }
472 extensionPtr->AsyncTaskBackup(extensionPtr->extension_->GetUsrConfig());
473 return;
474 }
475 HILOGE("Call extension onBackup failed, errInfo = %{public}s", errMsg.c_str());
476 if (!errMsg.empty()) {
477 std::string errInfo;
478 BJsonUtil::BuildExtensionErrInfo(errInfo, errCode, errMsg);
479 extensionPtr->AppResultReport(errInfo, BackupRestoreScenario::FULL_BACKUP, errCode);
480 }
481 extensionPtr->AppDone(errCode);
482 extensionPtr->DoClear();
483 };
484 }
485
OnBackupExCallback(wptr<BackupExtExtension> obj)486 std::function<void(ErrCode, const std::string)> BackupExtExtension::OnBackupExCallback(wptr<BackupExtExtension> obj)
487 {
488 HILOGI("Begin get HandleFullBackupCallbackEx");
489 return [obj](ErrCode errCode, const std::string backupExRetInfo) {
490 HILOGI("begin call backup");
491 auto extensionPtr = obj.promote();
492 if (extensionPtr == nullptr) {
493 HILOGE("Ext extension handle have been released");
494 return;
495 }
496 extensionPtr->OnBackupExFinish();
497 if (extensionPtr->extension_ == nullptr) {
498 HILOGE("Extension handle have been released");
499 return;
500 }
501 if (extensionPtr->isExecAppDone_.load()) {
502 HILOGE("Appdone has been executed for the current application");
503 return;
504 }
505 extensionPtr->extension_->InvokeAppExtMethod(errCode, backupExRetInfo);
506 if (errCode == ERR_OK) {
507 if (backupExRetInfo.size()) {
508 auto spendTime = extensionPtr->GetOnStartTimeCost();
509 if (spendTime >= BConstants::MAX_TIME_COST) {
510 AppRadar::Info info(extensionPtr->bundleName_, "", string("\"spend_time\":\" ").
511 append(to_string(spendTime)).append(string("ms\"")));
512 AppRadar::GetInstance().RecordBackupFuncRes(info, "BackupExtExtension::OnBackupExCallback",
513 AppRadar::GetInstance().GetUserId(), BizStageBackup::BIZ_STAGE_ON_BACKUP,
514 static_cast<int32_t>(ERR_OK));
515 }
516 HILOGI("Will notify backup result report");
517 extensionPtr->FinishOnProcessTask();
518 extensionPtr->AsyncTaskBackup(extensionPtr->extension_->GetUsrConfig());
519 extensionPtr->AppResultReport(backupExRetInfo, BackupRestoreScenario::FULL_BACKUP);
520 }
521 return;
522 }
523 HILOGE("Call extension onBackupEx failed, errInfo = %{public}s", backupExRetInfo.c_str());
524 extensionPtr->FinishOnProcessTask();
525 if (!backupExRetInfo.empty()) {
526 std::string errInfo;
527 BJsonUtil::BuildExtensionErrInfo(errInfo, errCode, backupExRetInfo);
528 extensionPtr->AppResultReport(errInfo, BackupRestoreScenario::FULL_BACKUP, errCode);
529 }
530 extensionPtr->AppDone(errCode);
531 extensionPtr->DoClear();
532 };
533 }
534
IncOnBackupCallback(wptr<BackupExtExtension> obj)535 std::function<void(ErrCode, const std::string)> BackupExtExtension::IncOnBackupCallback(wptr<BackupExtExtension> obj)
536 {
537 HILOGI("Begin get IncOnBackupCallback");
538 return [obj](ErrCode errCode, std::string errMsg) {
539 HILOGI("App onbackup end");
540 auto proxy = ServiceClient::GetInstance();
541 if (proxy == nullptr) {
542 throw BError(BError::Codes::EXT_BROKEN_BACKUP_SA, std::generic_category().message(errno));
543 }
544 auto extPtr = obj.promote();
545 if (extPtr == nullptr) {
546 HILOGE("Current extension execute call backup error, extPtr is empty");
547 return;
548 }
549 extPtr->OnBackupFinish();
550 if (extPtr->isExecAppDone_.load()) {
551 HILOGE("Appdone has been executed for the current application");
552 return;
553 }
554 HILOGI("Start GetAppLocalListAndDoIncrementalBackup");
555 extPtr->FinishOnProcessTask();
556 if (errCode == ERR_OK) {
557 auto spendTime = extPtr->GetOnStartTimeCost();
558 if (spendTime >= BConstants::MAX_TIME_COST) {
559 AppRadar::Info info(extPtr->bundleName_, "", string("\"spend_time\":\" ").
560 append(to_string(spendTime)).append(string("ms\"")));
561 AppRadar::GetInstance().RecordBackupFuncRes(info, "BackupExtExtension::IncOnBackupCallback",
562 AppRadar::GetInstance().GetUserId(), BizStageBackup::BIZ_STAGE_ON_BACKUP,
563 static_cast<int32_t>(ERR_OK));
564 }
565 proxy->GetAppLocalListAndDoIncrementalBackup();
566 return;
567 }
568 HILOGE("Call extension IncOnBackup failed, errInfo = %{public}s", errMsg.c_str());
569 if (!errMsg.empty()) {
570 std::string errInfo;
571 BJsonUtil::BuildExtensionErrInfo(errInfo, errCode, errMsg);
572 extPtr->AppResultReport(errInfo, BackupRestoreScenario::INCREMENTAL_BACKUP, errCode);
573 }
574 extPtr->AppIncrementalDone(errCode);
575 extPtr->DoClear();
576 };
577 }
578
IncOnBackupExCallback(wptr<BackupExtExtension> obj)579 std::function<void(ErrCode, const std::string)> BackupExtExtension::IncOnBackupExCallback(wptr<BackupExtExtension> obj)
580 {
581 HILOGI("Begin get HandleIncBackupEx callback");
582 return [obj](ErrCode errCode, const std::string backupExRetInfo) {
583 auto proxy = ServiceClient::GetInstance();
584 if (proxy == nullptr) {
585 throw BError(BError::Codes::EXT_BROKEN_BACKUP_SA, std::generic_category().message(errno));
586 }
587 auto extensionPtr = obj.promote();
588 if (extensionPtr == nullptr) {
589 HILOGE("Ext extension handle have been released");
590 return;
591 }
592 extensionPtr->OnBackupExFinish();
593 if (extensionPtr->extension_ == nullptr) {
594 HILOGE("Extension handle have been released");
595 return;
596 }
597 if (extensionPtr->isExecAppDone_.load()) {
598 HILOGE("Appdone has been executed for the current application");
599 return;
600 }
601 extensionPtr->extension_->InvokeAppExtMethod(errCode, backupExRetInfo);
602 if (errCode == ERR_OK) {
603 if (backupExRetInfo.size()) {
604 auto spendTime = extensionPtr->GetOnStartTimeCost();
605 if (spendTime >= BConstants::MAX_TIME_COST) {
606 AppRadar::Info info(extensionPtr->bundleName_, "", string("\"spend_time\":\" ").
607 append(to_string(spendTime)).append(string("ms\"")));
608 AppRadar::GetInstance().RecordBackupFuncRes(info, "BackupExtExtension::IncOnBackupExCallback",
609 AppRadar::GetInstance().GetUserId(), BizStageBackup::BIZ_STAGE_ON_BACKUP,
610 static_cast<int32_t>(ERR_OK));
611 }
612 HILOGI("Start GetAppLocalListAndDoIncrementalBackup");
613 extensionPtr->FinishOnProcessTask();
614 proxy->GetAppLocalListAndDoIncrementalBackup();
615 HILOGI("Will notify backup result report");
616 extensionPtr->AppResultReport(backupExRetInfo, BackupRestoreScenario::INCREMENTAL_BACKUP);
617 }
618 return;
619 }
620 HILOGE("Call extension IncOnBackupEx failed, errInfo = %{public}s", backupExRetInfo.c_str());
621 extensionPtr->FinishOnProcessTask();
622 if (!backupExRetInfo.empty()) {
623 std::string errInfo;
624 BJsonUtil::BuildExtensionErrInfo(errInfo, errCode, backupExRetInfo);
625 extensionPtr->AppResultReport(errInfo, BackupRestoreScenario::INCREMENTAL_BACKUP, errCode);
626 }
627 extensionPtr->AppIncrementalDone(errCode);
628 extensionPtr->DoClear();
629 };
630 }
631
ReportAppProcessInfo(const std::string processInfo,BackupRestoreScenario scenario)632 void BackupExtExtension::ReportAppProcessInfo(const std::string processInfo, BackupRestoreScenario scenario)
633 {
634 auto proxy = ServiceClient::GetInstance();
635 if (proxy == nullptr) {
636 HILOGE("Report app process error, proxy is empty");
637 return;
638 }
639 HILOGI("Will notify backup sa process result");
640 auto ret = proxy->ReportAppProcessInfo(processInfo, scenario);
641 if (ret != ERR_OK) {
642 HILOGE("Report app process error, ipc failed, ret:%{public}d", ret);
643 return;
644 }
645 }
646
StartOnProcessTaskThread(wptr<BackupExtExtension> obj,BackupRestoreScenario scenario)647 ErrCode BackupExtExtension::StartOnProcessTaskThread(wptr<BackupExtExtension> obj, BackupRestoreScenario scenario)
648 {
649 HILOGI("Begin Create onProcess Task Thread");
650 onProcessTimeoutTimer_.Setup();
651 isFirstCallOnProcess_.store(true);
652 StartOnProcessTimeOutTimer(obj, scenario);
653 SyncCallJsOnProcessTask(obj, scenario);
654 if (isExecAppDone_.load()) {
655 HILOGE("Call onProcess timeout, Current extension finished");
656 return BError(BError::Codes::EXT_ABILITY_TIMEOUT);
657 }
658 callJsOnProcessThread_ = std::thread([obj, scenario]() {
659 auto extPtr = obj.promote();
660 if (extPtr == nullptr) {
661 HILOGE("Create onProcess Task thread failed, extPtr is empty");
662 return;
663 }
664 extPtr->ExecCallOnProcessTask(obj, scenario);
665 });
666 HILOGI("End Create onProcess Task End");
667 return BError(BError::Codes::OK);
668 }
669
ExecCallOnProcessTask(wptr<BackupExtExtension> obj,BackupRestoreScenario scenario)670 void BackupExtExtension::ExecCallOnProcessTask(wptr<BackupExtExtension> obj, BackupRestoreScenario scenario)
671 {
672 HILOGI("Begin");
673 isFirstCallOnProcess_.store(false);
674 while (!stopCallJsOnProcess_.load()) {
675 std::unique_lock<std::mutex> lock(onProcessLock_);
676 execOnProcessCon_.wait_for(lock, std::chrono::seconds(BConstants::CALL_APP_ON_PROCESS_TIME_INTERVAL),
677 [this] { return this->stopCallJsOnProcess_.load(); });
678 if (stopCallJsOnProcess_.load()) {
679 HILOGE("Current extension execute js onProcess method finished");
680 return;
681 }
682 HILOGI("Continue call js method onProcess");
683 StartOnProcessTimeOutTimer(obj, scenario);
684 AsyncCallJsOnProcessTask(obj, scenario);
685 }
686 HILOGI("End");
687 }
688
OnBackupFinish()689 void BackupExtExtension::OnBackupFinish()
690 {
691 appStatistic_->onBackupSpend_.End();
692 }
693
OnBackupExFinish()694 void BackupExtExtension::OnBackupExFinish()
695 {
696 appStatistic_->onBackupexSpend_.End();
697 }
698
OnRestoreFinish()699 void BackupExtExtension::OnRestoreFinish()
700 {
701 appStatistic_->onRestoreSpend_.End();
702 }
703
OnRestoreExFinish()704 void BackupExtExtension::OnRestoreExFinish()
705 {
706 appStatistic_->onRestoreexSpend_.End();
707 }
708
DoBackupStart()709 void BackupExtExtension::DoBackupStart()
710 {
711 appStatistic_->doBackupSpend_.Start();
712 }
713
DoBackupEnd()714 void BackupExtExtension::DoBackupEnd()
715 {
716 appStatistic_->doBackupSpend_.End();
717 }
718
AsyncCallJsOnProcessTask(wptr<BackupExtExtension> obj,BackupRestoreScenario scenario)719 void BackupExtExtension::AsyncCallJsOnProcessTask(wptr<BackupExtExtension> obj, BackupRestoreScenario scenario)
720 {
721 HILOGI("Begin");
722 if (stopCallJsOnProcess_.load()) {
723 HILOGE("Current extension execute finished");
724 return;
725 }
726 auto task = [obj, scenario]() {
727 auto extPtr = obj.promote();
728 if (extPtr == nullptr) {
729 HILOGE("Async Call js onProcess error, extPtr is empty");
730 return;
731 }
732 extPtr->SyncCallJsOnProcessTask(obj, scenario);
733 };
734 onProcessTaskPool_.AddTask([task]() { task(); });
735 HILOGI("End");
736 }
737
SyncCallJsOnProcessTask(wptr<BackupExtExtension> obj,BackupRestoreScenario scenario)738 void BackupExtExtension::SyncCallJsOnProcessTask(wptr<BackupExtExtension> obj, BackupRestoreScenario scenario)
739 {
740 HILOGI("Begin");
741 if (stopCallJsOnProcess_.load()) {
742 HILOGE("Current extension execute finished");
743 return;
744 }
745 auto callBack = ReportOnProcessResultCallback(obj, scenario);
746 auto extenionPtr = obj.promote();
747 if (extenionPtr == nullptr || extenionPtr->extension_ == nullptr) {
748 HILOGE("Async call js onProcess failed, extenionPtr is empty");
749 return;
750 }
751 ErrCode ret = extenionPtr->extension_->OnProcess(callBack);
752 if (ret != ERR_OK) {
753 HILOGE("Call OnProcess Failed, ret:%{public}d", ret);
754 return;
755 }
756 HILOGI("End");
757 }
758
FinishOnProcessTask()759 void BackupExtExtension::FinishOnProcessTask()
760 {
761 HILOGI("Begin");
762 std::unique_lock<std::mutex> lock(onProcessLock_);
763 stopCallJsOnProcess_.store(true);
764 isFirstCallOnProcess_.store(false);
765 isExecAppDone_.store(false);
766 onProcessTimeoutCnt_ = 0;
767 execOnProcessCon_.notify_one();
768 lock.unlock();
769 if (callJsOnProcessThread_.joinable()) {
770 callJsOnProcessThread_.join();
771 }
772 HILOGI("End");
773 }
774
StartOnProcessTimeOutTimer(wptr<BackupExtExtension> obj,BackupRestoreScenario scenario)775 void BackupExtExtension::StartOnProcessTimeOutTimer(wptr<BackupExtExtension> obj, BackupRestoreScenario scenario)
776 {
777 HILOGI("Begin");
778 if (stopCallJsOnProcess_.load()) {
779 HILOGE("Current extension execute finished");
780 return;
781 }
782 auto timeoutCallback = [obj, scenario]() {
783 auto extPtr = obj.promote();
784 if (extPtr == nullptr) {
785 HILOGE("Start Create timeout callback failed, extPtr is empty");
786 return;
787 }
788 if (extPtr->onProcessTimeoutCnt_.load() >= BConstants::APP_ON_PROCESS_TIMEOUT_MAX_COUNT ||
789 extPtr->isFirstCallOnProcess_.load()) {
790 HILOGE("The extension invokes the onProcess for more than three times or the first invoking of the "
791 "onProcess times out, timeoutCnt:%{public}d", extPtr->onProcessTimeoutCnt_.load());
792 std::unique_lock<std::mutex> lock(extPtr->onProcessLock_);
793 extPtr->stopCallJsOnProcess_.store(true);
794 extPtr->isFirstCallOnProcess_.store(false);
795 extPtr->isExecAppDone_.store(true);
796 extPtr->onProcessTimeoutCnt_ = 0;
797 extPtr->execOnProcessCon_.notify_one();
798 lock.unlock();
799 if (scenario == BackupRestoreScenario::FULL_BACKUP || scenario == BackupRestoreScenario::FULL_RESTORE) {
800 extPtr->AppDone(BError(BError::Codes::EXT_ABILITY_TIMEOUT));
801 } else if (scenario == BackupRestoreScenario::INCREMENTAL_BACKUP ||
802 scenario == BackupRestoreScenario::INCREMENTAL_RESTORE) {
803 extPtr->AppIncrementalDone(BError(BError::Codes::EXT_ABILITY_TIMEOUT));
804 }
805 return;
806 }
807 extPtr->onProcessTimeoutCnt_++;
808 extPtr->onProcessTimeout_.store(true);
809 HILOGE("Extension onProcess timeout, Increase cnt:%{public}d", extPtr->onProcessTimeoutCnt_.load());
810 };
811 int timeout = isFirstCallOnProcess_.load() ? BConstants::FIRST_CALL_APP_ON_PROCESS_MAX_TIMEOUT :
812 BConstants::APP_ON_PROCESS_MAX_TIMEOUT;
813 uint32_t timerId = onProcessTimeoutTimer_.Register(timeoutCallback, timeout, true);
814 onProcessTimeoutTimerId_ = timerId;
815 HILOGI("End");
816 }
817
CloseOnProcessTimeOutTimer()818 void BackupExtExtension::CloseOnProcessTimeOutTimer()
819 {
820 HILOGI("Begin");
821 onProcessTimeoutTimer_.Unregister(onProcessTimeoutTimerId_);
822 HILOGI("End");
823 }
824
AppIncrementalDone(ErrCode errCode)825 void BackupExtExtension::AppIncrementalDone(ErrCode errCode)
826 {
827 HILOGI("Begin");
828 ReportAppStatistic("AppIncrementalDone", errCode);
829 auto proxy = ServiceClient::GetInstance();
830 if (proxy == nullptr) {
831 HILOGE("Failed to obtain the ServiceClient handle");
832 DoClear();
833 return;
834 }
835 auto ret = proxy->AppIncrementalDone(errCode);
836 if (ret != ERR_OK) {
837 HILOGE("Failed to notify the app done. err = %{public}d", ret);
838 }
839 if (HandleGetExtOnRelease()) {
840 HandleExtOnRelease(false, errCode);
841 }
842 }
843
GetBackupInfo(std::string & result)844 ErrCode BackupExtExtension::GetBackupInfo(std::string &result)
845 {
846 auto obj = wptr<BackupExtExtension>(this);
847 auto ptr = obj.promote();
848 if (ptr == nullptr) {
849 HILOGE("Failed to get ext extension.");
850 return BError(BError::Codes::EXT_INVAL_ARG, "extension getBackupInfo exception").GetCode();
851 }
852 if (ptr->extension_ == nullptr) {
853 HILOGE("Failed to get extension.");
854 return BError(BError::Codes::EXT_INVAL_ARG, "extension getBackupInfo exception").GetCode();
855 }
856 auto callBackup = [ptr](ErrCode errCode, const std::string result) {
857 if (ptr == nullptr) {
858 HILOGE("Failed to get ext extension.");
859 return;
860 }
861 HILOGI("GetBackupInfo callBackup start. errCode = %{public}d, result = %{public}s", errCode, result.c_str());
862 if (errCode == ERR_OK) {
863 ptr->backupInfo_ = result;
864 }
865 };
866 auto ret = ptr->extension_->GetBackupInfo(callBackup);
867 if (ret != ERR_OK) {
868 HILOGE("Failed to get backupInfo. err = %{public}d", ret);
869 return BError(BError::Codes::EXT_INVAL_ARG, "extension getBackupInfo exception").GetCode();
870 }
871 HILOGD("backupInfo = %s", backupInfo_.c_str());
872 result = backupInfo_;
873 backupInfo_.clear();
874
875 return ERR_OK;
876 }
877
UpdateFdSendRate(const std::string & bundleName,int32_t sendRate)878 ErrCode BackupExtExtension::UpdateFdSendRate(const std::string &bundleName, int32_t sendRate)
879 {
880 try {
881 std::lock_guard<std::mutex> lock(updateSendRateLock_);
882 HILOGI("Update SendRate, bundleName:%{public}s, sendRate:%{public}d", bundleName.c_str(), sendRate);
883 VerifyCaller();
884 bundleName_ = bundleName;
885 sendRate_ = sendRate;
886 if (sendRate > 0) {
887 appStatistic_->UpdateSendRateZeroSpend();
888 startSendFdRateCon_.notify_one();
889 } else {
890 appStatistic_->sendRateZeroStart_ = TimeUtils::GetTimeUS();
891 }
892 return ERR_OK;
893 } catch (...) {
894 HILOGE("Failed to UpdateFdSendRate");
895 return BError(BError::Codes::EXT_BROKEN_IPC).GetCode();
896 }
897 }
898
UpdateDfxInfo(int64_t uniqId,uint32_t extConnectSpend,const std::string & bundleName)899 ErrCode BackupExtExtension::UpdateDfxInfo(int64_t uniqId, uint32_t extConnectSpend, const std::string &bundleName)
900 {
901 appStatistic_->SetUniqId(uniqId);
902 appStatistic_->extConnectSpend_ = extConnectSpend;
903 appStatistic_->appCaller_ = bundleName;
904 return ERR_OK;
905 }
906
SetStagingPathProperties()907 bool BackupExtExtension::SetStagingPathProperties()
908 {
909 struct stat curBundleStat {};
910 if (lstat(BConstants::BUNDLE_BASE_DIR.c_str(), &curBundleStat) != 0) {
911 HILOGE("Failed to lstat, err = %{public}d", errno);
912 return false;
913 }
914 if (lchown(string(BConstants::PATH_BUNDLE_BACKUP_HOME).c_str(),
915 curBundleStat.st_uid, curBundleStat.st_gid) != 0) {
916 HILOGE("Failed to lchown, err = %{public}d", errno);
917 return false;
918 }
919 if (lchown(string(BConstants::PATH_BUNDLE_BACKUP_HOME_EL1).c_str(),
920 curBundleStat.st_uid, curBundleStat.st_gid) != 0) {
921 HILOGE("Failed to lchown, err = %{public}d", errno);
922 return false;
923 }
924 return true;
925 }
926
IfAllowToBackupRestore()927 bool BackupExtExtension::IfAllowToBackupRestore()
928 {
929 if (extension_ == nullptr) {
930 HILOGE("Failed to handle backup, extension is nullptr");
931 return false;
932 }
933 string usrConfig = extension_->GetUsrConfig();
934 BJsonCachedEntity<BJsonEntityExtensionConfig> cachedEntity(usrConfig);
935 auto cache = cachedEntity.Structuralize();
936 if (!cache.GetAllowToBackupRestore()) {
937 HILOGE("Application does not allow backup or restore");
938 return false;
939 }
940 return true;
941 }
942
User0OnBackup()943 ErrCode BackupExtExtension::User0OnBackup()
944 {
945 HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
946 if (!IfAllowToBackupRestore()) {
947 return BError(BError::Codes::EXT_FORBID_BACKUP_RESTORE, "Application does not allow backup or restore")
948 .GetCode();
949 }
950 AsyncTaskUser0Backup();
951 return ERR_OK;
952 }
953
AsyncTaskUser0Backup()954 void BackupExtExtension::AsyncTaskUser0Backup()
955 {
956 HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
957 auto task = [obj {wptr<BackupExtExtension>(this)}]() {
958 auto ptr = obj.promote();
959 BExcepUltils::BAssert(ptr, BError::Codes::EXT_BROKEN_FRAMEWORK, "Ext extension handle have been released");
960 BExcepUltils::BAssert(ptr->extension_, BError::Codes::EXT_INVAL_ARG, "Extension handle have been released");
961 const string config = ptr->extension_->GetUsrConfig();
962 try {
963 HILOGI("Do backup, start fwk timer begin.");
964 bool isFwkStart;
965 ptr->StartFwkTimer(isFwkStart);
966 if (!isFwkStart) {
967 HILOGE("Do backup, start fwk timer fail.");
968 return;
969 }
970 HILOGI("Do backup, start fwk timer end.");
971 BJsonCachedEntity<BJsonEntityExtensionConfig> cachedEntity(config);
972 auto cache = cachedEntity.Structuralize();
973 auto ret = ptr->User0DoBackup(cache);
974 if (ret != ERR_OK) {
975 HILOGE("User0DoBackup, err = %{public}d", ret);
976 ptr->AppIncrementalDone(BError::GetCodeByErrno(ret));
977 }
978 } catch (const BError &e) {
979 HILOGE("extension: AsyncTaskBackup error, err code:%{public}d", e.GetCode());
980 ptr->AppIncrementalDone(e.GetCode());
981 } catch (const exception &e) {
982 HILOGE("Catched an unexpected low-level exception %{public}s", e.what());
983 ptr->AppIncrementalDone(BError(BError::Codes::EXT_INVAL_ARG).GetCode());
984 } catch (...) {
985 HILOGE("Failed to restore the ext bundle");
986 ptr->AppIncrementalDone(BError(BError::Codes::EXT_INVAL_ARG).GetCode());
987 }
988 };
989
990 threadPool_.AddTask([task]() {
991 try {
992 task();
993 } catch (...) {
994 HILOGE("Failed to add task to thread pool");
995 }
996 });
997 }
998
DoUser0Backup(const BJsonEntityExtensionConfig & usrConfig)999 void BackupExtExtension::DoUser0Backup(const BJsonEntityExtensionConfig &usrConfig)
1000 {
1001 HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
1002 string path = string(BConstants::PATH_BUNDLE_BACKUP_HOME).append(BConstants::SA_BUNDLE_BACKUP_BACKUP);
1003 if (mkdir(path.data(), S_IRWXU) && errno != EEXIST) {
1004 throw BError(errno);
1005 }
1006 vector<string> includes = usrConfig.GetIncludes();
1007 vector<string> excludes = usrConfig.GetExcludes();
1008 auto task = [obj {wptr<BackupExtExtension>(this)}, includes, excludes]() {
1009 auto ptr = obj.promote();
1010 BExcepUltils::BAssert(ptr, BError::Codes::EXT_BROKEN_FRAMEWORK, "Ext extension handle have been released");
1011 try {
1012 auto [bigFile, smallFile] = BDir::GetBackupList(includes, excludes);
1013 vector<struct ReportFileInfo> allFiles;
1014 vector<struct ReportFileInfo> smallFiles;
1015 vector<struct ReportFileInfo> bigFiles;
1016 BDir::GetUser0FileStat(move(bigFile), move(smallFile), allFiles, smallFiles, bigFiles);
1017 auto ret = ptr->DoIncrementalBackup(allFiles, smallFiles, bigFiles);
1018 ptr->AppIncrementalDone(ret);
1019 HILOGI("User0 backup app done %{public}d", ret);
1020 } catch (const BError &e) {
1021 ptr->AppIncrementalDone(e.GetCode());
1022 } catch (const exception &e) {
1023 ptr->AppIncrementalDone(BError(BError::Codes::EXT_INVAL_ARG).GetCode());
1024 } catch (...) {
1025 HILOGE("Failed to restore the ext bundle");
1026 ptr->AppIncrementalDone(BError(BError::Codes::EXT_INVAL_ARG).GetCode());
1027 }
1028 };
1029
1030 threadPool_.AddTask([task]() {
1031 try {
1032 task();
1033 } catch (...) {
1034 HILOGE("Failed to add task to thread pool");
1035 }
1036 });
1037 }
1038
User0DoBackup(const BJsonEntityExtensionConfig & usrConfig)1039 int BackupExtExtension::User0DoBackup(const BJsonEntityExtensionConfig &usrConfig)
1040 {
1041 HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
1042 HILOGI("Start Do User0Backup");
1043 if (extension_ == nullptr) {
1044 HILOGE("Failed to do backup, extension is nullptr");
1045 return BError(BError::Codes::EXT_INVAL_ARG);
1046 }
1047 if (extension_->GetExtensionAction() != BConstants::ExtensionAction::BACKUP) {
1048 return EPERM;
1049 }
1050 DoUser0Backup(usrConfig);
1051 return ERR_OK;
1052 }
1053
UpdateFileStat(std::string filePath,uint64_t fileSize)1054 void BackupExtExtension::UpdateFileStat(std::string filePath, uint64_t fileSize)
1055 {
1056 appStatistic_->UpdateFileDist(ExtractFileExt(filePath), fileSize);
1057 uint32_t dirDepth = 0;
1058 const char* pstr = filePath.c_str();
1059 char pre = '-';
1060 uint32_t pathLen = filePath.size();
1061 for (uint32_t i = 0; i < pathLen; i++) {
1062 if (pstr[i] == '/' && pre != '/') {
1063 dirDepth++;
1064 }
1065 pre = pstr[i];
1066 }
1067 if (dirDepth > appStatistic_->dirDepth_) {
1068 appStatistic_->dirDepth_ = dirDepth;
1069 }
1070 }
1071
1072 /**
1073 * 获取增量的大文件的信息
1074 */
GetIncrmentBigInfos(const vector<struct ReportFileInfo> & files)1075 TarMap BackupExtExtension::GetIncrmentBigInfos(const vector<struct ReportFileInfo> &files)
1076 {
1077 auto getStringHash = [](const TarMap &tarMap, const string &str) -> string {
1078 ostringstream strHex;
1079 strHex << hex;
1080
1081 hash<string> strHash;
1082 size_t szHash = strHash(str);
1083 strHex << setfill('0') << setw(BConstants::BIG_FILE_NAME_SIZE) << szHash;
1084 string name = strHex.str();
1085 for (int i = 0; tarMap.find(name) != tarMap.end(); ++i, strHex.str("")) {
1086 szHash = strHash(str + to_string(i));
1087 strHex << setfill('0') << setw(BConstants::BIG_FILE_NAME_SIZE) << szHash;
1088 name = strHex.str();
1089 }
1090
1091 return name;
1092 };
1093
1094 TarMap bigFiles;
1095 for (const auto &item : files) {
1096 struct stat sta = {};
1097 if (stat(item.filePath.c_str(), &sta) != 0) {
1098 HILOGE("Failed to stat file %{public}s, err = %{public}d", item.filePath.c_str(), errno);
1099 throw errno;
1100 }
1101 appStatistic_->bigFileSize_ += static_cast<uint64_t>(sta.st_size);
1102 UpdateFileStat(item.filePath, sta.st_size);
1103 uint64_t hashStart = static_cast<uint64_t>(TimeUtils::GetTimeUS());
1104 string md5Name = getStringHash(bigFiles, item.filePath);
1105 appStatistic_->hashSpendUS_ += TimeUtils::GetSpendUS(hashStart);
1106 if (!md5Name.empty()) {
1107 bigFiles.emplace(md5Name, make_tuple(item.filePath, sta, true));
1108 }
1109 }
1110
1111 return bigFiles;
1112 }
1113
DoIncrementalBackupTask(UniqueFd incrementalFd,UniqueFd manifestFd)1114 int BackupExtExtension::DoIncrementalBackupTask(UniqueFd incrementalFd, UniqueFd manifestFd)
1115 {
1116 auto start = std::chrono::system_clock::now();
1117 vector<struct ReportFileInfo> allFiles;
1118 vector<struct ReportFileInfo> smallFiles;
1119 vector<struct ReportFileInfo> bigFiles;
1120 appStatistic_->doBackupSpend_.Start();
1121 FillFileInfos(move(incrementalFd), move(manifestFd), allFiles, smallFiles, bigFiles);
1122 auto ret = DoIncrementalBackup(allFiles, smallFiles, bigFiles);
1123 appStatistic_->doBackupSpend_.End();
1124 if (ret == ERR_OK) {
1125 auto end = std::chrono::system_clock::now();
1126 auto cost = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
1127 if (cost >= BConstants::MAX_TIME_COST) {
1128 std::stringstream ss;
1129 ss << R"("spendTime": )"<< cost << R"(ms, "totalFiles": )" << allFiles.size() << R"(, "smallFiles": )"
1130 << smallFiles.size() << R"(, "bigFiles": )" << bigFiles.size();
1131 AppRadar::Info info(bundleName_, "", ss.str());
1132 AppRadar::GetInstance().RecordBackupFuncRes(info, "BackupExtExtension::DoIncrementalBackupTask",
1133 AppRadar::GetInstance().GetUserId(), BizStageBackup::BIZ_STAGE_DO_BACKUP, static_cast<int32_t>(ret));
1134 }
1135 }
1136 return ret;
1137 }
1138
AsyncTaskDoIncrementalBackup(UniqueFd incrementalFd,UniqueFd manifestFd)1139 void BackupExtExtension::AsyncTaskDoIncrementalBackup(UniqueFd incrementalFd, UniqueFd manifestFd)
1140 {
1141 HILOGI("Do IncrementalBackup, start fwk timer begin.");
1142 bool isFwkStart;
1143 StartFwkTimer(isFwkStart);
1144 if (!isFwkStart) {
1145 HILOGE("Do IncrementalBackup, start fwk timer fail.");
1146 return;
1147 }
1148 HILOGI("Do IncrementalBackup, start fwk timer end.");
1149 int incrementalFdDup = dup(incrementalFd);
1150 int manifestFdDup = dup(manifestFd);
1151 if (incrementalFdDup < 0) {
1152 throw BError(BError::Codes::EXT_INVAL_ARG, "dup failed");
1153 }
1154 auto task = [obj {wptr<BackupExtExtension>(this)}, manifestFdDup, incrementalFdDup]() {
1155 auto ptr = obj.promote();
1156 BExcepUltils::BAssert(ptr, BError::Codes::EXT_BROKEN_FRAMEWORK, "Ext extension handle have been released");
1157 try {
1158 UniqueFd incrementalDupFd(dup(incrementalFdDup));
1159 UniqueFd manifestDupFd(dup(manifestFdDup));
1160 if (incrementalDupFd < 0) {
1161 throw BError(BError::Codes::EXT_INVAL_ARG, "dup failed");
1162 }
1163 close(incrementalFdDup);
1164 close(manifestFdDup);
1165 auto ret = ptr->DoIncrementalBackupTask(move(incrementalDupFd), move(manifestDupFd));
1166 ptr->AppIncrementalDone(ret);
1167 HILOGI("Incremental backup app done %{public}d", ret);
1168 } catch (const BError &e) {
1169 ptr->AppIncrementalDone(e.GetCode());
1170 } catch (const exception &e) {
1171 HILOGE("Catched an unexpected low-level exception %{public}s", e.what());
1172 ptr->AppIncrementalDone(BError(BError::Codes::EXT_INVAL_ARG).GetCode());
1173 } catch (...) {
1174 HILOGE("Failed to restore the ext bundle");
1175 ptr->AppIncrementalDone(BError(BError::Codes::EXT_INVAL_ARG).GetCode());
1176 }
1177 };
1178
1179 threadPool_.AddTask([task]() {
1180 try {
1181 task();
1182 } catch (...) {
1183 HILOGE("Failed to add task to thread pool");
1184 }
1185 });
1186 }
1187
AsyncTaskOnIncrementalBackup()1188 void BackupExtExtension::AsyncTaskOnIncrementalBackup()
1189 {
1190 auto task = [obj {wptr<BackupExtExtension>(this)}]() {
1191 auto ptr = obj.promote();
1192 BExcepUltils::BAssert(ptr, BError::Codes::EXT_BROKEN_FRAMEWORK, "Ext extension handle have been released");
1193 BExcepUltils::BAssert(ptr->extension_, BError::Codes::EXT_INVAL_ARG, "Extension handle have been released");
1194 try {
1195 if ((ptr->StartOnProcessTaskThread(obj, BackupRestoreScenario::INCREMENTAL_BACKUP)) != ERR_OK) {
1196 HILOGE("Call onProcess result is timeout");
1197 return;
1198 }
1199 auto callBackup = ptr->IncOnBackupCallback(obj);
1200 auto callBackupEx = ptr->IncOnBackupExCallback(obj);
1201 ptr->UpdateOnStartTime();
1202 ErrCode err = ptr->extension_->OnBackup(callBackup, callBackupEx);
1203 if (err != ERR_OK) {
1204 HILOGE("OnBackup done, err = %{public}d", err);
1205 ptr->AppIncrementalDone(BError::GetCodeByErrno(err));
1206 }
1207 } catch (const BError &e) {
1208 ptr->AppIncrementalDone(e.GetCode());
1209 } catch (const exception &e) {
1210 HILOGE("Catched an unexpected low-level exception %{public}s", e.what());
1211 ptr->AppIncrementalDone(BError(BError::Codes::EXT_INVAL_ARG).GetCode());
1212 } catch (...) {
1213 HILOGE("Failed to restore the ext bundle");
1214 ptr->AppIncrementalDone(BError(BError::Codes::EXT_INVAL_ARG).GetCode());
1215 }
1216 };
1217
1218 threadPool_.AddTask([task]() {
1219 try {
1220 task();
1221 } catch (...) {
1222 HILOGE("Failed to add task to thread pool");
1223 }
1224 });
1225 }
1226
GetIncrmentPartName()1227 static string GetIncrmentPartName()
1228 {
1229 auto now = chrono::system_clock::now();
1230 auto duration = now.time_since_epoch();
1231 auto milliseconds = chrono::duration_cast<chrono::milliseconds>(duration);
1232
1233 return to_string(milliseconds.count()) + "_part";
1234 }
1235
UpdateTarStat(uint64_t tarFileSize)1236 void BackupExtExtension::UpdateTarStat(uint64_t tarFileSize)
1237 {
1238 appStatistic_->tarFileCount_++;
1239 appStatistic_->tarFileSize_ += tarFileSize;
1240 }
1241
IncrementalPacket(const vector<struct ReportFileInfo> & infos,TarMap & tar,sptr<IService> proxy)1242 void BackupExtExtension::IncrementalPacket(const vector<struct ReportFileInfo> &infos, TarMap &tar,
1243 sptr<IService> proxy)
1244 {
1245 HILOGI("IncrementalPacket begin, infos count: %{public}zu", infos.size());
1246 string path = string(BConstants::PATH_BUNDLE_BACKUP_HOME).append(BConstants::SA_BUNDLE_BACKUP_BACKUP);
1247 uint64_t totalSize = 0;
1248 uint32_t fileCount = 0;
1249 vector<string> packFiles;
1250 vector<struct ReportFileInfo> tarInfos;
1251 TarFile::GetInstance().SetPacketMode(true); // 设置下打包模式
1252 auto startTime = std::chrono::system_clock::now();
1253 int fdNum = 0;
1254 string partName = GetIncrmentPartName();
1255 auto reportCb = ReportErrFileByProc(wptr<BackupExtExtension> {this}, curScenario_);
1256 uint64_t tarStart = static_cast<uint64_t>(TimeUtils::GetTimeMS());
1257 for (const auto &small : infos) {
1258 appStatistic_->smallFileSize_ += small.size;
1259 UpdateFileStat(small.filePath, small.size);
1260 totalSize += static_cast<uint64_t>(small.size);
1261 fileCount += 1;
1262 packFiles.emplace_back(small.filePath);
1263 tarInfos.emplace_back(small);
1264 if (totalSize >= BConstants::DEFAULT_SLICE_SIZE || fileCount >= BConstants::MAX_FILE_COUNT) {
1265 TarMap tarMap {};
1266 TarFile::GetInstance().Packet(packFiles, partName, path, tarMap, reportCb);
1267 UpdateTarStat(TarFile::GetInstance().GetTarFileSize());
1268 tar.insert(tarMap.begin(), tarMap.end());
1269 // 执行tar包回传功能
1270 WaitToSendFd(startTime, fdNum);
1271 IncrementalTarFileReady(tarMap, tarInfos, proxy);
1272 totalSize = 0;
1273 fileCount = 0;
1274 packFiles.clear();
1275 tarInfos.clear();
1276 fdNum += BConstants::FILE_AND_MANIFEST_FD_COUNT;
1277 RefreshTimeInfo(startTime, fdNum);
1278 }
1279 }
1280 if (fileCount > 0) {
1281 // 打包回传
1282 TarMap tarMap {};
1283 TarFile::GetInstance().Packet(packFiles, partName, path, tarMap, reportCb);
1284 UpdateTarStat(TarFile::GetInstance().GetTarFileSize());
1285 IncrementalTarFileReady(tarMap, tarInfos, proxy);
1286 fdNum = 1;
1287 WaitToSendFd(startTime, fdNum);
1288 tar.insert(tarMap.begin(), tarMap.end());
1289 packFiles.clear();
1290 tarInfos.clear();
1291 RefreshTimeInfo(startTime, fdNum);
1292 }
1293 appStatistic_->tarSpend_ = TimeUtils::GetSpendMS(tarStart);
1294 }
1295
DoIncrementalBackup(const vector<struct ReportFileInfo> & allFiles,const vector<struct ReportFileInfo> & smallFiles,const vector<struct ReportFileInfo> & bigFiles)1296 int BackupExtExtension::DoIncrementalBackup(const vector<struct ReportFileInfo> &allFiles,
1297 const vector<struct ReportFileInfo> &smallFiles,
1298 const vector<struct ReportFileInfo> &bigFiles)
1299 {
1300 HILOGI("Do increment backup begin");
1301 if (extension_ == nullptr) {
1302 HILOGE("Failed to do incremental backup, extension is nullptr");
1303 throw BError(BError::Codes::EXT_INVAL_ARG, "Extension is nullptr");
1304 }
1305 if (extension_->GetExtensionAction() != BConstants::ExtensionAction::BACKUP) {
1306 return EPERM;
1307 }
1308 string path = string(BConstants::PATH_BUNDLE_BACKUP_HOME).append(BConstants::SA_BUNDLE_BACKUP_BACKUP);
1309 if (mkdir(path.data(), S_IRWXU) && errno != EEXIST) {
1310 throw BError(errno);
1311 }
1312 auto proxy = ServiceClient::GetInstance();
1313 if (proxy == nullptr) {
1314 throw BError(BError::Codes::EXT_BROKEN_BACKUP_SA, std::generic_category().message(errno));
1315 }
1316 // 获取增量文件和全量数据
1317 if (smallFiles.empty() && bigFiles.empty()) {
1318 // 没有增量,则不需要上传
1319 TarMap tMap;
1320 ErrCode err = IncrementalAllFileReady(tMap, allFiles, proxy);
1321 HILOGI("Do increment backup, IncrementalAllFileReady end, file empty");
1322 return err;
1323 }
1324 // tar包数据
1325 TarMap tarMap;
1326 IncrementalPacket(smallFiles, tarMap, proxy);
1327 HILOGI("Do increment backup, IncrementalPacket end");
1328 // 最后回传大文件
1329 TarMap bigMap = GetIncrmentBigInfos(bigFiles);
1330 IncrementalBigFileReady(bigMap, bigFiles, proxy);
1331 HILOGI("Do increment backup, IncrementalBigFileReady end");
1332 bigMap.insert(tarMap.begin(), tarMap.end());
1333 // 回传manage.json和全量文件
1334 ErrCode err = IncrementalAllFileReady(bigMap, allFiles, proxy);
1335 HILOGI("End, bigFiles num:%{public}zu, smallFiles num:%{public}zu, allFiles num:%{public}zu", bigFiles.size(),
1336 smallFiles.size(), allFiles.size());
1337 return err;
1338 }
1339
ReportOnProcessResultCallback(wptr<BackupExtExtension> obj,BackupRestoreScenario scenario)1340 std::function<void(ErrCode, std::string)> BackupExtExtension::ReportOnProcessResultCallback(
1341 wptr<BackupExtExtension> obj, BackupRestoreScenario scenario)
1342 {
1343 return [obj, scenario](ErrCode errCode, const std::string processInfo) {
1344 auto extPtr = obj.promote();
1345 if (extPtr == nullptr) {
1346 HILOGE("Async call js onPreocess callback failed, exPtr is empty");
1347 return;
1348 }
1349 if (extPtr->onProcessTimeout_.load()) {
1350 HILOGE("The result of invoking onProcess is timeout.");
1351 extPtr->onProcessTimeout_.store(false);
1352 return;
1353 }
1354 extPtr->CloseOnProcessTimeOutTimer();
1355 extPtr->isFirstCallOnProcess_.store(false);
1356 extPtr->onProcessTimeout_.store(false);
1357 if (extPtr->onProcessTimeoutCnt_.load() > 0) {
1358 extPtr->onProcessTimeoutCnt_ = 0;
1359 HILOGI("onProcess execute success, reset onProcessTimeoutCnt");
1360 }
1361 if (processInfo.size() == 0) {
1362 HILOGE("Current extension has no js method named onProcess.");
1363 std::unique_lock<std::mutex> lock(extPtr->onProcessLock_);
1364 extPtr->isFirstCallOnProcess_.store(false);
1365 extPtr->stopCallJsOnProcess_.store(true);
1366 extPtr->execOnProcessCon_.notify_one();
1367 lock.unlock();
1368 return;
1369 }
1370 std::string processInfoJsonStr;
1371 BJsonUtil::BuildOnProcessRetInfo(processInfoJsonStr, processInfo);
1372 auto task = [obj, scenario, processInfoJsonStr]() {
1373 auto reportExtPtr = obj.promote();
1374 if (reportExtPtr == nullptr) {
1375 HILOGE("Report onProcess Result error, reportExtPtr is empty");
1376 return;
1377 }
1378 reportExtPtr->ReportAppProcessInfo(processInfoJsonStr, scenario);
1379 };
1380 extPtr->reportOnProcessRetPool_.AddTask([task]() { task(); });
1381 };
1382 }
1383
FillFileInfosWithoutCmp(vector<struct ReportFileInfo> & allFiles,vector<struct ReportFileInfo> & smallFiles,vector<struct ReportFileInfo> & bigFiles,UniqueFd incrementalFd)1384 void BackupExtExtension::FillFileInfosWithoutCmp(vector<struct ReportFileInfo> &allFiles,
1385 vector<struct ReportFileInfo> &smallFiles,
1386 vector<struct ReportFileInfo> &bigFiles,
1387 UniqueFd incrementalFd)
1388 {
1389 HILOGI("Fill file info without cmp begin");
1390 BReportEntity storageRp(move(incrementalFd));
1391 unordered_map<string, struct ReportFileInfo> localFilesInfo;
1392 while (storageRp.GetStorageReportInfos(localFilesInfo)) {
1393 for (auto localIter = localFilesInfo.begin(); localIter != localFilesInfo.end(); ++localIter) {
1394 const string &path = localIter->second.filePath;
1395 if (path.empty()) {
1396 HILOGE("GetStorageReportInfos failed");
1397 continue;
1398 }
1399 if (localIter->second.isIncremental && localIter->second.isDir) {
1400 smallFiles.emplace_back(localIter->second);
1401 }
1402 if (localIter->second.isDir) {
1403 allFiles.emplace_back(localIter->second);
1404 continue;
1405 }
1406 auto [res, fileHash] = BackupFileHash::HashWithSHA256(path);
1407 if (fileHash.empty()) {
1408 HILOGE("Do hash err, fileHash is empty, path: %{public}s", GetAnonyPath(path).c_str());
1409 continue;
1410 }
1411 localIter->second.hash = fileHash;
1412 if (ExtractFileExt(path) == "tar") {
1413 localIter->second.userTar = 1; // 1: default value, means true
1414 }
1415 allFiles.emplace_back(localIter->second);
1416 if (!localIter->second.isIncremental) {
1417 HILOGE("It's not incre, no need record %{public}s", GetAnonyPath(path).c_str());
1418 continue;
1419 }
1420 if (localIter->second.size <= BConstants::BIG_FILE_BOUNDARY) {
1421 smallFiles.emplace_back(localIter->second);
1422 continue;
1423 }
1424 bigFiles.emplace_back(localIter->second);
1425 }
1426 localFilesInfo.clear();
1427 }
1428 }
1429
FillFileInfosWithCmp(vector<struct ReportFileInfo> & allFiles,vector<struct ReportFileInfo> & smallFiles,vector<struct ReportFileInfo> & bigFiles,const unordered_map<string,struct ReportFileInfo> & cloudFiles,UniqueFd incrementalFd)1430 void BackupExtExtension::FillFileInfosWithCmp(vector<struct ReportFileInfo> &allFiles,
1431 vector<struct ReportFileInfo> &smallFiles,
1432 vector<struct ReportFileInfo> &bigFiles,
1433 const unordered_map<string, struct ReportFileInfo> &cloudFiles,
1434 UniqueFd incrementalFd)
1435 {
1436 HILOGI("Fill file info with cmp begin");
1437 BReportEntity storageRp(move(incrementalFd));
1438 unordered_map<string, struct ReportFileInfo> localFilesInfo;
1439 while (storageRp.GetStorageReportInfos(localFilesInfo)) {
1440 CompareFiles(allFiles, smallFiles, bigFiles, cloudFiles, localFilesInfo);
1441 localFilesInfo.clear();
1442 }
1443 }
1444
CompareFiles(vector<struct ReportFileInfo> & allFiles,vector<struct ReportFileInfo> & smallFiles,vector<struct ReportFileInfo> & bigFiles,const unordered_map<string,struct ReportFileInfo> & cloudFiles,unordered_map<string,struct ReportFileInfo> & localFilesInfo)1445 void BackupExtExtension::CompareFiles(vector<struct ReportFileInfo> &allFiles,
1446 vector<struct ReportFileInfo> &smallFiles,
1447 vector<struct ReportFileInfo> &bigFiles,
1448 const unordered_map<string, struct ReportFileInfo> &cloudFiles,
1449 unordered_map<string, struct ReportFileInfo> &localFilesInfo)
1450 {
1451 for (auto localIter = localFilesInfo.begin(); localIter != localFilesInfo.end(); ++localIter) {
1452 // 进行文件对比, 当后续使用 isUserTar 字段时需注意 字段解析函数
1453 const string &path = localIter->second.filePath;
1454 if (path.empty()) {
1455 HILOGE("GetStorageReportInfos failed");
1456 continue;
1457 }
1458 auto it = cloudFiles.find(path);
1459 bool isExist = (it != cloudFiles.end());
1460 if (localIter->second.isIncremental && !isExist && localIter->second.isDir) {
1461 smallFiles.emplace_back(localIter->second);
1462 }
1463 if (localIter->second.isDir) {
1464 allFiles.emplace_back(localIter->second);
1465 continue;
1466 }
1467 bool isChange = !(isExist && localIter->second.size == it->second.size &&
1468 localIter->second.mtime == it->second.mtime);
1469 if (isChange) {
1470 auto [res, fileHash] = BackupFileHash::HashWithSHA256(path);
1471 if (fileHash.empty()) {
1472 HILOGE("Do hash err, fileHash is empty");
1473 continue;
1474 }
1475 localIter->second.hash = fileHash;
1476 } else {
1477 localIter->second.hash = it->second.hash;
1478 }
1479
1480 if (ExtractFileExt(path) == "tar") {
1481 localIter->second.userTar = 1; // 1: default value, means true
1482 }
1483
1484 allFiles.emplace_back(localIter->second);
1485 if (localIter->second.isIncremental && (!isExist ||
1486 it->second.hash != localIter->second.hash)) {
1487 // 在云空间简报里不存在或者hash不一致
1488 if (localIter->second.size <= BConstants::BIG_FILE_BOUNDARY) {
1489 smallFiles.emplace_back(localIter->second);
1490 continue;
1491 }
1492 bigFiles.emplace_back(localIter->second);
1493 }
1494 }
1495 }
1496
IfCloudSpecialRestore(string tarName)1497 bool BackupExtExtension::IfCloudSpecialRestore(string tarName)
1498 {
1499 unordered_map<string, struct ReportFileInfo> result;
1500 GetTarIncludes(tarName, result);
1501 if (result.empty()) {
1502 HILOGI("is not CloudSpecialRestore");
1503 return false;
1504 }
1505 HILOGI("is CloudSpecialRestore");
1506 return true;
1507 }
1508
CloudSpecialRestore(string tarName,string untarPath,off_t tarFileSize)1509 ErrCode BackupExtExtension::CloudSpecialRestore(string tarName, string untarPath, off_t tarFileSize)
1510 {
1511 unordered_map<string, struct ReportFileInfo> result;
1512 GetTarIncludes(tarName, result);
1513 if (isDebug_) {
1514 FillEndFileInfos(untarPath, result);
1515 }
1516 auto unPacketRes = UntarFile::GetInstance().IncrementalUnPacket(tarName, untarPath, result);
1517 ErrCode err = ERR_OK;
1518 err = std::get<FIRST_PARAM>(unPacketRes);
1519 DealIncreUnPacketResult(tarFileSize, tarName, unPacketRes);
1520 HILOGI("Application recovered successfully, package path is %{public}s", tarName.c_str());
1521 DeleteBackupIncrementalTars(tarName);
1522 return err;
1523 }
1524
RmBigFileReportForSpecialCloneCloud(const std::string & srcFileName)1525 void BackupExtExtension::RmBigFileReportForSpecialCloneCloud(const std::string &srcFileName)
1526 {
1527 // 删除大文件的rp文件
1528 string reportFileName = GetReportFileName(srcFileName);
1529 std::unique_lock<std::mutex> lock(reportHashLock_);
1530 if (reportHashSrcPathMap_.empty()) {
1531 if (!RemoveFile(reportFileName)) {
1532 HILOGE("Failed to delete backup report %{public}s, err = %{public}d",
1533 GetAnonyPath(reportFileName).c_str(), errno);
1534 }
1535 return;
1536 }
1537 auto iter = reportHashSrcPathMap_.find(srcFileName);
1538 if (iter == reportHashSrcPathMap_.end()) {
1539 if (!RemoveFile(reportFileName)) {
1540 HILOGE("Failed to remove cuurent file report %{public}s, err = %{public}d",
1541 GetAnonyPath(reportFileName).c_str(), errno);
1542 }
1543 return;
1544 }
1545 std::string reportHashFilePath = iter->second;
1546 HILOGI("Will remove current reportHashFile, reportHashFilePath:%{public}s",
1547 GetAnonyPath(reportHashFilePath).c_str());
1548 if (!RemoveFile(reportHashFilePath)) {
1549 HILOGE("Failed to delete backup report %{public}s, err = %{public}d",
1550 GetAnonyPath(reportHashFilePath).c_str(), errno);
1551 }
1552 reportHashSrcPathMap_.erase(iter);
1553 }
1554
CalculateDataSizeTask(const string & config)1555 void BackupExtExtension::CalculateDataSizeTask(const string &config)
1556 {
1557 if (!StopExtTimer()) {
1558 throw BError(BError::Codes::EXT_TIMER_ERROR, "Failed to stop extTimer");
1559 }
1560 int64_t totalSize = 0;
1561 TarMap bigFileInfo;
1562 map<string, size_t> smallFiles;
1563 BJsonCachedEntity<BJsonEntityExtensionConfig> cachedEntity(config);
1564 auto cache = cachedEntity.Structuralize();
1565 DoBackupStart();
1566 auto [err, includeSize, excludeSize] = CalculateDataSize(cache, totalSize, bigFileInfo, smallFiles);
1567 ScanFileSingleton::GetInstance().SetIncludeSize(includeSize);
1568 ScanFileSingleton::GetInstance().SetExcludeSize(excludeSize);
1569 if (err != ERR_OK) {
1570 throw BError(BError::Codes::EXT_INVAL_ARG, "Failed to mkdir");
1571 }
1572 if (!RefreshDataSize(totalSize)) {
1573 throw BError(BError::Codes::EXT_INVAL_ARG, "Failed to RefreshDataSize");
1574 }
1575 bool isFwkStart;
1576 StartFwkTimer(isFwkStart);
1577 if (!isFwkStart) {
1578 HILOGE("Do backup, start fwk timer fail.");
1579 throw BError(BError::Codes::EXT_TIMER_ERROR, "Failed to start fwkTimer");
1580 }
1581 }
1582
DoBackUpTask(const string & config)1583 void BackupExtExtension::DoBackUpTask(const string &config)
1584 {
1585 BJsonCachedEntity<BJsonEntityExtensionConfig> cachedEntity(config);
1586 auto cache = cachedEntity.Structuralize();
1587 vector<string> excludes = cache.GetExcludes();
1588 vector<string> endExcludes = excludes;
1589 PreDealExcludes(endExcludes);
1590
1591 int ret = 0;
1592 TarMap fileBackupedInfo;
1593 while (!ScanFileSingleton::GetInstance().GetCompletedFlag()) {
1594 ScanFileSingleton::GetInstance().WaitForFiles();
1595 std::map<std::string, struct stat> incFiles = ScanFileSingleton::GetInstance().GetAllBigFiles();
1596 if (incFiles.empty()) {
1597 continue;
1598 }
1599 map<string, struct stat> bigFiles = MatchFiles(incFiles, endExcludes);
1600 TarMap bigFileInfo = convertFileToBigFiles(bigFiles);
1601 ret = DoBackupBigFiles(bigFileInfo, fileBackupedInfo.size());
1602 fileBackupedInfo.insert(bigFileInfo.begin(), bigFileInfo.end());
1603 }
1604
1605 map<string, size_t> incSmallFiles = ScanFileSingleton::GetInstance().GetAllSmallFiles();
1606 map<string, size_t> smallFiles = MatchFiles(incSmallFiles, endExcludes);
1607
1608 std::map<std::string, struct stat> incFiles = ScanFileSingleton::GetInstance().GetAllBigFiles();
1609 map<string, struct stat> bigFiles = MatchFiles(incFiles, endExcludes);
1610 TarMap bigFileInfo = convertFileToBigFiles(bigFiles);
1611 uint32_t includeSize = ScanFileSingleton::GetInstance().GetIncludeSize();
1612 uint32_t excludeSize = ScanFileSingleton::GetInstance().GetExcludeSize();
1613
1614 ret = DoBackup(bigFileInfo, fileBackupedInfo, smallFiles, includeSize, excludeSize);
1615 DoBackupEnd();
1616 ScanFileSingleton::GetInstance().SetCompletedFlag(false);
1617 AppDone(ret);
1618 HILOGI("backup app done %{public}d", ret);
1619 }
1620
1621 template <typename T>
MatchFiles(map<string,T> files,vector<string> endExcludes)1622 std::map<string, T> BackupExtExtension::MatchFiles(map<string, T> files, vector<string> endExcludes)
1623 {
1624 auto isMatch = [](const vector<string> &s, const string &str) -> bool {
1625 if (str.empty() || s.empty()) {
1626 return false;
1627 }
1628 for (const string &item : s) {
1629 if (fnmatch(item.data(), str.data(), FNM_LEADING_DIR) == 0) {
1630 return true;
1631 }
1632 }
1633 return false;
1634 };
1635
1636 std::map<std::string, T> excludesFiles;
1637 for (const auto &item : files) {
1638 if (!isMatch(endExcludes, item.first)) {
1639 excludesFiles.emplace(item);
1640 }
1641 }
1642 return excludesFiles;
1643 }
1644
DoBackupBigFiles(TarMap & bigFileInfo,uint32_t backupedFileSize)1645 int BackupExtExtension::DoBackupBigFiles(TarMap &bigFileInfo, uint32_t backupedFileSize)
1646 {
1647 HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
1648 HILOGI("Start do backup big files, bigFileInfo size: %{public}zu", bigFileInfo.size());
1649 if (extension_ == nullptr) {
1650 HILOGE("Failed to do backup big files, extension is nullptr.");
1651 return EPERM;
1652 }
1653 if (extension_->GetExtensionAction() != BConstants::ExtensionAction::BACKUP) {
1654 HILOGE("Failed to do backup big files, extension action is not back up.");
1655 return EPERM;
1656 }
1657
1658 auto proxy = ServiceClient::GetInstance();
1659 if (proxy == nullptr) {
1660 HILOGE("Failed to do backup big files, proxy is nullptr.");
1661 return EPERM;
1662 }
1663
1664 auto res = BigFileReady(bigFileInfo, proxy, backupedFileSize);
1665 HILOGI("HandleBackup finish, ret = %{public}d", res);
1666 return res;
1667 }
1668
convertFileToBigFiles(std::map<std::string,struct stat> files)1669 TarMap BackupExtExtension::convertFileToBigFiles(std::map<std::string, struct stat> files)
1670 {
1671 auto getStringHash = [](const TarMap &m, const string &str) -> string {
1672 ostringstream strHex;
1673 strHex << hex;
1674
1675 hash<string> strHash;
1676 size_t szHash = strHash(str);
1677 strHex << setfill('0') << setw(BConstants::BIG_FILE_NAME_SIZE) << szHash;
1678 string name = strHex.str();
1679 for (int i = 0; m.find(name) != m.end(); ++i, strHex.str("")) {
1680 szHash = strHash(str + to_string(i));
1681 strHex << setfill('0') << setw(BConstants::BIG_FILE_NAME_SIZE) << szHash;
1682 name = strHex.str();
1683 }
1684 return name;
1685 };
1686
1687 TarMap bigFileInfo;
1688 for (const auto& item : files) {
1689 string md5Name = getStringHash(bigFileInfo, item.first);
1690 if (!md5Name.empty()) {
1691 bigFileInfo.emplace(md5Name, make_tuple(item.first, item.second, true));
1692 }
1693 }
1694 return bigFileInfo;
1695 }
1696
PreDealExcludes(std::vector<std::string> & excludes)1697 void BackupExtExtension::PreDealExcludes(std::vector<std::string> &excludes)
1698 {
1699 size_t lenEx = excludes.size();
1700 int j = 0;
1701 for (size_t i = 0; i < lenEx; ++i) {
1702 if (!excludes[i].empty()) {
1703 if (excludes[i].at(excludes[i].size() - 1) == BConstants::FILE_SEPARATOR_CHAR) {
1704 excludes[i] += "*";
1705 }
1706 if (excludes[i].find(BConstants::FILE_SEPARATOR_CHAR) != string::npos &&
1707 excludes[i].at(0) != BConstants::FILE_SEPARATOR_CHAR) {
1708 excludes[i] = BConstants::FILE_SEPARATOR_CHAR + excludes[i];
1709 }
1710 excludes[j++] = excludes[i];
1711 }
1712 }
1713 excludes.resize(j);
1714 }
1715
GetIncrementalBackupFileHandle(int & fd,int & reportFd)1716 ErrCode BackupExtExtension::GetIncrementalBackupFileHandle(int &fd, int &reportFd)
1717 {
1718 auto [fdval, reportFdval] = GetIncrementalBackupFileHandle();
1719 fd = dup(fdval.Get());
1720 reportFd = dup(reportFdval.Get());
1721 return BError(BError::Codes::OK).GetCode();
1722 }
1723
GetIncrementalBackupFileHandle()1724 tuple<UniqueFd, UniqueFd> BackupExtExtension::GetIncrementalBackupFileHandle()
1725 {
1726 HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
1727 return {UniqueFd(BConstants::INVALID_FD_NUM), UniqueFd(BConstants::INVALID_FD_NUM)};
1728 }
1729
OnReleaseCallback(wptr<BackupExtExtension> obj)1730 std::function<void(ErrCode, const std::string)> BackupExtExtension::OnReleaseCallback(wptr<BackupExtExtension> obj)
1731 {
1732 HILOGI("Begin get HandleOnReleaseCallback");
1733 return [obj](ErrCode errCode, std::string errMsg) {
1734 HILOGI("OnReleaseCallback: App onRelease end");
1735 auto extPtr = obj.promote();
1736 if (extPtr == nullptr) {
1737 HILOGE("Ext extension handle have been released");
1738 return;
1739 }
1740 if (extPtr->extension_ == nullptr) {
1741 HILOGE("Extension handle have been released");
1742 return;
1743 }
1744 if (extPtr->stopWaitOnRelease_.load()) {
1745 HILOGE("App onRelease timeout");
1746 return;
1747 }
1748 std::unique_lock<std::mutex> lock(extPtr->execOnReleaseLock_);
1749 extPtr->stopWaitOnRelease_.store(true);
1750 extPtr->execOnReleaseCon_.notify_all();
1751 HILOGI("Extension onRelease end, errCode: %{public}d, errInfo: %{public}s", errCode, errMsg.c_str());
1752 };
1753 }
1754
HandleOnRelease(int32_t scenario)1755 ErrCode BackupExtExtension::HandleOnRelease(int32_t scenario)
1756 {
1757 try {
1758 HILOGI("HandleOnRelease Begin, scenario: %{public}d", scenario);
1759 VerifyCaller();
1760 std::unique_lock<std::mutex> onReleaseLock(onReleaseLock_);
1761 if (isOnReleased_.load()) {
1762 HILOGE("onRelease done, not need to do again");
1763 return ERR_OK;
1764 }
1765 auto task = [obj {wptr<BackupExtExtension>(this)}, scenario]() {
1766 auto extPtr = obj.promote();
1767 if (extPtr == nullptr || extPtr->extension_ == nullptr) {
1768 HILOGE("Call js onRelease failed, extensionPtr is empty");
1769 return;
1770 }
1771 auto callback = extPtr->OnReleaseCallback(obj);
1772 ErrCode ret = extPtr->extension_->OnRelease(callback, scenario);
1773 if (ret != ERR_OK) {
1774 HILOGE("Call onRelease failed, ret = %{public}d", ret);
1775 }
1776 };
1777 onReleaseTaskPool_.AddTask([task]() { task(); });
1778 HILOGI("Wait onRelease to do");
1779 std::unique_lock<std::mutex> lock(execOnReleaseLock_);
1780 execOnReleaseCon_.wait_for(lock, std::chrono::milliseconds(BConstants::APP_ON_RELEASE_MAX_TIMEOUT),
1781 [this] { return stopWaitOnRelease_.load(); });
1782 stopWaitOnRelease_.store(true);
1783 isOnReleased_.store(true);
1784 return ERR_OK;
1785 } catch (...) {
1786 HILOGE("Failed to HandleOnRelease");
1787 return BError(BError::Codes::EXT_BROKEN_IPC).GetCode();
1788 }
1789 }
1790
HandleExtDisconnect(bool isAppResultReport,ErrCode errCode)1791 void BackupExtExtension::HandleExtDisconnect(bool isAppResultReport, ErrCode errCode)
1792 {
1793 HILOGI("Begin, scenario:%{public}d, isAppResultReport:%{public}d, errCode:%{public}d", curScenario_,
1794 isAppResultReport, errCode);
1795 auto proxy = ServiceClient::GetInstance();
1796 if (proxy == nullptr) {
1797 HILOGE("Failed to obtain the ServiceClient handle");
1798 return;
1799 }
1800 auto ret = proxy->HandleExtDisconnect(curScenario_, isAppResultReport, errCode);
1801 if (ret != ERR_OK) {
1802 HILOGE("Failed to HandleExtDisconnect. err = %{public}d", ret);
1803 }
1804 }
1805
HandleGetExtOnRelease()1806 bool BackupExtExtension::HandleGetExtOnRelease()
1807 {
1808 HILOGI("HandleGetExtOnRelease begin");
1809 auto proxy = ServiceClient::GetInstance();
1810 if (proxy == nullptr) {
1811 HILOGE("Failed to obtain the ServiceClient handle");
1812 return false;
1813 }
1814 bool isExtOnRelease = false;
1815 auto ret = proxy->GetExtOnRelease(isExtOnRelease);
1816 if (ret != ERR_OK) {
1817 HILOGE("Failed to GetExtOnRelease. err = %{public}d", ret);
1818 }
1819 return isExtOnRelease;
1820 }
1821
HandleExtOnRelease(bool isAppResultReport,ErrCode errCode)1822 void BackupExtExtension::HandleExtOnRelease(bool isAppResultReport, ErrCode errCode)
1823 {
1824 HILOGI("HandleExtOnRelease begin");
1825 int32_t scenario = static_cast<int32_t>(BConstants::ExtensionScenario::RESTORE);
1826 if (curScenario_ == BackupRestoreScenario::FULL_BACKUP ||
1827 curScenario_ == BackupRestoreScenario::INCREMENTAL_BACKUP) {
1828 scenario = static_cast<int32_t>(BConstants::ExtensionScenario::BACKUP);
1829 }
1830 auto task = [obj {wptr<BackupExtExtension>(this)}, scenario, isAppResultReport, errCode]() {
1831 auto extPtr = obj.promote();
1832 if (extPtr == nullptr || extPtr->extension_ == nullptr) {
1833 HILOGE("Call js onRelease failed, extensionPtr is empty");
1834 return;
1835 }
1836 {
1837 std::unique_lock<std::mutex> onReleaseLock(extPtr->onReleaseLock_);
1838 if (extPtr->isOnReleased_.load()) {
1839 HILOGE("onRelease done, not need to do again");
1840 return;
1841 }
1842 auto callback = extPtr->OnReleaseCallback(obj);
1843 ErrCode ret = extPtr->extension_->OnRelease(callback, scenario);
1844 if (ret != ERR_OK) {
1845 HILOGE("Call onRelease failed, ret = %{public}d", ret);
1846 return;
1847 }
1848 std::unique_lock<std::mutex> lock(extPtr->execOnReleaseLock_);
1849 extPtr->execOnReleaseCon_.wait_for(lock, std::chrono::milliseconds(BConstants::APP_ON_RELEASE_MAX_TIMEOUT),
1850 [extPtr] { return extPtr->stopWaitOnRelease_.load(); });
1851 extPtr->stopWaitOnRelease_.store(true);
1852 extPtr->isOnReleased_.store(true);
1853 }
1854 extPtr->HandleExtDisconnect(isAppResultReport, errCode);
1855 };
1856 onReleaseTaskPool_.AddTask([task]() { task(); });
1857 }
1858
GetComInfoCallback(wptr<BackupExtExtension> obj)1859 std::function<void(ErrCode, const std::string)> BackupExtExtension::GetComInfoCallback(wptr<BackupExtExtension> obj)
1860 {
1861 HILOGI("Begin get GetComInfoCallback");
1862 return [obj](ErrCode errCode, std::string compatibilityInfo) {
1863 HILOGI("GetComInfoCallback: App getCompatibilityInfo end");
1864 auto extPtr = obj.promote();
1865 if (extPtr == nullptr) {
1866 HILOGE("Ext extension handle have been released");
1867 return;
1868 }
1869 if (extPtr->extension_ == nullptr) {
1870 HILOGE("Extension handle have been released");
1871 return;
1872 }
1873 if (extPtr->stopGetComInfo_.load()) {
1874 HILOGE("App getCompatibilityInfo timeout");
1875 return;
1876 }
1877 HILOGI("GetCompatibilityInfo end, errCode: %{public}d, compatibilityInfo size is %{public}zu",
1878 errCode, compatibilityInfo.size());
1879 std::unique_lock<std::mutex> lock(extPtr->getCompatibilityInfoLock_);
1880 extPtr->compatibilityInfo_ = compatibilityInfo;
1881 extPtr->stopGetComInfo_.store(true);
1882 extPtr->getCompatibilityInfoCon_.notify_all();
1883 };
1884 }
1885
HandleGetCompatibilityInfo(const string & extInfo,int32_t scenario,string & compatibilityInfo)1886 ErrCode BackupExtExtension::HandleGetCompatibilityInfo(const string &extInfo, int32_t scenario,
1887 string &compatibilityInfo)
1888 {
1889 try {
1890 HILOGI("Begin, scenario: %{public}d, extInfo size: %{public}zu", scenario, extInfo.size());
1891 VerifyCaller();
1892 auto ptr = wptr<BackupExtExtension>(this);
1893 auto callback = GetComInfoCallback(ptr);
1894 ErrCode ret = ERR_OK;
1895 compatibilityInfo = "";
1896 if (scenario == BConstants::ExtensionScenario::BACKUP) {
1897 ret = extension_->GetBackupCompatibilityInfo(callback, extInfo);
1898 } else if (scenario == BConstants::ExtensionScenario::RESTORE) {
1899 ret = extension_->GetRestoreCompatibilityInfo(callback, extInfo);
1900 } else {
1901 return BError(BError::Codes::EXT_INVAL_ARG).GetCode();
1902 }
1903 if (ret != ERR_OK) {
1904 HILOGE("Call GetCompatibilityInfo failed, ret = %{public}d", ret);
1905 return ret;
1906 }
1907 HILOGI("wait GetCompatibilityInfo");
1908 std::unique_lock<std::mutex> lock(getCompatibilityInfoLock_);
1909 auto noTimeout = getCompatibilityInfoCon_.wait_for(lock,
1910 std::chrono::milliseconds(BConstants::APP_GETCOMINFO_MAX_TIMEOUT),
1911 [this] { return this->stopGetComInfo_.load(); });
1912 if (noTimeout) {
1913 compatibilityInfo = compatibilityInfo_;
1914 }
1915 HILOGI("getCompatibilityInfo size: %{public}zu", compatibilityInfo.size());
1916 return ret;
1917 } catch (...) {
1918 HILOGE("Failed to HandleGetCompatibilityInfo");
1919 return BError(BError::Codes::EXT_BROKEN_IPC).GetCode();
1920 }
1921 }
1922 } // namespace OHOS::FileManagement::Backup
1923