• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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