From 96972b6063513e935122c7f5217a005003738e94 Mon Sep 17 00:00:00 2001 From: yang-jingbo1985 Date: Fri, 19 Jan 2024 09:28:23 +0800 Subject: [PATCH] =?UTF-8?q?SpecialCloneBACKUP=E9=80=82=E9=85=8D=20Signed-o?= =?UTF-8?q?ff-by:=20yangjingbo10=20?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I00ef4cc7d0e58f02aa60b13d0d3dc1d579ae841f --- .../native/backup_ext/src/ext_extension.cpp | 244 +++++++++++------- utils/include/b_resources/b_constants.h | 1 + utils/src/b_json/b_json_entity_ext_manage.cpp | 2 +- 3 files changed, 146 insertions(+), 101 deletions(-) diff --git a/frameworks/native/backup_ext/src/ext_extension.cpp b/frameworks/native/backup_ext/src/ext_extension.cpp index 2697e0413..9430d5844 100644 --- a/frameworks/native/backup_ext/src/ext_extension.cpp +++ b/frameworks/native/backup_ext/src/ext_extension.cpp @@ -70,25 +70,47 @@ void BackupExtExtension::VerifyCaller() } } -static string GenerateHashForFileName(const string &fName) +static bool CheckAndCreateDirectory(const string& filePath) { - ostringstream strHex; - strHex << hex; + size_t pos = filePath.rfind('/'); + if (pos == string::npos) { + return true; + } - hash strHash; - size_t szHash = strHash(fName); - strHex << setfill('0') << setw(BConstants::BIG_FILE_NAME_SIZE) << szHash; - return strHex.str(); + string folderPath = "/" + filePath.substr(0, pos); + if (access(folderPath.c_str(), F_OK) != 0) { + if (!ForceCreateDirectory(folderPath.data())) { + return false; + } + } + + return true; } -static bool CheckIfTarSuffix(const string &fileName) +static UniqueFd GetFileHandleForSpecialCloneCloud(const string &fileName) { - if (auto suffix = string_view(".tar"); - fileName.length() > suffix.length() && - equal(fileName.rbegin(), next(fileName.rbegin(), suffix.length()), suffix.rbegin(), suffix.rend())) { - return true; + HILOGE("!!!GetFileHandleForSpecialCloneCloud: fileName is %{public}s", fileName.data()); + string filePath = fileName; + if (fileName.front() != BConstants::FILE_SEPARATOR_CHAR) { + filePath = BConstants::FILE_SEPARATOR_CHAR + fileName; + } + size_t filePathPrefix = filePath.find_last_of(BConstants::FILE_SEPARATOR_CHAR); + if (filePathPrefix == string::npos) { + HILOGE("GetFileHandleForSpecialCloneCloud: Invalid fileName"); + throw BError(BError::Codes::EXT_INVAL_ARG, fileName); + } + string path = filePath.substr(0, filePathPrefix); + HILOGE("!!!GetFileHandleForSpecialCloneCloud: mdkir path is %{public}s", path.data()); + + if (access(path.c_str(), F_OK) != 0) { + HILOGE("!!!GetFileHandleForSpecialCloneCloud: no real path for %{public}s", path.data()); + bool created = ForceCreateDirectory(path.data()); + if (!created) { + string str = string("Failed to create restore folder."); + throw BError(BError::Codes::EXT_INVAL_ARG, str); + } } - return false; + return UniqueFd(open(fileName.data(), O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)); } UniqueFd BackupExtExtension::GetFileHandle(const string &fileName) @@ -101,6 +123,10 @@ UniqueFd BackupExtExtension::GetFileHandle(const string &fileName) VerifyCaller(); + if (extension_->SpeicalVersionForCloneAndCloud()) { + return GetFileHandleForSpecialCloneCloud(fileName); + } + 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)); @@ -108,13 +134,6 @@ UniqueFd BackupExtExtension::GetFileHandle(const string &fileName) } string tarName = path + fileName; - if (fileName.find('/') != string::npos) { - HILOGD("GetFileHandle: fileName include path symbol, need to make hash."); - tarName = path + GenerateHashForFileName(fileName); - if (CheckIfTarSuffix(fileName)) { - tarName += ".tar"; - } - } if (access(tarName.c_str(), F_OK) == 0) { throw BError(BError::Codes::EXT_INVAL_ARG, string("The file already exists")); } @@ -190,18 +209,33 @@ static ErrCode BigFileReady(sptr proxy) return ret; } -static bool IsAllFileReceived(vector tars) +static bool IsAllFileReceived(vector tars, bool isSpeicalVersion) { // 是否已收到索引文件 - if (find(tars.begin(), tars.end(), string(BConstants::EXT_BACKUP_MANAGE)) == tars.end()) { - return false; + if (isSpeicalVersion) { + HILOGI("Check if manage.json is received for SpeicalVersion."); + string manageFileName = INDEX_FILE_RESTORE; + if (manageFileName.front() == BConstants::FILE_SEPARATOR_CHAR) { + manageFileName = manageFileName.substr(1); + } + HILOGI("!!!!!IsAllFileReceived manageFileName %{public}s", manageFileName.c_str()); + if (find(tars.begin(), tars.end(), manageFileName) == tars.end()) { + return false; + } + } else { + HILOGI("Check if manage.json is received."); + if (find(tars.begin(), tars.end(), string(BConstants::EXT_BACKUP_MANAGE)) == tars.end()) { + return false; + } } + HILOGE("!!!!!IsAllFileReceived Found Mange"); // 获取索引文件内容 BJsonCachedEntity cachedEntity(UniqueFd(open(INDEX_FILE_RESTORE.data(), O_RDONLY))); auto cache = cachedEntity.Structuralize(); set info = cache.GetExtManage(); - + HILOGE("!!!!!IsAllFileReceived info.size %{public}d", (int32_t)info.size()); + HILOGE("!!!!!IsAllFileReceived tars.size %{public}d", (int32_t)tars.size()); // 从数量上判断是否已经全部收到 if (tars.size() <= info.size()) { return false; @@ -220,31 +254,26 @@ ErrCode BackupExtExtension::PublishFile(const string &fileName) throw BError(BError::Codes::EXT_INVAL_ARG, "Action is invalid"); } VerifyCaller(); + // 是否指定克隆模式 + bool isSpeicalVersion = extension_->SpeicalVersionForCloneAndCloud(); string path = string(BConstants::PATH_BUNDLE_BACKUP_HOME).append(BConstants::SA_BUNDLE_BACKUP_RESTORE); - string tarName = path + fileName; - // 带路径的文件名在这里转换为hash值 - if (fileName.find('/') != string::npos) { - HILOGD("PublishFile: fileName include path symbol, need to make hash."); - tarName = path + GenerateHashForFileName(fileName); - if (CheckIfTarSuffix(fileName)) { - tarName += ".tar"; - } - } + string tarName = isSpeicalVersion ? fileName : path + fileName; + HILOGE("!!!!!PublishFile %{public}s", tarName.c_str()); { - BExcepUltils::VerifyPath(tarName, true); + BExcepUltils::VerifyPath(tarName, !isSpeicalVersion); unique_lock lock(lock_); if (find(tars_.begin(), tars_.end(), fileName) != tars_.end() || access(tarName.data(), F_OK) != 0) { throw BError(BError::Codes::EXT_INVAL_ARG, "The file does not exist"); } tars_.push_back(fileName); - if (!IsAllFileReceived(tars_)) { + if (!IsAllFileReceived(tars_, isSpeicalVersion)) { return ERR_OK; } } - // 异步执行解压操作 if (extension_->AllowToBackupRestore()) { + HILOGE("!!!!!AsyncTaskRestore %{public}s", tarName.c_str()); AsyncTaskRestore(); } @@ -384,25 +413,6 @@ int BackupExtExtension::DoRestore(const string &fileName) string path = string(BConstants::PATH_BUNDLE_BACKUP_HOME).append(BConstants::SA_BUNDLE_BACKUP_RESTORE); string tarName = path + fileName; - // 带路径的恢复需要找到hash后的待解压文件 - if (fileName.find('/') != string::npos) { - HILOGD("DoRestore: fileName include path symbol, need to make hash."); - string filePath = path + GenerateHashForFileName(fileName); - size_t pos = filePath.rfind('/'); - if (pos == string::npos) { - return EPERM; - } - string folderPath = filePath.substr(0, pos); - if (!ForceCreateDirectory(folderPath.data())) { - HILOGE("Failed to create directory"); - return EPERM; - } - tarName = filePath; - if (CheckIfTarSuffix(fileName)) { - tarName += ".tar"; - } - } - // 当用户指定fullBackupOnly字段或指定版本的恢复,解压目录当前在/backup/restore if (extension_->SpeicalVersionForCloneAndCloud() || extension_->UseFullBackupOnly()) { UntarFile::GetInstance().UnPacket(tarName, path); @@ -452,44 +462,74 @@ void BackupExtExtension::AsyncTaskBackup(const string config) }); } -static bool RestoreBigFilesWithPath(string& fileName, const string& path, - const string& hashName, const string& filePath) +static void RestoreBigFilesForSpecialCloneCloud(ExtManageInfo item) { - // 带路径的文件名在这里转换为hash值 - HILOGD("RestoreBigFiles: fileName include path symbol, need to make hash."); - fileName = path + GenerateHashForFileName(hashName); - if (access(fileName.data(), F_OK) != 0) { - HILOGI("file does not exist"); - return false; + HILOGE("!!! RestoreBigFilesForSpecialCloneCloud. item.hashName is %{public}s", item.hashName.data()); + struct stat& sta = item.sta; + string fileName = item.hashName; + if (chmod(fileName.c_str(), sta.st_mode) != 0) { + HILOGE("Failed to chmod filePath, err = %{public}d", errno); } - size_t pos = filePath.rfind('/'); - if (pos == string::npos) { - return false; - } - string folderPath = "/" + filePath.substr(0, pos); - if (!ForceCreateDirectory(folderPath.data())) { - HILOGE("Failed to create directory"); - return false; + struct timespec tv[2] = {sta.st_atim, sta.st_mtim}; + UniqueFd fd(open(fileName.data(), O_RDONLY)); + if (futimens(fd.Get(), tv) != 0) { + HILOGE("Failed to change the file time. %{public}s , %{public}d", fileName.c_str(), errno); } - return true; } -static bool CheckAndCreateDirectory(const string& filePath) +static ErrCode RestoreTarForSpeicalCloneCloud(ExtManageInfo item) { - size_t pos = filePath.rfind('/'); - if (pos == string::npos) { - return true; + HILOGE("!!! RestoreTarForSpeicalCloneCloud. item.hashName is %{public}s", item.hashName.data()); + HILOGE("!!! RestoreTarForSpeicalCloneCloud. item.fileName is %{public}s", item.fileName.data()); + string tarName = item.hashName; + if (item.fileName.empty()) { + HILOGE("Invalid untar path info for tar %{public}s", tarName.c_str()); + return ERR_INVALID_VALUE; + } + string untarPath = item.fileName; + if (untarPath.back() != BConstants::FILE_SEPARATOR_CHAR) { + untarPath += BConstants::FILE_SEPARATOR_CHAR; } + HILOGE("!!! RestoreTarForSpeicalCloneCloud. untarPath is %{public}s", untarPath.data()); + UntarFile::GetInstance().UnPacket(tarName, untarPath); - string folderPath = "/" + filePath.substr(0, pos); - if (access(folderPath.c_str(), F_OK) != 0) { - if (!ForceCreateDirectory(folderPath.data())) { - return false; + if (!RemoveFile(tarName)) { + HILOGE("Failed to delete the backup tar %{public}s", tarName.c_str()); + } + return ERR_OK; +} + +static ErrCode RestoreFilesForSpecialCloneCloud() +{ + // 获取索引文件内容 + string path = string(BConstants::PATH_BUNDLE_BACKUP_HOME).append(BConstants::SA_BUNDLE_BACKUP_RESTORE); + HILOGE("!!! RestoreFilesForSpecialCloneCloud. path is %{public}s", path.data()); + BJsonCachedEntity cachedEntity(UniqueFd(open(INDEX_FILE_RESTORE.data(), O_RDONLY))); + auto cache = cachedEntity.Structuralize(); + auto info = cache.GetExtManageInfo(); + + for (auto &item : info) { + HILOGE("!!! RestoreFilesForSpecialCloneCloud. item.hashName is %{public}s", item.hashName.data()); + if (item.hashName.empty()) { + continue; + } + HILOGE("!!! RestoreFilesForSpecialCloneCloud. item.hashName is valid %{public}s", item.hashName.data()); + if (item.isUserTar || item.isBigFile) { + // 大文件处理 + RestoreBigFilesForSpecialCloneCloud(item); + } else { + // 待解压tar文件处理 + if (RestoreTarForSpeicalCloneCloud(item) != ERR_OK) { + HILOGE("Failed to restore tar file %{public}s", item.hashName.c_str()); + return ERR_INVALID_VALUE; + } } } - - return true; + if (!RemoveFile(INDEX_FILE_RESTORE)) { + HILOGE("Failed to delete the backup index %{public}s", INDEX_FILE_RESTORE.c_str()); + } + return ERR_OK; } static bool RestoreBigFilePrecheck(string& fileName, const string& path, @@ -500,25 +540,17 @@ static bool RestoreBigFilePrecheck(string& fileName, const string& path, return false; } - // 带路径的文件名特殊处理 - if (hashName.find('/') != string::npos) { - if (!RestoreBigFilesWithPath(fileName, path, hashName, filePath)) { - HILOGE("failed to restore big files with path %{public}s", filePath.c_str()); - return false; - } - } else { // 不带路径的文件名 - if (access(fileName.data(), F_OK) != 0) { - HILOGI("file does not exist"); - return false; - } - - // 目录不存在且只有大文件时,不能通过untar创建,需要检查并创建 - if (!CheckAndCreateDirectory(filePath)) { - HILOGE("failed to create directory %{public}s", filePath.c_str()); - return false; - } + // 不带路径的文件名 + if (access(fileName.data(), F_OK) != 0) { + HILOGI("file does not exist"); + return false; } + // 目录不存在且只有大文件时,不能通过untar创建,需要检查并创建 + if (!CheckAndCreateDirectory(filePath)) { + HILOGE("failed to create directory %{public}s", filePath.c_str()); + return false; + } return true; } @@ -618,8 +650,20 @@ void BackupExtExtension::AsyncTaskRestore() BExcepUltils::BAssert(ptr, BError::Codes::EXT_BROKEN_FRAMEWORK, "Ext extension handle have been already released"); try { - // 解压 int ret = ERR_OK; + if (ptr->extension_->SpeicalVersionForCloneAndCloud()) { + HILOGI("!!!!AsyncTaskRestore RestoreFilesForSpecialCloneCloud."); + ret = RestoreFilesForSpecialCloneCloud(); + if (ret == ERR_OK) { + HILOGI("after extra, do restore."); + ptr->AsyncTaskRestoreForUpgrade(); + } else { + ptr->AppDone(ret); + ptr->DoClear(); + } + return; + } + // 解压 for (auto item : tars) { // 处理要解压的tar文件 if (ExtractFileExt(item) == "tar" && !IsUserTar(item, INDEX_FILE_RESTORE)) { ret = ptr->DoRestore(item); diff --git a/utils/include/b_resources/b_constants.h b/utils/include/b_resources/b_constants.h index e832d95bd..78b5ed4d9 100644 --- a/utils/include/b_resources/b_constants.h +++ b/utils/include/b_resources/b_constants.h @@ -62,6 +62,7 @@ constexpr int EXT_CONNECT_MAX_COUNT = 3; // extension 最大启动数 constexpr int EXT_CONNECT_MAX_TIME = 15000; // SA 启动 extension 等待连接最大时间 constexpr int IPC_MAX_WAIT_TIME = 3000; // IPC通讯最大等待时间(s) +constexpr char FILE_SEPARATOR_CHAR = '/'; constexpr int DEFAULT_VFS_CACHE_PRESSURE = 100; // 默认内存回收参数 constexpr int BACKUP_VFS_CACHE_PRESSURE = 10000; // 备份过程修改参数 diff --git a/utils/src/b_json/b_json_entity_ext_manage.cpp b/utils/src/b_json/b_json_entity_ext_manage.cpp index badebe52f..41658735d 100644 --- a/utils/src/b_json/b_json_entity_ext_manage.cpp +++ b/utils/src/b_json/b_json_entity_ext_manage.cpp @@ -241,7 +241,7 @@ std::vector BJsonEntityExtManage::GetExtManageInfo() const } HILOGI("GetExtManageInfo, fileName:%{public}s, isUserTar:%{public}d, isBigFile:%{public}d", fileName.data(), isUserTar, isBigFile); - if (!fileName.empty() && !path.empty()) { + if (!fileName.empty()) { ExtManageInfo info = { .hashName = fileName, .fileName = path, .sta = sta, .isUserTar = isUserTar, .isBigFile = isBigFile}; infos.emplace_back(info); -- Gitee