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 <iomanip>
23 #include <map>
24 #include <regex>
25 #include <string>
26 #include <thread>
27 #include <tuple>
28 #include <unordered_map>
29 #include <vector>
30
31 #include <directory_ex.h>
32 #include <sys/stat.h>
33 #include <unistd.h>
34
35 #include <directory_ex.h>
36 #include <unique_fd.h>
37
38 #include "accesstoken_kit.h"
39 #include "bundle_mgr_client.h"
40 #include "errors.h"
41 #include "ipc_skeleton.h"
42
43 #include "b_error/b_error.h"
44 #include "b_error/b_excep_utils.h"
45 #include "b_filesystem/b_dir.h"
46 #include "b_filesystem/b_file.h"
47 #include "b_filesystem/b_file_hash.h"
48 #include "b_json/b_json_cached_entity.h"
49 #include "b_jsonutil/b_jsonutil.h"
50 #include "b_ohos/startup/backup_para.h"
51 #include "b_radar/b_radar.h"
52 #include "b_tarball/b_tarball_factory.h"
53 #include "filemgmt_libhilog.h"
54 #include "hitrace_meter.h"
55 #include "i_service.h"
56 #include "sandbox_helper.h"
57 #include "service_proxy.h"
58 #include "tar_file.h"
59 #include "b_anony/b_anony.h"
60
61 namespace OHOS::FileManagement::Backup {
62 const uint32_t MAX_FD_GROUP_USE_TIME = 1000; // 每组打开最大时间1000ms
63
WaitToSendFd(std::chrono::system_clock::time_point & startTime,int & fdSendNum)64 void BackupExtExtension::WaitToSendFd(std::chrono::system_clock::time_point &startTime, int &fdSendNum)
65 {
66 HILOGD("WaitToSendFd Begin");
67 std::unique_lock<std::mutex> lock(startSendMutex_);
68 startSendFdRateCon_.wait(lock, [this] { return sendRate_ > 0; });
69 if (fdSendNum >= sendRate_) {
70 HILOGI("current time fd num is max rate, bundle name:%{public}s, rate:%{public}d", bundleName_.c_str(),
71 sendRate_);
72 auto curTime = std::chrono::system_clock::now();
73 auto useTimeMs = std::chrono::duration_cast<std::chrono::milliseconds>(curTime - startTime).count();
74 if (useTimeMs < MAX_FD_GROUP_USE_TIME) {
75 int32_t sleepTime = MAX_FD_GROUP_USE_TIME - useTimeMs;
76 HILOGI("will wait time:%{public}d ms", sleepTime);
77 std::this_thread::sleep_for(std::chrono::milliseconds(sleepTime));
78 } else {
79 HILOGW("current fd send num exceeds one second");
80 }
81 fdSendNum = 0;
82 startTime = std::chrono::system_clock::now();
83 }
84 HILOGD("WaitToSendFd End");
85 }
86
RefreshTimeInfo(std::chrono::system_clock::time_point & startTime,int & fdSendNum)87 void BackupExtExtension::RefreshTimeInfo(std::chrono::system_clock::time_point &startTime, int &fdSendNum)
88 {
89 auto currentTime = std::chrono::system_clock::now();
90 auto useTime = std::chrono::duration_cast<std::chrono::milliseconds>(currentTime - startTime).count();
91 if (useTime >= MAX_FD_GROUP_USE_TIME) {
92 HILOGI("RefreshTimeInfo Begin, fdSendNum is:%{public}d", fdSendNum);
93 startTime = std::chrono::system_clock::now();
94 fdSendNum = 0;
95 }
96 }
97
SetClearDataFlag(bool isClearData)98 void BackupExtExtension::SetClearDataFlag(bool isClearData)
99 {
100 isClearData_ = isClearData;
101 HILOGI("set clear data flag:%{public}d", isClearData);
102 if (extension_ == nullptr) {
103 HILOGE("Extension handle have been released");
104 return;
105 }
106 if (!extension_->WasFromSpecialVersion() && !extension_->RestoreDataReady()) {
107 DoClear();
108 }
109 }
110
GetBundlePath()111 string BackupExtExtension::GetBundlePath()
112 {
113 if (bundleName_ == BConstants::BUNDLE_FILE_MANAGER) {
114 return string(BConstants::PATH_FILEMANAGE_BACKUP_HOME).append(BConstants::SA_BUNDLE_BACKUP_RESTORE);
115 } else if (bundleName_ == BConstants::BUNDLE_MEDIAL_DATA) {
116 return string(BConstants::PATH_MEDIALDATA_BACKUP_HOME).append(BConstants::SA_BUNDLE_BACKUP_RESTORE);
117 }
118 return string(BConstants::PATH_BUNDLE_BACKUP_HOME).append(BConstants::SA_BUNDLE_BACKUP_RESTORE);
119 }
120
GetIdxFileInfos(bool isSpecialVersion)121 std::map<std::string, off_t> BackupExtExtension::GetIdxFileInfos(bool isSpecialVersion)
122 {
123 string restoreDir = isSpecialVersion ? "" : GetBundlePath();
124 auto extManageInfo = GetExtManageInfo(isSpecialVersion);
125 std::map<std::string, off_t> idxFileInfos;
126 for (size_t i = 0; i < extManageInfo.size(); ++i) {
127 std::string realPath = restoreDir + extManageInfo[i].hashName;
128 idxFileInfos[realPath] = extManageInfo[i].sta.st_size;
129 }
130 return idxFileInfos;
131 }
132
CheckTmpDirFileInfos(bool isSpecialVersion)133 void BackupExtExtension::CheckTmpDirFileInfos(bool isSpecialVersion)
134 {
135 ErrFileInfo errFiles;
136 auto idxFileInfos = GetIdxFileInfos(isSpecialVersion);
137 struct stat attr;
138 for (const auto &it : idxFileInfos) {
139 if (it.first.size() >= PATH_MAX || stat(it.first.data(), &attr) == -1) {
140 HILOGE("(Debug) Failed to get stat of %{public}s, errno = %{public}d", GetAnonyPath(it.first).c_str(),
141 errno);
142 errFiles[it.first].emplace_back(errno);
143 } else if (it.second != attr.st_size) {
144 HILOGE("(Debug) RecFile:%{public}s size err, recSize: %{public}" PRId64 ", idxSize: %{public}" PRId64 "",
145 GetAnonyPath(it.first).c_str(), attr.st_size, it.second);
146 errFiles[it.first] = std::vector<int>();
147 }
148 }
149 HILOGE("(Debug) Temp file check result: Total file: %{public}zu, err file: %{public}zu", idxFileInfos.size(),
150 errFiles.size());
151 if (!errFiles.empty()) {
152 HILOGE("(Debug) The received file and idx is not same");
153 std::stringstream ss;
154 ss << R"("totalFile": )" << idxFileInfos.size() << R"(, "restoreFile": )"
155 << idxFileInfos.size() - errFiles.size() << R"(, "info": "different received file and idx")";
156 AppRadar::Info info (bundleName_, "", ss.str());
157 AppRadar::GetInstance().RecordRestoreFuncRes(info, "BackupExtExtension::CheckTmpDirFileInfos",
158 AppRadar::GetInstance().GetUserId(), BizStageRestore::BIZ_STAGE_CHECK_DATA_FAIL,
159 static_cast<int32_t>(BError::BackupErrorCode::E_UKERR));
160 } else {
161 HILOGI("(Debug) The received file and idx is same");
162 }
163 }
164
CheckRestoreFileInfos()165 tuple<bool, vector<string>> BackupExtExtension::CheckRestoreFileInfos()
166 {
167 vector<string> errFiles;
168 struct stat curFileStat {};
169 for (const auto &it : endFileInfos_) {
170 if (lstat(it.first.c_str(), &curFileStat) != 0) {
171 HILOGE("Failed to lstat %{public}s, err = %{public}d", GetAnonyPath(it.first).c_str(), errno);
172 errFiles.emplace_back(it.first);
173 errFileInfos_[it.first].emplace_back(errno);
174 } else if (curFileStat.st_size != it.second) {
175 HILOGE("File size error, file: %{public}s, idx: %{public}" PRId64 ", act: %{public}" PRId64 "",
176 GetAnonyPath(it.first).c_str(), it.second, curFileStat.st_size);
177 errFiles.emplace_back(it.first);
178 errFileInfos_[it.first].emplace_back(errno);
179 }
180 }
181 for (const auto &it : errFileInfos_) {
182 for (const auto &codeIt : it.second) {
183 HILOGE("(Debug) errfileInfos file = %{public}s -> %{public}d", GetAnonyPath(it.first).c_str(), codeIt);
184 }
185 }
186 HILOGE("(Debug) End file check result Total file: %{public}zu, err file: %{public}zu", endFileInfos_.size(),
187 errFileInfos_.size());
188 if (errFiles.size()) {
189 std::stringstream ss;
190 ss << R"("totalFile": )" << endFileInfos_.size() << R"(, "restoreFile": )"
191 << endFileInfos_.size() - errFileInfos_.size();
192 AppRadar::Info info (bundleName_, "", ss.str());
193 AppRadar::GetInstance().RecordRestoreFuncRes(info, "BackupExtExtension::CheckRestoreFileInfos",
194 AppRadar::GetInstance().GetUserId(), BizStageRestore::BIZ_STAGE_CHECK_DATA_FAIL,
195 static_cast<int32_t>(BError::BackupErrorCode::E_UKERR));
196 return { false, errFiles };
197 }
198 return { true, errFiles };
199 }
200
OnRestoreCallback(wptr<BackupExtExtension> obj)201 std::function<void(ErrCode, std::string)> BackupExtExtension::OnRestoreCallback(wptr<BackupExtExtension> obj)
202 {
203 HILOGI("Begin get full restore onRestore callback");
204 return [obj](ErrCode errCode, std::string errMsg) {
205 auto extensionPtr = obj.promote();
206 if (extensionPtr == nullptr) {
207 HILOGE("Ext extension handle have been released");
208 return;
209 }
210 if (extensionPtr->isExecAppDone_.load()) {
211 HILOGE("Appdone has been executed for the current application");
212 return;
213 }
214 HILOGI("Current bundle will execute app done");
215 if (errCode == ERR_OK) {
216 auto spendTime = extensionPtr->GetOnStartTimeCost();
217 if (spendTime >= BConstants::MAX_TIME_COST) {
218 std::stringstream ss;
219 ss << R"("spendTime": )"<< spendTime << "ms";
220 AppRadar::Info info (extensionPtr->bundleName_, "", ss.str());
221 AppRadar::GetInstance().RecordRestoreFuncRes(info, "BackupExtExtension::OnRestoreCallback",
222 AppRadar::GetInstance().GetUserId(), BizStageRestore::BIZ_STAGE_ON_RESTORE, ERR_OK);
223 }
224 }
225 extensionPtr->FinishOnProcessTask();
226 if (errMsg.empty()) {
227 extensionPtr->AppDone(errCode);
228 } else {
229 std::string errInfo;
230 BJsonUtil::BuildExtensionErrInfo(errInfo, errCode, errMsg);
231 extensionPtr->AppResultReport(errInfo, BackupRestoreScenario::FULL_RESTORE, errCode);
232 }
233 extensionPtr->DoClear();
234 };
235 }
236
OnRestoreExCallback(wptr<BackupExtExtension> obj)237 std::function<void(ErrCode, std::string)> BackupExtExtension::OnRestoreExCallback(wptr<BackupExtExtension> obj)
238 {
239 HILOGI("Begin get full restore onRestoreEx callback");
240 return [obj](ErrCode errCode, const std::string restoreRetInfo) {
241 auto extensionPtr = obj.promote();
242 if (extensionPtr == nullptr) {
243 HILOGE("Ext extension handle have been released");
244 return;
245 }
246 if (extensionPtr->extension_ == nullptr) {
247 HILOGE("Extension handle have been released");
248 return;
249 }
250 if (extensionPtr->isExecAppDone_.load()) {
251 HILOGE("Appdone has been executed for the current application");
252 return;
253 }
254 if (errCode == ERR_OK && !restoreRetInfo.empty()) {
255 auto spendTime = extensionPtr->GetOnStartTimeCost();
256 if (spendTime >= BConstants::MAX_TIME_COST) {
257 std::stringstream ss;
258 ss << R"("spendTime": )"<< spendTime << "ms";
259 AppRadar::Info info (extensionPtr->bundleName_, "", ss.str());
260 AppRadar::GetInstance().RecordRestoreFuncRes(info, "BackupExtExtension::OnRestoreExCallback",
261 AppRadar::GetInstance().GetUserId(), BizStageRestore::BIZ_STAGE_ON_RESTORE, ERR_OK);
262 }
263 }
264 extensionPtr->FinishOnProcessTask();
265 extensionPtr->extension_->InvokeAppExtMethod(errCode, restoreRetInfo);
266 if (errCode == ERR_OK) {
267 if (restoreRetInfo.size()) {
268 HILOGI("Will notify restore result report");
269 extensionPtr->AppResultReport(restoreRetInfo, BackupRestoreScenario::FULL_RESTORE);
270 }
271 return;
272 }
273 if (restoreRetInfo.empty()) {
274 extensionPtr->AppDone(errCode);
275 extensionPtr->DoClear();
276 } else {
277 std::string errInfo;
278 BJsonUtil::BuildExtensionErrInfo(errInfo, errCode, restoreRetInfo);
279 extensionPtr->AppResultReport(errInfo, BackupRestoreScenario::FULL_RESTORE, errCode);
280 extensionPtr->DoClear();
281 }
282 };
283 }
284
AppDoneCallbackEx(wptr<BackupExtExtension> obj)285 std::function<void(ErrCode, std::string)> BackupExtExtension::AppDoneCallbackEx(wptr<BackupExtExtension> obj)
286 {
287 HILOGI("Begin get callback for appDone");
288 return [obj](ErrCode errCode, std::string errMsg) {
289 HILOGI("begin call callBackupExAppDone");
290 auto extensionPtr = obj.promote();
291 if (extensionPtr == nullptr) {
292 HILOGE("Ext extension handle have been released");
293 return;
294 }
295 extensionPtr->AppDone(errCode);
296 extensionPtr->DoClear();
297 };
298 }
299
IncreOnRestoreExCallback(wptr<BackupExtExtension> obj)300 std::function<void(ErrCode, std::string)> BackupExtExtension::IncreOnRestoreExCallback(wptr<BackupExtExtension> obj)
301 {
302 HILOGI("Begin get callback for increment onRestoreEx");
303 return [obj](ErrCode errCode, const std::string restoreRetInfo) {
304 HILOGI("begin call increment restoreEx");
305 auto extensionPtr = obj.promote();
306 if (extensionPtr == nullptr) {
307 HILOGE("Ext extension handle have been released");
308 return;
309 }
310 if (extensionPtr->extension_ == nullptr) {
311 HILOGE("Extension handle have been released");
312 return;
313 }
314 if (extensionPtr->isExecAppDone_.load()) {
315 HILOGE("Appdone has been executed for the current application");
316 return;
317 }
318 if (errCode == ERR_OK && !restoreRetInfo.empty()) {
319 auto spendTime = extensionPtr->GetOnStartTimeCost();
320 if (spendTime >= BConstants::MAX_TIME_COST) {
321 std::stringstream ss;
322 ss << R"("spendTime": )"<< spendTime << "ms";
323 AppRadar::Info info (extensionPtr->bundleName_, "", ss.str());
324 AppRadar::GetInstance().RecordRestoreFuncRes(info, "BackupExtExtension::IncreOnRestoreExCallback",
325 AppRadar::GetInstance().GetUserId(),
326 BizStageRestore::BIZ_STAGE_ON_RESTORE, ERR_OK);
327 }
328 }
329 extensionPtr->FinishOnProcessTask();
330 extensionPtr->extension_->InvokeAppExtMethod(errCode, restoreRetInfo);
331 if (errCode == ERR_OK) {
332 if (restoreRetInfo.size()) {
333 extensionPtr->AppResultReport(restoreRetInfo, BackupRestoreScenario::INCREMENTAL_RESTORE);
334 }
335 return;
336 }
337 if (restoreRetInfo.empty()) {
338 extensionPtr->AppIncrementalDone(errCode);
339 extensionPtr->DoClear();
340 } else {
341 std::string errInfo;
342 BJsonUtil::BuildExtensionErrInfo(errInfo, errCode, restoreRetInfo);
343 extensionPtr->AppResultReport(errInfo, BackupRestoreScenario::INCREMENTAL_RESTORE, errCode);
344 extensionPtr->DoClear();
345 }
346 };
347 }
348
IncreOnRestoreCallback(wptr<BackupExtExtension> obj)349 std::function<void(ErrCode, std::string)> BackupExtExtension::IncreOnRestoreCallback(wptr<BackupExtExtension> obj)
350 {
351 return [obj](ErrCode errCode, std::string errMsg) {
352 auto extensionPtr = obj.promote();
353 if (extensionPtr == nullptr) {
354 HILOGE("Ext extension handle have been released");
355 return;
356 }
357 if (extensionPtr->isExecAppDone_.load()) {
358 HILOGE("Appdone has been executed for the current application");
359 return;
360 }
361 HILOGI("Current bundle will execute app done");
362 if (errCode == ERR_OK) {
363 auto spendTime = extensionPtr->GetOnStartTimeCost();
364 if (spendTime >= BConstants::MAX_TIME_COST) {
365 std::stringstream ss;
366 ss << R"("spendTime": )"<< spendTime << "ms";
367 AppRadar::Info info (extensionPtr->bundleName_, "", ss.str());
368 AppRadar::GetInstance().RecordRestoreFuncRes(info, "BackupExtExtension::IncreOnRestoreCallback",
369 AppRadar::GetInstance().GetUserId(), BizStageRestore::BIZ_STAGE_ON_RESTORE, ERR_OK);
370 }
371 }
372 extensionPtr->FinishOnProcessTask();
373 if (errMsg.empty()) {
374 extensionPtr->AppIncrementalDone(errCode);
375 } else {
376 std::string errInfo;
377 BJsonUtil::BuildExtensionErrInfo(errInfo, errCode, errMsg);
378 extensionPtr->AppResultReport(errInfo, BackupRestoreScenario::INCREMENTAL_RESTORE, errCode);
379 }
380 extensionPtr->DoClear();
381 };
382 }
383
GetOnStartTimeCost()384 int32_t BackupExtExtension::GetOnStartTimeCost()
385 {
386 auto onBackupRestoreEnd = std::chrono::system_clock::now();
387 std::lock_guard<std::mutex> lock(onStartTimeLock_);
388 auto spendTime = std::chrono::duration_cast<std::chrono::milliseconds>(onBackupRestoreEnd - g_onStart).count();
389 return spendTime;
390 }
391
OnBackupCallback(wptr<BackupExtExtension> obj)392 std::function<void(ErrCode, const std::string)> BackupExtExtension::OnBackupCallback(wptr<BackupExtExtension> obj)
393 {
394 HILOGI("Begin get HandleFullBackupCallbackEx");
395 return [obj](ErrCode errCode, std::string errMsg) {
396 HILOGI("begin call backup");
397 auto extensionPtr = obj.promote();
398 if (extensionPtr == nullptr) {
399 HILOGE("Ext extension handle have been released");
400 return;
401 }
402 if (extensionPtr->extension_ == nullptr) {
403 HILOGE("Extension handle have been released");
404 return;
405 }
406 if (extensionPtr->isExecAppDone_.load()) {
407 HILOGE("Appdone has been executed for the current application");
408 return;
409 }
410 extensionPtr->FinishOnProcessTask();
411 if (errCode == ERR_OK) {
412 auto spendTime = extensionPtr->GetOnStartTimeCost();
413 if (spendTime >= BConstants::MAX_TIME_COST) {
414 AppRadar::Info info(extensionPtr->bundleName_, "", string("\"spend_time\":\" ").
415 append(to_string(spendTime)).append(string("ms\"")));
416 AppRadar::GetInstance().RecordBackupFuncRes(info, "BackupExtExtension::OnBackupCallback",
417 AppRadar::GetInstance().GetUserId(), BizStageBackup::BIZ_STAGE_ON_BACKUP,
418 static_cast<int32_t>(ERR_OK));
419 }
420 extensionPtr->AsyncTaskBackup(extensionPtr->extension_->GetUsrConfig());
421 return;
422 }
423 HILOGE("Call extension onBackup failed, errInfo = %{public}s", errMsg.c_str());
424 if (!errMsg.empty()) {
425 std::string errInfo;
426 BJsonUtil::BuildExtensionErrInfo(errInfo, errCode, errMsg);
427 extensionPtr->AppResultReport(errInfo, BackupRestoreScenario::FULL_BACKUP, errCode);
428 }
429 extensionPtr->AppDone(errCode);
430 extensionPtr->DoClear();
431 };
432 }
433
OnBackupExCallback(wptr<BackupExtExtension> obj)434 std::function<void(ErrCode, const std::string)> BackupExtExtension::OnBackupExCallback(wptr<BackupExtExtension> obj)
435 {
436 HILOGI("Begin get HandleFullBackupCallbackEx");
437 return [obj](ErrCode errCode, const std::string backupExRetInfo) {
438 HILOGI("begin call backup");
439 auto extensionPtr = obj.promote();
440 if (extensionPtr == nullptr) {
441 HILOGE("Ext extension handle have been released");
442 return;
443 }
444 if (extensionPtr->extension_ == nullptr) {
445 HILOGE("Extension handle have been released");
446 return;
447 }
448 if (extensionPtr->isExecAppDone_.load()) {
449 HILOGE("Appdone has been executed for the current application");
450 return;
451 }
452 extensionPtr->extension_->InvokeAppExtMethod(errCode, backupExRetInfo);
453 if (errCode == ERR_OK) {
454 if (backupExRetInfo.size()) {
455 auto spendTime = extensionPtr->GetOnStartTimeCost();
456 if (spendTime >= BConstants::MAX_TIME_COST) {
457 AppRadar::Info info(extensionPtr->bundleName_, "", string("\"spend_time\":\" ").
458 append(to_string(spendTime)).append(string("ms\"")));
459 AppRadar::GetInstance().RecordBackupFuncRes(info, "BackupExtExtension::OnBackupExCallback",
460 AppRadar::GetInstance().GetUserId(), BizStageBackup::BIZ_STAGE_ON_BACKUP,
461 static_cast<int32_t>(ERR_OK));
462 }
463 HILOGI("Will notify backup result report");
464 extensionPtr->FinishOnProcessTask();
465 extensionPtr->AsyncTaskBackup(extensionPtr->extension_->GetUsrConfig());
466 extensionPtr->AppResultReport(backupExRetInfo, BackupRestoreScenario::FULL_BACKUP);
467 }
468 return;
469 }
470 HILOGE("Call extension onBackupEx failed, errInfo = %{public}s", backupExRetInfo.c_str());
471 extensionPtr->FinishOnProcessTask();
472 if (!backupExRetInfo.empty()) {
473 std::string errInfo;
474 BJsonUtil::BuildExtensionErrInfo(errInfo, errCode, backupExRetInfo);
475 extensionPtr->AppResultReport(errInfo, BackupRestoreScenario::FULL_BACKUP, errCode);
476 }
477 extensionPtr->AppDone(errCode);
478 extensionPtr->DoClear();
479 };
480 }
481
IncOnBackupCallback(wptr<BackupExtExtension> obj)482 std::function<void(ErrCode, const std::string)> BackupExtExtension::IncOnBackupCallback(wptr<BackupExtExtension> obj)
483 {
484 HILOGI("Begin get IncOnBackupCallback");
485 return [obj](ErrCode errCode, std::string errMsg) {
486 HILOGI("App onbackup end");
487 auto proxy = ServiceProxy::GetInstance();
488 if (proxy == nullptr) {
489 throw BError(BError::Codes::EXT_BROKEN_BACKUP_SA, std::generic_category().message(errno));
490 }
491 auto extPtr = obj.promote();
492 if (extPtr == nullptr) {
493 HILOGE("Current extension execute call backup error, extPtr is empty");
494 return;
495 }
496 if (extPtr->isExecAppDone_.load()) {
497 HILOGE("Appdone has been executed for the current application");
498 return;
499 }
500 HILOGI("Start GetAppLocalListAndDoIncrementalBackup");
501 extPtr->FinishOnProcessTask();
502 if (errCode == ERR_OK) {
503 auto spendTime = extPtr->GetOnStartTimeCost();
504 if (spendTime >= BConstants::MAX_TIME_COST) {
505 AppRadar::Info info(extPtr->bundleName_, "", string("\"spend_time\":\" ").
506 append(to_string(spendTime)).append(string("ms\"")));
507 AppRadar::GetInstance().RecordBackupFuncRes(info, "BackupExtExtension::IncOnBackupCallback",
508 AppRadar::GetInstance().GetUserId(), BizStageBackup::BIZ_STAGE_ON_BACKUP,
509 static_cast<int32_t>(ERR_OK));
510 }
511 proxy->GetAppLocalListAndDoIncrementalBackup();
512 return;
513 }
514 HILOGE("Call extension IncOnBackup failed, errInfo = %{public}s", errMsg.c_str());
515 if (!errMsg.empty()) {
516 std::string errInfo;
517 BJsonUtil::BuildExtensionErrInfo(errInfo, errCode, errMsg);
518 extPtr->AppResultReport(errInfo, BackupRestoreScenario::INCREMENTAL_BACKUP, errCode);
519 }
520 extPtr->AppIncrementalDone(errCode);
521 extPtr->DoClear();
522 };
523 }
524
IncOnBackupExCallback(wptr<BackupExtExtension> obj)525 std::function<void(ErrCode, const std::string)> BackupExtExtension::IncOnBackupExCallback(wptr<BackupExtExtension> obj)
526 {
527 HILOGI("Begin get HandleIncBackupEx callback");
528 return [obj](ErrCode errCode, const std::string backupExRetInfo) {
529 auto proxy = ServiceProxy::GetInstance();
530 if (proxy == nullptr) {
531 throw BError(BError::Codes::EXT_BROKEN_BACKUP_SA, std::generic_category().message(errno));
532 }
533 auto extensionPtr = obj.promote();
534 if (extensionPtr == nullptr) {
535 HILOGE("Ext extension handle have been released");
536 return;
537 }
538 if (extensionPtr->extension_ == nullptr) {
539 HILOGE("Extension handle have been released");
540 return;
541 }
542 if (extensionPtr->isExecAppDone_.load()) {
543 HILOGE("Appdone has been executed for the current application");
544 return;
545 }
546 extensionPtr->extension_->InvokeAppExtMethod(errCode, backupExRetInfo);
547 if (errCode == ERR_OK) {
548 if (backupExRetInfo.size()) {
549 auto spendTime = extensionPtr->GetOnStartTimeCost();
550 if (spendTime >= BConstants::MAX_TIME_COST) {
551 AppRadar::Info info(extensionPtr->bundleName_, "", string("\"spend_time\":\" ").
552 append(to_string(spendTime)).append(string("ms\"")));
553 AppRadar::GetInstance().RecordBackupFuncRes(info, "BackupExtExtension::IncOnBackupExCallback",
554 AppRadar::GetInstance().GetUserId(), BizStageBackup::BIZ_STAGE_ON_BACKUP,
555 static_cast<int32_t>(ERR_OK));
556 }
557 HILOGI("Start GetAppLocalListAndDoIncrementalBackup");
558 extensionPtr->FinishOnProcessTask();
559 proxy->GetAppLocalListAndDoIncrementalBackup();
560 HILOGI("Will notify backup result report");
561 extensionPtr->AppResultReport(backupExRetInfo, BackupRestoreScenario::INCREMENTAL_BACKUP);
562 }
563 return;
564 }
565 HILOGE("Call extension IncOnBackupEx failed, errInfo = %{public}s", backupExRetInfo.c_str());
566 extensionPtr->FinishOnProcessTask();
567 if (!backupExRetInfo.empty()) {
568 std::string errInfo;
569 BJsonUtil::BuildExtensionErrInfo(errInfo, errCode, backupExRetInfo);
570 extensionPtr->AppResultReport(errInfo, BackupRestoreScenario::INCREMENTAL_BACKUP, errCode);
571 }
572 extensionPtr->AppIncrementalDone(errCode);
573 extensionPtr->DoClear();
574 };
575 }
576
ReportAppProcessInfo(const std::string processInfo,BackupRestoreScenario scenario)577 void BackupExtExtension::ReportAppProcessInfo(const std::string processInfo, BackupRestoreScenario scenario)
578 {
579 auto proxy = ServiceProxy::GetInstance();
580 if (proxy == nullptr) {
581 HILOGE("Report app process error, proxy is empty");
582 return;
583 }
584 HILOGI("Will notify backup sa process result");
585 auto ret = proxy->ReportAppProcessInfo(processInfo, scenario);
586 if (ret != ERR_OK) {
587 HILOGE("Report app process error, ipc failed, ret:%{public}d", ret);
588 return;
589 }
590 }
591
StartOnProcessTaskThread(wptr<BackupExtExtension> obj,BackupRestoreScenario scenario)592 ErrCode BackupExtExtension::StartOnProcessTaskThread(wptr<BackupExtExtension> obj, BackupRestoreScenario scenario)
593 {
594 HILOGI("Begin Create onProcess Task Thread");
595 onProcessTimeoutTimer_.Setup();
596 isFirstCallOnProcess_.store(true);
597 StartOnProcessTimeOutTimer(obj, scenario);
598 SyncCallJsOnProcessTask(obj, scenario);
599 if (isExecAppDone_.load()) {
600 HILOGE("Call onProcess timeout, Current extension finished");
601 return BError(BError::Codes::EXT_ABILITY_TIMEOUT);
602 }
603 callJsOnProcessThread_ = std::thread([obj, scenario]() {
604 auto extPtr = obj.promote();
605 if (extPtr == nullptr) {
606 HILOGE("Create onProcess Task thread failed, extPtr is empty");
607 return;
608 }
609 extPtr->ExecCallOnProcessTask(obj, scenario);
610 });
611 HILOGI("End Create onProcess Task End");
612 return BError(BError::Codes::OK);
613 }
614
ExecCallOnProcessTask(wptr<BackupExtExtension> obj,BackupRestoreScenario scenario)615 void BackupExtExtension::ExecCallOnProcessTask(wptr<BackupExtExtension> obj, BackupRestoreScenario scenario)
616 {
617 HILOGI("Begin");
618 isFirstCallOnProcess_.store(false);
619 while (!stopCallJsOnProcess_.load()) {
620 std::unique_lock<std::mutex> lock(onProcessLock_);
621 execOnProcessCon_.wait_for(lock, std::chrono::seconds(BConstants::CALL_APP_ON_PROCESS_TIME_INTERVAL),
622 [this] { return this->stopCallJsOnProcess_.load(); });
623 if (stopCallJsOnProcess_.load()) {
624 HILOGE("Current extension execute js onProcess method finished");
625 return;
626 }
627 HILOGI("Continue call js method onProcess");
628 StartOnProcessTimeOutTimer(obj, scenario);
629 AsyncCallJsOnProcessTask(obj, scenario);
630 }
631 HILOGI("End");
632 }
633
AsyncCallJsOnProcessTask(wptr<BackupExtExtension> obj,BackupRestoreScenario scenario)634 void BackupExtExtension::AsyncCallJsOnProcessTask(wptr<BackupExtExtension> obj, BackupRestoreScenario scenario)
635 {
636 HILOGI("Begin");
637 if (stopCallJsOnProcess_.load()) {
638 HILOGE("Current extension execute finished");
639 return;
640 }
641 auto task = [obj, scenario]() {
642 auto extPtr = obj.promote();
643 if (extPtr == nullptr) {
644 HILOGE("Async Call js onProcess error, extPtr is empty");
645 return;
646 }
647 extPtr->SyncCallJsOnProcessTask(obj, scenario);
648 };
649 onProcessTaskPool_.AddTask([task]() { task(); });
650 HILOGI("End");
651 }
652
SyncCallJsOnProcessTask(wptr<BackupExtExtension> obj,BackupRestoreScenario scenario)653 void BackupExtExtension::SyncCallJsOnProcessTask(wptr<BackupExtExtension> obj, BackupRestoreScenario scenario)
654 {
655 HILOGI("Begin");
656 if (stopCallJsOnProcess_.load()) {
657 HILOGE("Current extension execute finished");
658 return;
659 }
660 auto callBack = ReportOnProcessResultCallback(obj, scenario);
661 auto extenionPtr = obj.promote();
662 if (extenionPtr == nullptr || extenionPtr->extension_ == nullptr) {
663 HILOGE("Async call js onProcess failed, extenionPtr is empty");
664 return;
665 }
666 ErrCode ret = extenionPtr->extension_->OnProcess(callBack);
667 if (ret != ERR_OK) {
668 HILOGE("Call OnProcess Failed, ret:%{public}d", ret);
669 return;
670 }
671 HILOGI("End");
672 }
673
FinishOnProcessTask()674 void BackupExtExtension::FinishOnProcessTask()
675 {
676 HILOGI("Begin");
677 std::unique_lock<std::mutex> lock(onProcessLock_);
678 stopCallJsOnProcess_.store(true);
679 isFirstCallOnProcess_.store(false);
680 isExecAppDone_.store(false);
681 onProcessTimeoutCnt_ = 0;
682 execOnProcessCon_.notify_one();
683 lock.unlock();
684 if (callJsOnProcessThread_.joinable()) {
685 callJsOnProcessThread_.join();
686 }
687 HILOGI("End");
688 }
689
StartOnProcessTimeOutTimer(wptr<BackupExtExtension> obj,BackupRestoreScenario scenario)690 void BackupExtExtension::StartOnProcessTimeOutTimer(wptr<BackupExtExtension> obj, BackupRestoreScenario scenario)
691 {
692 HILOGI("Begin");
693 if (stopCallJsOnProcess_.load()) {
694 HILOGE("Current extension execute finished");
695 return;
696 }
697 auto timeoutCallback = [obj, scenario]() {
698 auto extPtr = obj.promote();
699 if (extPtr == nullptr) {
700 HILOGE("Start Create timeout callback failed, extPtr is empty");
701 return;
702 }
703 if (extPtr->onProcessTimeoutCnt_.load() >= BConstants::APP_ON_PROCESS_TIMEOUT_MAX_COUNT ||
704 extPtr->isFirstCallOnProcess_.load()) {
705 HILOGE("The extension invokes the onProcess for more than three times or the first invoking of the"
706 "onProcess times out, timeoutCnt:%{public}d", extPtr->onProcessTimeoutCnt_.load());
707 std::unique_lock<std::mutex> lock(extPtr->onProcessLock_);
708 extPtr->stopCallJsOnProcess_.store(true);
709 extPtr->isFirstCallOnProcess_.store(false);
710 extPtr->isExecAppDone_.store(true);
711 extPtr->onProcessTimeoutCnt_ = 0;
712 extPtr->execOnProcessCon_.notify_one();
713 lock.unlock();
714 if (scenario == BackupRestoreScenario::FULL_BACKUP || scenario == BackupRestoreScenario::FULL_RESTORE) {
715 extPtr->AppDone(BError(BError::Codes::EXT_ABILITY_TIMEOUT));
716 } else if (scenario == BackupRestoreScenario::INCREMENTAL_BACKUP ||
717 scenario == BackupRestoreScenario::INCREMENTAL_RESTORE) {
718 extPtr->AppIncrementalDone(BError(BError::Codes::EXT_ABILITY_TIMEOUT));
719 }
720 return;
721 }
722 extPtr->onProcessTimeoutCnt_++;
723 extPtr->onProcessTimeout_.store(true);
724 HILOGE("Extension onProcess timeout, Increase cnt:%{public}d", extPtr->onProcessTimeoutCnt_.load());
725 };
726 int timeout = isFirstCallOnProcess_.load() ? BConstants::FIRST_CALL_APP_ON_PROCESS_MAX_TIMEOUT :
727 BConstants::APP_ON_PROCESS_MAX_TIMEOUT;
728 uint32_t timerId = onProcessTimeoutTimer_.Register(timeoutCallback, timeout, true);
729 onProcessTimeoutTimerId_ = timerId;
730 HILOGI("End");
731 }
732
CloseOnProcessTimeOutTimer()733 void BackupExtExtension::CloseOnProcessTimeOutTimer()
734 {
735 HILOGI("Begin");
736 onProcessTimeoutTimer_.Unregister(onProcessTimeoutTimerId_);
737 HILOGI("End");
738 }
739
AppIncrementalDone(ErrCode errCode)740 void BackupExtExtension::AppIncrementalDone(ErrCode errCode)
741 {
742 HILOGI("Begin");
743 auto proxy = ServiceProxy::GetInstance();
744 if (proxy == nullptr) {
745 HILOGE("Failed to obtain the ServiceProxy handle");
746 DoClear();
747 return;
748 }
749 auto ret = proxy->AppIncrementalDone(errCode);
750 if (ret != ERR_OK) {
751 HILOGE("Failed to notify the app done. err = %{public}d", ret);
752 }
753 }
754
GetBackupInfo(std::string & result)755 ErrCode BackupExtExtension::GetBackupInfo(std::string &result)
756 {
757 auto obj = wptr<BackupExtExtension>(this);
758 auto ptr = obj.promote();
759 if (ptr == nullptr) {
760 HILOGE("Failed to get ext extension.");
761 return BError(BError::Codes::EXT_INVAL_ARG, "extension getBackupInfo exception").GetCode();
762 }
763 if (ptr->extension_ == nullptr) {
764 HILOGE("Failed to get extension.");
765 return BError(BError::Codes::EXT_INVAL_ARG, "extension getBackupInfo exception").GetCode();
766 }
767 auto callBackup = [ptr](ErrCode errCode, const std::string result) {
768 if (ptr == nullptr) {
769 HILOGE("Failed to get ext extension.");
770 return;
771 }
772 HILOGI("GetBackupInfo callBackup start. errCode = %{public}d, result = %{public}s", errCode, result.c_str());
773 if (errCode == ERR_OK) {
774 ptr->backupInfo_ = result;
775 }
776 };
777 auto ret = ptr->extension_->GetBackupInfo(callBackup);
778 if (ret != ERR_OK) {
779 HILOGE("Failed to get backupInfo. err = %{public}d", ret);
780 return BError(BError::Codes::EXT_INVAL_ARG, "extension getBackupInfo exception").GetCode();
781 }
782 HILOGD("backupInfo = %s", backupInfo_.c_str());
783 result = backupInfo_;
784 backupInfo_.clear();
785
786 return ERR_OK;
787 }
788
UpdateFdSendRate(std::string & bundleName,int32_t sendRate)789 ErrCode BackupExtExtension::UpdateFdSendRate(std::string &bundleName, int32_t sendRate)
790 {
791 try {
792 std::lock_guard<std::mutex> lock(updateSendRateLock_);
793 HILOGI("Update SendRate, bundleName:%{public}s, sendRate:%{public}d", bundleName.c_str(), sendRate);
794 VerifyCaller();
795 bundleName_ = bundleName;
796 sendRate_ = sendRate;
797 if (sendRate > 0) {
798 startSendFdRateCon_.notify_one();
799 }
800 return ERR_OK;
801 } catch (...) {
802 HILOGE("Failed to UpdateFdSendRate");
803 return BError(BError::Codes::EXT_BROKEN_IPC).GetCode();
804 }
805 }
806
SetStagingPathProperties()807 bool BackupExtExtension::SetStagingPathProperties()
808 {
809 struct stat curBundleStat {};
810 if (lstat(BConstants::BUNDLE_BASE_DIR.c_str(), &curBundleStat) != 0) {
811 HILOGE("Failed to lstat, err = %{public}d", errno);
812 return false;
813 }
814 if (lchown(string(BConstants::PATH_BUNDLE_BACKUP_HOME).c_str(),
815 curBundleStat.st_uid, curBundleStat.st_gid) != 0) {
816 HILOGE("Failed to lchown, err = %{public}d", errno);
817 return false;
818 }
819 if (lchown(string(BConstants::PATH_BUNDLE_BACKUP_HOME_EL1).c_str(),
820 curBundleStat.st_uid, curBundleStat.st_gid) != 0) {
821 HILOGE("Failed to lchown, err = %{public}d", errno);
822 return false;
823 }
824 return true;
825 }
826
IfAllowToBackupRestore()827 bool BackupExtExtension::IfAllowToBackupRestore()
828 {
829 if (extension_ == nullptr) {
830 HILOGE("Failed to handle backup, extension is nullptr");
831 return false;
832 }
833 string usrConfig = extension_->GetUsrConfig();
834 BJsonCachedEntity<BJsonEntityExtensionConfig> cachedEntity(usrConfig);
835 auto cache = cachedEntity.Structuralize();
836 if (!cache.GetAllowToBackupRestore()) {
837 HILOGE("Application does not allow backup or restore");
838 return false;
839 }
840 return true;
841 }
842
User0OnBackup()843 ErrCode BackupExtExtension::User0OnBackup()
844 {
845 HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
846 if (!IfAllowToBackupRestore()) {
847 return BError(BError::Codes::EXT_FORBID_BACKUP_RESTORE, "Application does not allow backup or restore")
848 .GetCode();
849 }
850 AsyncTaskUser0Backup();
851 return ERR_OK;
852 }
853
AsyncTaskUser0Backup()854 void BackupExtExtension::AsyncTaskUser0Backup()
855 {
856 HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
857 auto task = [obj {wptr<BackupExtExtension>(this)}]() {
858 auto ptr = obj.promote();
859 BExcepUltils::BAssert(ptr, BError::Codes::EXT_BROKEN_FRAMEWORK, "Ext extension handle have been released");
860 BExcepUltils::BAssert(ptr->extension_, BError::Codes::EXT_INVAL_ARG, "Extension handle have been released");
861 const string config = ptr->extension_->GetUsrConfig();
862 try {
863 HILOGI("Do backup, start fwk timer begin.");
864 bool isFwkStart;
865 ptr->StartFwkTimer(isFwkStart);
866 if (!isFwkStart) {
867 HILOGE("Do backup, start fwk timer fail.");
868 return;
869 }
870 HILOGI("Do backup, start fwk timer end.");
871 BJsonCachedEntity<BJsonEntityExtensionConfig> cachedEntity(config);
872 auto cache = cachedEntity.Structuralize();
873 auto ret = ptr->User0DoBackup(cache);
874 if (ret != ERR_OK) {
875 HILOGE("User0DoBackup, err = %{public}d", ret);
876 ptr->AppIncrementalDone(BError::GetCodeByErrno(ret));
877 }
878 } catch (const BError &e) {
879 HILOGE("extension: AsyncTaskBackup error, err code:%{public}d", e.GetCode());
880 ptr->AppIncrementalDone(e.GetCode());
881 } catch (const exception &e) {
882 HILOGE("Catched an unexpected low-level exception %{public}s", e.what());
883 ptr->AppIncrementalDone(BError(BError::Codes::EXT_INVAL_ARG).GetCode());
884 } catch (...) {
885 HILOGE("Failed to restore the ext bundle");
886 ptr->AppIncrementalDone(BError(BError::Codes::EXT_INVAL_ARG).GetCode());
887 }
888 };
889
890 threadPool_.AddTask([task]() {
891 try {
892 task();
893 } catch (...) {
894 HILOGE("Failed to add task to thread pool");
895 }
896 });
897 }
898
DoUser0Backup(const BJsonEntityExtensionConfig & usrConfig)899 void BackupExtExtension::DoUser0Backup(const BJsonEntityExtensionConfig &usrConfig)
900 {
901 HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
902 string path = string(BConstants::PATH_BUNDLE_BACKUP_HOME).append(BConstants::SA_BUNDLE_BACKUP_BACKUP);
903 if (mkdir(path.data(), S_IRWXU) && errno != EEXIST) {
904 throw BError(errno);
905 }
906 vector<string> includes = usrConfig.GetIncludes();
907 vector<string> excludes = usrConfig.GetExcludes();
908 auto task = [obj {wptr<BackupExtExtension>(this)}, includes, excludes]() {
909 auto ptr = obj.promote();
910 BExcepUltils::BAssert(ptr, BError::Codes::EXT_BROKEN_FRAMEWORK, "Ext extension handle have been released");
911 try {
912 auto [bigFile, smallFile] = BDir::GetBackupList(includes, excludes);
913 vector<struct ReportFileInfo> allFiles;
914 vector<struct ReportFileInfo> smallFiles;
915 vector<struct ReportFileInfo> bigFiles;
916 BDir::GetUser0FileStat(move(bigFile), move(smallFile), allFiles, smallFiles, bigFiles);
917 auto ret = ptr->DoIncrementalBackup(allFiles, smallFiles, bigFiles);
918 ptr->AppIncrementalDone(ret);
919 HILOGI("User0 backup app done %{public}d", ret);
920 } catch (const BError &e) {
921 ptr->AppIncrementalDone(e.GetCode());
922 } catch (const exception &e) {
923 ptr->AppIncrementalDone(BError(BError::Codes::EXT_INVAL_ARG).GetCode());
924 } catch (...) {
925 HILOGE("Failed to restore the ext bundle");
926 ptr->AppIncrementalDone(BError(BError::Codes::EXT_INVAL_ARG).GetCode());
927 }
928 };
929
930 threadPool_.AddTask([task]() {
931 try {
932 task();
933 } catch (...) {
934 HILOGE("Failed to add task to thread pool");
935 }
936 });
937 }
938
User0DoBackup(const BJsonEntityExtensionConfig & usrConfig)939 int BackupExtExtension::User0DoBackup(const BJsonEntityExtensionConfig &usrConfig)
940 {
941 HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
942 HILOGI("Start Do User0Backup");
943 if (extension_ == nullptr) {
944 HILOGE("Failed to do backup, extension is nullptr");
945 return BError(BError::Codes::EXT_INVAL_ARG);
946 }
947 if (extension_->GetExtensionAction() != BConstants::ExtensionAction::BACKUP) {
948 return EPERM;
949 }
950 DoUser0Backup(usrConfig);
951 return ERR_OK;
952 }
953
954 /**
955 * 获取增量的大文件的信息
956 */
GetIncrmentBigInfos(const vector<struct ReportFileInfo> & files)957 static TarMap GetIncrmentBigInfos(const vector<struct ReportFileInfo> &files)
958 {
959 auto getStringHash = [](const TarMap &tarMap, const string &str) -> string {
960 ostringstream strHex;
961 strHex << hex;
962
963 hash<string> strHash;
964 size_t szHash = strHash(str);
965 strHex << setfill('0') << setw(BConstants::BIG_FILE_NAME_SIZE) << szHash;
966 string name = strHex.str();
967 for (int i = 0; tarMap.find(name) != tarMap.end(); ++i, strHex.str("")) {
968 szHash = strHash(str + to_string(i));
969 strHex << setfill('0') << setw(BConstants::BIG_FILE_NAME_SIZE) << szHash;
970 name = strHex.str();
971 }
972
973 return name;
974 };
975
976 TarMap bigFiles;
977 for (const auto &item : files) {
978 struct stat sta = {};
979 if (stat(item.filePath.c_str(), &sta) != 0) {
980 HILOGE("Failed to stat file %{public}s, err = %{public}d", item.filePath.c_str(), errno);
981 throw errno;
982 }
983 string md5Name = getStringHash(bigFiles, item.filePath);
984 if (!md5Name.empty()) {
985 bigFiles.emplace(md5Name, make_tuple(item.filePath, sta, true));
986 }
987 }
988
989 return bigFiles;
990 }
991
DoIncrementalBackupTask(UniqueFd incrementalFd,UniqueFd manifestFd)992 int BackupExtExtension::DoIncrementalBackupTask(UniqueFd incrementalFd, UniqueFd manifestFd)
993 {
994 auto start = std::chrono::system_clock::now();
995 vector<struct ReportFileInfo> allFiles;
996 vector<struct ReportFileInfo> smallFiles;
997 vector<struct ReportFileInfo> bigFiles;
998 FillFileInfos(move(incrementalFd), move(manifestFd), allFiles, smallFiles, bigFiles);
999 auto ret = DoIncrementalBackup(allFiles, smallFiles, bigFiles);
1000 if (ret == ERR_OK) {
1001 auto end = std::chrono::system_clock::now();
1002 auto cost = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
1003 if (cost >= BConstants::MAX_TIME_COST) {
1004 std::stringstream ss;
1005 ss << R"("spendTime": )"<< cost << R"(ms, "totalFiles": )" << allFiles.size() << R"(, "smallFiles": )"
1006 << smallFiles.size() << R"(, "bigFiles": )" << bigFiles.size();
1007 AppRadar::Info info(bundleName_, "", ss.str());
1008 AppRadar::GetInstance().RecordBackupFuncRes(info, "BackupExtExtension::DoIncrementalBackupTask",
1009 AppRadar::GetInstance().GetUserId(), BizStageBackup::BIZ_STAGE_DO_BACKUP, static_cast<int32_t>(ret));
1010 }
1011 }
1012 return ret;
1013 }
1014
AsyncTaskDoIncrementalBackup(UniqueFd incrementalFd,UniqueFd manifestFd)1015 void BackupExtExtension::AsyncTaskDoIncrementalBackup(UniqueFd incrementalFd, UniqueFd manifestFd)
1016 {
1017 HILOGI("Do IncrementalBackup, start fwk timer begin.");
1018 bool isFwkStart;
1019 StartFwkTimer(isFwkStart);
1020 if (!isFwkStart) {
1021 HILOGE("Do IncrementalBackup, start fwk timer fail.");
1022 return;
1023 }
1024 HILOGI("Do IncrementalBackup, start fwk timer end.");
1025 int incrementalFdDup = dup(incrementalFd);
1026 int manifestFdDup = dup(manifestFd);
1027 if (incrementalFdDup < 0) {
1028 throw BError(BError::Codes::EXT_INVAL_ARG, "dup failed");
1029 }
1030 auto task = [obj {wptr<BackupExtExtension>(this)}, manifestFdDup, incrementalFdDup]() {
1031 auto ptr = obj.promote();
1032 BExcepUltils::BAssert(ptr, BError::Codes::EXT_BROKEN_FRAMEWORK, "Ext extension handle have been released");
1033 try {
1034 UniqueFd incrementalDupFd(dup(incrementalFdDup));
1035 UniqueFd manifestDupFd(dup(manifestFdDup));
1036 if (incrementalDupFd < 0) {
1037 throw BError(BError::Codes::EXT_INVAL_ARG, "dup failed");
1038 }
1039 close(incrementalFdDup);
1040 close(manifestFdDup);
1041 auto ret = ptr->DoIncrementalBackupTask(move(incrementalDupFd), move(manifestDupFd));
1042 ptr->AppIncrementalDone(ret);
1043 HILOGI("Incremental backup app done %{public}d", ret);
1044 } catch (const BError &e) {
1045 ptr->AppIncrementalDone(e.GetCode());
1046 } catch (const exception &e) {
1047 HILOGE("Catched an unexpected low-level exception %{public}s", e.what());
1048 ptr->AppIncrementalDone(BError(BError::Codes::EXT_INVAL_ARG).GetCode());
1049 } catch (...) {
1050 HILOGE("Failed to restore the ext bundle");
1051 ptr->AppIncrementalDone(BError(BError::Codes::EXT_INVAL_ARG).GetCode());
1052 }
1053 };
1054
1055 threadPool_.AddTask([task]() {
1056 try {
1057 task();
1058 } catch (...) {
1059 HILOGE("Failed to add task to thread pool");
1060 }
1061 });
1062 }
1063
AsyncTaskOnIncrementalBackup()1064 void BackupExtExtension::AsyncTaskOnIncrementalBackup()
1065 {
1066 auto task = [obj {wptr<BackupExtExtension>(this)}]() {
1067 auto ptr = obj.promote();
1068 BExcepUltils::BAssert(ptr, BError::Codes::EXT_BROKEN_FRAMEWORK, "Ext extension handle have been released");
1069 BExcepUltils::BAssert(ptr->extension_, BError::Codes::EXT_INVAL_ARG, "Extension handle have been released");
1070 try {
1071 ptr->curScenario_ = BackupRestoreScenario::INCREMENTAL_BACKUP;
1072 if ((ptr->StartOnProcessTaskThread(obj, BackupRestoreScenario::INCREMENTAL_BACKUP)) != ERR_OK) {
1073 HILOGE("Call onProcess result is timeout");
1074 return;
1075 }
1076 auto callBackup = ptr->IncOnBackupCallback(obj);
1077 auto callBackupEx = ptr->IncOnBackupExCallback(obj);
1078 ptr->UpdateOnStartTime();
1079 ErrCode err = ptr->extension_->OnBackup(callBackup, callBackupEx);
1080 if (err != ERR_OK) {
1081 HILOGE("OnBackup done, err = %{public}d", err);
1082 ptr->AppIncrementalDone(BError::GetCodeByErrno(err));
1083 }
1084 } catch (const BError &e) {
1085 ptr->AppIncrementalDone(e.GetCode());
1086 } catch (const exception &e) {
1087 HILOGE("Catched an unexpected low-level exception %{public}s", e.what());
1088 ptr->AppIncrementalDone(BError(BError::Codes::EXT_INVAL_ARG).GetCode());
1089 } catch (...) {
1090 HILOGE("Failed to restore the ext bundle");
1091 ptr->AppIncrementalDone(BError(BError::Codes::EXT_INVAL_ARG).GetCode());
1092 }
1093 };
1094
1095 threadPool_.AddTask([task]() {
1096 try {
1097 task();
1098 } catch (...) {
1099 HILOGE("Failed to add task to thread pool");
1100 }
1101 });
1102 }
1103
GetIncrmentPartName()1104 static string GetIncrmentPartName()
1105 {
1106 auto now = chrono::system_clock::now();
1107 auto duration = now.time_since_epoch();
1108 auto milliseconds = chrono::duration_cast<chrono::milliseconds>(duration);
1109
1110 return to_string(milliseconds.count()) + "_part";
1111 }
1112
IncrementalPacket(const vector<struct ReportFileInfo> & infos,TarMap & tar,sptr<IService> proxy)1113 void BackupExtExtension::IncrementalPacket(const vector<struct ReportFileInfo> &infos, TarMap &tar,
1114 sptr<IService> proxy)
1115 {
1116 HILOGI("IncrementalPacket begin, infos count: %{public}zu", infos.size());
1117 string path = string(BConstants::PATH_BUNDLE_BACKUP_HOME).append(BConstants::SA_BUNDLE_BACKUP_BACKUP);
1118 uint64_t totalSize = 0;
1119 uint32_t fileCount = 0;
1120 vector<string> packFiles;
1121 vector<struct ReportFileInfo> tarInfos;
1122 TarFile::GetInstance().SetPacketMode(true); // 设置下打包模式
1123 auto startTime = std::chrono::system_clock::now();
1124 int fdNum = 0;
1125 string partName = GetIncrmentPartName();
1126 auto reportCb = ReportErrFileByProc(wptr<BackupExtExtension> {this}, curScenario_);
1127 for (const auto &small : infos) {
1128 totalSize += static_cast<uint64_t>(small.size);
1129 fileCount += 1;
1130 packFiles.emplace_back(small.filePath);
1131 tarInfos.emplace_back(small);
1132 if (totalSize >= BConstants::DEFAULT_SLICE_SIZE || fileCount >= BConstants::MAX_FILE_COUNT) {
1133 TarMap tarMap {};
1134 TarFile::GetInstance().Packet(packFiles, partName, path, tarMap, reportCb);
1135 tar.insert(tarMap.begin(), tarMap.end());
1136 // 执行tar包回传功能
1137 WaitToSendFd(startTime, fdNum);
1138 IncrementalTarFileReady(tarMap, tarInfos, proxy);
1139 totalSize = 0;
1140 fileCount = 0;
1141 packFiles.clear();
1142 tarInfos.clear();
1143 fdNum += BConstants::FILE_AND_MANIFEST_FD_COUNT;
1144 RefreshTimeInfo(startTime, fdNum);
1145 }
1146 }
1147 if (fileCount > 0) {
1148 // 打包回传
1149 TarMap tarMap {};
1150 TarFile::GetInstance().Packet(packFiles, partName, path, tarMap, reportCb);
1151 IncrementalTarFileReady(tarMap, tarInfos, proxy);
1152 fdNum = 1;
1153 WaitToSendFd(startTime, fdNum);
1154 tar.insert(tarMap.begin(), tarMap.end());
1155 packFiles.clear();
1156 tarInfos.clear();
1157 RefreshTimeInfo(startTime, fdNum);
1158 }
1159 }
1160
DoIncrementalBackup(const vector<struct ReportFileInfo> & allFiles,const vector<struct ReportFileInfo> & smallFiles,const vector<struct ReportFileInfo> & bigFiles)1161 int BackupExtExtension::DoIncrementalBackup(const vector<struct ReportFileInfo> &allFiles,
1162 const vector<struct ReportFileInfo> &smallFiles,
1163 const vector<struct ReportFileInfo> &bigFiles)
1164 {
1165 HILOGI("Do increment backup begin");
1166 if (extension_ == nullptr) {
1167 HILOGE("Failed to do incremental backup, extension is nullptr");
1168 throw BError(BError::Codes::EXT_INVAL_ARG, "Extension is nullptr");
1169 }
1170 if (extension_->GetExtensionAction() != BConstants::ExtensionAction::BACKUP) {
1171 return EPERM;
1172 }
1173 string path = string(BConstants::PATH_BUNDLE_BACKUP_HOME).append(BConstants::SA_BUNDLE_BACKUP_BACKUP);
1174 if (mkdir(path.data(), S_IRWXU) && errno != EEXIST) {
1175 throw BError(errno);
1176 }
1177 auto proxy = ServiceProxy::GetInstance();
1178 if (proxy == nullptr) {
1179 throw BError(BError::Codes::EXT_BROKEN_BACKUP_SA, std::generic_category().message(errno));
1180 }
1181 // 获取增量文件和全量数据
1182 if (smallFiles.empty() && bigFiles.empty()) {
1183 // 没有增量,则不需要上传
1184 TarMap tMap;
1185 ErrCode err = IncrementalAllFileReady(tMap, allFiles, proxy);
1186 HILOGI("Do increment backup, IncrementalAllFileReady end, file empty");
1187 return err;
1188 }
1189 // tar包数据
1190 TarMap tarMap;
1191 IncrementalPacket(smallFiles, tarMap, proxy);
1192 HILOGI("Do increment backup, IncrementalPacket end");
1193 // 最后回传大文件
1194 TarMap bigMap = GetIncrmentBigInfos(bigFiles);
1195 IncrementalBigFileReady(bigMap, bigFiles, proxy);
1196 HILOGI("Do increment backup, IncrementalBigFileReady end");
1197 bigMap.insert(tarMap.begin(), tarMap.end());
1198 // 回传manage.json和全量文件
1199 ErrCode err = IncrementalAllFileReady(bigMap, allFiles, proxy);
1200 HILOGI("End, bigFiles num:%{public}zu, smallFiles num:%{public}zu, allFiles num:%{public}zu", bigFiles.size(),
1201 smallFiles.size(), allFiles.size());
1202 return err;
1203 }
1204
ReportOnProcessResultCallback(wptr<BackupExtExtension> obj,BackupRestoreScenario scenario)1205 std::function<void(ErrCode, std::string)> BackupExtExtension::ReportOnProcessResultCallback(
1206 wptr<BackupExtExtension> obj, BackupRestoreScenario scenario)
1207 {
1208 return [obj, scenario](ErrCode errCode, const std::string processInfo) {
1209 auto extPtr = obj.promote();
1210 if (extPtr == nullptr) {
1211 HILOGE("Async call js onPreocess callback failed, exPtr is empty");
1212 return;
1213 }
1214 if (extPtr->onProcessTimeout_.load()) {
1215 HILOGE("The result of invoking onProcess is timeout.");
1216 extPtr->onProcessTimeout_.store(false);
1217 return;
1218 }
1219 extPtr->CloseOnProcessTimeOutTimer();
1220 extPtr->isFirstCallOnProcess_.store(false);
1221 extPtr->onProcessTimeout_.store(false);
1222 if (extPtr->onProcessTimeoutCnt_.load() > 0) {
1223 extPtr->onProcessTimeoutCnt_ = 0;
1224 HILOGI("onProcess execute success, reset onProcessTimeoutCnt");
1225 }
1226 if (processInfo.size() == 0) {
1227 HILOGE("Current extension has no js method named onProcess.");
1228 std::unique_lock<std::mutex> lock(extPtr->onProcessLock_);
1229 extPtr->isFirstCallOnProcess_.store(false);
1230 extPtr->stopCallJsOnProcess_.store(true);
1231 extPtr->execOnProcessCon_.notify_one();
1232 lock.unlock();
1233 return;
1234 }
1235 std::string processInfoJsonStr;
1236 BJsonUtil::BuildOnProcessRetInfo(processInfoJsonStr, processInfo);
1237 auto task = [obj, scenario, processInfoJsonStr]() {
1238 auto reportExtPtr = obj.promote();
1239 if (reportExtPtr == nullptr) {
1240 HILOGE("Report onProcess Result error, reportExtPtr is empty");
1241 return;
1242 }
1243 reportExtPtr->ReportAppProcessInfo(processInfoJsonStr, scenario);
1244 };
1245 extPtr->reportOnProcessRetPool_.AddTask([task]() { task(); });
1246 };
1247 }
1248
FillFileInfosWithoutCmp(vector<struct ReportFileInfo> & allFiles,vector<struct ReportFileInfo> & smallFiles,vector<struct ReportFileInfo> & bigFiles,UniqueFd incrementalFd)1249 void BackupExtExtension::FillFileInfosWithoutCmp(vector<struct ReportFileInfo> &allFiles,
1250 vector<struct ReportFileInfo> &smallFiles,
1251 vector<struct ReportFileInfo> &bigFiles,
1252 UniqueFd incrementalFd)
1253 {
1254 HILOGI("Fill file info without cmp begin");
1255 BReportEntity storageRp(move(incrementalFd));
1256 unordered_map<string, struct ReportFileInfo> localFilesInfo;
1257 while (storageRp.GetStorageReportInfos(localFilesInfo)) {
1258 for (auto localIter = localFilesInfo.begin(); localIter != localFilesInfo.end(); ++localIter) {
1259 const string &path = localIter->second.filePath;
1260 if (path.empty()) {
1261 HILOGE("GetStorageReportInfos failed");
1262 continue;
1263 }
1264 if (localIter->second.isIncremental && localIter->second.isDir) {
1265 smallFiles.emplace_back(localIter->second);
1266 }
1267 if (localIter->second.isDir) {
1268 allFiles.emplace_back(localIter->second);
1269 continue;
1270 }
1271 auto [res, fileHash] = BackupFileHash::HashWithSHA256(path);
1272 if (fileHash.empty()) {
1273 HILOGE("Do hash err, fileHash is empty, path: %{public}s", GetAnonyPath(path).c_str());
1274 continue;
1275 }
1276 localIter->second.hash = fileHash;
1277 if (ExtractFileExt(path) == "tar") {
1278 localIter->second.userTar = 1; // 1: default value, means true
1279 }
1280 allFiles.emplace_back(localIter->second);
1281 if (!localIter->second.isIncremental) {
1282 HILOGE("It's not incre, no need record %{public}s", GetAnonyPath(path).c_str());
1283 continue;
1284 }
1285 if (localIter->second.size <= BConstants::BIG_FILE_BOUNDARY) {
1286 smallFiles.emplace_back(localIter->second);
1287 continue;
1288 }
1289 bigFiles.emplace_back(localIter->second);
1290 }
1291 localFilesInfo.clear();
1292 }
1293 }
1294
FillFileInfosWithCmp(vector<struct ReportFileInfo> & allFiles,vector<struct ReportFileInfo> & smallFiles,vector<struct ReportFileInfo> & bigFiles,const unordered_map<string,struct ReportFileInfo> & cloudFiles,UniqueFd incrementalFd)1295 void BackupExtExtension::FillFileInfosWithCmp(vector<struct ReportFileInfo> &allFiles,
1296 vector<struct ReportFileInfo> &smallFiles,
1297 vector<struct ReportFileInfo> &bigFiles,
1298 const unordered_map<string, struct ReportFileInfo> &cloudFiles,
1299 UniqueFd incrementalFd)
1300 {
1301 HILOGI("Fill file info with cmp begin");
1302 BReportEntity storageRp(move(incrementalFd));
1303 unordered_map<string, struct ReportFileInfo> localFilesInfo;
1304 while (storageRp.GetStorageReportInfos(localFilesInfo)) {
1305 CompareFiles(allFiles, smallFiles, bigFiles, cloudFiles, localFilesInfo);
1306 localFilesInfo.clear();
1307 }
1308 }
1309
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)1310 void BackupExtExtension::CompareFiles(vector<struct ReportFileInfo> &allFiles,
1311 vector<struct ReportFileInfo> &smallFiles,
1312 vector<struct ReportFileInfo> &bigFiles,
1313 const unordered_map<string, struct ReportFileInfo> &cloudFiles,
1314 unordered_map<string, struct ReportFileInfo> &localFilesInfo)
1315 {
1316 for (auto localIter = localFilesInfo.begin(); localIter != localFilesInfo.end(); ++localIter) {
1317 // 进行文件对比, 当后续使用 isUserTar 字段时需注意 字段解析函数
1318 const string &path = localIter->second.filePath;
1319 if (path.empty()) {
1320 HILOGE("GetStorageReportInfos failed");
1321 continue;
1322 }
1323 auto it = cloudFiles.find(path);
1324 bool isExist = (it != cloudFiles.end());
1325 if (localIter->second.isIncremental && !isExist && localIter->second.isDir) {
1326 smallFiles.emplace_back(localIter->second);
1327 }
1328 if (localIter->second.isDir) {
1329 allFiles.emplace_back(localIter->second);
1330 continue;
1331 }
1332 bool isChange = !(isExist && localIter->second.size == it->second.size &&
1333 localIter->second.mtime == it->second.mtime);
1334 if (isChange) {
1335 auto [res, fileHash] = BackupFileHash::HashWithSHA256(path);
1336 if (fileHash.empty()) {
1337 HILOGE("Do hash err, fileHash is empty");
1338 continue;
1339 }
1340 localIter->second.hash = fileHash;
1341 } else {
1342 localIter->second.hash = it->second.hash;
1343 }
1344
1345 if (ExtractFileExt(path) == "tar") {
1346 localIter->second.userTar = 1; // 1: default value, means true
1347 }
1348
1349 allFiles.emplace_back(localIter->second);
1350 if (localIter->second.isIncremental && (!isExist ||
1351 it->second.hash != localIter->second.hash)) {
1352 // 在云空间简报里不存在或者hash不一致
1353 if (localIter->second.size <= BConstants::BIG_FILE_BOUNDARY) {
1354 smallFiles.emplace_back(localIter->second);
1355 continue;
1356 }
1357 bigFiles.emplace_back(localIter->second);
1358 }
1359 }
1360 }
1361
IfCloudSpecialRestore(string tarName)1362 bool BackupExtExtension::IfCloudSpecialRestore(string tarName)
1363 {
1364 unordered_map<string, struct ReportFileInfo> result;
1365 GetTarIncludes(tarName, result);
1366 if (result.empty()) {
1367 HILOGI("is not CloudSpecialRestore");
1368 return false;
1369 }
1370 HILOGI("is CloudSpecialRestore");
1371 return true;
1372 }
1373
CloudSpecialRestore(string tarName,string untarPath,off_t tarFileSize)1374 ErrCode BackupExtExtension::CloudSpecialRestore(string tarName, string untarPath, off_t tarFileSize)
1375 {
1376 unordered_map<string, struct ReportFileInfo> result;
1377 GetTarIncludes(tarName, result);
1378 if (isDebug_) {
1379 FillEndFileInfos(untarPath, result);
1380 }
1381 auto unPacketRes = UntarFile::GetInstance().IncrementalUnPacket(tarName, untarPath, result);
1382 ErrCode err = ERR_OK;
1383 err = std::get<FIRST_PARAM>(unPacketRes);
1384 if (int tmpErr = DealIncreUnPacketResult(tarFileSize, tarName, unPacketRes); tmpErr != ERR_OK) {
1385 return BError(BError::Codes::EXT_FORBID_BACKUP_RESTORE).GetCode();
1386 }
1387 HILOGI("Application recovered successfully, package path is %{public}s", tarName.c_str());
1388 DeleteBackupIncrementalTars(tarName);
1389 return err;
1390 }
1391
RmBigFileReportForSpecialCloneCloud(const std::string & srcFileName)1392 void BackupExtExtension::RmBigFileReportForSpecialCloneCloud(const std::string &srcFileName)
1393 {
1394 // 删除大文件的rp文件
1395 string reportFileName = GetReportFileName(srcFileName);
1396 std::unique_lock<std::mutex> lock(reportHashLock_);
1397 if (reportHashSrcPathMap_.empty()) {
1398 if (!RemoveFile(reportFileName)) {
1399 HILOGE("Failed to delete backup report %{public}s, err = %{public}d",
1400 GetAnonyPath(reportFileName).c_str(), errno);
1401 }
1402 return;
1403 }
1404 auto iter = reportHashSrcPathMap_.find(srcFileName);
1405 if (iter == reportHashSrcPathMap_.end()) {
1406 if (!RemoveFile(reportFileName)) {
1407 HILOGE("Failed to remove cuurent file report %{public}s, err = %{public}d",
1408 GetAnonyPath(reportFileName).c_str(), errno);
1409 }
1410 return;
1411 }
1412 std::string reportHashFilePath = iter->second;
1413 HILOGI("Will remove current reportHashFile, reportHashFilePath:%{public}s",
1414 GetAnonyPath(reportHashFilePath).c_str());
1415 if (!RemoveFile(reportHashFilePath)) {
1416 HILOGE("Failed to delete backup report %{public}s, err = %{public}d",
1417 GetAnonyPath(reportHashFilePath).c_str(), errno);
1418 }
1419 reportHashSrcPathMap_.erase(iter);
1420 }
1421 } // namespace OHOS::FileManagement::Backup
1422