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