From df8384cc1d8471e58b6e885bd65a23c0ee608ab0 Mon Sep 17 00:00:00 2001 From: yang-jingbo1985 Date: Sat, 25 Nov 2023 18:11:26 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E6=8C=81=E5=B8=A6=E8=B7=AF=E5=BE=84?= =?UTF-8?q?=E7=9A=84=E6=96=87=E4=BB=B6=E5=90=8D=EF=BC=8C=E6=81=A2=E5=A4=8D?= =?UTF-8?q?=E6=97=B6=E5=BA=8F=E4=BC=98=E5=8C=96=20Signed-off-by:=20yangjin?= =?UTF-8?q?gbo10=20?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I0c76571418decab8749e9adb58bd6a8a312aeb46 --- .../native/backup_ext/include/ext_extension.h | 7 + .../native/backup_ext/src/ext_extension.cpp | 171 ++++++++++++++++-- services/backup_sa/src/module_ipc/service.cpp | 6 - 3 files changed, 158 insertions(+), 26 deletions(-) diff --git a/frameworks/native/backup_ext/include/ext_extension.h b/frameworks/native/backup_ext/include/ext_extension.h index c39e05fcd..77151d99f 100644 --- a/frameworks/native/backup_ext/include/ext_extension.h +++ b/frameworks/native/backup_ext/include/ext_extension.h @@ -21,6 +21,7 @@ #include #include "b_json/b_json_entity_extension_config.h" +#include "b_json/b_json_entity_ext_manage.h" #include "b_resources/b_constants.h" #include "ext_backup_js.h" #include "ext_extension_stub.h" @@ -95,9 +96,15 @@ private: void AsyncTaskOnBackup(); + bool isIndexReadyForRestore(std::vector indexInfos_); + + bool getInfoFromIndexFile(std::vector indexInfos_); + private: std::shared_mutex lock_; std::shared_ptr extension_; + std::vector indexInfos_; + std::vector waitedFiles_; std::vector tars_; OHOS::ThreadPool threadPool_; }; diff --git a/frameworks/native/backup_ext/src/ext_extension.cpp b/frameworks/native/backup_ext/src/ext_extension.cpp index e5d16903c..d9a12c9c5 100644 --- a/frameworks/native/backup_ext/src/ext_extension.cpp +++ b/frameworks/native/backup_ext/src/ext_extension.cpp @@ -53,6 +53,8 @@ const string INDEX_FILE_RESTORE = string(BConstants::PATH_BUNDLE_BACKUP_HOME). append(BConstants::EXT_BACKUP_MANAGE); using namespace std; +static set indexFileInfos; + void BackupExtExtension::VerifyCaller() { HILOGI("begin"); @@ -68,6 +70,87 @@ void BackupExtExtension::VerifyCaller() } } +static void createDirectory(const string &path) +{ + string::size_type index = 0; + do { + string subPath; + index = path.find('/', index + 1); + if (index == string::npos) { + subPath = path; + } else { + subPath = path.substr(0, index); + } + if (access(subPath.c_str(), F_OK) != 0) { + if (mkdir(subPath.c_str(), (S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) != 0 && errno != EEXIST) { + string str = string("Failed to create folder. ").append(std::generic_category().message(errno)); + throw BError(BError::Codes::EXT_INVAL_ARG, str); + } + } + } while (index != string::npos); +} + +bool BackupExtExtension::isIndexReadyForRestore(std::vector indexInfos_) +{ + shared_lock lock(lock_); + if (indexInfos_.empty()) { + return false; + } + return true; +} + +bool BackupExtExtension::getInfoFromIndexFile(std::vector indexInfos_) +{ + if (access(INDEX_FILE_RESTORE.data(), F_OK) != 0) { + HILOGE("Index file does not exist"); + return false; + } + + // 获取索引文件内容 + BJsonCachedEntity cachedEntity(UniqueFd(open(INDEX_FILE_RESTORE.data(), O_RDONLY))); + auto cache = cachedEntity.Structuralize(); + // 写入索引信息加锁 + unique_lock lock(lock_); + indexInfos_ = cache.GetExtManageInfo(); + return true; +} + +static UniqueFd createFileFromIndexFile(ExtManageInfo& manageInfo) +{ + string filePath = manageInfo.fileName; + struct stat sta = manageInfo.sta; + + // 创建目录 + createDirectory(filePath.data()); + + // 创建FD + auto fd = UniqueFd(open(filePath.data(), O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)); + struct timespec tv[2] = {sta.st_atim, sta.st_mtim}; + if (futimens(fd.Get(), tv) != 0) { + HILOGE("failed to change the file time. %{public}s , %{public}d", filePath.c_str(), errno); + } + + return fd; +} + +static bool IsUserTar(const string &tarFile, const string &indexFile) +{ + if (tarFile.empty()) { + return false; + } + BJsonCachedEntity cachedEntity(UniqueFd(open(indexFile.data(), O_RDONLY))); + auto cache = cachedEntity.Structuralize(); + auto info = cache.GetExtManageInfo(); + for (auto &item : info) { + if (item.hashName == tarFile) { + HILOGI("tarFile:%{public}s isUserTar:%{public}d", tarFile.data(), item.isUserTar); + return item.isUserTar; + } + } + HILOGE("Can not find tarFile %{public}s", tarFile.data()); + return false; +} + UniqueFd BackupExtExtension::GetFileHandle(const string &fileName) { try { @@ -76,10 +159,41 @@ UniqueFd BackupExtExtension::GetFileHandle(const string &fileName) throw BError(BError::Codes::EXT_INVAL_ARG, "Action is invalid"); } + // 如果是manage.json + if (strcmp(fileName.data(), BConstants::EXT_BACKUP_MANAGE.data()) == 0) { + HILOGI("Index file is published before receive getFileHandle. "); + return UniqueFd(-1); + } + VerifyCaller(); - if (fileName.find('/') != string::npos) { - throw BError(BError::Codes::EXT_INVAL_ARG, "Filename is not valid"); + // 查看manage.json信息是否已经获取 + if (!isIndexReadyForRestore(indexInfos_)) { + HILOGI("Index file is not ready for restore"); + waitedFiles_.emplace_back(fileName); + return UniqueFd(-1); + } + + // 从Manage.json中获取对应的文件信息 + ExtManageInfo manageInfo; + bool isFind = false; + for (auto &item : indexInfos_) { + if (strcmp(item.hashName.data(), fileName.data()) == 0) { + manageInfo = item; + isFind = true; + break; + } + } + + if (!isFind) { + throw BError(BError::Codes::EXT_INVAL_ARG, "failed to get the fileName from manage.json"); + return UniqueFd(-1); + } + + // 普通大文件或者userTar + if (ExtractFileExt(fileName) != "tar" || IsUserTar(fileName, INDEX_FILE_RESTORE)) { + HILOGI("FileName contains path symbol."); + return createFileFromIndexFile(manageInfo); } string path = string(BConstants::PATH_BUNDLE_BACKUP_HOME).append(BConstants::SA_BUNDLE_BACKUP_RESTORE); @@ -195,6 +309,30 @@ ErrCode BackupExtExtension::PublishFile(const string &fileName) } VerifyCaller(); + // 对于manage.json,需要读取文件信息到容器 + if (strcmp(fileName.data(), BConstants::EXT_BACKUP_MANAGE.data()) == 0) { + if (!getInfoFromIndexFile(indexInfos_)) { + throw BError(BError::Codes::EXT_INVAL_ARG, "Index file not exist"); + } + for (auto &waitedFile : waitedFiles_) { + auto task = [obj {wptr(this)}, waitedFile]() { + auto ptr = obj.promote(); + ptr->GetFileHandle(waitedFile); + }; + // 读取等待中的waitedFiles_,触发操作 + threadPool_.AddTask([task]() { + try { + task(); + } catch (...) { + HILOGE("Failed to add task to thread pool"); + } + }); + } + unique_lock lock(lock_); + tars_.push_back(fileName); + return ERR_OK; + } + string path = string(BConstants::PATH_BUNDLE_BACKUP_HOME).append(BConstants::SA_BUNDLE_BACKUP_RESTORE); string tarName = path + fileName; { @@ -242,24 +380,6 @@ ErrCode BackupExtExtension::HandleBackup() return 0; } -static bool IsUserTar(const string &tarFile, const string &indexFile) -{ - if (tarFile.empty()) { - return false; - } - BJsonCachedEntity cachedEntity(UniqueFd(open(indexFile.data(), O_RDONLY))); - auto cache = cachedEntity.Structuralize(); - auto info = cache.GetExtManageInfo(); - for (auto &item : info) { - if (item.hashName == tarFile) { - HILOGI("tarFile:%{public}s isUserTar:%{public}d", tarFile.data(), item.isUserTar); - return item.isUserTar; - } - } - HILOGE("Can not find tarFile %{public}s", tarFile.data()); - return false; -} - static map> GetBigFileInfo(const vector &includes, const vector &excludes) { @@ -654,6 +774,17 @@ ErrCode BackupExtExtension::HandleRestore() if (extension_->WasFromSpeicalVersion() && extension_->RestoreDataReady()) { HILOGI("Restore directly when upgrading."); AsyncTaskRestoreForUpgrade(); + } else { + // To provide fd for manage.json first. + auto proxy = ServiceProxy::GetInstance(); + ErrCode ret = + proxy->AppFileReady(string(BConstants::EXT_BACKUP_MANAGE), UniqueFd(open(INDEX_FILE_BACKUP.data(), O_RDONLY))); + if (SUCCEEDED(ret)) { + HILOGI("Restore start: Manage.json request successfully"); + } else { + HILOGI("Restore start: AppFileReady interface fails to be invoked: %{public}d", ret); + } + return ret; } return 0; diff --git a/services/backup_sa/src/module_ipc/service.cpp b/services/backup_sa/src/module_ipc/service.cpp index 937146137..93d5c85dc 100644 --- a/services/backup_sa/src/module_ipc/service.cpp +++ b/services/backup_sa/src/module_ipc/service.cpp @@ -353,9 +353,6 @@ ErrCode Service::PublishFile(const BFileInfo &fileInfo) sched_->Sched(fileInfo.owner); return BError(BError::Codes::OK); } - if (fileInfo.fileName.find('/') != string::npos) { - throw BError(BError::Codes::SA_INVAL_ARG, "Filename is not valid"); - } auto backUpConnection = session_->GetExtConnection(fileInfo.owner); @@ -513,9 +510,6 @@ ErrCode Service::GetFileHandle(const string &bundleName, const string &fileName) } return BError(BError::Codes::OK); } - if (fileName.find('/') != string::npos) { - throw BError(BError::Codes::SA_INVAL_ARG, "Filename is not valid"); - } auto action = session_->GetServiceSchedAction(bundleName); if (action == BConstants::ServiceSchedAction::RUNNING) { auto backUpConnection = session_->GetExtConnection(bundleName); -- Gitee