• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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         HILOGI("Current bundle will execute app done");
210         if (errCode == ERR_OK) {
211             auto spendTime = extensionPtr->GetOnStartTimeCost();
212             if (spendTime >= BConstants::MAX_TIME_COST) {
213                 std::stringstream ss;
214                 ss << R"("spendTime": )"<< spendTime << "ms";
215                 AppRadar::Info info (extensionPtr->bundleName_, "", ss.str());
216                 AppRadar::GetInstance().RecordRestoreFuncRes(info, "BackupExtExtension::OnRestoreCallback",
217                     AppRadar::GetInstance().GetUserId(), BizStageRestore::BIZ_STAGE_ON_RESTORE, ERR_OK);
218             }
219         }
220         extensionPtr->FinishOnProcessTask();
221         if (errMsg.empty()) {
222             extensionPtr->AppDone(errCode);
223         } else {
224             std::string errInfo;
225             BJsonUtil::BuildExtensionErrInfo(errInfo, errCode, errMsg);
226             extensionPtr->AppResultReport(errInfo, BackupRestoreScenario::FULL_RESTORE, errCode);
227         }
228         extensionPtr->DoClear();
229     };
230 }
231 
OnRestoreExCallback(wptr<BackupExtExtension> obj)232 std::function<void(ErrCode, std::string)> BackupExtExtension::OnRestoreExCallback(wptr<BackupExtExtension> obj)
233 {
234     HILOGI("Begin get full restore onRestoreEx callback");
235     return [obj](ErrCode errCode, const std::string restoreRetInfo) {
236         auto extensionPtr = obj.promote();
237         if (extensionPtr == nullptr) {
238             HILOGE("Ext extension handle have been released");
239             return;
240         }
241         if (extensionPtr->extension_ == nullptr) {
242             HILOGE("Extension handle have been released");
243             return;
244         }
245         if (errCode == ERR_OK && !restoreRetInfo.empty()) {
246             auto spendTime = extensionPtr->GetOnStartTimeCost();
247             if (spendTime >= BConstants::MAX_TIME_COST) {
248                 std::stringstream ss;
249                 ss << R"("spendTime": )"<< spendTime << "ms";
250                 AppRadar::Info info (extensionPtr->bundleName_, "", ss.str());
251                 AppRadar::GetInstance().RecordRestoreFuncRes(info, "BackupExtExtension::OnRestoreExCallback",
252                     AppRadar::GetInstance().GetUserId(), BizStageRestore::BIZ_STAGE_ON_RESTORE, ERR_OK);
253             }
254         }
255         extensionPtr->FinishOnProcessTask();
256         extensionPtr->extension_->InvokeAppExtMethod(errCode, restoreRetInfo);
257         if (errCode == ERR_OK) {
258             if (restoreRetInfo.size()) {
259                 HILOGI("Will notify restore result report");
260                 extensionPtr->AppResultReport(restoreRetInfo, BackupRestoreScenario::FULL_RESTORE);
261             }
262             return;
263         }
264         if (restoreRetInfo.empty()) {
265             extensionPtr->AppDone(errCode);
266             extensionPtr->DoClear();
267         } else {
268             std::string errInfo;
269             BJsonUtil::BuildExtensionErrInfo(errInfo, errCode, restoreRetInfo);
270             extensionPtr->AppResultReport(errInfo, BackupRestoreScenario::FULL_RESTORE, errCode);
271             extensionPtr->DoClear();
272         }
273     };
274 }
275 
AppDoneCallbackEx(wptr<BackupExtExtension> obj)276 std::function<void(ErrCode, std::string)> BackupExtExtension::AppDoneCallbackEx(wptr<BackupExtExtension> obj)
277 {
278     HILOGI("Begin get callback for appDone");
279     return [obj](ErrCode errCode, std::string errMsg) {
280         HILOGI("begin call callBackupExAppDone");
281         auto extensionPtr = obj.promote();
282         if (extensionPtr == nullptr) {
283             HILOGE("Ext extension handle have been released");
284             return;
285         }
286         extensionPtr->AppDone(errCode);
287         extensionPtr->DoClear();
288     };
289 }
290 
IncreOnRestoreExCallback(wptr<BackupExtExtension> obj)291 std::function<void(ErrCode, std::string)> BackupExtExtension::IncreOnRestoreExCallback(wptr<BackupExtExtension> obj)
292 {
293     HILOGI("Begin get callback for increment onRestoreEx");
294     return [obj](ErrCode errCode, const std::string restoreRetInfo) {
295         HILOGI("begin call increment restoreEx");
296         auto extensionPtr = obj.promote();
297         if (extensionPtr == nullptr) {
298             HILOGE("Ext extension handle have been released");
299             return;
300         }
301         if (extensionPtr->extension_ == nullptr) {
302             HILOGE("Extension handle have been released");
303             return;
304         }
305         if (errCode == ERR_OK && !restoreRetInfo.empty()) {
306             auto spendTime = extensionPtr->GetOnStartTimeCost();
307             if (spendTime >= BConstants::MAX_TIME_COST) {
308                 std::stringstream ss;
309                 ss << R"("spendTime": )"<< spendTime << "ms";
310                 AppRadar::Info info (extensionPtr->bundleName_, "", ss.str());
311                 AppRadar::GetInstance().RecordRestoreFuncRes(info, "BackupExtExtension::IncreOnRestoreExCallback",
312                     AppRadar::GetInstance().GetUserId(),
313                     BizStageRestore::BIZ_STAGE_ON_RESTORE, ERR_OK);
314             }
315         }
316         extensionPtr->FinishOnProcessTask();
317         extensionPtr->extension_->InvokeAppExtMethod(errCode, restoreRetInfo);
318         if (errCode == ERR_OK) {
319             if (restoreRetInfo.size()) {
320                 extensionPtr->AppResultReport(restoreRetInfo, BackupRestoreScenario::INCREMENTAL_RESTORE);
321             }
322             return;
323         }
324         if (restoreRetInfo.empty()) {
325             extensionPtr->AppIncrementalDone(errCode);
326             extensionPtr->DoClear();
327         } else {
328             std::string errInfo;
329             BJsonUtil::BuildExtensionErrInfo(errInfo, errCode, restoreRetInfo);
330             extensionPtr->AppResultReport(errInfo, BackupRestoreScenario::INCREMENTAL_RESTORE, errCode);
331             extensionPtr->DoClear();
332         }
333     };
334 }
335 
IncreOnRestoreCallback(wptr<BackupExtExtension> obj)336 std::function<void(ErrCode, std::string)> BackupExtExtension::IncreOnRestoreCallback(wptr<BackupExtExtension> obj)
337 {
338     return [obj](ErrCode errCode, std::string errMsg) {
339         auto extensionPtr = obj.promote();
340         if (extensionPtr == nullptr) {
341             HILOGE("Ext extension handle have been released");
342             return;
343         }
344         HILOGI("Current bundle will execute app done");
345         if (errCode == ERR_OK) {
346             auto spendTime = extensionPtr->GetOnStartTimeCost();
347             if (spendTime >= BConstants::MAX_TIME_COST) {
348                 std::stringstream ss;
349                 ss << R"("spendTime": )"<< spendTime << "ms";
350                 AppRadar::Info info (extensionPtr->bundleName_, "", ss.str());
351                 AppRadar::GetInstance().RecordRestoreFuncRes(info, "BackupExtExtension::IncreOnRestoreCallback",
352                     AppRadar::GetInstance().GetUserId(), BizStageRestore::BIZ_STAGE_ON_RESTORE, ERR_OK);
353             }
354         }
355         extensionPtr->FinishOnProcessTask();
356         if (errMsg.empty()) {
357             extensionPtr->AppIncrementalDone(errCode);
358         } else {
359             std::string errInfo;
360             BJsonUtil::BuildExtensionErrInfo(errInfo, errCode, errMsg);
361             extensionPtr->AppResultReport(errInfo, BackupRestoreScenario::INCREMENTAL_RESTORE, errCode);
362         }
363         extensionPtr->DoClear();
364     };
365 }
366 
GetOnStartTimeCost()367 int32_t BackupExtExtension::GetOnStartTimeCost()
368 {
369     auto onBackupRestoreEnd = std::chrono::system_clock::now();
370     std::lock_guard<std::mutex> lock(onStartTimeLock_);
371     auto spendTime = std::chrono::duration_cast<std::chrono::milliseconds>(onBackupRestoreEnd - g_onStart).count();
372     return spendTime;
373 }
374 
OnBackupCallback(wptr<BackupExtExtension> obj)375 std::function<void(ErrCode, const std::string)> BackupExtExtension::OnBackupCallback(wptr<BackupExtExtension> obj)
376 {
377     HILOGI("Begin get HandleFullBackupCallbackEx");
378     return [obj](ErrCode errCode, std::string errMsg) {
379         HILOGI("begin call backup");
380         auto extensionPtr = obj.promote();
381         if (extensionPtr == nullptr) {
382             HILOGE("Ext extension handle have been released");
383             return;
384         }
385         if (extensionPtr->extension_ == nullptr) {
386             HILOGE("Extension handle have been released");
387             return;
388         }
389         extensionPtr->FinishOnProcessTask();
390         if (errCode == ERR_OK) {
391             auto spendTime = extensionPtr->GetOnStartTimeCost();
392             if (spendTime >= BConstants::MAX_TIME_COST) {
393                 AppRadar::Info info(extensionPtr->bundleName_, "", string("\"spend_time\":\" ").
394                     append(to_string(spendTime)).append(string("ms\"")));
395                 AppRadar::GetInstance().RecordBackupFuncRes(info, "BackupExtExtension::OnBackupCallback",
396                     AppRadar::GetInstance().GetUserId(), BizStageBackup::BIZ_STAGE_ON_BACKUP,
397                     static_cast<int32_t>(ERR_OK));
398             }
399             extensionPtr->AsyncTaskBackup(extensionPtr->extension_->GetUsrConfig());
400             return;
401         }
402         HILOGE("Call extension onBackup failed, errInfo = %{public}s", errMsg.c_str());
403         if (!errMsg.empty()) {
404             std::string errInfo;
405             BJsonUtil::BuildExtensionErrInfo(errInfo, errCode, errMsg);
406             extensionPtr->AppResultReport(errInfo, BackupRestoreScenario::FULL_BACKUP, errCode);
407         }
408         extensionPtr->AppDone(errCode);
409         extensionPtr->DoClear();
410     };
411 }
412 
OnBackupExCallback(wptr<BackupExtExtension> obj)413 std::function<void(ErrCode, const std::string)> BackupExtExtension::OnBackupExCallback(wptr<BackupExtExtension> obj)
414 {
415     HILOGI("Begin get HandleFullBackupCallbackEx");
416     return [obj](ErrCode errCode, const std::string backupExRetInfo) {
417         HILOGI("begin call backup");
418         auto extensionPtr = obj.promote();
419         if (extensionPtr == nullptr) {
420             HILOGE("Ext extension handle have been released");
421             return;
422         }
423         if (extensionPtr->extension_ == nullptr) {
424             HILOGE("Extension handle have been released");
425             return;
426         }
427         extensionPtr->extension_->InvokeAppExtMethod(errCode, backupExRetInfo);
428         if (errCode == ERR_OK) {
429             if (backupExRetInfo.size()) {
430                 auto spendTime = extensionPtr->GetOnStartTimeCost();
431                 if (spendTime >= BConstants::MAX_TIME_COST) {
432                     AppRadar::Info info(extensionPtr->bundleName_, "", string("\"spend_time\":\" ").
433                         append(to_string(spendTime)).append(string("ms\"")));
434                     AppRadar::GetInstance().RecordBackupFuncRes(info, "BackupExtExtension::OnBackupExCallback",
435                         AppRadar::GetInstance().GetUserId(), BizStageBackup::BIZ_STAGE_ON_BACKUP,
436                         static_cast<int32_t>(ERR_OK));
437                 }
438                 HILOGI("Will notify backup result report");
439                 extensionPtr->FinishOnProcessTask();
440                 extensionPtr->AsyncTaskBackup(extensionPtr->extension_->GetUsrConfig());
441                 extensionPtr->AppResultReport(backupExRetInfo, BackupRestoreScenario::FULL_BACKUP);
442             }
443             return;
444         }
445         HILOGE("Call extension onBackupEx failed, errInfo = %{public}s", backupExRetInfo.c_str());
446         extensionPtr->FinishOnProcessTask();
447         if (!backupExRetInfo.empty()) {
448             std::string errInfo;
449             BJsonUtil::BuildExtensionErrInfo(errInfo, errCode, backupExRetInfo);
450             extensionPtr->AppResultReport(errInfo, BackupRestoreScenario::FULL_BACKUP, errCode);
451         }
452         extensionPtr->AppDone(errCode);
453         extensionPtr->DoClear();
454     };
455 }
456 
IncOnBackupCallback(wptr<BackupExtExtension> obj)457 std::function<void(ErrCode, const std::string)> BackupExtExtension::IncOnBackupCallback(wptr<BackupExtExtension> obj)
458 {
459     HILOGI("Begin get IncOnBackupCallback");
460     return [obj](ErrCode errCode, std::string errMsg) {
461         HILOGI("App onbackup end");
462         auto proxy = ServiceProxy::GetInstance();
463         if (proxy == nullptr) {
464             throw BError(BError::Codes::EXT_BROKEN_BACKUP_SA, std::generic_category().message(errno));
465         }
466         auto extPtr = obj.promote();
467         if (extPtr == nullptr) {
468             HILOGE("Current extension execute call backup error, extPtr is empty");
469             return;
470         }
471         HILOGI("Start GetAppLocalListAndDoIncrementalBackup");
472         extPtr->FinishOnProcessTask();
473         if (errCode == ERR_OK) {
474             auto spendTime = extPtr->GetOnStartTimeCost();
475             if (spendTime >= BConstants::MAX_TIME_COST) {
476                 AppRadar::Info info(extPtr->bundleName_, "", string("\"spend_time\":\" ").
477                     append(to_string(spendTime)).append(string("ms\"")));
478                 AppRadar::GetInstance().RecordBackupFuncRes(info, "BackupExtExtension::IncOnBackupCallback",
479                     AppRadar::GetInstance().GetUserId(), BizStageBackup::BIZ_STAGE_ON_BACKUP,
480                     static_cast<int32_t>(ERR_OK));
481             }
482             proxy->GetAppLocalListAndDoIncrementalBackup();
483             return;
484         }
485         HILOGE("Call extension IncOnBackup failed, errInfo = %{public}s", errMsg.c_str());
486         if (!errMsg.empty()) {
487             std::string errInfo;
488             BJsonUtil::BuildExtensionErrInfo(errInfo, errCode, errMsg);
489             extPtr->AppResultReport(errInfo, BackupRestoreScenario::INCREMENTAL_BACKUP, errCode);
490         }
491         extPtr->AppIncrementalDone(errCode);
492         extPtr->DoClear();
493     };
494 }
495 
IncOnBackupExCallback(wptr<BackupExtExtension> obj)496 std::function<void(ErrCode, const std::string)> BackupExtExtension::IncOnBackupExCallback(wptr<BackupExtExtension> obj)
497 {
498     HILOGI("Begin get HandleIncBackupEx callback");
499     return [obj](ErrCode errCode, const std::string backupExRetInfo) {
500         auto proxy = ServiceProxy::GetInstance();
501         if (proxy == nullptr) {
502             throw BError(BError::Codes::EXT_BROKEN_BACKUP_SA, std::generic_category().message(errno));
503         }
504         auto extensionPtr = obj.promote();
505         if (extensionPtr == nullptr) {
506             HILOGE("Ext extension handle have been released");
507             return;
508         }
509         if (extensionPtr->extension_ == nullptr) {
510             HILOGE("Extension handle have been released");
511             return;
512         }
513         extensionPtr->extension_->InvokeAppExtMethod(errCode, backupExRetInfo);
514         if (errCode == ERR_OK) {
515             if (backupExRetInfo.size()) {
516                 auto spendTime = extensionPtr->GetOnStartTimeCost();
517                 if (spendTime >= BConstants::MAX_TIME_COST) {
518                     AppRadar::Info info(extensionPtr->bundleName_, "", string("\"spend_time\":\" ").
519                         append(to_string(spendTime)).append(string("ms\"")));
520                     AppRadar::GetInstance().RecordBackupFuncRes(info, "BackupExtExtension::IncOnBackupExCallback",
521                         AppRadar::GetInstance().GetUserId(), BizStageBackup::BIZ_STAGE_ON_BACKUP,
522                         static_cast<int32_t>(ERR_OK));
523                 }
524                 HILOGI("Start GetAppLocalListAndDoIncrementalBackup");
525                 extensionPtr->FinishOnProcessTask();
526                 proxy->GetAppLocalListAndDoIncrementalBackup();
527                 HILOGI("Will notify backup result report");
528                 extensionPtr->AppResultReport(backupExRetInfo, BackupRestoreScenario::INCREMENTAL_BACKUP);
529             }
530             return;
531         }
532         HILOGE("Call extension IncOnBackupEx failed, errInfo = %{public}s", backupExRetInfo.c_str());
533         extensionPtr->FinishOnProcessTask();
534         if (!backupExRetInfo.empty()) {
535             std::string errInfo;
536             BJsonUtil::BuildExtensionErrInfo(errInfo, errCode, backupExRetInfo);
537             extensionPtr->AppResultReport(errInfo, BackupRestoreScenario::INCREMENTAL_BACKUP, errCode);
538         }
539         extensionPtr->AppIncrementalDone(errCode);
540         extensionPtr->DoClear();
541     };
542 }
543 
ReportAppProcessInfo(const std::string processInfo,BackupRestoreScenario scenario)544 void BackupExtExtension::ReportAppProcessInfo(const std::string processInfo, BackupRestoreScenario scenario)
545 {
546     auto proxy = ServiceProxy::GetInstance();
547     if (proxy == nullptr) {
548         HILOGE("Report app process error, proxy is empty");
549         return;
550     }
551     HILOGI("Will notify backup sa process result");
552     auto ret = proxy->ReportAppProcessInfo(processInfo, scenario);
553     if (ret != ERR_OK) {
554         HILOGE("Report app process error, ipc failed, ret:%{public}d", ret);
555         return;
556     }
557 }
558 
StartOnProcessTaskThread(wptr<BackupExtExtension> obj,BackupRestoreScenario scenario)559 ErrCode BackupExtExtension::StartOnProcessTaskThread(wptr<BackupExtExtension> obj, BackupRestoreScenario scenario)
560 {
561     HILOGI("Begin Create onProcess Task Thread");
562     onProcessTimeoutTimer_.Setup();
563     isFirstCallOnProcess_.store(true);
564     StartOnProcessTimeOutTimer(obj, scenario);
565     SyncCallJsOnProcessTask(obj, scenario);
566     if (isExecAppDone_.load()) {
567         HILOGE("Call onProcess timeout, Current extension finished");
568         return BError(BError::Codes::EXT_ABILITY_TIMEOUT);
569     }
570     callJsOnProcessThread_ = std::thread([obj, scenario]() {
571         auto extPtr = obj.promote();
572         if (extPtr == nullptr) {
573             HILOGE("Create onProcess Task thread failed, extPtr is empty");
574             return;
575         }
576         extPtr->ExecCallOnProcessTask(obj, scenario);
577     });
578     HILOGI("End Create onProcess Task End");
579     return BError(BError::Codes::OK);
580 }
581 
ExecCallOnProcessTask(wptr<BackupExtExtension> obj,BackupRestoreScenario scenario)582 void BackupExtExtension::ExecCallOnProcessTask(wptr<BackupExtExtension> obj, BackupRestoreScenario scenario)
583 {
584     HILOGI("Begin");
585     isFirstCallOnProcess_.store(false);
586     while (!stopCallJsOnProcess_.load()) {
587         std::unique_lock<std::mutex> lock(onProcessLock_);
588         execOnProcessCon_.wait_for(lock, std::chrono::seconds(BConstants::CALL_APP_ON_PROCESS_TIME_INTERVAL),
589             [this] { return this->stopCallJsOnProcess_.load(); });
590         if (stopCallJsOnProcess_.load()) {
591             HILOGE("Current extension execute js onProcess method finished");
592             return;
593         }
594         HILOGI("Continue call js method onProcess");
595         StartOnProcessTimeOutTimer(obj, scenario);
596         AsyncCallJsOnProcessTask(obj, scenario);
597     }
598     HILOGI("End");
599 }
600 
AsyncCallJsOnProcessTask(wptr<BackupExtExtension> obj,BackupRestoreScenario scenario)601 void BackupExtExtension::AsyncCallJsOnProcessTask(wptr<BackupExtExtension> obj, BackupRestoreScenario scenario)
602 {
603     HILOGI("Begin");
604     if (stopCallJsOnProcess_.load()) {
605         HILOGE("Current extension execute finished");
606         return;
607     }
608     auto task = [obj, scenario]() {
609         auto extPtr = obj.promote();
610         if (extPtr == nullptr) {
611             HILOGE("Async Call js onProcess error, extPtr is empty");
612             return;
613         }
614         extPtr->SyncCallJsOnProcessTask(obj, scenario);
615     };
616     onProcessTaskPool_.AddTask([task]() { task(); });
617     HILOGI("End");
618 }
619 
SyncCallJsOnProcessTask(wptr<BackupExtExtension> obj,BackupRestoreScenario scenario)620 void BackupExtExtension::SyncCallJsOnProcessTask(wptr<BackupExtExtension> obj, BackupRestoreScenario scenario)
621 {
622     HILOGI("Begin");
623     if (stopCallJsOnProcess_.load()) {
624         HILOGE("Current extension execute finished");
625         return;
626     }
627     auto callBack = [obj, scenario](ErrCode errCode, const std::string processInfo) {
628         auto extPtr = obj.promote();
629         if (extPtr == nullptr) {
630             HILOGE("Async call js onPreocess callback failed, exPtr is empty");
631             return;
632         }
633         if (extPtr->onProcessTimeout_.load()) {
634             HILOGE("The result of invoking onProcess is timeout.");
635             extPtr->onProcessTimeout_.store(false);
636             return;
637         }
638         extPtr->CloseOnProcessTimeOutTimer();
639         extPtr->isFirstCallOnProcess_.store(false);
640         extPtr->onProcessTimeout_.store(false);
641         if (extPtr->onProcessTimeoutCnt_.load() > 0) {
642             extPtr->onProcessTimeoutCnt_ = 0;
643             HILOGI("onProcess execute success, reset onProcessTimeoutCnt");
644         }
645         if (processInfo.size() == 0) {
646             HILOGE("Current extension has no js method named onProcess.");
647             std::unique_lock<std::mutex> lock(extPtr->onProcessLock_);
648             extPtr->isFirstCallOnProcess_.store(false);
649             extPtr->stopCallJsOnProcess_.store(true);
650             extPtr->execOnProcessCon_.notify_one();
651             lock.unlock();
652             return;
653         }
654         std::string processInfoJsonStr;
655         BJsonUtil::BuildOnProcessRetInfo(processInfoJsonStr, processInfo);
656         extPtr->ReportAppProcessInfo(processInfoJsonStr, scenario);
657     };
658     auto extenionPtr = obj.promote();
659     if (extenionPtr == nullptr) {
660         HILOGE("Async call js onProcess failed, extenionPtr is empty");
661         return;
662     }
663     ErrCode ret = extenionPtr->extension_->OnProcess(callBack);
664     if (ret != ERR_OK) {
665         HILOGE("Call OnProcess Failed, ret:%{public}d", ret);
666         return;
667     }
668     HILOGI("End");
669 }
670 
FinishOnProcessTask()671 void BackupExtExtension::FinishOnProcessTask()
672 {
673     HILOGI("Begin");
674     std::unique_lock<std::mutex> lock(onProcessLock_);
675     stopCallJsOnProcess_.store(true);
676     isFirstCallOnProcess_.store(false);
677     isExecAppDone_.store(false);
678     onProcessTimeoutCnt_ = 0;
679     execOnProcessCon_.notify_one();
680     lock.unlock();
681     if (callJsOnProcessThread_.joinable()) {
682         callJsOnProcessThread_.join();
683     }
684     HILOGI("End");
685 }
686 
StartOnProcessTimeOutTimer(wptr<BackupExtExtension> obj,BackupRestoreScenario scenario)687 void BackupExtExtension::StartOnProcessTimeOutTimer(wptr<BackupExtExtension> obj, BackupRestoreScenario scenario)
688 {
689     HILOGI("Begin");
690     if (stopCallJsOnProcess_.load()) {
691         HILOGE("Current extension execute finished");
692         return;
693     }
694     auto timeoutCallback = [obj, scenario]() {
695         auto extPtr = obj.promote();
696         if (extPtr == nullptr) {
697             HILOGE("Start Create timeout callback failed, extPtr is empty");
698             return;
699         }
700         if (extPtr->onProcessTimeoutCnt_.load() >= BConstants::APP_ON_PROCESS_TIMEOUT_MAX_COUNT ||
701             extPtr->isFirstCallOnProcess_.load()) {
702             HILOGE("The extension invokes the onProcess for more than three times or the first invoking of the "
703                    "onProcess times out, timeoutCnt:%{public}d", extPtr->onProcessTimeoutCnt_.load());
704             std::unique_lock<std::mutex> lock(extPtr->onProcessLock_);
705             extPtr->stopCallJsOnProcess_.store(true);
706             extPtr->isFirstCallOnProcess_.store(false);
707             extPtr->isExecAppDone_.store(true);
708             extPtr->onProcessTimeoutCnt_ = 0;
709             extPtr->execOnProcessCon_.notify_one();
710             lock.unlock();
711             if (scenario == BackupRestoreScenario::FULL_BACKUP || scenario == BackupRestoreScenario::FULL_RESTORE) {
712                 extPtr->AppDone(BError(BError::Codes::EXT_ABILITY_TIMEOUT));
713             } else if (scenario == BackupRestoreScenario::INCREMENTAL_BACKUP ||
714                 scenario == BackupRestoreScenario::INCREMENTAL_RESTORE) {
715                 extPtr->AppIncrementalDone(BError(BError::Codes::EXT_ABILITY_TIMEOUT));
716             }
717             return;
718         }
719         extPtr->onProcessTimeoutCnt_++;
720         extPtr->onProcessTimeout_.store(true);
721         HILOGE("Extension onProcess timeout, Increase cnt:%{public}d", extPtr->onProcessTimeoutCnt_.load());
722     };
723     int timeout = isFirstCallOnProcess_.load() ? BConstants::FIRST_CALL_APP_ON_PROCESS_MAX_TIMEOUT :
724                                                  BConstants::APP_ON_PROCESS_MAX_TIMEOUT;
725     uint32_t timerId = onProcessTimeoutTimer_.Register(timeoutCallback, timeout, true);
726     onProcessTimeoutTimerId_ = timerId;
727     HILOGI("End");
728 }
729 
CloseOnProcessTimeOutTimer()730 void BackupExtExtension::CloseOnProcessTimeOutTimer()
731 {
732     HILOGI("Begin");
733     onProcessTimeoutTimer_.Unregister(onProcessTimeoutTimerId_);
734     HILOGI("End");
735 }
736 
AppIncrementalDone(ErrCode errCode)737 void BackupExtExtension::AppIncrementalDone(ErrCode errCode)
738 {
739     HILOGI("Begin");
740     auto proxy = ServiceProxy::GetInstance();
741         if (proxy == nullptr) {
742         HILOGE("Failed to obtain the ServiceProxy handle");
743         DoClear();
744         return;
745     }
746     auto ret = proxy->AppIncrementalDone(errCode);
747     if (ret != ERR_OK) {
748         HILOGE("Failed to notify the app done. err = %{public}d", ret);
749     }
750 }
751 
GetBackupInfo(std::string & result)752 ErrCode BackupExtExtension::GetBackupInfo(std::string &result)
753 {
754     auto obj = wptr<BackupExtExtension>(this);
755     auto ptr = obj.promote();
756     if (ptr == nullptr) {
757         HILOGE("Failed to get ext extension.");
758         return BError(BError::Codes::EXT_INVAL_ARG, "extension getBackupInfo exception").GetCode();
759     }
760     if (ptr->extension_ == nullptr) {
761         HILOGE("Failed to get extension.");
762         return BError(BError::Codes::EXT_INVAL_ARG, "extension getBackupInfo exception").GetCode();
763     }
764     auto callBackup = [ptr](ErrCode errCode, const std::string result) {
765         if (ptr == nullptr) {
766             HILOGE("Failed to get ext extension.");
767             return;
768         }
769         HILOGI("GetBackupInfo callBackup start. errCode = %{public}d, result = %{public}s", errCode, result.c_str());
770         if (errCode == ERR_OK) {
771             ptr->backupInfo_ = result;
772         }
773     };
774     auto ret = ptr->extension_->GetBackupInfo(callBackup);
775     if (ret != ERR_OK) {
776         HILOGE("Failed to get backupInfo. err = %{public}d", ret);
777         return BError(BError::Codes::EXT_INVAL_ARG, "extension getBackupInfo exception").GetCode();
778     }
779     HILOGD("backupInfo = %s", backupInfo_.c_str());
780     result = backupInfo_;
781     backupInfo_.clear();
782 
783     return ERR_OK;
784 }
785 
UpdateFdSendRate(std::string & bundleName,int32_t sendRate)786 ErrCode BackupExtExtension::UpdateFdSendRate(std::string &bundleName, int32_t sendRate)
787 {
788     try {
789         std::lock_guard<std::mutex> lock(updateSendRateLock_);
790         HILOGI("Update SendRate, bundleName:%{public}s, sendRate:%{public}d", bundleName.c_str(), sendRate);
791         VerifyCaller();
792         bundleName_ = bundleName;
793         sendRate_ = sendRate;
794         if (sendRate > 0) {
795             startSendFdRateCon_.notify_one();
796         }
797         return ERR_OK;
798     } catch (...) {
799         HILOGE("Failed to UpdateFdSendRate");
800         return BError(BError::Codes::EXT_BROKEN_IPC).GetCode();
801     }
802 }
803 
SetStagingPathProperties()804 bool BackupExtExtension::SetStagingPathProperties()
805 {
806     struct stat curBundleStat {};
807     if (lstat(BConstants::BUNDLE_BASE_DIR.c_str(), &curBundleStat) != 0) {
808         HILOGE("Failed to lstat, err = %{public}d", errno);
809         return false;
810     }
811     if (lchown(string(BConstants::PATH_BUNDLE_BACKUP_HOME).c_str(),
812         curBundleStat.st_uid, curBundleStat.st_gid) != 0) {
813         HILOGE("Failed to lchown, err = %{public}d", errno);
814         return false;
815     }
816     if (lchown(string(BConstants::PATH_BUNDLE_BACKUP_HOME_EL1).c_str(),
817         curBundleStat.st_uid, curBundleStat.st_gid) != 0) {
818         HILOGE("Failed to lchown, err = %{public}d", errno);
819         return false;
820     }
821     return true;
822 }
823 
IfAllowToBackupRestore()824 bool BackupExtExtension::IfAllowToBackupRestore()
825 {
826     if (extension_ == nullptr) {
827         HILOGE("Failed to handle backup, extension is nullptr");
828         return false;
829     }
830     string usrConfig = extension_->GetUsrConfig();
831     BJsonCachedEntity<BJsonEntityExtensionConfig> cachedEntity(usrConfig);
832     auto cache = cachedEntity.Structuralize();
833     if (!cache.GetAllowToBackupRestore()) {
834         HILOGE("Application does not allow backup or restore");
835         return false;
836     }
837     return true;
838 }
839 
User0OnBackup()840 ErrCode BackupExtExtension::User0OnBackup()
841 {
842     HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
843     if (!IfAllowToBackupRestore()) {
844         return BError(BError::Codes::EXT_FORBID_BACKUP_RESTORE, "Application does not allow backup or restore")
845             .GetCode();
846     }
847     AsyncTaskUser0Backup();
848     return ERR_OK;
849 }
850 
AsyncTaskUser0Backup()851 void BackupExtExtension::AsyncTaskUser0Backup()
852 {
853     HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
854     auto task = [obj {wptr<BackupExtExtension>(this)}]() {
855         auto ptr = obj.promote();
856         BExcepUltils::BAssert(ptr, BError::Codes::EXT_BROKEN_FRAMEWORK, "Ext extension handle have been released");
857         const string config = ptr->extension_->GetUsrConfig();
858         try {
859             HILOGI("Do backup, start fwk timer begin.");
860             bool isFwkStart;
861             ptr->StartFwkTimer(isFwkStart);
862             if (!isFwkStart) {
863                 HILOGE("Do backup, start fwk timer fail.");
864                 return;
865             }
866             HILOGI("Do backup, start fwk timer end.");
867             BJsonCachedEntity<BJsonEntityExtensionConfig> cachedEntity(config);
868             auto cache = cachedEntity.Structuralize();
869             auto ret = ptr->User0DoBackup(cache);
870             if (ret != ERR_OK) {
871                 HILOGE("User0DoBackup, err = %{pubilc}d", ret);
872                 ptr->AppIncrementalDone(BError::GetCodeByErrno(ret));
873             }
874         } catch (const BError &e) {
875             HILOGE("extension: AsyncTaskBackup error, err code:%{public}d", e.GetCode());
876             ptr->AppIncrementalDone(e.GetCode());
877         } catch (const exception &e) {
878             HILOGE("Catched an unexpected low-level exception %{public}s", e.what());
879             ptr->AppIncrementalDone(BError(BError::Codes::EXT_INVAL_ARG).GetCode());
880         } catch (...) {
881             HILOGE("Failed to restore the ext bundle");
882             ptr->AppIncrementalDone(BError(BError::Codes::EXT_INVAL_ARG).GetCode());
883         }
884     };
885 
886     threadPool_.AddTask([task]() {
887         try {
888             task();
889         } catch (...) {
890             HILOGE("Failed to add task to thread pool");
891         }
892     });
893 }
894 
DoUser0Backup(const BJsonEntityExtensionConfig & usrConfig)895 void BackupExtExtension::DoUser0Backup(const BJsonEntityExtensionConfig &usrConfig)
896 {
897     HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
898     string path = string(BConstants::PATH_BUNDLE_BACKUP_HOME).append(BConstants::SA_BUNDLE_BACKUP_BACKUP);
899     if (mkdir(path.data(), S_IRWXU) && errno != EEXIST) {
900         throw BError(errno);
901     }
902     vector<string> includes = usrConfig.GetIncludes();
903     vector<string> excludes = usrConfig.GetExcludes();
904     auto task = [obj {wptr<BackupExtExtension>(this)}, includes, excludes]() {
905         auto ptr = obj.promote();
906         BExcepUltils::BAssert(ptr, BError::Codes::EXT_BROKEN_FRAMEWORK, "Ext extension handle have been released");
907         try {
908             auto [bigFile, smallFile] = BDir::GetBackupList(includes, excludes);
909             vector<struct ReportFileInfo> allFiles;
910             vector<struct ReportFileInfo> smallFiles;
911             vector<struct ReportFileInfo> bigFiles;
912             BDir::GetUser0FileStat(move(bigFile), move(smallFile), allFiles, smallFiles, bigFiles);
913             auto ret = ptr->DoIncrementalBackup(allFiles, smallFiles, bigFiles);
914             ptr->AppIncrementalDone(ret);
915             HILOGI("User0 backup app done %{public}d", ret);
916         } catch (const BError &e) {
917             ptr->AppIncrementalDone(e.GetCode());
918         } catch (const exception &e) {
919             ptr->AppIncrementalDone(BError(BError::Codes::EXT_INVAL_ARG).GetCode());
920         } catch (...) {
921             HILOGE("Failed to restore the ext bundle");
922             ptr->AppIncrementalDone(BError(BError::Codes::EXT_INVAL_ARG).GetCode());
923         }
924     };
925 
926     threadPool_.AddTask([task]() {
927         try {
928             task();
929         } catch (...) {
930             HILOGE("Failed to add task to thread pool");
931         }
932     });
933 }
934 
User0DoBackup(const BJsonEntityExtensionConfig & usrConfig)935 int BackupExtExtension::User0DoBackup(const BJsonEntityExtensionConfig &usrConfig)
936 {
937     HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
938     if (extension_ == nullptr) {
939         HILOGE("Failed to do backup, extension is nullptr");
940         return BError(BError::Codes::EXT_INVAL_ARG);
941     }
942     if (extension_->GetExtensionAction() != BConstants::ExtensionAction::BACKUP) {
943         return EPERM;
944     }
945     DoUser0Backup(usrConfig);
946     return ERR_OK;
947 }
948 } // namespace OHOS::FileManagement::Backup
949