diff --git a/services/backup_sa/src/module_external/sms_adapter.cpp b/services/backup_sa/src/module_external/sms_adapter.cpp index a0b683afc4a56d04cd7bfbeaf774179308c9f7ca..f50a07bda66233ca71528bd2dfcbe18dd10d97f9 100644 --- a/services/backup_sa/src/module_external/sms_adapter.cpp +++ b/services/backup_sa/src/module_external/sms_adapter.cpp @@ -22,6 +22,7 @@ #include "filemgmt_libhilog.h" #include "iservice_registry.h" #include "system_ability_definition.h" +#include "module_external/storage_manager_service.h" namespace OHOS::FileManagement::Backup { using namespace std; @@ -29,32 +30,14 @@ using namespace std; namespace { const string MEDIA_LIBRARY_HAP = "com.ohos.medialibrary.medialibrarydata"; const string EXTERNAL_FILE_HAP = "com.ohos.UserFile.ExternalFileManager"; -const string MEDIA_TYPE = "media"; -const string FILE_TYPE = "file"; const int64_t ERR_SIZE = -1; } // namespace -static sptr GetStorageManager() -{ - auto saMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); - if (saMgr == nullptr) { - throw BError(BError::Codes::SA_BROKEN_IPC, "Failed to get system ability manager"); - } - - auto storageObj = saMgr->GetSystemAbility(STORAGE_MANAGER_MANAGER_ID); - if (storageObj == nullptr) { - throw BError(BError::Codes::SA_BROKEN_IPC, "Failed to get storage manager service"); - } - - return iface_cast(storageObj); -} - StorageManager::BundleStats StorageMgrAdapter::GetBundleStats(const string &bundleName) { StorageManager::BundleStats bundleStats; - auto storageMgr = GetStorageManager(); - if (storageMgr->GetBundleStats(bundleName, bundleStats, 0, 0)) { - throw BError(BError::Codes::SA_BROKEN_IPC, "Failed to get bundle stats"); + if (!StorageManagerService::GetInstance().GetBundleStats(bundleName, bundleStats)) { + HILOGE("An error occured StorageMgrAdapter GetBundleStats"); } return bundleStats; } @@ -62,15 +45,14 @@ StorageManager::BundleStats StorageMgrAdapter::GetBundleStats(const string &bund int64_t StorageMgrAdapter::GetUserStorageStats(const std::string &bundleName, int32_t userId) { StorageManager::StorageStats bundleStats; - auto storageMgr = GetStorageManager(); if (bundleName == MEDIA_LIBRARY_HAP) { - if (storageMgr->GetUserStorageStatsByType(userId, bundleStats, MEDIA_TYPE)) { + if (StorageManagerService::GetInstance().GetUserStorageStatsByType(userId, bundleStats, MEDIA_TYPE) != E_OK) { HILOGE("Failed to get user media storage stats"); return ERR_SIZE; } return bundleStats.image_ + bundleStats.video_; } else if (bundleName == EXTERNAL_FILE_HAP) { - if (storageMgr->GetUserStorageStatsByType(userId, bundleStats, FILE_TYPE)) { + if (StorageManagerService::GetInstance().GetUserStorageStatsByType(userId, bundleStats, FILE_TYPE) != E_OK) { HILOGE("Failed to get user file storage stats"); return ERR_SIZE; } @@ -81,9 +63,8 @@ int64_t StorageMgrAdapter::GetUserStorageStats(const std::string &bundleName, in int32_t StorageMgrAdapter::UpdateMemPara(int32_t size) { - auto storageMgr = GetStorageManager(); int32_t oldSize = BConstants::DEFAULT_VFS_CACHE_PRESSURE; - if (storageMgr->UpdateMemoryPara(size, oldSize)) { + if (StorageManagerService::GetInstance().UpdateMemoryPara(size, oldSize) != E_OK) { HILOGE("An error occured StorageMgrAdapter UpdateMemPara"); return BConstants::DEFAULT_VFS_CACHE_PRESSURE; } @@ -94,11 +75,11 @@ int32_t StorageMgrAdapter::GetBundleStatsForIncrease(uint32_t userId, const std: const std::vector &incrementalBackTimes, std::vector &pkgFileSizes, std::vector &incPkgFileSizes) { - auto storageMgr = GetStorageManager(); - if (storageMgr->GetBundleStatsForIncrease(userId, bundleNames, incrementalBackTimes, pkgFileSizes, - incPkgFileSizes)) { - throw BError(BError::Codes::SA_BROKEN_IPC, "Failed to get user storage stats"); + if (StorageManagerService::GetInstance().GetBundleStatsForIncrease(userId, bundleNames, incrementalBackTimes, + pkgFileSizes, incPkgFileSizes) != E_OK) { + HILOGE("An error occured StorageManagerService GetBundleStatsForIncrease"); + return E_ERR; } - return 0; + return E_OK; } -} // namespace OHOS::FileManagement::Backup +} // namespace OHOS::FileManagement::Backup \ No newline at end of file diff --git a/services/backup_sa/src/module_external/storage_manager_service.cpp b/services/backup_sa/src/module_external/storage_manager_service.cpp index 335406de8bdc8d036cb25e5ad6fa97604112bace..22a78759de4a21763f863a06316cf589f4d2f341 100644 --- a/services/backup_sa/src/module_external/storage_manager_service.cpp +++ b/services/backup_sa/src/module_external/storage_manager_service.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025 Huawei Device Co., Ltd. + * Copyright (c) 2024-2025 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -38,6 +38,11 @@ namespace OHOS::FileManagement::Backup { using namespace std; std::recursive_mutex mMountsLock; +static bool PathSortFunc(const std::string &path1, const std::string &path2) +{ + return path1 < path2; +} + static std::string GetQuotaSrcMountPath(const std::string &target) { std::lock_guard lock(mMountsLock); @@ -122,6 +127,34 @@ int32_t StorageManagerService::GetMediaStorageStats(StorageManager::StorageStats void StorageManagerService::GetMediaTypeAndSize(const std::shared_ptr &resultSet, StorageManager::StorageStats &storageStats) { + if (resultSet == nullptr) { + HILOGE("StorageStatusService::GetMediaTypeAndSize, input resultSet is nullptr."); + return; + } + int thumbnailType = -1; + while (resultSet->GoToNextRow() == E_OK) { + int32_t index = 0; + int mediatype = 0; + int64_t size = 0; + if (resultSet->GetColumnIndex("media_type", index) || resultSet->GetInt(index, mediatype)) { + HILOGE("get media_type column index or int value err."); + continue; + } + if (resultSet->GetColumnIndex("size", index) || resultSet->GetLong(index, size)) { + HILOGE("get size column index or long value err."); + continue; + } + HILOGI("media type: %{public}d, size: %{public}lld", mediatype, static_cast(size)); + if (mediatype == MEDIA_TYPE_IMAGE || mediatype == thumbnailType) { + storageStats.image_ += size; + } else if (mediatype == MEDIA_TYPE_AUDIO) { + storageStats.audio_ = size; + } else if (mediatype == MEDIA_TYPE_VIDEO) { + storageStats.video_ = size; + } else { + HILOGW("unsupprted media_type: %{public}d", mediatype); + } + } } int32_t StorageManagerService::GetFileStorageStats(int32_t userId, StorageManager::StorageStats &storageStats) @@ -204,6 +237,62 @@ int32_t StorageManagerService::GetBundleStatsForIncrease(uint32_t userId, const void StorageManagerService::GetBundleStatsForIncreaseEach(uint32_t userId, std::string &bundleName, int64_t lastBackupTime, std::vector &pkgFileSizes, std::vector &incPkgFileSizes) { + // input parameters + BundleStatsParas paras = {.userId = userId, .bundleName = bundleName, + .lastBackupTime = lastBackupTime, .fileSizeSum = 0, .incFileSizeSum = 0}; + + // obtain includes, excludes in backup extension config + auto [includes, excludes] = ReadIncludesExcludesPath(bundleName, lastBackupTime, userId); + if (includes.empty()) { + pkgFileSizes.emplace_back(0); + incPkgFileSizes.emplace_back(0); + return; + } + // physical paths + std::vector phyIncludes; + // map about sandbox path to physical path + std::map pathMap; + + // recognize physical path for include directory + DealWithIncludeFiles(paras, includes, phyIncludes, pathMap); + if (phyIncludes.empty()) { + HILOGE("Incorrect convert for include sandbox path for %{private}s", bundleName.c_str()); + pkgFileSizes.emplace_back(0); + incPkgFileSizes.emplace_back(0); + return; + } + + // recognize physical path for exclude directory + std::vector phyExcludes; + for (const auto &exclude : excludes) { + std::string excludeStr = exclude; + if (excludeStr.front() != FILE_SEPARATOR_CHAR) { + excludeStr = FILE_SEPARATOR_CHAR + excludeStr; + } + // convert sandbox to physical path + ConvertSandboxRealPath(userId, bundleName, excludeStr, phyExcludes, pathMap); + } + + std::string filePath = BACKUP_PATH_PREFIX + std::to_string(userId) + BACKUP_PATH_SURFFIX + + bundleName + FILE_SEPARATOR_CHAR + BACKUP_STAT_SYMBOL + std::to_string(lastBackupTime); + std::ofstream statFile; + statFile.open(filePath.data(), std::ios::out | std::ios::trunc); + if (!statFile.is_open()) { + HILOGE("creat file fail, errno:%{public}d.", errno); + pkgFileSizes.emplace_back(0); + incPkgFileSizes.emplace_back(0); + return; + } + statFile << VER_10_LINE1 << std::endl; + statFile << VER_10_LINE2 << std::endl; + + DeduplicationPath(phyIncludes); + ScanExtensionPath(paras, phyIncludes, phyExcludes, pathMap, statFile); + // calculate summary file sizes + pkgFileSizes.emplace_back(paras.fileSizeSum); + incPkgFileSizes.emplace_back(paras.incFileSizeSum); + HILOGI("bundleName: %{public}s, size: %{public}lld", bundleName.c_str(), static_cast(paras.fileSizeSum)); + statFile.close(); } std::tuple, std::vector> StorageManagerService::ReadIncludesExcludesPath( @@ -252,32 +341,141 @@ void StorageManagerService::DealWithIncludeFiles(const BundleStatsParas ¶s, const std::vector &includes, std::vector &phyIncludes, std::map& pathMap) { + uint32_t userId = paras.userId; + std::string bundleName = paras.bundleName; + for (const auto &include : includes) { + std::string includeStr = include; + if (includeStr.front() != FILE_SEPARATOR_CHAR) { + includeStr = FILE_SEPARATOR_CHAR + includeStr; + } + if (includeStr.find(BASE_EL1 + DEFAULT_PATH_WITH_WILDCARD) == 0 || + includeStr.find(BASE_EL2 + DEFAULT_PATH_WITH_WILDCARD) == 0) { + // recognize sandbox path to physical path with wild card + RecognizeSandboxWildCard(userId, bundleName, includeStr, phyIncludes, pathMap); + if (phyIncludes.empty()) { + HILOGE("DealWithIncludeFiles failed to recognize path with wildcard %{private}s", bundleName.c_str()); + continue; + } + } else { + // convert sandbox to physical path + ConvertSandboxRealPath(userId, bundleName, includeStr, phyIncludes, pathMap); + } + } } void StorageManagerService::ConvertSandboxRealPath(const uint32_t userId, const std::string &bundleName, const std::string &sandboxPathStr, std::vector &realPaths, std::map& pathMap) { + std::string uriString; + if (sandboxPathStr.find(NORMAL_SAND_PREFIX) == 0) { + // for normal hap, start with file://bundleName + uriString = URI_PREFIX + bundleName; + } else if (sandboxPathStr.find(FILE_SAND_PREFIX) == 0) { + // for public files, start with file://docs + uriString = URI_PREFIX + FILE_AUTHORITY; + } else if (sandboxPathStr.find(MEDIA_SAND_PREFIX) == 0) { + std::string physicalPath = sandboxPathStr; + physicalPath.insert(MEDIA_SAND_PREFIX.length(), FILE_SEPARATOR_CHAR + std::to_string(userId)); + realPaths.emplace_back(physicalPath); + pathMap.insert({physicalPath, sandboxPathStr}); + return; + } else if (sandboxPathStr.find(MEDIA_CLOUD_SAND_PREFIX) == 0) { + std::string physicalPath = sandboxPathStr; + physicalPath.insert(MEDIA_CLOUD_SAND_PREFIX.length(), FILE_SEPARATOR_CHAR + std::to_string(userId)); + realPaths.emplace_back(physicalPath); + pathMap.insert({physicalPath, sandboxPathStr}); + return; + } + + if (!uriString.empty()) { + std::string sandboxPathUriStr = AppFileService::SandboxHelper::Encode(sandboxPathStr); + uriString += sandboxPathUriStr; + AppFileService::ModuleFileUri::FileUri uri(uriString); + // files + std::string physicalPath; + int ret = AppFileService::SandboxHelper::GetBackupPhysicalPath(uri.ToString(), std::to_string(userId), + physicalPath); + if (ret != 0) { + HILOGE("Get physical path failed with %{public}d", ret); + return; + } + realPaths.emplace_back(physicalPath); + pathMap.insert({physicalPath, sandboxPathStr}); + } } void StorageManagerService::DeduplicationPath(std::vector &configPaths) { + sort(configPaths.begin(), configPaths.end(), PathSortFunc); + auto it = unique(configPaths.begin(), configPaths.end(), [](const std::string &path1, const std::string &path2) { + return path1 == path2; + }); + configPaths.erase(it, configPaths.end()); } void StorageManagerService::ScanExtensionPath(BundleStatsParas ¶s, const std::vector &includes, const std::vector &excludes, std::map &pathMap, std::ofstream &statFile) { + std::map excludesMap; + for (auto exclude : excludes) { + SetExcludePathMap(exclude, excludesMap); + } + // all file with stats in include directory + for (const auto &includeDir : includes) { + // Check if includeDir is a file path + auto [isSucc, isDir] = CheckIfDirForIncludes(includeDir, paras, pathMap, statFile, excludesMap); + if (!isSucc) { + continue; + } + // recognize all file in include directory + if (isDir && !GetIncludesFileStats(includeDir, paras, pathMap, statFile, excludesMap)) { + HILOGE("Faied to get include files for includeDir"); + } + } } void StorageManagerService::RecognizeSandboxWildCard(const uint32_t userId, const std::string &bundleName, const std::string &sandboxPathStr, std::vector &phyIncludes, std::map& pathMap) { + if (sandboxPathStr.find(BASE_EL1 + DEFAULT_PATH_WITH_WILDCARD) == 0) { + std::string physicalPrefix = PHY_APP + EL1 + FILE_SEPARATOR_CHAR + std::to_string(userId) + BASE + + bundleName + FILE_SEPARATOR_CHAR; + std::string relatePath = sandboxPathStr.substr(BASE_EL1.size()); + if (!GetPathWildCard(userId, bundleName, physicalPrefix + relatePath, phyIncludes, pathMap)) { + HILOGE("el1 GetPathWildCard dir path invaild"); + } + } else if (sandboxPathStr.find(BASE_EL2 + DEFAULT_PATH_WITH_WILDCARD) == 0) { + std::string physicalPrefix = PHY_APP + EL2 + FILE_SEPARATOR_CHAR + std::to_string(userId) + BASE + + bundleName + FILE_SEPARATOR_CHAR; + std::string relatePath = sandboxPathStr.substr(BASE_EL2.size()); + if (!GetPathWildCard(userId, bundleName, physicalPrefix + relatePath, phyIncludes, pathMap)) { + HILOGE("el2 GetPathWildCard dir path invaild"); + } + } } void StorageManagerService::SetExcludePathMap(std::string &excludePath, std::map &excludesMap) { + if (excludePath.empty()) { + HILOGE("SetExcludePathMap Param failed"); + return; + } + struct stat fileStatInfo = {0}; + if (stat(excludePath.c_str(), &fileStatInfo) != 0) { + HILOGE("SetExcludePathMap call stat error %{private}s, errno:%{public}d", excludePath.c_str(), errno); + return; + } + if (S_ISDIR(fileStatInfo.st_mode)) { + if (excludePath.back() != FILE_SEPARATOR_CHAR) { + excludePath.push_back(FILE_SEPARATOR_CHAR); + } + excludesMap.insert({excludePath, true}); + } else { + excludesMap.insert({excludePath, false}); + } } std::tuple StorageManagerService::CheckIfDirForIncludes(const std::string &path, BundleStatsParas ¶s, @@ -325,6 +523,58 @@ bool StorageManagerService::GetIncludesFileStats(const std::string &dir, BundleS std::map &pathMap, std::ofstream &statFile, std::map &excludesMap) { + std::string sandboxDir = dir; + auto it = pathMap.find(dir); + if (it != pathMap.end()) { + sandboxDir = it->second; + } + // stat current directory info + AddOuterDirIntoFileStat(dir, paras, sandboxDir, statFile, excludesMap); + + std::stack folderStack; + std::string filePath; + folderStack.push(dir); + // stat files and sub-directory in current directory info + while (!folderStack.empty()) { + filePath = folderStack.top(); + folderStack.pop(); + DIR *dirPtr = opendir(filePath.c_str()); + if (dirPtr == nullptr) { + HILOGE("GetIncludesFileStats open file dir:%{private}s fail, errno:%{public}d", filePath.c_str(), errno); + continue; + } + if (filePath.back() != FILE_SEPARATOR_CHAR) { + filePath.push_back(FILE_SEPARATOR_CHAR); + } + + struct dirent *entry = nullptr; + while ((entry = readdir(dirPtr)) != nullptr) { + if ((strcmp(entry->d_name, ".") == 0) || (strcmp(entry->d_name, "..") == 0)) { + continue; + } + std::string path = filePath + entry->d_name; + struct stat fileInfo = {0}; + if (stat(path.c_str(), &fileInfo) != 0) { + HILOGE("GetIncludesFileStats call stat error %{private}s, errno:%{public}d", path.c_str(), errno); + fileInfo.st_size = 0; + } + struct FileStat fileStat = {}; + fileStat.filePath = PhysicalToSandboxPath(dir, sandboxDir, path); + fileStat.fileSize = fileInfo.st_size; + CheckOverLongPath(fileStat.filePath); + // mode + fileStat.mode = static_cast(fileInfo.st_mode); + int64_t lastUpdateTime = static_cast(fileInfo.st_mtime); + fileStat.lastUpdateTime = lastUpdateTime; + fileStat.isIncre = (paras.lastBackupTime == 0 || lastUpdateTime > paras.lastBackupTime) ? true : false; + if (entry->d_type == DT_DIR) { + fileStat.isDir = true; + folderStack.push(path); + } + InsertStatFile(path, fileStat, statFile, excludesMap, paras); + } + closedir(dirPtr); + } return true; } @@ -332,21 +582,146 @@ bool StorageManagerService::GetPathWildCard(uint32_t userId, const std::string & const std::string &includeWildCard, std::vector &includePathList, std::map &pathMap) { + size_t pos = includeWildCard.rfind(WILDCARD_DEFAULT_INCLUDE); + if (pos == std::string::npos) { + HILOGE("GetPathWildCard: path should include *"); + return false; + } + std::string pathBeforeWildCard = includeWildCard.substr(0, pos); + DIR *dirPtr = opendir(pathBeforeWildCard.c_str()); + if (dirPtr == nullptr) { + HILOGE("GetPathWildCard open file dir:%{public}s fail, errno:%{public}d", pathBeforeWildCard.c_str(), errno); + return false; + } + struct dirent *entry = nullptr; + std::vector subDirs; + while ((entry = readdir(dirPtr)) != nullptr) { + if ((strcmp(entry->d_name, ".") == 0) || (strcmp(entry->d_name, "..") == 0)) { + continue; + } + std::string path = pathBeforeWildCard + entry->d_name; + if (entry->d_type == DT_DIR) { + subDirs.emplace_back(path); + } + } + closedir(dirPtr); + for (auto &subDir : subDirs) { + DIR *subDirPtr = opendir(subDir.c_str()); + if (subDirPtr == nullptr) { + HILOGE("GetPathWildCard open file dir:%{private}s fail, errno:%{public}d", subDir.c_str(), errno); + return false; + } + while ((entry = readdir(subDirPtr)) != nullptr) { + if ((strcmp(entry->d_name, ".") == 0) || (strcmp(entry->d_name, "..") == 0)) { + continue; + } + std::string dirName = std::string(entry->d_name); + + std::string path = subDir + FILE_SEPARATOR_CHAR + entry->d_name; + if (entry->d_type == DT_DIR && (dirName == DEFAULT_INCLUDE_PATH_IN_HAP_FILES || + dirName == DEFAULT_INCLUDE_PATH_IN_HAP_DATABASE || + dirName == DEFAULT_INCLUDE_PATH_IN_HAP_PREFERENCE)) { + includePathList.emplace_back(path); + AddPathMapForPathWildCard(userId, bundleName, path, pathMap); + } + } + closedir(subDirPtr); + } return true; } bool StorageManagerService::ExcludeFilter(std::map &excludesMap, const std::string &path) { + if (path.empty()) { + HILOGE("ExcludeFilter Param failed"); + return true; + } + std::string formatPath = path; + for (auto exclude = excludesMap.begin(); exclude != excludesMap.end(); exclude++) { + if (exclude->second != true) { + if (formatPath.compare(exclude->first) == 0) { + return true; + } + } else { + if (formatPath.compare(0, exclude->first.size(), exclude->first) == 0 && + (formatPath.size() == exclude->first.size() || formatPath[exclude->first.size()] == '/')) { + return true; + } + } + } return false; } void StorageManagerService::WriteFileList(std::ofstream &statFile, struct FileStat fileStat, BundleStatsParas ¶s) { + if (!statFile.is_open() || fileStat.filePath.empty()) { + HILOGE("WriteFileList Param failed"); + return; + } + std::string fileLine = ""; + bool encodeFlag = false; + if (fileStat.filePath.find(LINE_SEP) != std::string::npos) { + fileLine += AppFileService::SandboxHelper::Encode(fileStat.filePath) + FILE_CONTENT_SEPARATOR; + encodeFlag = true; + } else { + fileLine += fileStat.filePath + FILE_CONTENT_SEPARATOR; + } + fileLine += std::to_string(fileStat.mode) + FILE_CONTENT_SEPARATOR; + if (fileStat.isDir) { + fileLine += std::to_string(1) + FILE_CONTENT_SEPARATOR; + } else { + fileLine += std::to_string(0) + FILE_CONTENT_SEPARATOR; + } + fileLine += std::to_string(fileStat.fileSize) + FILE_CONTENT_SEPARATOR; + fileLine += std::to_string(fileStat.lastUpdateTime) + FILE_CONTENT_SEPARATOR; + fileLine += FILE_CONTENT_SEPARATOR; + if (fileStat.isIncre) { + fileLine += std::to_string(1); + } else { + fileLine += std::to_string(0); + } + fileLine += FILE_CONTENT_SEPARATOR; + if (encodeFlag) { + fileLine += std::to_string(1); + } else { + fileLine += std::to_string(0); + } + // te file line + statFile << fileLine << std::endl; + if (fileStat.isIncre) { + paras.incFileSizeSum += fileStat.fileSize; + } + paras.fileSizeSum += fileStat.fileSize; } bool StorageManagerService::AddOuterDirIntoFileStat(const std::string &dir, BundleStatsParas ¶s, const std::string &sandboxDir, std::ofstream &statFile, std::map &excludesMap) { + if (!statFile.is_open() || dir.empty()) { + HILOGE("AddOuterDirIntoFileStat Param failed"); + return false; + } + struct stat fileInfo = {0}; + if (stat(dir.c_str(), &fileInfo) != 0) { + HILOGE("AddOuterDirIntoFileStat call stat error %{private}s, fail errno:%{public}d", dir.c_str(), errno); + return false; + } + struct FileStat fileStat = {}; + fileStat.filePath = PhysicalToSandboxPath(dir, sandboxDir, dir); + fileStat.fileSize = fileInfo.st_size; + // mode + fileStat.mode = static_cast(fileInfo.st_mode); + int64_t lastUpdateTime = static_cast(fileInfo.st_mtime); + fileStat.lastUpdateTime = lastUpdateTime; + fileStat.isIncre = (paras.lastBackupTime == 0 || lastUpdateTime > paras.lastBackupTime) ? true : false; + fileStat.isDir = true; + std::string formatPath = dir; + if (formatPath.back() != FILE_SEPARATOR_CHAR) { + formatPath.push_back(FILE_SEPARATOR_CHAR); + } + if (ExcludeFilter(excludesMap, formatPath) == false) { + WriteFileList(statFile, fileStat, paras); + } return true; } @@ -361,11 +736,36 @@ std::string StorageManagerService::PhysicalToSandboxPath(const std::string &dir, void StorageManagerService::InsertStatFile(const std::string &path, struct FileStat fileStat, std::ofstream &statFile, std::map &excludesMap, BundleStatsParas ¶s) { + if (!statFile.is_open() || path.empty()) { + HILOGE("InsertStatFile Param failed"); + return; + } + std::string formatPath = path; + if (fileStat.isDir == true && formatPath.back() != FILE_SEPARATOR_CHAR) { + formatPath.push_back(FILE_SEPARATOR_CHAR); + } + if (!ExcludeFilter(excludesMap, formatPath)) { + WriteFileList(statFile, fileStat, paras); + } } bool StorageManagerService::AddPathMapForPathWildCard(uint32_t userId, const std::string &bundleName, const std::string &phyPath, std::map &pathMap) { + std::string physicalPrefixEl1 = PHY_APP + EL1 + FILE_SEPARATOR_CHAR + std::to_string(userId) + BASE + + bundleName + FILE_SEPARATOR_CHAR; + std::string physicalPrefixEl2 = PHY_APP + EL2 + FILE_SEPARATOR_CHAR + std::to_string(userId) + BASE + + bundleName + FILE_SEPARATOR_CHAR; + if (phyPath.find(physicalPrefixEl1) == 0) { + std::string relatePath = phyPath.substr(physicalPrefixEl1.size()); + pathMap.insert({phyPath, BASE_EL1 + relatePath}); + } else if (phyPath.find(physicalPrefixEl2) == 0) { + std::string relatePath = phyPath.substr(physicalPrefixEl2.size()); + pathMap.insert({phyPath, BASE_EL2 + relatePath}); + } else { + HILOGE("Invalid phyiscal path"); + return false; + } return true; } @@ -379,4 +779,5 @@ uint32_t StorageManagerService::CheckOverLongPath(const std::string &path) } return len; } + } // namespace OHOS::FileManagement::Backup \ No newline at end of file diff --git a/tests/unittests/backup_sa/module_external/storage_manager_service_test.cpp b/tests/unittests/backup_sa/module_external/storage_manager_service_test.cpp index 9b1a34425b92ef1ce3d9b6b7630f048851fa909c..5cf4c353e66e598a9319530254515de17cde72ef 100644 --- a/tests/unittests/backup_sa/module_external/storage_manager_service_test.cpp +++ b/tests/unittests/backup_sa/module_external/storage_manager_service_test.cpp @@ -138,4 +138,359 @@ HWTEST_F(StorageManagerServiceTest, Storage_Manager_ServiceTest_ReadIncludesExcl EXPECT_TRUE(std::get<0>(result).empty()); EXPECT_TRUE(std::get<1>(result).empty()); } + +/** + * @tc.name: Storage_Manager_ServiceTest_DealWithIncludeFiles_001 + * @tc.desc: check the DealWithIncludeFiles function + * @tc.type: FUNC + * @tc.require: AR000IGCR7 + */ +HWTEST_F(StorageManagerServiceTest, Storage_Manager_ServiceTest_DealWithIncludeFiles_001, + testing::ext::TestSize.Level1) +{ + std::string bundleName = CAMERA_BUNDLENAME; + BundleStatsParas paras = {.userId = 100, .bundleName = bundleName, + .lastBackupTime = 0, .fileSizeSum = 0, .incFileSizeSum = 0}; + std::vector includes = {"data/storage/el1/base/" + DEFAULT_PATH_WITH_WILDCARD}; + std::vector phyIncludes; + std::map pathMap; + StorageManagerService::GetInstance().DealWithIncludeFiles(paras, includes, phyIncludes, pathMap); + EXPECT_TRUE(phyIncludes.empty()); +} + +/** + * @tc.name: Storage_Manager_ServiceTest_DealWithIncludeFiles_002 + * @tc.desc: check the DealWithIncludeFiles function + * @tc.type: FUNC + * @tc.require: AR000IGCR7 + */ +HWTEST_F(StorageManagerServiceTest, Storage_Manager_ServiceTest_DealWithIncludeFiles_002, + testing::ext::TestSize.Level1) +{ + std::string bundleName = CAMERA_BUNDLENAME; + BundleStatsParas paras = {.userId = 100, .bundleName = bundleName, + .lastBackupTime = 0, .fileSizeSum = 0, .incFileSizeSum = 0}; + std::vector includes = {NORMAL_SAND_PREFIX}; + std::vector phyIncludes; + std::map pathMap; + StorageManagerService::GetInstance().DealWithIncludeFiles(paras, includes, phyIncludes, pathMap); + EXPECT_TRUE(phyIncludes.empty()); +} + +/** + * @tc.name: Storage_Manager_ServiceTest_DealWithIncludeFiles_003 + * @tc.desc: check the DealWithIncludeFiles function + * @tc.type: FUNC + * @tc.require: AR000IGCR7 + */ +HWTEST_F(StorageManagerServiceTest, Storage_Manager_ServiceTest_DealWithIncludeFiles_003, + testing::ext::TestSize.Level1) +{ + std::string bundleName = "testBundle"; + BundleStatsParas paras = {.userId = 100, .bundleName = bundleName, + .lastBackupTime = 0, .fileSizeSum = 0, .incFileSizeSum = 0}; + std::vector includes = {}; + std::vector phyIncludes; + std::map pathMap; + StorageManagerService::GetInstance().DealWithIncludeFiles(paras, includes, phyIncludes, pathMap); + EXPECT_TRUE(phyIncludes.empty()); +} + +/** + * @tc.name: Storage_Manager_ServiceTest_ConvertSandboxRealPath_001 + * @tc.desc: check the ConvertSandboxRealPath function + * @tc.type: FUNC + * @tc.require: AR000IGCR7 + */ +HWTEST_F(StorageManagerServiceTest, Storage_Manager_ServiceTest_ConvertSandboxRealPath_001, + testing::ext::TestSize.Level1) +{ + uint32_t userId = 100; + std::string bundleName = "com.example.app"; + std::string sandboxPathStr = NORMAL_SAND_PREFIX + "/path/to/file"; + std::vector realPaths; + std::map pathMap; + StorageManagerService::GetInstance().ConvertSandboxRealPath(userId, bundleName, sandboxPathStr, realPaths, pathMap); + EXPECT_TRUE(realPaths.empty()); + EXPECT_TRUE(pathMap.empty()); +} + +/** + * @tc.name: Storage_Manager_ServiceTest_ConvertSandboxRealPath_002 + * @tc.desc: check the ConvertSandboxRealPath function + * @tc.type: FUNC + * @tc.require: AR000IGCR7 + */ +HWTEST_F(StorageManagerServiceTest, Storage_Manager_ServiceTest_ConvertSandboxRealPath_002, + testing::ext::TestSize.Level1) +{ + uint32_t userId = 100; + std::string bundleName = CAMERA_BUNDLENAME; + std::string sandboxPathStr = NORMAL_SAND_PREFIX + "/el2/database/"; + std::vector realPaths; + std::map pathMap; + StorageManagerService::GetInstance().ConvertSandboxRealPath(userId, bundleName, sandboxPathStr, realPaths, pathMap); + std::string uriString = URI_PREFIX + bundleName + AppFileService::SandboxHelper::Encode(sandboxPathStr); + AppFileService::ModuleFileUri::FileUri uri(uriString); + std::string physicalPath; + AppFileService::SandboxHelper::GetBackupPhysicalPath(uri.ToString(), std::to_string(userId), physicalPath); + EXPECT_FALSE(realPaths.empty()); + EXPECT_FALSE(pathMap.empty()); + EXPECT_EQ(realPaths[0], physicalPath); + EXPECT_EQ(pathMap[realPaths[0]], sandboxPathStr); +} + +/** + * @tc.name: Storage_Manager_ServiceTest_CheckIfDirForIncludes_001 + * @tc.desc: check the CheckIfDirForIncludes function + * @tc.type: FUNC + * @tc.require: AR000IGCR7 + */ +HWTEST_F(StorageManagerServiceTest, Storage_Manager_ServiceTest_CheckIfDirForIncludes_001, + testing::ext::TestSize.Level1) +{ + ofstream closedStatFile; + std::string bundleName = "testBundle"; + BundleStatsParas paras = {.userId = 100, .bundleName = bundleName, + .lastBackupTime = 0, .fileSizeSum = 0, .incFileSizeSum = 0}; + std::map pathMap; + std::map excludesMap; + auto result = StorageManagerService::GetInstance().CheckIfDirForIncludes("test_path", paras, + pathMap, closedStatFile, excludesMap); + EXPECT_EQ(result, std::make_tuple(false, false)); +} + +/** + * @tc.name: Storage_Manager_ServiceTest_CheckIfDirForIncludes_002 + * @tc.desc: check the CheckIfDirForIncludes function + * @tc.type: FUNC + * @tc.require: AR000IGCR7 + */ +HWTEST_F(StorageManagerServiceTest, Storage_Manager_ServiceTest_CheckIfDirForIncludes_002, + testing::ext::TestSize.Level1) +{ + ofstream statFile; + std::string bundleName = "testBundle"; + BundleStatsParas paras = {.userId = 100, .bundleName = bundleName, + .lastBackupTime = 0, .fileSizeSum = 0, .incFileSizeSum = 0}; + std::map pathMap; + std::map excludesMap; + auto result = StorageManagerService::GetInstance().CheckIfDirForIncludes("", paras, pathMap, statFile, excludesMap); + EXPECT_EQ(result, std::make_tuple(false, false)); +} + +/** + * @tc.name: Storage_Manager_ServiceTest_CheckIfDirForIncludes_003 + * @tc.desc: check the CheckIfDirForIncludes function + * @tc.type: FUNC + * @tc.require: AR000IGCR7 + */ +HWTEST_F(StorageManagerServiceTest, Storage_Manager_ServiceTest_CheckIfDirForIncludes_003, + testing::ext::TestSize.Level1) +{ + std::ofstream statFile; + fs::path tempPath = "/data/temp.txt"; + + try { + fs::path dirPath = tempPath.parent_path(); + if (!fs::exists(dirPath)) { + fs::create_directories(dirPath); + } + fs::path canonicalPath = fs::canonical(fs::absolute(tempPath)); + statFile.open(canonicalPath, std::ios::out | std::ios::trunc); + EXPECT_FALSE(!statFile.is_open()) << "file can not open"; + std::string bundleName = "testBundle"; + BundleStatsParas paras = {.userId = 100, .bundleName = bundleName, + .lastBackupTime = 0, .fileSizeSum = 0, .incFileSizeSum = 0}; + std::map pathMap; + std::map excludesMap; + auto result = StorageManagerService::GetInstance().CheckIfDirForIncludes("/data/service", paras, pathMap, + statFile, excludesMap); + EXPECT_EQ(result, std::make_tuple(true, true)); + fs::remove(canonicalPath); + } catch (const fs::filesystem_error& e) { + std::cerr << "Filesystem error: " << e.what() << '\n'; + } + + statFile.open("/system/etc/NOTICE.TXT", ios::out | ios::trunc); + EXPECT_FALSE(!statFile.is_open()) << "file can not open"; + std::string bundleName = "testBundle"; + BundleStatsParas paras = {.userId = 100, .bundleName = bundleName, + .lastBackupTime = 0, .fileSizeSum = 0, .incFileSizeSum = 0}; + std::map pathMap; + std::map excludesMap; + auto result = StorageManagerService::GetInstance().CheckIfDirForIncludes("/data/service", paras, pathMap, + statFile, excludesMap); + EXPECT_EQ(result, std::make_tuple(true, true)); +} + +/** + * @tc.name: Storage_Manager_ServiceTest_ExcludeFilter_001 + * @tc.desc: check the ExcludeFilter function + * @tc.type: FUNC + * @tc.require: AR000IGCR7 + */ +HWTEST_F(StorageManagerServiceTest, Storage_Manager_ServiceTest_ExcludeFilter_001, + testing::ext::TestSize.Level1) +{ + std::map excludesMap; + std::string path = ""; + bool result = StorageManagerService::GetInstance().ExcludeFilter(excludesMap, path); + EXPECT_TRUE(result); +} + +/** + * @tc.name: Storage_Manager_ServiceTest_ExcludeFilter_002 + * @tc.desc: check the ExcludeFilter function + * @tc.type: FUNC + * @tc.require: AR000IGCR7 + */ +HWTEST_F(StorageManagerServiceTest, Storage_Manager_ServiceTest_ExcludeFilter_002, + testing::ext::TestSize.Level1) +{ + std::map excludesMap; + std::string path = "/path/to/file"; + bool result = StorageManagerService::GetInstance().ExcludeFilter(excludesMap, path); + EXPECT_FALSE(result); +} + +/** + * @tc.name: Storage_Manager_ServiceTest_GetUserStorageStatsByType_001 + * @tc.desc: check the GetUserStorageStatsByType function + * @tc.type: FUNC + * @tc.require: AR000IGCR7 + */ +HWTEST_F(StorageManagerServiceTest, Storage_Manager_ServiceTest_GetUserStorageStatsByType_001, + testing::ext::TestSize.Level1) +{ + StorageManager::StorageStats storageStats; + std::string type = "MEDIA_TYPE"; + int32_t userId = 100; + int64_t result = StorageManagerService::GetInstance().GetUserStorageStatsByType(userId, storageStats, type); + EXPECT_EQ(result, E_ERR); + EXPECT_EQ(storageStats.video_, 0); + EXPECT_EQ(storageStats.image_, 0); + EXPECT_EQ(storageStats.file_, 0); +} + +/** + * @tc.name: Storage_Manager_ServiceTest_GetUserStorageStatsByType_002 + * @tc.desc: check the GetUserStorageStatsByType function + * @tc.type: FUNC + * @tc.require: AR000IGCR7 + */ +HWTEST_F(StorageManagerServiceTest, Storage_Manager_ServiceTest_GetUserStorageStatsByType_002, + testing::ext::TestSize.Level1) +{ + StorageManager::StorageStats storageStats; + std::string type = "FILE_TYPE"; + int32_t userId = 100; + int64_t result = StorageManagerService::GetInstance().GetUserStorageStatsByType(userId, storageStats, type); + EXPECT_EQ(result, E_ERR); + EXPECT_EQ(storageStats.video_, 0); + EXPECT_EQ(storageStats.image_, 0); + EXPECT_EQ(storageStats.file_, 0); +} + +/** + * @tc.name: Storage_Manager_ServiceTest_GetUserStorageStatsByType_003 + * @tc.desc: check the GetUserStorageStatsByType function + * @tc.type: FUNC + * @tc.require: AR000IGCR7 + */ +HWTEST_F(StorageManagerServiceTest, Storage_Manager_ServiceTest_GetUserStorageStatsByType_003, + testing::ext::TestSize.Level1) +{ + StorageManager::StorageStats storageStats; + std::string type = "OTHER_TYPE"; + int32_t userId = 100; + int64_t result = StorageManagerService::GetInstance().GetUserStorageStatsByType(userId, storageStats, type); + EXPECT_EQ(result, E_ERR); + EXPECT_EQ(storageStats.video_, 0); + EXPECT_EQ(storageStats.image_, 0); + EXPECT_EQ(storageStats.file_, 0); +} + +/** + * @tc.name: Storage_Manager_ServiceTest_GetMediaTypeAndSize_001 + * @tc.desc: check the GetMediaTypeAndSize function + * @tc.type: FUNC + * @tc.require: AR000IGCR7 + */ +HWTEST_F(StorageManagerServiceTest, Storage_Manager_ServiceTest_GetMediaTypeAndSize_001, + testing::ext::TestSize.Level1) +{ + StorageManager::StorageStats storageStats; + StorageManagerService::GetInstance().GetMediaTypeAndSize(nullptr, storageStats); + EXPECT_EQ(storageStats.image_, 0); + EXPECT_EQ(storageStats.audio_, 0); + EXPECT_EQ(storageStats.video_, 0); +} + +/** + * @tc.name: Storage_Manager_ServiceTest_GetMediaTypeAndSize_002 + * @tc.desc: check the GetMediaTypeAndSize function + * @tc.type: FUNC + * @tc.require: AR000IGCR7 + */ +HWTEST_F(StorageManagerServiceTest, Storage_Manager_ServiceTest_GetMediaTypeAndSize_002, + testing::ext::TestSize.Level1) +{ + auto resultSet = std::make_shared(); + StorageManager::StorageStats storageStats; + StorageManagerService::GetInstance().GetMediaTypeAndSize(nullptr, storageStats); + EXPECT_EQ(storageStats.image_, 0); + EXPECT_EQ(storageStats.audio_, 0); + EXPECT_EQ(storageStats.video_, 0); +} + +/** + * @tc.name: Storage_Manager_ServiceTest_GetQuotaSrcMountPath_001 + * @tc.desc: check the GetQuotaSrcMountPath function + * @tc.type: FUNC + * @tc.require: AR000IGCR7 + */ +HWTEST_F(StorageManagerServiceTest, Storage_Manager_ServiceTest_GetQuotaSrcMountPath_001, + testing::ext::TestSize.Level1) +{ + mQuotaReverseMounts.insert(std::make_pair("/path1", "/mount1")); + mQuotaReverseMounts.insert(std::make_pair("/path2", "/mount2")); + std::string target = "/path1"; + std::string expectedPath = "/mount1"; + std::string actualPath = GetQuotaSrcMountPath(target); + EXPECT_EQ(expectedPath, actualPath); + mQuotaReverseMounts.clear(); +} + +/** + * @tc.name: Storage_Manager_ServiceTest_GetQuotaSrcMountPath_002 + * @tc.desc: check the GetQuotaSrcMountPath function + * @tc.type: FUNC + * @tc.require: AR000IGCR7 + */ +HWTEST_F(StorageManagerServiceTest, Storage_Manager_ServiceTest_GetQuotaSrcMountPath_002, + testing::ext::TestSize.Level1) +{ + mQuotaReverseMounts.insert(std::make_pair("/path1", "/mount1")); + mQuotaReverseMounts.insert(std::make_pair("/path1", "/mount1")); + std::string target = "/path3"; + std::string expectedPath = ""; + std::string actualPath = GetQuotaSrcMountPath(target); + EXPECT_EQ(expectedPath, actualPath); + mQuotaReverseMounts.clear(); +} + +/** + * @tc.name: Storage_Manager_ServiceTest_PathSortFunc_001 + * @tc.desc: check the PathSortFunc function + * @tc.type: FUNC + * @tc.require: AR000IGCR7 + */ +HWTEST_F(StorageManagerServiceTest, Storage_Manager_ServiceTest_PathSortFunc_001, + testing::ext::TestSize.Level1) +{ + std::string path1 = "AAA"; + std::string path2 = "BBB"; + EXPECT_TRUE(PathSortFunc(path1, path2)); } +} \ No newline at end of file