修改文件分析返回类型,增加简报字段

Signed-off-by: zhuruigan <zhuruigan@huawei.com>
Change-Id: If595a481d7bc32fbc8dbd2853232bd79d696a494
This commit is contained in:
zhuruigan 2024-02-05 16:18:35 +08:00
parent 678212522a
commit 416164e31b
10 changed files with 61 additions and 427 deletions

View File

@ -34,7 +34,7 @@ public:
static UntarFile &GetInstance(); static UntarFile &GetInstance();
int UnPacket(const std::string &tarFile, const std::string &rootPath); int UnPacket(const std::string &tarFile, const std::string &rootPath);
int IncrementalUnPacket(const std::string &tarFile, const std::string &rootPath, int IncrementalUnPacket(const std::string &tarFile, const std::string &rootPath,
const std::map<std::string, struct ReportFileInfo> &includes); const std::unordered_map<std::string, struct ReportFileInfo> &includes);
private: private:
UntarFile() = default; UntarFile() = default;
@ -147,7 +147,7 @@ private:
off_t tarFileBlockCnt_ {0}; off_t tarFileBlockCnt_ {0};
off_t pos_ {0}; off_t pos_ {0};
size_t readCnt_ {0}; size_t readCnt_ {0};
std::map<std::string, struct ReportFileInfo> includes_; std::unordered_map<std::string, struct ReportFileInfo> includes_;
}; };
} // namespace OHOS::FileManagement::Backup } // namespace OHOS::FileManagement::Backup

View File

