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