From f589362b6b48217561bafe721f16e50e1218e7bb Mon Sep 17 00:00:00 2001 From: yang-jingbo1985 Date: Sun, 18 Feb 2024 18:09:02 +0800 Subject: [PATCH] =?UTF-8?q?=E5=85=8B=E9=9A=86=E4=BA=91=E5=A4=87=E4=BB=BD?= =?UTF-8?q?=E5=A4=A7=E6=96=87=E4=BB=B6=E6=81=A2=E5=A4=8D=E4=BC=98=E5=8C=96?= =?UTF-8?q?=20Signed-off-by:=20yangjingbo10=20?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: If086d8b310980f51669607f75cfd3d42cebb3229 --- .../native/backup_ext/include/ext_extension.h | 2 + .../native/backup_ext/src/ext_extension.cpp | 169 +++++++++++++++--- 2 files changed, 148 insertions(+), 23 deletions(-) diff --git a/frameworks/native/backup_ext/include/ext_extension.h b/frameworks/native/backup_ext/include/ext_extension.h index 5120b9285..9935a47f5 100644 --- a/frameworks/native/backup_ext/include/ext_extension.h +++ b/frameworks/native/backup_ext/include/ext_extension.h @@ -23,6 +23,7 @@ #include +#include "b_json/b_json_entity_ext_manage.h" #include "b_json/b_json_entity_extension_config.h" #include "b_json/b_report_entity.h" #include "b_resources/b_constants.h" @@ -139,6 +140,7 @@ private: std::shared_mutex lock_; std::shared_ptr extension_; std::vector tars_; + std::map manageJsonItems_; OHOS::ThreadPool threadPool_; }; } // namespace OHOS::FileManagement::Backup diff --git a/frameworks/native/backup_ext/src/ext_extension.cpp b/frameworks/native/backup_ext/src/ext_extension.cpp index 3c29b896c..27faadb2c 100644 --- a/frameworks/native/backup_ext/src/ext_extension.cpp +++ b/frameworks/native/backup_ext/src/ext_extension.cpp @@ -103,7 +103,7 @@ static bool CheckAndCreateDirectory(const string& filePath) static UniqueFd GetFileHandleForSpecialCloneCloud(const string &fileName) { HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__); - HILOGE("GetFileHandleForSpecialCloneCloud: fileName is %{public}s", fileName.data()); + HILOGI("GetFileHandleForSpecialCloneCloud: fileName is %{public}s", fileName.data()); string filePath = fileName; if (fileName.front() != BConstants::FILE_SEPARATOR_CHAR) { filePath = BConstants::FILE_SEPARATOR_CHAR + fileName; @@ -124,6 +124,49 @@ static UniqueFd GetFileHandleForSpecialCloneCloud(const string &fileName) return UniqueFd(open(fileName.data(), O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)); } +static UniqueFd GetFileHandleForManageJsonFirst(const string &fileName, map manageJsonItems) +{ + HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__); + HILOGI("GetFileHandleForManageJsonFirst: fileName is %{public}s", fileName.data()); + + auto it = manageJsonItems.find(fileName); + if (it == manageJsonItems.end()) { + HILOGE("GetFileHandleForManageJsonFirst: FileName not match the manage.json"); + throw BError(BError::Codes::EXT_INVAL_ARG, fileName); + } + auto item = it->second; + string filePath = item.fileName; + if (!item.isUserTar && !item.isBigFile) { + // tar files (not user tar) will be moved to temporary directory as before + string path = string(BConstants::PATH_BUNDLE_BACKUP_HOME).append(BConstants::SA_BUNDLE_BACKUP_RESTORE); + if (mkdir(path.data(), S_IRWXU) && errno != EEXIST) { + string str = string("Failed to create restore folder. ").append(generic_category().message(errno)); + throw BError(BError::Codes::EXT_INVAL_ARG, str); + } + + filePath = path + fileName; + if (access(filePath.data(), F_OK) == 0) { + throw BError(BError::Codes::EXT_INVAL_ARG, string("The file already exists")); + } + } else { + // big file and user tar would be moved to destination path defined in manage.json + size_t filePathPrefix = filePath.find_last_of(BConstants::FILE_SEPARATOR_CHAR); + if (filePathPrefix == string::npos) { + HILOGE("GetFileHandleForManageJsonFirst: Invalid fileName"); + throw BError(BError::Codes::EXT_INVAL_ARG, fileName); + } + string path = filePath.substr(0, filePathPrefix); + if (access(path.data(), F_OK) != 0) { + bool created = ForceCreateDirectory(path.data()); + if (!created) { + string str = string("Failed to create restore folder."); + throw BError(BError::Codes::EXT_INVAL_ARG, str); + } + } + } + return UniqueFd(open(filePath.data(), O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)); +} + UniqueFd BackupExtExtension::GetFileHandle(const string &fileName) { HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__); @@ -139,6 +182,10 @@ UniqueFd BackupExtExtension::GetFileHandle(const string &fileName) return GetFileHandleForSpecialCloneCloud(fileName); } + if (!manageJsonItems_.empty()) { + return GetFileHandleForManageJsonFirst(fileName, manageJsonItems_); + } + string path = string(BConstants::PATH_BUNDLE_BACKUP_HOME).append(BConstants::SA_BUNDLE_BACKUP_RESTORE); if (mkdir(path.data(), S_IRWXU) && errno != EEXIST) { string str = string("Failed to create restore folder. ").append(std::generic_category().message(errno)); @@ -317,6 +364,25 @@ static bool IsAllFileReceived(vector tars, bool isSpeicalVersion) return includes(tars.begin(), tars.end(), info.begin(), info.end()); } +static void ReadManageJsonInfo(std::map &manageJsonItems) +{ + UniqueFd fd(open(INDEX_FILE_RESTORE.data(), O_RDONLY)); + if (fd < 0) { + HILOGE("ReadManageJsonInfo: open manage json file failed, err = %{public}d", errno); + throw BError(BError::Codes::EXT_INVAL_ARG, "Open manage json file failed"); + } + + BJsonCachedEntity cachedEntity(move(fd)); + auto cache = cachedEntity.Structuralize(); + auto info = cache.GetExtManageInfo(); + for (auto &item : info) { + if (item.hashName.empty()) { + continue; + } + manageJsonItems.emplace(item.hashName, item); + } +} + ErrCode BackupExtExtension::PublishFile(const string &fileName) { HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__); @@ -329,8 +395,24 @@ ErrCode BackupExtExtension::PublishFile(const string &fileName) // 是否指定克隆模式 bool isSpeicalVersion = extension_->SpeicalVersionForCloneAndCloud(); + // check if manage.json is the first received file in restore process + // if Yes, read it and save its item infos to manageJsonItems_ map. + if (fileName == BConstants::EXT_BACKUP_MANAGE && tars_.empty()) { + ReadManageJsonInfo(manageJsonItems_); + } + string path = string(BConstants::PATH_BUNDLE_BACKUP_HOME).append(BConstants::SA_BUNDLE_BACKUP_RESTORE); string tarName = isSpeicalVersion ? fileName : path + fileName; + // check if manageJsonItems_ is not null and include fileName + if (!manageJsonItems_.empty()) { + auto it = manageJsonItems_.find(fileName); + if (it == manageJsonItems_.end()) { + HILOGE("PublishFile: FileName not match the manage.json"); + throw BError(BError::Codes::EXT_INVAL_ARG, fileName); + } + // destination file is real path not temporary path + tarName = it->second.fileName; + } { BExcepUltils::VerifyPath(tarName, !isSpeicalVersion); unique_lock lock(lock_); @@ -527,6 +609,11 @@ int BackupExtExtension::DoRestore(const string &fileName) if (extension_->GetExtensionAction() != BConstants::ExtensionAction::RESTORE) { return EPERM; } + + if (ExtractFileExt(fileName) != "tar" || IsUserTar(fileName, INDEX_FILE_RESTORE)) { + HILOGI("Only non-user tar file need to unpack, package path is %{public}s", fileName.c_str()); + return ERR_OK; + } // REM: 给定version // REM: 解压启动Extension时即挂载好的备份目录中的数据 string path = string(BConstants::PATH_BUNDLE_BACKUP_HOME).append(BConstants::SA_BUNDLE_BACKUP_RESTORE); @@ -614,7 +701,7 @@ void BackupExtExtension::AsyncTaskBackup(const string config) }); } -static void RestoreBigFilesForSpecialCloneCloud(ExtManageInfo item) +static void RestoreBigFilesForDirectCopy(ExtManageInfo item) { HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__); struct stat& sta = item.sta; @@ -630,6 +717,18 @@ static void RestoreBigFilesForSpecialCloneCloud(ExtManageInfo item) } } +static ErrCode RestoreTarForManageJsonFirst(ExtManageInfo item) +{ + HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__); + string tarName = item.fileName; + UntarFile::GetInstance().UnPacket(tarName, "/"); + + if (!RemoveFile(tarName)) { + HILOGE("Failed to delete the backup tar %{public}s", tarName.c_str()); + } + return ERR_OK; +} + static ErrCode RestoreTarForSpeicalCloneCloud(ExtManageInfo item) { HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__); @@ -650,6 +749,37 @@ static ErrCode RestoreTarForSpeicalCloneCloud(ExtManageInfo item) return ERR_OK; } +static ErrCode RestoreFilesForManageJsonFirst() +{ + HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__); + // 获取索引文件内容 + string path = string(BConstants::PATH_BUNDLE_BACKUP_HOME).append(BConstants::SA_BUNDLE_BACKUP_RESTORE); + BJsonCachedEntity cachedEntity(UniqueFd(open(INDEX_FILE_RESTORE.data(), O_RDONLY))); + auto cache = cachedEntity.Structuralize(); + auto info = cache.GetExtManageInfo(); + + for (auto &item : info) { + if (item.hashName.empty()) { + continue; + } + if (item.isUserTar || item.isBigFile) { + // 大文件处理 + RestoreBigFilesForDirectCopy(item); + } else { + // 待解压tar文件处理 + if (RestoreTarForManageJsonFirst(item) != ERR_OK) { + HILOGE("Failed to restore tar file %{public}s", item.hashName.c_str()); + return ERR_INVALID_VALUE; + } + } + } + if (!RemoveFile(INDEX_FILE_RESTORE)) { + HILOGE("Failed to delete the backup index %{public}s", INDEX_FILE_RESTORE.c_str()); + } + HILOGI("after extra, do restore for ManageJsonFirst."); + return ERR_OK; +} + static ErrCode RestoreFilesForSpecialCloneCloud() { HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__); @@ -665,7 +795,7 @@ static ErrCode RestoreFilesForSpecialCloneCloud() } if (item.isUserTar || item.isBigFile) { // 大文件处理 - RestoreBigFilesForSpecialCloneCloud(item); + RestoreBigFilesForDirectCopy(item); } else { // 待解压tar文件处理 if (RestoreTarForSpeicalCloneCloud(item) != ERR_OK) { @@ -833,29 +963,22 @@ void BackupExtExtension::AsyncTaskRestore() int ret = ERR_OK; if (ptr->extension_->SpeicalVersionForCloneAndCloud()) { ret = RestoreFilesForSpecialCloneCloud(); - if (ret == ERR_OK) { - ptr->AsyncTaskRestoreForUpgrade(); - } else { - ptr->AppDone(ret); - ptr->DoClear(); - } - return; - } - // 解压 - for (auto item : tars) { // 处理要解压的tar文件 - if (ExtractFileExt(item) == "tar" && !IsUserTar(item, INDEX_FILE_RESTORE)) { + } else if (ptr->manageJsonItems_.empty()) { + ret = RestoreFilesForManageJsonFirst(); + } else { + // 解压 + for (auto item : tars) { // 处理要解压的tar文件 ret = ptr->DoRestore(item); } + // 恢复用户tar包以及大文件 + // 目的地址是否需要拼接path(临时目录),FullBackupOnly为true并且非特殊场景 + bool appendTargetPath = ptr->extension_->UseFullBackupOnly() && + !ptr->extension_->SpeicalVersionForCloneAndCloud(); + RestoreBigFiles(appendTargetPath); + + // delete 1.tar/manage.json + DeleteBackupTars(); } - // 恢复用户tar包以及大文件 - // 目的地址是否需要拼接path(临时目录),FullBackupOnly为true并且非特殊场景 - bool appendTargetPath = ptr->extension_->UseFullBackupOnly() && - !ptr->extension_->SpeicalVersionForCloneAndCloud(); - RestoreBigFiles(appendTargetPath); - - // delete 1.tar/manage.json - DeleteBackupTars(); - if (ret == ERR_OK) { HILOGI("after extra, do restore."); ptr->AsyncTaskRestoreForUpgrade(); -- Gitee