1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "ext_extension.h"
17 
18 #include <algorithm>
19 #include <chrono>
20 #include <fstream>
21 #include <iomanip>
22 #include <map>
23 #include <regex>
24 #include <string>
25 #include <thread>
26 #include <tuple>
27 #include <unordered_map>
28 #include <vector>
29 
30 #include <directory_ex.h>
31 #include <sys/stat.h>
32 #include <unistd.h>
33 
34 #include <directory_ex.h>
35 #include <unique_fd.h>
36 
37 #include "accesstoken_kit.h"
38 #include "bundle_mgr_client.h"
39 #include "errors.h"
40 #include "ipc_skeleton.h"
41 
42 #include "b_error/b_error.h"
43 #include "b_error/b_excep_utils.h"
44 #include "b_filesystem/b_dir.h"
45 #include "b_filesystem/b_file.h"
46 #include "b_filesystem/b_file_hash.h"
47 #include "b_json/b_json_cached_entity.h"
48 #include "b_jsonutil/b_jsonutil.h"
49 #include "b_ohos/startup/backup_para.h"
50 #include "b_radar/b_radar.h"
51 #include "b_tarball/b_tarball_factory.h"
52 #include "filemgmt_libhilog.h"
53 #include "hitrace_meter.h"
54 #include "i_service.h"
55 #include "sandbox_helper.h"
56 #include "service_proxy.h"
57 #include "tar_file.h"
58 #include "b_anony/b_anony.h"
59 
60 namespace OHOS::FileManagement::Backup {
61 const uint32_t MAX_FD_GROUP_USE_TIME = 1000; // 每组打开最大时间1000ms
62 
WaitToSendFd(std::chrono::system_clock::time_point & startTime,int & fdSendNum)63 void BackupExtExtension::WaitToSendFd(std::chrono::system_clock::time_point &startTime, int &fdSendNum)
64 {
65     HILOGD("WaitToSendFd Begin");
66     std::unique_lock<std::mutex> lock(startSendMutex_);
67     startSendFdRateCon_.wait(lock, [this] { return sendRate_ > 0; });
68     if (fdSendNum >= sendRate_) {
69         HILOGI("current time fd num is max rate, bundle name:%{public}s, rate:%{public}d", bundleName_.c_str(),
70             sendRate_);
71         auto curTime = std::chrono::system_clock::now();
72         auto useTimeMs = std::chrono::duration_cast<std::chrono::milliseconds>(curTime - startTime).count();
73         if (useTimeMs < MAX_FD_GROUP_USE_TIME) {
74             int32_t sleepTime = MAX_FD_GROUP_USE_TIME - useTimeMs;
75             HILOGI("will wait time:%{public}d ms", sleepTime);
76             std::this_thread::sleep_for(std::chrono::milliseconds(sleepTime));
77         } else {
78             HILOGW("current fd send num exceeds one second");
79         }
80         fdSendNum = 0;
81         startTime = std::chrono::system_clock::now();
82     }
83     HILOGD("WaitToSendFd End");
84 }
85 
RefreshTimeInfo(std::chrono::system_clock::time_point & startTime,int & fdSendNum)86 void BackupExtExtension::RefreshTimeInfo(std::chrono::system_clock::time_point &startTime, int &fdSendNum)
87 {
88     auto currentTime = std::chrono::system_clock::now();
89     auto useTime = std::chrono::duration_cast<std::chrono::milliseconds>(currentTime - startTime).count();
90     if (useTime >= MAX_FD_GROUP_USE_TIME) {
91         HILOGI("RefreshTimeInfo Begin, fdSendNum is:%{public}d", fdSendNum);
92         startTime = std::chrono::system_clock::now();
93         fdSendNum = 0;
94     }
95 }
96 
SetClearDataFlag(bool isClearData)97 void BackupExtExtension::SetClearDataFlag(bool isClearData)
98 {
99     isClearData_ = isClearData;
100     HILOGI("set clear data flag:%{public}d", isClearData);
101     if (extension_ == nullptr) {
102         HILOGE("Extension handle have been released");
103         return;
104     }
105     if (!extension_->WasFromSpecialVersion() && !extension_->RestoreDataReady()) {
106         DoClear();
107     }
108 }
109 
GetBundlePath()110 string BackupExtExtension::GetBundlePath()
111 {
112     if (bundleName_ == BConstants::BUNDLE_FILE_MANAGER) {
113         return string(BConstants::PATH_FILEMANAGE_BACKUP_HOME).append(BConstants::SA_BUNDLE_BACKUP_RESTORE);
114     } else if (bundleName_ == BConstants::BUNDLE_MEDIAL_DATA) {
115         return string(BConstants::PATH_MEDIALDATA_BACKUP_HOME).append(BConstants::SA_BUNDLE_BACKUP_RESTORE);
116     }
117     return string(BConstants::PATH_BUNDLE_BACKUP_HOME).append(BConstants::SA_BUNDLE_BACKUP_RESTORE);
118 }
119 
GetIdxFileInfos(bool isSpecialVersion)120 std::map<std::string, off_t> BackupExtExtension::GetIdxFileInfos(bool isSpecialVersion)
121 {
122     string restoreDir = isSpecialVersion ? "" : GetBundlePath();
123     auto extManageInfo = GetExtManageInfo();
124     std::map<std::string, off_t> idxFileInfos;
125     for (size_t i = 0; i < extManageInfo.size(); ++i) {
126         std::string realPath = restoreDir + extManageInfo[i].hashName;
127         idxFileInfos[realPath] = extManageInfo[i].sta.st_size;
128     }
129     return idxFileInfos;
130 }
131 
CheckTmpDirFileInfos(bool isSpecialVersion)132 void BackupExtExtension::CheckTmpDirFileInfos(bool isSpecialVersion)
133 {
134     ErrFileInfo errFiles;
135     auto idxFileInfos = GetIdxFileInfos(isSpecialVersion);
136     struct stat attr;
137     for (auto it : idxFileInfos) {
138         if (it.first.size() >= PATH_MAX || stat(it.first.data(), &attr) == -1) {
139             HILOGE("(Debug) Failed to get stat of %{public}s, errno = %{public}d", GetAnonyPath(it.first).c_str(),
140                 errno);
141             errFiles[it.first].push_back(errno);
142         } else if (it.second != attr.st_size && (!S_ISDIR(attr.st_mode))) {
143             HILOGE("(Debug) RecFile:%{public}s size err, recSize: %{public}" PRId64 ", idxSize: %{public}" PRId64 "",
144                 GetAnonyPath(it.first).c_str(), attr.st_size, it.second);
145             errFiles[it.first] = std::vector<int>();
146         }
147     }
148     HILOGE("(Debug) Temp file check result: Total file: %{public}zu, err file: %{public}zu", idxFileInfos.size(),
149         errFiles.size());
150     if (!errFiles.empty()) {
151         HILOGE("(Debug) The received file and idx is not same");
152         std::stringstream ss;
153         ss << R"("totalFile": )" << idxFileInfos.size() << R"(, "restoreFile": )"
154             << idxFileInfos.size() - errFiles.size() << R"(, "info": "different received file and idx")";
155         AppRadar::Info info (bundleName_, "", ss.str());
156         AppRadar::GetInstance().RecordRestoreFuncRes(info, "BackupExtExtension::CheckTmpDirFileInfos",
157             AppRadar::GetInstance().GetUserId(), BizStageRestore::BIZ_STAGE_CHECK_DATA_FAIL,
158             static_cast<int32_t>(BError::BackupErrorCode::E_UKERR));
159     } else {
160         HILOGI("(Debug) The received file and idx is same");
161     }
162 }
163 
CheckRestoreFileInfos()164 tuple<bool, vector<string>> BackupExtExtension::CheckRestoreFileInfos()
165 {
166     vector<string> errFiles;
167     struct stat curFileStat {};
168     for (const auto &it : endFileInfos_) {
169         if (lstat(it.first.c_str(), &curFileStat) != 0) {
170             HILOGE("Failed to lstat %{public}s, err = %{public}d", GetAnonyPath(it.first).c_str(), errno);
171             errFiles.emplace_back(it.first);
172             errFileInfos_[it.first].push_back(errno);
173         } else if (curFileStat.st_size != it.second && (!S_ISDIR(curFileStat.st_mode))) {
174             HILOGE("File size error, file: %{public}s, idx: %{public}" PRId64 ", act: %{public}" PRId64 "",
175                 GetAnonyPath(it.first).c_str(), it.second, curFileStat.st_size);
176             errFiles.emplace_back(it.first);
177             errFileInfos_[it.first].push_back(errno);
178         }
179     }
180     for (const auto &it : errFileInfos_) {
181         for (const auto &codeIt : it.second) {
182             HILOGE("(Debug)  errfileInfos file = %{public}s -> %{public}d", GetAnonyPath(it.first).c_str(), codeIt);
183         }
184     }
185     HILOGE("(Debug) End file check result Total file: %{public}zu, err file: %{public}zu", endFileInfos_.size(),
186         errFileInfos_.size());
187     if (errFiles.size()) {
188         std::stringstream ss;
189         ss << R"("totalFile": )" << endFileInfos_.size() << R"(, "restoreFile": )"
190             << endFileInfos_.size() - errFileInfos_.size();
191         AppRadar::Info info (bundleName_, "", ss.str());
192         AppRadar::GetInstance().RecordRestoreFuncRes(info, "BackupExtExtension::CheckRestoreFileInfos",
193             AppRadar::GetInstance().GetUserId(), BizStageRestore::BIZ_STAGE_CHECK_DATA_FAIL,
194             static_cast<int32_t>(BError::BackupErrorCode::E_UKERR));
195         return { false, errFiles };
196     }
197     return { true, errFiles };
198 }
199 
OnRestoreCallback(wptr<BackupExtExtension> obj)200 std::function<void(ErrCode, std::string)> BackupExtExtension::OnRestoreCallback(wptr<BackupExtExtension> obj)
201 {
202     HILOGI("Begin get full restore onRestore callback");
203     return [obj](ErrCode errCode, std::string errMsg) {
204         auto extensionPtr = obj.promote();
205         if (extensionPtr == nullptr) {
206             HILOGE("Ext extension handle have been released");
207             return;
208         }
209         if (extensionPtr->isExecAppDone_.load()) {
210             HILOGE("Appdone has been executed for the current application");
211             return;
212         }
213         HILOGI("Current bundle will execute app done");
214         if (errCode == ERR_OK) {
215             auto spendTime = extensionPtr->GetOnStartTimeCost();
216             if (spendTime >= BConstants::MAX_TIME_COST) {
217                 std::stringstream ss;
218                 ss << R"("spendTime": )"<< spendTime << "ms";
219                 AppRadar::Info info (extensionPtr->bundleName_, "", ss.str());
220                 AppRadar::GetInstance().RecordRestoreFuncRes(info, "BackupExtExtension::OnRestoreCallback",
221                     AppRadar::GetInstance().GetUserId(), BizStageRestore::BIZ_STAGE_ON_RESTORE, ERR_OK);
222             }
223         }
224         extensionPtr->FinishOnProcessTask();
225         if (errMsg.empty()) {
226             extensionPtr->AppDone(errCode);
227         } else {
228             std::string errInfo;
229             BJsonUtil::BuildExtensionErrInfo(errInfo, errCode, errMsg);
230             extensionPtr->AppResultReport(errInfo, BackupRestoreScenario::FULL_RESTORE, errCode);
231         }
232         extensionPtr->DoClear();
233     };
234 }
235 
OnRestoreExCallback(wptr<BackupExtExtension> obj)236 std::function<void(ErrCode, std::string)> BackupExtExtension::OnRestoreExCallback(wptr<BackupExtExtension> obj)
237 {
238     HILOGI("Begin get full restore onRestoreEx callback");
239     return [obj](ErrCode errCode, const std::string restoreRetInfo) {
240         auto extensionPtr = obj.promote();
241         if (extensionPtr == nullptr) {
242             HILOGE("Ext extension handle have been released");
243             return;
244         }
245         if (extensionPtr->extension_ == nullptr) {
246             HILOGE("Extension handle have been released");
247             return;
248         }
249         if (extensionPtr->isExecAppDone_.load()) {
250             HILOGE("Appdone has been executed for the current application");
251             return;
252         }
253         if (errCode == ERR_OK && !restoreRetInfo.empty()) {
254             auto spendTime = extensionPtr->GetOnStartTimeCost();
255             if (spendTime >= BConstants::MAX_TIME_COST) {
256                 std::stringstream ss;
257                 ss << R"("spendTime": )"<< spendTime << "ms";
258                 AppRadar::Info info (extensionPtr->bundleName_, "", ss.str());
259                 AppRadar::GetInstance().RecordRestoreFuncRes(info, "BackupExtExtension::OnRestoreExCallback",
260                     AppRadar::GetInstance().GetUserId(), BizStageRestore::BIZ_STAGE_ON_RESTORE, ERR_OK);
261             }
262         }
263         extensionPtr->FinishOnProcessTask();
264         extensionPtr->extension_->InvokeAppExtMethod(errCode, restoreRetInfo);
265         if (errCode == ERR_OK) {
266             if (restoreRetInfo.size()) {
267                 HILOGI("Will notify restore result report");
268                 extensionPtr->AppResultReport(restoreRetInfo, BackupRestoreScenario::FULL_RESTORE);
269             }
270             return;
271         }
272         if (restoreRetInfo.empty()) {
273             extensionPtr->AppDone(errCode);
274             extensionPtr->DoClear();
275         } else {
276             std::string errInfo;
277             BJsonUtil::BuildExtensionErrInfo(errInfo, errCode, restoreRetInfo);
278             extensionPtr->AppResultReport(errInfo, BackupRestoreScenario::FULL_RESTORE, errCode);
279             extensionPtr->DoClear();
280         }
281     };
282 }
283 
AppDoneCallbackEx(wptr<BackupExtExtension> obj)284 std::function<void(ErrCode, std::string)> BackupExtExtension::AppDoneCallbackEx(wptr<BackupExtExtension> obj)
285 {
286     HILOGI("Begin get callback for appDone");
287     return [obj](ErrCode errCode, std::string errMsg) {
288         HILOGI("begin call callBackupExAppDone");
289         auto extensionPtr = obj.promote();
290         if (extensionPtr == nullptr) {
291             HILOGE("Ext extension handle have been released");
292             return;
293         }
294         extensionPtr->AppDone(errCode);
295         extensionPtr->DoClear();
296     };
297 }
298 
IncreOnRestoreExCallback(wptr<BackupExtExtension> obj)299 std::function<void(ErrCode, std::string)> BackupExtExtension::IncreOnRestoreExCallback(wptr<BackupExtExtension> obj)
300 {
301     HILOGI("Begin get callback for increment onRestoreEx");
302     return [obj](ErrCode errCode, const std::string restoreRetInfo) {
303         HILOGI("begin call increment restoreEx");
304         auto extensionPtr = obj.promote();
305         if (extensionPtr == nullptr) {
306             HILOGE("Ext extension handle have been released");
307             return;
308         }
309         if (extensionPtr->extension_ == nullptr) {
310             HILOGE("Extension handle have been released");
311             return;
312         }
313         if (extensionPtr->isExecAppDone_.load()) {
314             HILOGE("Appdone has been executed for the current application");
315             return;
316         }
317         if (errCode == ERR_OK && !restoreRetInfo.empty()) {
318             auto spendTime = extensionPtr->GetOnStartTimeCost();
319             if (spendTime >= BConstants::MAX_TIME_COST) {
320                 std::stringstream ss;
321                 ss << R"("spendTime": )"<< spendTime << "ms";
322                 AppRadar::Info info (extensionPtr->bundleName_, "", ss.str());
323                 AppRadar::GetInstance().RecordRestoreFuncRes(info, "BackupExtExtension::IncreOnRestoreExCallback",
324                     AppRadar::GetInstance().GetUserId(),
325                     BizStageRestore::BIZ_STAGE_ON_RESTORE, ERR_OK);
326             }
327         }
328         extensionPtr->FinishOnProcessTask();
329         extensionPtr->extension_->InvokeAppExtMethod(errCode, restoreRetInfo);
330         if (errCode == ERR_OK) {
331             if (restoreRetInfo.size()) {
332                 extensionPtr->AppResultReport(restoreRetInfo, BackupRestoreScenario::INCREMENTAL_RESTORE);
333             }
334             return;
335         }
336         if (restoreRetInfo.empty()) {
337             extensionPtr->AppIncrementalDone(errCode);
338             extensionPtr->DoClear();
339         } else {
340             std::string errInfo;
341             BJsonUtil::BuildExtensionErrInfo(errInfo, errCode, restoreRetInfo);
342             extensionPtr->AppResultReport(errInfo, BackupRestoreScenario::INCREMENTAL_RESTORE, errCode);
343             extensionPtr->DoClear();
344         }
345     };
346 }
347 
IncreOnRestoreCallback(wptr<BackupExtExtension> obj)348 std::function<void(ErrCode, std::string)> BackupExtExtension::IncreOnRestoreCallback(wptr<BackupExtExtension> obj)
349 {
350     return [obj](ErrCode errCode, std::string errMsg) {
351         auto extensionPtr = obj.promote();
352         if (extensionPtr == nullptr) {
353             HILOGE("Ext extension handle have been released");
354             return;
355         }
356         if (extensionPtr->isExecAppDone_.load()) {
357             HILOGE("Appdone has been executed for the current application");
358             return;
359         }
360         HILOGI("Current bundle will execute app done");
361         if (errCode == ERR_OK) {
362             auto spendTime = extensionPtr->GetOnStartTimeCost();
363             if (spendTime >= BConstants::MAX_TIME_COST) {
364                 std::stringstream ss;
365                 ss << R"("spendTime": )"<< spendTime << "ms";
366                 AppRadar::Info info (extensionPtr->bundleName_, "", ss.str());
367                 AppRadar::GetInstance().RecordRestoreFuncRes(info, "BackupExtExtension::IncreOnRestoreCallback",
368                     AppRadar::GetInstance().GetUserId(), BizStageRestore::BIZ_STAGE_ON_RESTORE, ERR_OK);
369             }
370         }
371         extensionPtr->FinishOnProcessTask();
372         if (errMsg.empty()) {
373             extensionPtr->AppIncrementalDone(errCode);
374         } else {
375             std::string errInfo;
376             BJsonUtil::BuildExtensionErrInfo(errInfo, errCode, errMsg);
377             extensionPtr->AppResultReport(errInfo, BackupRestoreScenario::INCREMENTAL_RESTORE, errCode);
378         }
379         extensionPtr->DoClear();
380     };
381 }
382 
GetOnStartTimeCost()383 int32_t BackupExtExtension::GetOnStartTimeCost()
384 {
385     auto onBackupRestoreEnd = std::chrono::system_clock::now();
386     std::lock_guard<std::mutex> lock(onStartTimeLock_);
387     auto spendTime = std::chrono::duration_cast<std::chrono::milliseconds>(onBackupRestoreEnd - g_onStart).count();
388     return spendTime;
389 }
390 
OnBackupCallback(wptr<BackupExtExtension> obj)391 std::function<void(ErrCode, const std::string)> BackupExtExtension::OnBackupCallback(wptr<BackupExtExtension> obj)
392 {
393     HILOGI("Begin get HandleFullBackupCallbackEx");
394     return [obj](ErrCode errCode, std::string errMsg) {
395         HILOGI("begin call backup");
396         auto extensionPtr = obj.promote();
397         if (extensionPtr == nullptr) {
398             HILOGE("Ext extension handle have been released");
399             return;
400         }
401         if (extensionPtr->extension_ == nullptr) {
402             HILOGE("Extension handle have been released");
403             return;
404         }
405         if (extensionPtr->isExecAppDone_.load()) {
406             HILOGE("Appdone has been executed for the current application");
407             return;
408         }
409         extensionPtr->FinishOnProcessTask();
410         if (errCode == ERR_OK) {
411             auto spendTime = extensionPtr->GetOnStartTimeCost();
412             if (spendTime >= BConstants::MAX_TIME_COST) {
413                 AppRadar::Info info(extensionPtr->bundleName_, "", string("\"spend_time\":\" ").
414                     append(to_string(spendTime)).append(string("ms\"")));
415                 AppRadar::GetInstance().RecordBackupFuncRes(info, "BackupExtExtension::OnBackupCallback",
416                     AppRadar::GetInstance().GetUserId(), BizStageBackup::BIZ_STAGE_ON_BACKUP,
417                     static_cast<int32_t>(ERR_OK));
418             }
419             extensionPtr->AsyncTaskBackup(extensionPtr->extension_->GetUsrConfig());
420             return;
421         }
422         HILOGE("Call extension onBackup failed, errInfo = %{public}s", errMsg.c_str());
423         if (!errMsg.empty()) {
424             std::string errInfo;
425             BJsonUtil::BuildExtensionErrInfo(errInfo, errCode, errMsg);
426             extensionPtr->AppResultReport(errInfo, BackupRestoreScenario::FULL_BACKUP, errCode);
427         }
428         extensionPtr->AppDone(errCode);
429         extensionPtr->DoClear();
430     };
431 }
432 
OnBackupExCallback(wptr<BackupExtExtension> obj)433 std::function<void(ErrCode, const std::string)> BackupExtExtension::OnBackupExCallback(wptr<BackupExtExtension> obj)
434 {
435     HILOGI("Begin get HandleFullBackupCallbackEx");
436     return [obj](ErrCode errCode, const std::string backupExRetInfo) {
437         HILOGI("begin call backup");
438         auto extensionPtr = obj.promote();
439         if (extensionPtr == nullptr) {
440             HILOGE("Ext extension handle have been released");
441             return;
442         }
443         if (extensionPtr->extension_ == nullptr) {
444             HILOGE("Extension handle have been released");
445             return;
446         }
447         if (extensionPtr->isExecAppDone_.load()) {
448             HILOGE("Appdone has been executed for the current application");
449             return;
450         }
451         extensionPtr->extension_->InvokeAppExtMethod(errCode, backupExRetInfo);
452         if (errCode == ERR_OK) {
453             if (backupExRetInfo.size()) {
454                 auto spendTime = extensionPtr->GetOnStartTimeCost();
455                 if (spendTime >= BConstants::MAX_TIME_COST) {
456                     AppRadar::Info info(extensionPtr->bundleName_, "", string("\"spend_time\":\" ").
457                         append(to_string(spendTime)).append(string("ms\"")));
458                     AppRadar::GetInstance().RecordBackupFuncRes(info, "BackupExtExtension::OnBackupExCallback",
459                         AppRadar::GetInstance().GetUserId(), BizStageBackup::BIZ_STAGE_ON_BACKUP,
460                         static_cast<int32_t>(ERR_OK));
461                 }
462                 HILOGI("Will notify backup result report");
463                 extensionPtr->FinishOnProcessTask();
464                 extensionPtr->AsyncTaskBackup(extensionPtr->extension_->GetUsrConfig());
465                 extensionPtr->AppResultReport(backupExRetInfo, BackupRestoreScenario::FULL_BACKUP);
466             }
467             return;
468         }
469         HILOGE("Call extension onBackupEx failed, errInfo = %{public}s", backupExRetInfo.c_str());
470         extensionPtr->FinishOnProcessTask();
471         if (!backupExRetInfo.empty()) {
472             std::string errInfo;
473             BJsonUtil::BuildExtensionErrInfo(errInfo, errCode, backupExRetInfo);
474             extensionPtr->AppResultReport(errInfo, BackupRestoreScenario::FULL_BACKUP, errCode);
475         }
476         extensionPtr->AppDone(errCode);
477         extensionPtr->DoClear();
478     };
479 }
480 
IncOnBackupCallback(wptr<BackupExtExtension> obj)481 std::function<void(ErrCode, const std::string)> BackupExtExtension::IncOnBackupCallback(wptr<BackupExtExtension> obj)
482 {
483     HILOGI("Begin get IncOnBackupCallback");
484     return [obj](ErrCode errCode, std::string errMsg) {
485         HILOGI("App onbackup end");
486         auto proxy = ServiceProxy::GetInstance();
487         if (proxy == nullptr) {
488             throw BError(BError::Codes::EXT_BROKEN_BACKUP_SA, std::generic_category().message(errno));
489         }
490         auto extPtr = obj.promote();
491         if (extPtr == nullptr) {
492             HILOGE("Current extension execute call backup error, extPtr is empty");
493             return;
494         }
495         if (extPtr->isExecAppDone_.load()) {
496             HILOGE("Appdone has been executed for the current application");
497             return;
498         }
499         HILOGI("Start GetAppLocalListAndDoIncrementalBackup");
500         extPtr->FinishOnProcessTask();
501         if (errCode == ERR_OK) {
502             auto spendTime = extPtr->GetOnStartTimeCost();
503             if (spendTime >= BConstants::MAX_TIME_COST) {
504                 AppRadar::Info info(extPtr->bundleName_, "", string("\"spend_time\":\" ").
505                     append(to_string(spendTime)).append(string("ms\"")));
506                 AppRadar::GetInstance().RecordBackupFuncRes(info, "BackupExtExtension::IncOnBackupCallback",
507                     AppRadar::GetInstance().GetUserId(), BizStageBackup::BIZ_STAGE_ON_BACKUP,
508                     static_cast<int32_t>(ERR_OK));
509             }
510             proxy->GetAppLocalListAndDoIncrementalBackup();
511             return;
512         }
513         HILOGE("Call extension IncOnBackup failed, errInfo = %{public}s", errMsg.c_str());
514         if (!errMsg.empty()) {
515             std::string errInfo;
516             BJsonUtil::BuildExtensionErrInfo(errInfo, errCode, errMsg);
517             extPtr->AppResultReport(errInfo, BackupRestoreScenario::INCREMENTAL_BACKUP, errCode);
518         }
519         extPtr->AppIncrementalDone(errCode);
520         extPtr->DoClear();
521     };
522 }
523 
IncOnBackupExCallback(wptr<BackupExtExtension> obj)524 std::function<void(ErrCode, const std::string)> BackupExtExtension::IncOnBackupExCallback(wptr<BackupExtExtension> obj)
525 {
526     HILOGI("Begin get HandleIncBackupEx callback");
527     return [obj](ErrCode errCode, const std::string backupExRetInfo) {
528         auto proxy = ServiceProxy::GetInstance();
529         if (proxy == nullptr) {
530             throw BError(BError::Codes::EXT_BROKEN_BACKUP_SA, std::generic_category().message(errno));
531         }
532         auto extensionPtr = obj.promote();
533         if (extensionPtr == nullptr) {
534             HILOGE("Ext extension handle have been released");
535             return;
536         }
537         if (extensionPtr->extension_ == nullptr) {
538             HILOGE("Extension handle have been released");
539             return;
540         }
541         if (extensionPtr->isExecAppDone_.load()) {
542             HILOGE("Appdone has been executed for the current application");
543             return;
544         }
545         extensionPtr->extension_->InvokeAppExtMethod(errCode, backupExRetInfo);
546         if (errCode == ERR_OK) {
547             if (backupExRetInfo.size()) {
548                 auto spendTime = extensionPtr->GetOnStartTimeCost();
549                 if (spendTime >= BConstants::MAX_TIME_COST) {
550                     AppRadar::Info info(extensionPtr->bundleName_, "", string("\"spend_time\":\" ").
551                         append(to_string(spendTime)).append(string("ms\"")));
552                     AppRadar::GetInstance().RecordBackupFuncRes(info, "BackupExtExtension::IncOnBackupExCallback",
553                         AppRadar::GetInstance().GetUserId(), BizStageBackup::BIZ_STAGE_ON_BACKUP,
554                         static_cast<int32_t>(ERR_OK));
555                 }
556                 HILOGI("Start GetAppLocalListAndDoIncrementalBackup");
557                 extensionPtr->FinishOnProcessTask();
558                 proxy->GetAppLocalListAndDoIncrementalBackup();
559                 HILOGI("Will notify backup result report");
560                 extensionPtr->AppResultReport(backupExRetInfo, BackupRestoreScenario::INCREMENTAL_BACKUP);
561             }
562             return;
563         }
564         HILOGE("Call extension IncOnBackupEx failed, errInfo = %{public}s", backupExRetInfo.c_str());
565         extensionPtr->FinishOnProcessTask();
566         if (!backupExRetInfo.empty()) {
567             std::string errInfo;
568             BJsonUtil::BuildExtensionErrInfo(errInfo, errCode, backupExRetInfo);
569             extensionPtr->AppResultReport(errInfo, BackupRestoreScenario::INCREMENTAL_BACKUP, errCode);
570         }
571         extensionPtr->AppIncrementalDone(errCode);
572         extensionPtr->DoClear();
573     };
574 }
575 
ReportAppProcessInfo(const std::string processInfo,BackupRestoreScenario scenario)576 void BackupExtExtension::ReportAppProcessInfo(const std::string processInfo, BackupRestoreScenario scenario)
577 {
578     auto proxy = ServiceProxy::GetInstance();
579     if (proxy == nullptr) {
580         HILOGE("Report app process error, proxy is empty");
581         return;
582     }
583     HILOGI("Will notify backup sa process result");
584     auto ret = proxy->ReportAppProcessInfo(processInfo, scenario);
585     if (ret != ERR_OK) {
586         HILOGE("Report app process error, ipc failed, ret:%{public}d", ret);
587         return;
588     }
589 }
590 
StartOnProcessTaskThread(wptr<BackupExtExtension> obj,BackupRestoreScenario scenario)591 ErrCode BackupExtExtension::StartOnProcessTaskThread(wptr<BackupExtExtension> obj, BackupRestoreScenario scenario)
592 {
593     HILOGI("Begin Create onProcess Task Thread");
594     onProcessTimeoutTimer_.Setup();
595     isFirstCallOnProcess_.store(true);
596     StartOnProcessTimeOutTimer(obj, scenario);
597     SyncCallJsOnProcessTask(obj, scenario);
598     if (isExecAppDone_.load()) {
599         HILOGE("Call onProcess timeout, Current extension finished");
600         return BError(BError::Codes::EXT_ABILITY_TIMEOUT);
601     }
602     callJsOnProcessThread_ = std::thread([obj, scenario]() {
603         auto extPtr = obj.promote();
604         if (extPtr == nullptr) {
605             HILOGE("Create onProcess Task thread failed, extPtr is empty");
606             return;
607         }
608         extPtr->ExecCallOnProcessTask(obj, scenario);
609     });
610     HILOGI("End Create onProcess Task End");
611     return BError(BError::Codes::OK);
612 }
613 
ExecCallOnProcessTask(wptr<BackupExtExtension> obj,BackupRestoreScenario scenario)614 void BackupExtExtension::ExecCallOnProcessTask(wptr<BackupExtExtension> obj, BackupRestoreScenario scenario)
615 {
616     HILOGI("Begin");
617     isFirstCallOnProcess_.store(false);
618     while (!stopCallJsOnProcess_.load()) {
619         std::unique_lock<std::mutex> lock(onProcessLock_);
620         execOnProcessCon_.wait_for(lock, std::chrono::seconds(BConstants::CALL_APP_ON_PROCESS_TIME_INTERVAL),
621             [this] { return this->stopCallJsOnProcess_.load(); });
622         if (stopCallJsOnProcess_.load()) {
623             HILOGE("Current extension execute js onProcess method finished");
624             return;
625         }
626         HILOGI("Continue call js method onProcess");
627         StartOnProcessTimeOutTimer(obj, scenario);
628         AsyncCallJsOnProcessTask(obj, scenario);
629     }
630     HILOGI("End");
631 }
632 
AsyncCallJsOnProcessTask(wptr<BackupExtExtension> obj,BackupRestoreScenario scenario)633 void BackupExtExtension::AsyncCallJsOnProcessTask(wptr<BackupExtExtension> obj, BackupRestoreScenario scenario)
634 {
635     HILOGI("Begin");
636     if (stopCallJsOnProcess_.load()) {
637         HILOGE("Current extension execute finished");
638         return;
639     }
640     auto task = [obj, scenario]() {
641         auto extPtr = obj.promote();
642         if (extPtr == nullptr) {
643             HILOGE("Async Call js onProcess error, extPtr is empty");
644             return;
645         }
646         extPtr->SyncCallJsOnProcessTask(obj, scenario);
647     };
648     onProcessTaskPool_.AddTask([task]() { task(); });
649     HILOGI("End");
650 }
651 
SyncCallJsOnProcessTask(wptr<BackupExtExtension> obj,BackupRestoreScenario scenario)652 void BackupExtExtension::SyncCallJsOnProcessTask(wptr<BackupExtExtension> obj, BackupRestoreScenario scenario)
653 {
654     HILOGI("Begin");
655     if (stopCallJsOnProcess_.load()) {
656         HILOGE("Current extension execute finished");
657         return;
658     }
659     auto callBack = ReportOnProcessResultCallback(obj, scenario);
660     auto extenionPtr = obj.promote();
661     if (extenionPtr == nullptr) {
662         HILOGE("Async call js onProcess failed, extenionPtr is empty");
663         return;
664     }
665     ErrCode ret = extenionPtr->extension_->OnProcess(callBack);
666     if (ret != ERR_OK) {
667         HILOGE("Call OnProcess Failed, ret:%{public}d", ret);
668         return;
669     }
670     HILOGI("End");
671 }
672 
FinishOnProcessTask()673 void BackupExtExtension::FinishOnProcessTask()
674 {
675     HILOGI("Begin");
676     std::unique_lock<std::mutex> lock(onProcessLock_);
677     stopCallJsOnProcess_.store(true);
678     isFirstCallOnProcess_.store(false);
679     isExecAppDone_.store(false);
680     onProcessTimeoutCnt_ = 0;
681     execOnProcessCon_.notify_one();
682     lock.unlock();
683     if (callJsOnProcessThread_.joinable()) {
684         callJsOnProcessThread_.join();
685     }
686     HILOGI("End");
687 }
688 
StartOnProcessTimeOutTimer(wptr<BackupExtExtension> obj,BackupRestoreScenario scenario)689 void BackupExtExtension::StartOnProcessTimeOutTimer(wptr<BackupExtExtension> obj, BackupRestoreScenario scenario)
690 {
691     HILOGI("Begin");
692     if (stopCallJsOnProcess_.load()) {
693         HILOGE("Current extension execute finished");
694         return;
695     }
696     auto timeoutCallback = [obj, scenario]() {
697         auto extPtr = obj.promote();
698         if (extPtr == nullptr) {
699             HILOGE("Start Create timeout callback failed, extPtr is empty");
700             return;
701         }
702         if (extPtr->onProcessTimeoutCnt_.load() >= BConstants::APP_ON_PROCESS_TIMEOUT_MAX_COUNT ||
703             extPtr->isFirstCallOnProcess_.load()) {
704             HILOGE("The extension invokes the onProcess for more than three times or the first invoking of the "
705                    "onProcess times out, timeoutCnt:%{public}d", extPtr->onProcessTimeoutCnt_.load());
706             std::unique_lock<std::mutex> lock(extPtr->onProcessLock_);
707             extPtr->stopCallJsOnProcess_.store(true);
708             extPtr->isFirstCallOnProcess_.store(false);
709             extPtr->isExecAppDone_.store(true);
710             extPtr->onProcessTimeoutCnt_ = 0;
711             extPtr->execOnProcessCon_.notify_one();
712             lock.unlock();
713             if (scenario == BackupRestoreScenario::FULL_BACKUP || scenario == BackupRestoreScenario::FULL_RESTORE) {
714                 extPtr->AppDone(BError(BError::Codes::EXT_ABILITY_TIMEOUT));
715             } else if (scenario == BackupRestoreScenario::INCREMENTAL_BACKUP ||
716                 scenario == BackupRestoreScenario::INCREMENTAL_RESTORE) {
717                 extPtr->AppIncrementalDone(BError(BError::Codes::EXT_ABILITY_TIMEOUT));
718             }
719             return;
720         }
721         extPtr->onProcessTimeoutCnt_++;
722         extPtr->onProcessTimeout_.store(true);
723         HILOGE("Extension onProcess timeout, Increase cnt:%{public}d", extPtr->onProcessTimeoutCnt_.load());
724     };
725     int timeout = isFirstCallOnProcess_.load() ? BConstants::FIRST_CALL_APP_ON_PROCESS_MAX_TIMEOUT :
726                                                  BConstants::APP_ON_PROCESS_MAX_TIMEOUT;
727     uint32_t timerId = onProcessTimeoutTimer_.Register(timeoutCallback, timeout, true);
728     onProcessTimeoutTimerId_ = timerId;
729     HILOGI("End");
730 }
731 
CloseOnProcessTimeOutTimer()732 void BackupExtExtension::CloseOnProcessTimeOutTimer()
733 {
734     HILOGI("Begin");
735     onProcessTimeoutTimer_.Unregister(onProcessTimeoutTimerId_);
736     HILOGI("End");
737 }
738 
AppIncrementalDone(ErrCode errCode)739 void BackupExtExtension::AppIncrementalDone(ErrCode errCode)
740 {
741     HILOGI("Begin");
742     auto proxy = ServiceProxy::GetInstance();
743         if (proxy == nullptr) {
744         HILOGE("Failed to obtain the ServiceProxy handle");
745         DoClear();
746         return;
747     }
748     auto ret = proxy->AppIncrementalDone(errCode);
749     if (ret != ERR_OK) {
750         HILOGE("Failed to notify the app done. err = %{public}d", ret);
751     }
752 }
753 
GetBackupInfo(std::string & result)754 ErrCode BackupExtExtension::GetBackupInfo(std::string &result)
755 {
756     auto obj = wptr<BackupExtExtension>(this);
757     auto ptr = obj.promote();
758     if (ptr == nullptr) {
759         HILOGE("Failed to get ext extension.");
760         return BError(BError::Codes::EXT_INVAL_ARG, "extension getBackupInfo exception").GetCode();
761     }
762     if (ptr->extension_ == nullptr) {
763         HILOGE("Failed to get extension.");
764         return BError(BError::Codes::EXT_INVAL_ARG, "extension getBackupInfo exception").GetCode();
765     }
766     auto callBackup = [ptr](ErrCode errCode, const std::string result) {
767         if (ptr == nullptr) {
768             HILOGE("Failed to get ext extension.");
769             return;
770         }
771         HILOGI("GetBackupInfo callBackup start. errCode = %{public}d, result = %{public}s", errCode, result.c_str());
772         if (errCode == ERR_OK) {
773             ptr->backupInfo_ = result;
774         }
775     };
776     auto ret = ptr->extension_->GetBackupInfo(callBackup);
777     if (ret != ERR_OK) {
778         HILOGE("Failed to get backupInfo. err = %{public}d", ret);
779         return BError(BError::Codes::EXT_INVAL_ARG, "extension getBackupInfo exception").GetCode();
780     }
781     HILOGD("backupInfo = %s", backupInfo_.c_str());
782     result = backupInfo_;
783     backupInfo_.clear();
784 
785     return ERR_OK;
786 }
787 
UpdateFdSendRate(std::string & bundleName,int32_t sendRate)788 ErrCode BackupExtExtension::UpdateFdSendRate(std::string &bundleName, int32_t sendRate)
789 {
790     try {
791         std::lock_guard<std::mutex> lock(updateSendRateLock_);
792         HILOGI("Update SendRate, bundleName:%{public}s, sendRate:%{public}d", bundleName.c_str(), sendRate);
793         VerifyCaller();
794         bundleName_ = bundleName;
795         sendRate_ = sendRate;
796         if (sendRate > 0) {
797             startSendFdRateCon_.notify_one();
798         }
799         return ERR_OK;
800     } catch (...) {
801         HILOGE("Failed to UpdateFdSendRate");
802         return BError(BError::Codes::EXT_BROKEN_IPC).GetCode();
803     }
804 }
805 
SetStagingPathProperties()806 bool BackupExtExtension::SetStagingPathProperties()
807 {
808     struct stat curBundleStat {};
809     if (lstat(BConstants::BUNDLE_BASE_DIR.c_str(), &curBundleStat) != 0) {
810         HILOGE("Failed to lstat, err = %{public}d", errno);
811         return false;
812     }
813     if (lchown(string(BConstants::PATH_BUNDLE_BACKUP_HOME).c_str(),
814         curBundleStat.st_uid, curBundleStat.st_gid) != 0) {
815         HILOGE("Failed to lchown, err = %{public}d", errno);
816         return false;
817     }
818     if (lchown(string(BConstants::PATH_BUNDLE_BACKUP_HOME_EL1).c_str(),
819         curBundleStat.st_uid, curBundleStat.st_gid) != 0) {
820         HILOGE("Failed to lchown, err = %{public}d", errno);
821         return false;
822     }
823     return true;
824 }
825 
IfAllowToBackupRestore()826 bool BackupExtExtension::IfAllowToBackupRestore()
827 {
828     if (extension_ == nullptr) {
829         HILOGE("Failed to handle backup, extension is nullptr");
830         return false;
831     }
832     string usrConfig = extension_->GetUsrConfig();
833     BJsonCachedEntity<BJsonEntityExtensionConfig> cachedEntity(usrConfig);
834     auto cache = cachedEntity.Structuralize();
835     if (!cache.GetAllowToBackupRestore()) {
836         HILOGE("Application does not allow backup or restore");
837         return false;
838     }
839     return true;
840 }
841 
User0OnBackup()842 ErrCode BackupExtExtension::User0OnBackup()
843 {
844     HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
845     if (!IfAllowToBackupRestore()) {
846         return BError(BError::Codes::EXT_FORBID_BACKUP_RESTORE, "Application does not allow backup or restore")
847             .GetCode();
848     }
849     AsyncTaskUser0Backup();
850     return ERR_OK;
851 }
852 
AsyncTaskUser0Backup()853 void BackupExtExtension::AsyncTaskUser0Backup()
854 {
855     HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
856     auto task = [obj {wptr<BackupExtExtension>(this)}]() {
857         auto ptr = obj.promote();
858         BExcepUltils::BAssert(ptr, BError::Codes::EXT_BROKEN_FRAMEWORK, "Ext extension handle have been released");
859         const string config = ptr->extension_->GetUsrConfig();
860         try {
861             HILOGI("Do backup, start fwk timer begin.");
862             bool isFwkStart;
863             ptr->StartFwkTimer(isFwkStart);
864             if (!isFwkStart) {
865                 HILOGE("Do backup, start fwk timer fail.");
866                 return;
867             }
868             HILOGI("Do backup, start fwk timer end.");
869             BJsonCachedEntity<BJsonEntityExtensionConfig> cachedEntity(config);
870             auto cache = cachedEntity.Structuralize();
871             auto ret = ptr->User0DoBackup(cache);
872             if (ret != ERR_OK) {
873                 HILOGE("User0DoBackup, err = %{pubilc}d", ret);
874                 ptr->AppIncrementalDone(BError::GetCodeByErrno(ret));
875             }
876         } catch (const BError &e) {
877             HILOGE("extension: AsyncTaskBackup error, err code:%{public}d", e.GetCode());
878             ptr->AppIncrementalDone(e.GetCode());
879         } catch (const exception &e) {
880             HILOGE("Catched an unexpected low-level exception %{public}s", e.what());
881             ptr->AppIncrementalDone(BError(BError::Codes::EXT_INVAL_ARG).GetCode());
882         } catch (...) {
883             HILOGE("Failed to restore the ext bundle");
884             ptr->AppIncrementalDone(BError(BError::Codes::EXT_INVAL_ARG).GetCode());
885         }
886     };
887 
888     threadPool_.AddTask([task]() {
889         try {
890             task();
891         } catch (...) {
892             HILOGE("Failed to add task to thread pool");
893         }
894     });
895 }
896 
DoUser0Backup(const BJsonEntityExtensionConfig & usrConfig)897 void BackupExtExtension::DoUser0Backup(const BJsonEntityExtensionConfig &usrConfig)
898 {
899     HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
900     string path = string(BConstants::PATH_BUNDLE_BACKUP_HOME).append(BConstants::SA_BUNDLE_BACKUP_BACKUP);
901     if (mkdir(path.data(), S_IRWXU) && errno != EEXIST) {
902         throw BError(errno);
903     }
904     vector<string> includes = usrConfig.GetIncludes();
905     vector<string> excludes = usrConfig.GetExcludes();
906     auto task = [obj {wptr<BackupExtExtension>(this)}, includes, excludes]() {
907         auto ptr = obj.promote();
908         BExcepUltils::BAssert(ptr, BError::Codes::EXT_BROKEN_FRAMEWORK, "Ext extension handle have been released");
909         try {
910             auto [bigFile, smallFile] = BDir::GetBackupList(includes, excludes);
911             vector<struct ReportFileInfo> allFiles;
912             vector<struct ReportFileInfo> smallFiles;
913             vector<struct ReportFileInfo> bigFiles;
914             BDir::GetUser0FileStat(move(bigFile), move(smallFile), allFiles, smallFiles, bigFiles);
915             auto ret = ptr->DoIncrementalBackup(allFiles, smallFiles, bigFiles);
916             ptr->AppIncrementalDone(ret);
917             HILOGI("User0 backup app done %{public}d", ret);
918         } catch (const BError &e) {
919             ptr->AppIncrementalDone(e.GetCode());
920         } catch (const exception &e) {
921             ptr->AppIncrementalDone(BError(BError::Codes::EXT_INVAL_ARG).GetCode());
922         } catch (...) {
923             HILOGE("Failed to restore the ext bundle");
924             ptr->AppIncrementalDone(BError(BError::Codes::EXT_INVAL_ARG).GetCode());
925         }
926     };
927 
928     threadPool_.AddTask([task]() {
929         try {
930             task();
931         } catch (...) {
932             HILOGE("Failed to add task to thread pool");
933         }
934     });
935 }
936 
User0DoBackup(const BJsonEntityExtensionConfig & usrConfig)937 int BackupExtExtension::User0DoBackup(const BJsonEntityExtensionConfig &usrConfig)
938 {
939     HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
940     if (extension_ == nullptr) {
941         HILOGE("Failed to do backup, extension is nullptr");
942         return BError(BError::Codes::EXT_INVAL_ARG);
943     }
944     if (extension_->GetExtensionAction() != BConstants::ExtensionAction::BACKUP) {
945         return EPERM;
946     }
947     DoUser0Backup(usrConfig);
948     return ERR_OK;
949 }
950 
ReportOnProcessResultCallback(wptr<BackupExtExtension> obj,BackupRestoreScenario scenario)951 std::function<void(ErrCode, std::string)> BackupExtExtension::ReportOnProcessResultCallback(
952     wptr<BackupExtExtension> obj, BackupRestoreScenario scenario)
953 {
954     return [obj, scenario](ErrCode errCode, const std::string processInfo) {
955         auto extPtr = obj.promote();
956         if (extPtr == nullptr) {
957             HILOGE("Async call js onPreocess callback failed, exPtr is empty");
958             return;
959         }
960         if (extPtr->onProcessTimeout_.load()) {
961             HILOGE("The result of invoking onProcess is timeout.");
962             extPtr->onProcessTimeout_.store(false);
963             return;
964         }
965         extPtr->CloseOnProcessTimeOutTimer();
966         extPtr->isFirstCallOnProcess_.store(false);
967         extPtr->onProcessTimeout_.store(false);
968         if (extPtr->onProcessTimeoutCnt_.load() > 0) {
969             extPtr->onProcessTimeoutCnt_ = 0;
970             HILOGI("onProcess execute success, reset onProcessTimeoutCnt");
971         }
972         if (processInfo.size() == 0) {
973             HILOGE("Current extension has no js method named onProcess.");
974             std::unique_lock<std::mutex> lock(extPtr->onProcessLock_);
975             extPtr->isFirstCallOnProcess_.store(false);
976             extPtr->stopCallJsOnProcess_.store(true);
977             extPtr->execOnProcessCon_.notify_one();
978             lock.unlock();
979             return;
980         }
981         std::string processInfoJsonStr;
982         BJsonUtil::BuildOnProcessRetInfo(processInfoJsonStr, processInfo);
983         auto task = [obj, scenario, processInfoJsonStr]() {
984             auto reportExtPtr = obj.promote();
985             if (reportExtPtr == nullptr) {
986                 HILOGE("Report onProcess Result error, reportExtPtr is empty");
987                 return;
988             }
989             reportExtPtr->ReportAppProcessInfo(processInfoJsonStr, scenario);
990         };
991         extPtr->reportOnProcessRetPool_.AddTask([task]() { task(); });
992     };
993 }
994 } // namespace OHOS::FileManagement::Backup
995