@ -23,8 +23,10 @@
#include <regex> #include <regex>
#include <string> #include <string>
#include <tuple> #include <tuple>
#include <unordered_map>
#include <vector> #include <vector>
#include <directory_ex.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <unistd.h> #include <unistd.h>
@ -47,8 +49,8 @@
#include "b_resources/b_constants.h" #include "b_resources/b_constants.h"
#include "b_tarball/b_tarball_factory.h" #include "b_tarball/b_tarball_factory.h"
#include "filemgmt_libhilog.h" #include "filemgmt_libhilog.h"
#include "service_proxy.h"
#include "hitrace_meter.h" #include "hitrace_meter.h"
#include "service_proxy.h"
#include "tar_file.h" #include "tar_file.h"
#include "untar_file.h" #include "untar_file.h"
@ -84,7 +86,7 @@ void BackupExtExtension::VerifyCaller()
} }
} }
static bool CheckAndCreateDirectory(const string& filePath) static bool CheckAndCreateDirectory(const string &filePath)
{ {
size_t pos = filePath.rfind('/'); size_t pos = filePath.rfind('/');
if (pos == string::npos) { if (pos == string::npos) {
@ -184,7 +186,7 @@ ErrCode BackupExtExtension::GetIncrementalFileHandle(const string &fileName)
if (access(tarName.c_str(), F_OK) == 0) { if (access(tarName.c_str(), F_OK) == 0) {
throw BError(BError::Codes::EXT_INVAL_ARG, string("The file already exists")); throw BError(BError::Codes::EXT_INVAL_ARG, string("The file already exists"));
} }
UniqueFd fd (open(tarName.data(), O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)); UniqueFd fd(open(tarName.data(), O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR));
if (fd < 0) { if (fd < 0) {
HILOGE("Failed to open tar file = %{private}s, err = %{public}d", tarName.c_str(), errno); HILOGE("Failed to open tar file = %{private}s, err = %{public}d", tarName.c_str(), errno);
throw BError(BError::Codes::EXT_INVAL_ARG, string("open tar file failed")); throw BError(BError::Codes::EXT_INVAL_ARG, string("open tar file failed"));
@ -195,7 +197,7 @@ ErrCode BackupExtExtension::GetIncrementalFileHandle(const string &fileName)
if (access(reportName.c_str(), F_OK) == 0) { if (access(reportName.c_str(), F_OK) == 0) {
throw BError(BError::Codes::EXT_INVAL_ARG, string("The report file already exists")); throw BError(BError::Codes::EXT_INVAL_ARG, string("The report file already exists"));
} }
UniqueFd reportFd (open(reportName.data(), O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)); UniqueFd reportFd(open(reportName.data(), O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR));
if (reportFd < 0) { if (reportFd < 0) {
HILOGE("Failed to open report file = %{private}s, err = %{public}d", reportName.c_str(), errno); HILOGE("Failed to open report file = %{private}s, err = %{public}d", reportName.c_str(), errno);
throw BError(BError::Codes::EXT_INVAL_ARG, string("open report file failed")); throw BError(BError::Codes::EXT_INVAL_ARG, string("open report file failed"));
@ -431,8 +433,7 @@ static bool IsUserTar(const string &tarFile, const string &indexFile)
BJsonCachedEntity<BJsonEntityExtManage> cachedEntity(UniqueFd(open(filePath.data(), O_RDONLY))); BJsonCachedEntity<BJsonEntityExtManage> cachedEntity(UniqueFd(open(filePath.data(), O_RDONLY)));
auto cache = cachedEntity.Structuralize(); auto cache = cachedEntity.Structuralize();
auto info = cache.GetExtManageInfo(); auto info = cache.GetExtManageInfo();
auto iter = find_if(info.begin(), info.end(), auto iter = find_if(info.begin(), info.end(), [&tarFile](const auto &item) { return item.hashName == tarFile; });
[&tarFile](const auto& item) { return item.hashName == tarFile; });
if (iter != info.end()) { if (iter != info.end()) {
HILOGI("tarFile:%{public}s isUserTar:%{public}d", tarFile.data(), iter->isUserTar); HILOGI("tarFile:%{public}s isUserTar:%{public}d", tarFile.data(), iter->isUserTar);
return iter->isUserTar; return iter->isUserTar;
@ -543,7 +544,7 @@ int BackupExtExtension::DoRestore(const string &fileName)
return ERR_OK; return ERR_OK;
} }
static map<string, struct ReportFileInfo> GetTarIncludes(const string &tarName) static unordered_map<string, struct ReportFileInfo> GetTarIncludes(const string &tarName)
{ {
// 获取简报文件内容 // 获取简报文件内容
string reportName = GetReportFileName(tarName); string reportName = GetReportFileName(tarName);
@ -617,7 +618,7 @@ void BackupExtExtension::AsyncTaskBackup(const string config)
static void RestoreBigFilesForSpecialCloneCloud(ExtManageInfo item) static void RestoreBigFilesForSpecialCloneCloud(ExtManageInfo item)
{ {
HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__); HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
struct stat& sta = item.sta; struct stat &sta = item.sta;
string fileName = item.hashName; string fileName = item.hashName;
if (chmod(fileName.c_str(), sta.st_mode) != 0) { if (chmod(fileName.c_str(), sta.st_mode) != 0) {
HILOGE("Failed to chmod filePath, err = %{public}d", errno); HILOGE("Failed to chmod filePath, err = %{public}d", errno);
@ -681,8 +682,7 @@ static ErrCode RestoreFilesForSpecialCloneCloud()
return ERR_OK; return ERR_OK;
} }
static bool RestoreBigFilePrecheck(string& fileName, const string& path, static bool RestoreBigFilePrecheck(string &fileName, const string &path, const string &hashName, const string &filePath)
const string& hashName, const string& filePath)
{ {
if (filePath.empty()) { if (filePath.empty()) {
HILOGE("file path is empty. %{public}s", filePath.c_str()); HILOGE("file path is empty. %{public}s", filePath.c_str());
@ -703,8 +703,9 @@ static bool RestoreBigFilePrecheck(string& fileName, const string& path,
return true; return true;
} }
static void RestoreBigFileAfter(const string& fileName, const string& filePath, const struct stat& sta, static void RestoreBigFileAfter(const string &fileName,
const set<string>& lks) const string &filePath,
const struct stat &sta)
{ {
if (chmod(filePath.c_str(), sta.st_mode) != 0) { if (chmod(filePath.c_str(), sta.st_mode) != 0) {
HILOGE("Failed to chmod filePath, err = %{public}d", errno); HILOGE("Failed to chmod filePath, err = %{public}d", errno);
@ -729,12 +730,6 @@ static void RestoreBigFileAfter(const string& fileName, const string& filePath,
} }
} }
for (const auto &lksPath : lks) {
if (link(filePath.data(), lksPath.data())) {
HILOGE("failed to create hard link file, errno : %{public}d", errno);
}
}
struct timespec tv[2] = {sta.st_atim, sta.st_mtim}; struct timespec tv[2] = {sta.st_atim, sta.st_mtim};
UniqueFd fd(open(filePath.data(), O_RDONLY)); UniqueFd fd(open(filePath.data(), O_RDONLY));
if (futimens(fd.Get(), tv) != 0) { if (futimens(fd.Get(), tv) != 0) {
@ -768,7 +763,7 @@ static void RestoreBigFiles(bool appendTargetPath)
continue; continue;
} }
RestoreBigFileAfter(fileName, filePath, item.sta, cache.GetHardLinkInfo(item.hashName)); RestoreBigFileAfter(fileName, filePath, item.sta);
} }
} }
@ -849,8 +844,8 @@ void BackupExtExtension::AsyncTaskRestore()
} }
// 恢复用户tar包以及大文件 // 恢复用户tar包以及大文件
// 目的地址是否需要拼接path(临时目录)FullBackupOnly为true并且非特殊场景 // 目的地址是否需要拼接path(临时目录)FullBackupOnly为true并且非特殊场景
bool appendTargetPath = ptr->extension_->UseFullBackupOnly() && bool appendTargetPath =
!ptr->extension_->SpeicalVersionForCloneAndCloud(); ptr->extension_->UseFullBackupOnly() && !ptr->extension_->SpeicalVersionForCloneAndCloud();
RestoreBigFiles(appendTargetPath); RestoreBigFiles(appendTargetPath);
// delete 1.tar/manage.json // delete 1.tar/manage.json
@ -904,8 +899,8 @@ void BackupExtExtension::AsyncTaskIncrementalRestore()
} }
// 恢复用户tar包以及大文件 // 恢复用户tar包以及大文件
// 目的地址是否需要拼接path(临时目录)FullBackupOnly为true并且非特殊场景 // 目的地址是否需要拼接path(临时目录)FullBackupOnly为true并且非特殊场景
bool appendTargetPath = ptr->extension_->UseFullBackupOnly() && bool appendTargetPath =
!ptr->extension_->SpeicalVersionForCloneAndCloud(); ptr->extension_->UseFullBackupOnly() && !ptr->extension_->SpeicalVersionForCloneAndCloud();
RestoreBigFiles(appendTargetPath); RestoreBigFiles(appendTargetPath);
// delete 1.tar/manage.json // delete 1.tar/manage.json
@ -1137,6 +1132,11 @@ ErrCode BackupExtExtension::HandleRestore()
return 0; return 0;
} }
static bool CheckTar(const string &fileName)
{
return ExtractFileExt(fileName) == "tar";
}
using CompareFilesResult = tuple<map<string, struct ReportFileInfo>, using CompareFilesResult = tuple<map<string, struct ReportFileInfo>,
map<string, struct ReportFileInfo>, map<string, struct ReportFileInfo>,
map<string, struct stat>, map<string, struct stat>,
@ -1145,9 +1145,9 @@ using CompareFilesResult = tuple<map<string, struct ReportFileInfo>,
static CompareFilesResult CompareFiles(const UniqueFd &cloudFd, const UniqueFd &storageFd) static CompareFilesResult CompareFiles(const UniqueFd &cloudFd, const UniqueFd &storageFd)
{ {
BReportEntity cloudRp(UniqueFd(cloudFd.Get())); BReportEntity cloudRp(UniqueFd(cloudFd.Get()));
map<string, struct ReportFileInfo> cloudFiles = cloudRp.GetReportInfos(); unordered_map<string, struct ReportFileInfo> cloudFiles = cloudRp.GetReportInfos();
BReportEntity storageRp(UniqueFd(storageFd.Get())); BReportEntity storageRp(UniqueFd(storageFd.Get()));
map<string, struct ReportFileInfo> storageFiles = storageRp.GetReportInfos(); unordered_map<string, struct ReportFileInfo> storageFiles = storageRp.GetReportInfos();
map<string, struct ReportFileInfo> allFiles; map<string, struct ReportFileInfo> allFiles;
map<string, struct ReportFileInfo> smallFiles; map<string, struct ReportFileInfo> smallFiles;
map<string, struct stat> bigFiles; map<string, struct stat> bigFiles;
@ -1155,7 +1155,8 @@ static CompareFilesResult CompareFiles(const UniqueFd &cloudFd, const UniqueFd &
for (auto &item : storageFiles) { for (auto &item : storageFiles) {
// 进行文件对比 // 进行文件对比
string path = item.first; string path = item.first;
if (item.second.isIncremental == true && item.second.isDir == true) { bool isExist = cloudFiles.find(path) != cloudFiles.end() ? true : false;
if (item.second.isIncremental == true && item.second.isDir == true && !isExist) {
smallFiles.try_emplace(path, item.second); smallFiles.try_emplace(path, item.second);
} }
if (item.second.isIncremental == true && item.second.isDir == false) { if (item.second.isIncremental == true && item.second.isDir == false) {
@ -1165,13 +1166,14 @@ static CompareFilesResult CompareFiles(const UniqueFd &cloudFd, const UniqueFd &
} }
item.second.hash = fileHash; item.second.hash = fileHash;
item.second.isIncremental = true; item.second.isIncremental = true;
} else { }
item.second.hash = (cloudFiles.find(path) == cloudFiles.end()) ? cloudFiles[path].hash : "";
if (item.second.isDir == false && CheckTar(path)) {
item.second.userTar = 1;
} }
allFiles.try_emplace(path, item.second); allFiles.try_emplace(path, item.second);
if (cloudFiles.find(path) == cloudFiles.end() || if (!isExist || (item.second.isDir == false && item.second.isIncremental == true &&
(item.second.isDir == false && item.second.isIncremental == true &&
cloudFiles.find(path)->second.hash != item.second.hash)) { cloudFiles.find(path)->second.hash != item.second.hash)) {
// 在云空间简报里不存在或者hash不一致 // 在云空间简报里不存在或者hash不一致
if (item.second.size < BConstants::BIG_FILE_BOUNDARY) { if (item.second.size < BConstants::BIG_FILE_BOUNDARY) {
@ -1216,12 +1218,12 @@ static void WriteFile(const string &filename, const map<string, struct ReportFil
fstream f; fstream f;
f.open(filename.data(), ios::out); f.open(filename.data(), ios::out);
// 前面2行先填充进去 // 前面2行先填充进去
f << "version=1.0&attrNum=6" << endl; f << "version=1.0&attrNum=7" << endl;
f << "path;mode;dir;size;mtime;hash" << endl; f << "path;mode;dir;size;mtime;hash;usertar" << endl;
for (auto item : srcFiles) { for (auto item : srcFiles) {
struct ReportFileInfo info = item.second; struct ReportFileInfo info = item.second;
string str = item.first + ";" + info.mode + ";" + to_string(info.isDir) + ";" + to_string(info.size); string str = item.first + ";" + info.mode + ";" + to_string(info.isDir) + ";" + to_string(info.size);
str += ";" + to_string(info.mtime) + ";" + info.hash; str += ";" + to_string(info.mtime) + ";" + info.hash + ";" + to_string(info.userTar);
f << str << endl; f << str << endl;
} }
f.close(); f.close();

View File

@ -114,6 +114,8 @@ bool TarFile::TraversalFile(string &filePath)
} }
if (currentTarFileSize_ >= DEFAULT_SLICE_SIZE) { if (currentTarFileSize_ >= DEFAULT_SLICE_SIZE) {
HILOGI("Current tar file size is over %{public}d, start to slice",
static_cast<int32_t>(DEFAULT_SLICE_SIZE / MB_TO_BYTE));
fileCount_ = 0; fileCount_ = 0;
FillSplitTailBlocks(); FillSplitTailBlocks();
CreateSplitTarFile(); CreateSplitTarFile();

View File

@ -95,7 +95,7 @@ int UntarFile::UnPacket(const string &tarFile, const string &rootPath)
} }
int UntarFile::IncrementalUnPacket(const string &tarFile, const string &rootPath, int UntarFile::IncrementalUnPacket(const string &tarFile, const string &rootPath,
const map<string, struct ReportFileInfo> &includes) const unordered_map<string, struct ReportFileInfo> &includes)
{ {
includes_ = includes; includes_ = includes;
tarFilePtr_ = fopen(tarFile.c_str(), "rb"); tarFilePtr_ = fopen(tarFile.c_str(), "rb");

View File

@ -279,7 +279,6 @@ HWTEST_F(BJsonEntityExtManageTest, b_json_entity_ext_manage_0300, testing::ext::
* 03() * 03()
* 0012 * 0012
* () * ()
* 0SetHardLinkInfo向索引文件中对应记录添加硬链接
* 1SetExtManage * 1SetExtManage
* 2GetExtManage * 2GetExtManage
* 3GetExtManageInfo(stat数据) * 3GetExtManageInfo(stat数据)
@ -319,15 +318,6 @@ HWTEST_F(BJsonEntityExtManageTest, b_json_entity_ext_manage_0400, testing::ext::
info.emplace(testFile3HexName, make_tuple(pathTestFile3, GetFileStat(pathTestFile3), true)); info.emplace(testFile3HexName, make_tuple(pathTestFile3, GetFileStat(pathTestFile3), true));
cache.SetExtManage(info); cache.SetExtManage(info);
// 向索引文件中的三条记录分别追加0、1、2条硬链接信息
set<string> hardLinks1, hardLinks2, hardLinks3;
cache.SetHardLinkInfo(testFile1HexName, hardLinks1);
hardLinks2.emplace(root + "testFile2hardlink1");
cache.SetHardLinkInfo(testFile2HexName, hardLinks2);
hardLinks3.emplace(root + "testFile3hardlink1");
hardLinks3.emplace(root + "testFile3hardlink2");
cache.SetHardLinkInfo(testFile3HexName, hardLinks3);
// 预置结果集,用以在读取索引文件后做结果判断 // 预置结果集,用以在读取索引文件后做结果判断
set<string> resultFileName {testFile1HexName, testFile2HexName, testFile3HexName}; set<string> resultFileName {testFile1HexName, testFile2HexName, testFile3HexName};
@ -338,15 +328,6 @@ HWTEST_F(BJsonEntityExtManageTest, b_json_entity_ext_manage_0400, testing::ext::
auto fileInfo = cache.GetExtManageInfo(); auto fileInfo = cache.GetExtManageInfo();
EXPECT_EQ(fileInfo.size(), info.size()); EXPECT_EQ(fileInfo.size(), info.size());
EXPECT_TRUE(IsEqual(fileInfo, info)); EXPECT_TRUE(IsEqual(fileInfo, info));
// 传入无效文件名"00000000",测试读取文件硬链接接口是否正确返回
auto testFile0HardLinks = cache.GetHardLinkInfo("00000000");
EXPECT_TRUE(testFile0HardLinks.empty());
auto testFile1HardLinks = cache.GetHardLinkInfo(testFile1HexName);
EXPECT_TRUE(testFile1HardLinks.empty());
auto testFile2HardLinks = cache.GetHardLinkInfo(testFile2HexName);
EXPECT_EQ(testFile2HardLinks, hardLinks2);
auto testFile3HardLinks = cache.GetHardLinkInfo(testFile3HexName);
EXPECT_EQ(testFile3HardLinks, hardLinks3);
} catch (...) { } catch (...) {
EXPECT_TRUE(false); EXPECT_TRUE(false);
GTEST_LOG_(INFO) << "BJsonEntityExtManageTest-an exception occurred."; GTEST_LOG_(INFO) << "BJsonEntityExtManageTest-an exception occurred.";
@ -394,24 +375,14 @@ HWTEST_F(BJsonEntityExtManageTest, b_json_entity_ext_manage_0500, testing::ext::
auto cache = cachedEntity.Structuralize(); auto cache = cachedEntity.Structuralize();
// 生成三条有用数据并写入索引文件 // 生成三条有用数据并写入索引文件
// 通过重用原始文件的stat向该记录追加(0/1/2)条硬链接文件信息
map<string, tuple<string, struct stat, bool>> info; map<string, tuple<string, struct stat, bool>> info;
struct stat sta = {}; struct stat sta = {};
info.emplace(testFile1HexName, make_tuple(pathTestFile1, GetFileStat(pathTestFile1), true)); info.emplace(testFile1HexName, make_tuple(pathTestFile1, GetFileStat(pathTestFile1), true));
info.emplace(testFile2HexName, make_tuple(pathTestFile2, sta = GetFileStat(pathTestFile2), true)); info.emplace(testFile2HexName, make_tuple(pathTestFile2, sta = GetFileStat(pathTestFile2), true));
info.emplace("testFile2hardlink1", make_tuple(root + "testFile2hardlink1", sta, true));
info.emplace(testFile3HexName, make_tuple(pathTestFile3, sta = GetFileStat(pathTestFile3), true)); info.emplace(testFile3HexName, make_tuple(pathTestFile3, sta = GetFileStat(pathTestFile3), true));
info.emplace("testFile3hardlink1", make_tuple(root + "testFile3hardlink1", sta, true));
info.emplace("testFile3hardlink2", make_tuple(root + "testFile3hardlink2", sta, true));
cache.SetExtManage(info); cache.SetExtManage(info);
// 预置结果集,用以在读取索引文件后做结果判断 // 预置结果集,用以在读取索引文件后做结果判断
// 将info中的硬链接信息删除保留原始文件信息作为后续结果值判断的比较对象
info.erase("testFile2hardlink1");
info.erase("testFile3hardlink1");
info.erase("testFile3hardlink2");
set<string> hardLinks2 {root + "testFile2hardlink1"};
set<string> hardLinks3 {root + "testFile3hardlink1", root + "testFile3hardlink2"};
set<string> resultFileName {testFile1HexName, testFile2HexName, testFile3HexName}; set<string> resultFileName {testFile1HexName, testFile2HexName, testFile3HexName};
// 读取索引文件内容并做结果判断 // 读取索引文件内容并做结果判断
@ -421,12 +392,6 @@ HWTEST_F(BJsonEntityExtManageTest, b_json_entity_ext_manage_0500, testing::ext::
auto fileInfo = cache.GetExtManageInfo(); auto fileInfo = cache.GetExtManageInfo();
EXPECT_EQ(fileInfo.size(), info.size()); EXPECT_EQ(fileInfo.size(), info.size());
EXPECT_TRUE(IsEqual(fileInfo, info)); EXPECT_TRUE(IsEqual(fileInfo, info));
auto testFile1HardLinks = cache.GetHardLinkInfo(testFile1HexName);
EXPECT_TRUE(testFile1HardLinks.empty());
auto testFile2HardLinks = cache.GetHardLinkInfo(testFile2HexName);
EXPECT_EQ(testFile2HardLinks, hardLinks2);
auto testFile3HardLinks = cache.GetHardLinkInfo(testFile3HexName);
EXPECT_EQ(testFile3HardLinks, hardLinks3);
} catch (...) { } catch (...) {
EXPECT_TRUE(false); EXPECT_TRUE(false);
GTEST_LOG_(INFO) << "BJsonEntityExtManageTest-an exception occurred."; GTEST_LOG_(INFO) << "BJsonEntityExtManageTest-an exception occurred.";
@ -434,38 +399,6 @@ HWTEST_F(BJsonEntityExtManageTest, b_json_entity_ext_manage_0500, testing::ext::
GTEST_LOG_(INFO) << "BJsonEntityExtManageTest-end b_json_entity_ext_manage_0500"; GTEST_LOG_(INFO) << "BJsonEntityExtManageTest-end b_json_entity_ext_manage_0500";
} }
/**
* @tc.number: SUB_backup_b_json_entity_ext_manage_0600
* @tc.name: b_json_entity_ext_manage_0600
* @tc.desc: SetExtManage接口中的FindLinks在设备号或INode数目为0时能否成功通过GetExtManage获取相关信息
* @tc.size: MEDIUM
* @tc.type: FUNC
* @tc.level Level 0
* @tc.require: I6F3GV
*/
HWTEST_F(BJsonEntityExtManageTest, b_json_entity_ext_manage_0600, testing::ext::TestSize.Level0)
{
GTEST_LOG_(INFO) << "BJsonEntityExtManageTest-begin b_json_entity_ext_manage_0600";
try {
map<string, tuple<string, struct stat, bool>> mp = {{"key", {"first", {}, true}}};
Json::Value jv;
BJsonEntityExtManage extMg(jv);
extMg.SetExtManage(mp);
set<string> ss = extMg.GetExtManage();
EXPECT_EQ(ss.size(), 1);
std::get<INDEX_SECOND>(mp.at("key")).st_dev = 1;
extMg.SetExtManage(mp);
ss = extMg.GetExtManage();
EXPECT_EQ(ss.size(), 1);
} catch (...) {
EXPECT_TRUE(false);
GTEST_LOG_(INFO) << "BJsonEntityExtManageTest-an exception occurred.";
}
GTEST_LOG_(INFO) << "BJsonEntityExtManageTest-end b_json_entity_ext_manage_0600";
}
/** /**
* @tc.number: SUB_backup_b_json_entity_ext_manage_0700 * @tc.number: SUB_backup_b_json_entity_ext_manage_0700
* @tc.name: b_json_entity_ext_manage_0700 * @tc.name: b_json_entity_ext_manage_0700
@ -590,187 +523,4 @@ HWTEST_F(BJsonEntityExtManageTest, b_json_entity_ext_manage_0803, testing::ext::
} }
GTEST_LOG_(INFO) << "BJsonEntityExtManageTest-end b_json_entity_ext_manage_0803"; GTEST_LOG_(INFO) << "BJsonEntityExtManageTest-end b_json_entity_ext_manage_0803";
} }
/**
* @tc.number: SUB_backup_bb_json_entity_ext_manage_0900
* @tc.name: b_json_entity_ext_manage_0900
* @tc.desc: SetHardLinkInfo接口和GetHardLinkInfo接口在不符合相关条件时能否成功返回false和空set
* @tc.size: MEDIUM
* @tc.type: FUNC
* @tc.level Level 0
* @tc.require: I6F3GV
*/
HWTEST_F(BJsonEntityExtManageTest, b_json_entity_ext_manage_0900, testing::ext::TestSize.Level0)
{
GTEST_LOG_(INFO) << "BJsonEntityExtManageTest-begin b_json_entity_ext_manage_0900";
try {
string_view sv = R"({"key":1})";
BJsonCachedEntity<BJsonEntityExtManage> cachedEntity(sv);
auto cache = cachedEntity.Structuralize();
EXPECT_FALSE(cache.SetHardLinkInfo("", {}));
Json::Value jv;
BJsonEntityExtManage extMg(jv);
EXPECT_FALSE(extMg.SetHardLinkInfo("1", {}));
EXPECT_FALSE(cache.SetHardLinkInfo("1", {}));
EXPECT_EQ(cache.GetHardLinkInfo(""), set<string>());
EXPECT_EQ(extMg.GetHardLinkInfo("1"), set<string>());
EXPECT_EQ(cache.GetHardLinkInfo("1"), set<string>());
} catch (...) {
EXPECT_TRUE(false);
GTEST_LOG_(INFO) << "BJsonEntityExtManageTest-an exception occurred.";
}
GTEST_LOG_(INFO) << "BJsonEntityExtManageTest-end b_json_entity_ext_manage_0900";
}
/**
* @tc.number: SUB_backup_b_json_entity_ext_manage_0901
* @tc.name: b_json_entity_ext_manage_0901
* @tc.desc: SetHardLinkInfo接口和GetHardLinkInfo接口在不符合相关条件时能否成功返回false和空set
* @tc.size: MEDIUM
* @tc.type: FUNC
* @tc.level Level 0
* @tc.require: I6F3GV
*/
HWTEST_F(BJsonEntityExtManageTest, b_json_entity_ext_manage_0901, testing::ext::TestSize.Level0)
{
GTEST_LOG_(INFO) << "BJsonEntityExtManageTest-begin b_json_entity_ext_manage_0901";
try {
string_view sv = R"({"key":1})";
BJsonCachedEntity<BJsonEntityExtManage> cachedEntity(sv);
auto cache = cachedEntity.Structuralize();
EXPECT_FALSE(cache.SetHardLinkInfo("#4$5%", {}));
Json::Value jv;
BJsonEntityExtManage extMg(jv);
EXPECT_FALSE(extMg.SetHardLinkInfo("1", {}));
EXPECT_FALSE(cache.SetHardLinkInfo("1", {}));
EXPECT_EQ(cache.GetHardLinkInfo("#4$5%"), set<string>());
EXPECT_EQ(extMg.GetHardLinkInfo("1"), set<string>());
EXPECT_EQ(cache.GetHardLinkInfo("1"), set<string>());
} catch (...) {
EXPECT_TRUE(false);
GTEST_LOG_(INFO) << "BJsonEntityExtManageTest-an exception occurred.";
}
GTEST_LOG_(INFO) << "BJsonEntityExtManageTest-end b_json_entity_ext_manage_0901";
}
/**
* @tc.number: SUB_backup_b_json_entity_ext_manage_0902
* @tc.name: b_json_entity_ext_manage_0902
* @tc.desc: SetHardLinkInfo接口和GetHardLinkInfo接口在不符合相关条件时能否成功返回false和空set
* @tc.size: MEDIUM
* @tc.type: FUNC
* @tc.level Level 0
* @tc.require: I6F3GV
*/
HWTEST_F(BJsonEntityExtManageTest, b_json_entity_ext_manage_0902, testing::ext::TestSize.Level0)
{
GTEST_LOG_(INFO) << "BJsonEntityExtManageTest-begin b_json_entity_ext_manage_0902";
try {
string_view sv = R"({"key":1})";
BJsonCachedEntity<BJsonEntityExtManage> cachedEntity(sv);
auto cache = cachedEntity.Structuralize();
EXPECT_FALSE(cache.SetHardLinkInfo("测试代码", {}));
Json::Value jv;
BJsonEntityExtManage extMg(jv);
EXPECT_FALSE(extMg.SetHardLinkInfo("1", {}));
EXPECT_FALSE(cache.SetHardLinkInfo("1", {}));
EXPECT_EQ(cache.GetHardLinkInfo("测试代码"), set<string>());
EXPECT_EQ(extMg.GetHardLinkInfo("1"), set<string>());
EXPECT_EQ(cache.GetHardLinkInfo("1"), set<string>());
} catch (...) {
EXPECT_TRUE(false);
GTEST_LOG_(INFO) << "BJsonEntityExtManageTest-an exception occurred.";
}
GTEST_LOG_(INFO) << "BJsonEntityExtManageTest-end b_json_entity_ext_manage_0902";
}
/**
* @tc.number: SUB_backup_b_json_entity_ext_manage_0903
* @tc.name: b_json_entity_ext_manage_0903
* @tc.desc: SetHardLinkInfo接口和GetHardLinkInfo接口在不符合相关条件时能否成功返回false和空set
* @tc.size: MEDIUM
* @tc.type: FUNC
* @tc.level Level 0
* @tc.require: I6F3GV
*/
HWTEST_F(BJsonEntityExtManageTest, b_json_entity_ext_manage_0903, testing::ext::TestSize.Level0)
{
GTEST_LOG_(INFO) << "BJsonEntityExtManageTest-begin b_json_entity_ext_manage_0903";
try {
string_view sv = R"({"key":1})";
BJsonCachedEntity<BJsonEntityExtManage> cachedEntity(sv);
auto cache = cachedEntity.Structuralize();
EXPECT_FALSE(cache.SetHardLinkInfo("ABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDA\
BCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCD", {}));
Json::Value jv;
BJsonEntityExtManage extMg(jv);
EXPECT_FALSE(extMg.SetHardLinkInfo("1", {}));
EXPECT_FALSE(cache.SetHardLinkInfo("1", {}));
EXPECT_EQ(cache.GetHardLinkInfo("ABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDA\
BCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCD"), set<string>());
EXPECT_EQ(extMg.GetHardLinkInfo("1"), set<string>());
EXPECT_EQ(cache.GetHardLinkInfo("1"), set<string>());
} catch (...) {
EXPECT_TRUE(false);
GTEST_LOG_(INFO) << "BJsonEntityExtManageTest-an exception occurred.";
}
GTEST_LOG_(INFO) << "BJsonEntityExtManageTest-end b_json_entity_ext_manage_0903";
}
/**
* @tc.number: SUB_backup_b_json_entity_ext_manage_0904
* @tc.name: b_json_entity_ext_manage_0904
* @tc.desc: SetHardLinkInfo接口和GetHardLinkInfo接口在不符合相关条件时能否成功返回false和空set
* @tc.size: MEDIUM
* @tc.type: FUNC
* @tc.level Level 0
* @tc.require: I6F3GV
*/
HWTEST_F(BJsonEntityExtManageTest, b_json_entity_ext_manage_0904, testing::ext::TestSize.Level0)
{
GTEST_LOG_(INFO) << "BJsonEntityExtManageTest-begin b_json_entity_ext_manage_0904";
try {
string_view sv = R"({"key":1})";
BJsonCachedEntity<BJsonEntityExtManage> cachedEntity(sv);
auto cache = cachedEntity.Structuralize();
EXPECT_FALSE(cache.SetHardLinkInfo("", {""""""""""""""""""""""""""""""""""""""""""""""""""}));
Json::Value jv;
BJsonEntityExtManage extMg(jv);
EXPECT_FALSE(extMg.SetHardLinkInfo("测试代码", {}));
EXPECT_FALSE(cache.SetHardLinkInfo("#4$5%", {}));
EXPECT_EQ(cache.GetHardLinkInfo(""), set<string>());
EXPECT_EQ(extMg.GetHardLinkInfo("测试代码"), set<string>());
EXPECT_EQ(cache.GetHardLinkInfo("#4$5%"), set<string>());
} catch (...) {
EXPECT_TRUE(false);
GTEST_LOG_(INFO) << "BJsonEntityExtManageTest-an exception occurred.";
}
GTEST_LOG_(INFO) << "BJsonEntityExtManageTest-end b_json_entity_ext_manage_0904";
}
} // namespace OHOS::FileManagement::Backup } // namespace OHOS::FileManagement::Backup

View File

@ -78,7 +78,7 @@ HWTEST_F(BReportEntityTest, b_report_entity_GetReportInfos_0100, testing::ext::T
const auto [filePath, res] = GetTestFile(tm, content); const auto [filePath, res] = GetTestFile(tm, content);
BReportEntity cloudRp(UniqueFd(open(filePath.data(), O_RDONLY, 0))); BReportEntity cloudRp(UniqueFd(open(filePath.data(), O_RDONLY, 0)));
map<string, struct ReportFileInfo> cloudFiles = cloudRp.GetReportInfos(); unordered_map<string, struct ReportFileInfo> cloudFiles = cloudRp.GetReportInfos();
bool flag = false; bool flag = false;

View File

@ -62,24 +62,6 @@ public:
*/ */
std::vector<ExtManageInfo> GetExtManageInfo() const; std::vector<ExtManageInfo> GetExtManageInfo() const;
/**
* @brief Set the hard link Information
*
* @param origin
* @param hardLinks
* @return true
* @return false
*/
bool SetHardLinkInfo(const std::string origin, const std::set<std::string> hardLinks);
/**
* @brief Get the hard link Information
*
* @param origin
* @return const
*/
const std::set<std::string> GetHardLinkInfo(const string origin);
public: public:
/** /**
* @brief T(Json::Value&, std::any) * @brief T(Json::Value&, std::any)

View File

@ -32,6 +32,7 @@ struct ReportFileInfo {
off_t mtime {0}; off_t mtime {0};
std::string hash; std::string hash;
bool isIncremental {false}; bool isIncremental {false};
off_t userTar {0};
}; };
class BReportEntity { class BReportEntity {
@ -41,7 +42,7 @@ public:
* *
* @return std::map<string, ReportFileInfo> * @return std::map<string, ReportFileInfo>
*/ */
std::map<std::string, struct ReportFileInfo> GetReportInfos(); std::unordered_map<std::string, struct ReportFileInfo> GetReportInfos();
public: public:
/** /**

View File

@ -32,15 +32,8 @@ namespace {
const int32_t DEFAULT_MODE = 0100660; // 0660 const int32_t DEFAULT_MODE = 0100660; // 0660
} }
static bool CheckBigFile(const string &tarFile) static bool CheckBigFile(struct stat sta)
{ {
HILOGI("CheckBigFile tarFile:%{public}s", tarFile.data());
struct stat sta;
int ret = stat(tarFile.c_str(), &sta);
if (ret != 0) {
HILOGE("stat file failed, file:%{public}s", tarFile.c_str());
return false;
}
if (sta.st_size > BConstants::BIG_FILE_BOUNDARY) { if (sta.st_size > BConstants::BIG_FILE_BOUNDARY) {
return true; return true;
} }
@ -54,8 +47,7 @@ static bool CheckBigFile(const string &tarFile)
*/ */
static bool CheckOwnPackTar(const string &fileName) static bool CheckOwnPackTar(const string &fileName)
{ {
if (access(fileName.c_str(), F_OK) != 0) { if (ExtractFileExt(fileName) != "tar") {
HILOGE("file does not exists");
return false; return false;
} }
// 如果不是在默认路径下的文件包不属于自身打包的tar文件 // 如果不是在默认路径下的文件包不属于自身打包的tar文件
@ -66,6 +58,8 @@ static bool CheckOwnPackTar(const string &fileName)
} catch (const BError &e) { } catch (const BError &e) {
HILOGE("file is not backup path"); HILOGE("file is not backup path");
return false; return false;
} catch (...) {
return false;
} }
string::size_type pathPos = absPath.find(defaultBackupPath); string::size_type pathPos = absPath.find(defaultBackupPath);
@ -80,17 +74,22 @@ static bool CheckOwnPackTar(const string &fileName)
} }
string firstName = string(tarFile).substr(0, pos); string firstName = string(tarFile).substr(0, pos);
// 判断文件名是否包含part (兼容增量)
string::size_type partPos = firstName.find("part");
if (partPos == string::npos) {
return false;
}
return (firstName == "part") && (ExtractFileExt(tarFile) == "tar"); return true;
} }
static bool CheckUserTar(const string &fileName) static bool CheckUserTar(const string &fileName, struct stat sta)
{ {
if (access(fileName.c_str(), F_OK) != 0) { if (access(fileName.c_str(), F_OK) != 0) {
HILOGI("file does not exists"); HILOGI("file does not exists");
return false; return false;
} }
return (ExtractFileExt(fileName) == "tar") && CheckBigFile(fileName); return (ExtractFileExt(fileName) == "tar") && CheckBigFile(sta);
} }
Json::Value Stat2JsonValue(struct stat sta) Json::Value Stat2JsonValue(struct stat sta)
@ -157,49 +156,14 @@ void BJsonEntityExtManage::SetExtManage(const map<string, tuple<string, struct s
{ {
obj_.clear(); obj_.clear();
vector<bool> vec(info.size(), false); for (auto item = info.begin(); item != info.end(); ++item) {
auto FindLinks = [&vec](map<string, tuple<string, struct stat, bool>>::const_iterator it,
unsigned long index) -> set<string> {
if (std::get<1>(it->second).st_dev == 0 || std::get<1>(it->second).st_ino == 0) {
return {};
}
set<string> lks;
auto item = it;
item++;
for (auto i = index + 1; i < vec.size(); ++i, ++item) {
if (std::get<1>(it->second).st_dev == std::get<1>(item->second).st_dev &&
std::get<1>(it->second).st_ino == std::get<1>(item->second).st_ino) {
vec[i] = true;
lks.insert(std::get<0>(item->second));
HILOGI("lks insert %{public}s", std::get<0>(item->second).c_str());
}
HILOGI("lks doesn't insert %{public}s", std::get<0>(item->second).c_str());
}
return lks;
};
unsigned long index = 0;
for (auto item = info.begin(); item != info.end(); ++item, ++index) {
if (vec[index]) {
HILOGI("skipped file is %{public}s", item->first.c_str());
continue;
}
HILOGI("file name is %{public}s", item->first.c_str());
Json::Value value; Json::Value value;
value["fileName"] = item->first; value["fileName"] = item->first;
auto [path, sta, isBeforeTar] = item->second; auto [path, sta, isBeforeTar] = item->second;
value["information"]["path"] = path; value["information"]["path"] = path;
value["information"]["stat"] = Stat2JsonValue(sta); value["information"]["stat"] = Stat2JsonValue(sta);
value["isUserTar"] = isBeforeTar && CheckUserTar(path); value["isUserTar"] = isBeforeTar && CheckUserTar(path, sta);
value["isBigFile"] = !CheckOwnPackTar(path) && CheckBigFile(path); value["isBigFile"] = !CheckOwnPackTar(path) && CheckBigFile(sta);
set<string> lks = FindLinks(item, index);
for (const auto &lk : lks) {
value["hardlinks"].append(lk);
}
obj_.append(value); obj_.append(value);
} }
@ -268,71 +232,4 @@ std::vector<ExtManageInfo> BJsonEntityExtManage::GetExtManageInfo() const
return infos; return infos;
} }
bool BJsonEntityExtManage::SetHardLinkInfo(const string origin, const set<string> hardLinks)
{
if (origin.empty()) {
HILOGE("origin file name can not empty");
return false;
}
if (!obj_) {
HILOGE("Uninitialized JSon Object reference");
return false;
}
if (!obj_.isArray()) {
HILOGE("json object isn't an array");
return false;
}
for (Json::Value &item : obj_) {
string fileName = item.isObject() && item.isMember("fileName") && item["fileName"].isString()
? item["fileName"].asString()
: "";
if (origin == fileName) {
for (const auto &lk : hardLinks) {
item["hardlinks"].append(lk);
}
return true;
}
}
return false;
}
const set<string> BJsonEntityExtManage::GetHardLinkInfo(const string origin)
{
if (origin.empty()) {
HILOGE("origin file name can not empty");
return {};
}
if (!obj_) {
HILOGE("Uninitialized JSon Object reference");
return {};
}
if (!obj_.isArray()) {
HILOGE("json object isn't an array");
return {};
}
set<string> hardlinks;
for (const Json::Value &item : obj_) {
if (!item.isObject()) {
continue;
}
string fileName = item.isMember("fileName") && item["fileName"].isString() ? item["fileName"].asString() : "";
if (origin != fileName) {
continue;
}
if (!(item.isMember("hardlinks") && item["hardlinks"].isArray())) {
break;
}
for (const auto &lk : item["hardlinks"]) {
if (lk.isString()) {
hardlinks.emplace(lk.asString());
}
}
}
return hardlinks;
}
} // namespace OHOS::FileManagement::Backup } // namespace OHOS::FileManagement::Backup

View File

@ -111,7 +111,7 @@ static ErrCode ParseReportInfo(struct ReportFileInfo &fileStat,
static void DealLine(unordered_map<string, int> &keys, static void DealLine(unordered_map<string, int> &keys,
int &num, int &num,
const string &line, const string &line,
map<string, struct ReportFileInfo> &infos) unordered_map<string, struct ReportFileInfo> &infos)
{ {
string currentLine = line; string currentLine = line;
if (currentLine[currentLine.length() - 1] == LINE_WRAP) { if (currentLine[currentLine.length() - 1] == LINE_WRAP) {
@ -137,9 +137,9 @@ static void DealLine(unordered_map<string, int> &keys,
} }
} }
map<string, struct ReportFileInfo> BReportEntity::GetReportInfos() unordered_map<string, struct ReportFileInfo> BReportEntity::GetReportInfos()
{ {
map<string, struct ReportFileInfo> infos {}; unordered_map<string, struct ReportFileInfo> infos {};
char buffer[HASH_BUFFER_SIZE]; char buffer[HASH_BUFFER_SIZE];
ssize_t bytesRead; ssize_t bytesRead;