From 73b3c10c9f4a31e877c4b9926d936527c88e401d Mon Sep 17 00:00:00 2001 From: y30045862 Date: Wed, 25 Oct 2023 20:45:27 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=96=87=E4=BB=B6=E5=A4=B9?= =?UTF-8?q?=E6=97=B6=E9=97=B4=E5=8F=98=E5=8C=96=E9=97=AE=E9=A2=98=20Signed?= =?UTF-8?q?-off-by:=20yangjingbo10=20?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Ic011700d9cc1f4900daea849f9228dd0ade6f360 --- .../trash/src/file_trash_n_exporter.cpp | 144 +++++++----------- utils/file_util.h | 33 +++- 2 files changed, 80 insertions(+), 97 deletions(-) diff --git a/interfaces/kits/native/trash/src/file_trash_n_exporter.cpp b/interfaces/kits/native/trash/src/file_trash_n_exporter.cpp index bfaf4a02..0fde2716 100644 --- a/interfaces/kits/native/trash/src/file_trash_n_exporter.cpp +++ b/interfaces/kits/native/trash/src/file_trash_n_exporter.cpp @@ -69,7 +69,7 @@ static string GetTimeSlotFromPath(const string &path) // 获取时间戳目录位置 size_t trashPathWithTimePrefixPos = realFilePathWithTime.find_first_of("/"); if (trashPathWithTimePrefixPos == string::npos) { - HILOG_ERROR("GetTimeSlotFromPath: Invalid path = %{public}s", path.c_str()); + HILOG_ERROR("GetTimeSlotFromPath: Invalid path"); return ""; } string timeSlot = realFilePathWithTime.substr(0, trashPathWithTimePrefixPos); @@ -84,7 +84,6 @@ static int RecursiveFunc(const string &path, vector &dirents) HILOG_ERROR("Failed to request heap memory."); return ENOMEM; } - HILOG_DEBUG("RecursiveFunc: scandir path = %{public}s", path.c_str()); int num = scandir(path.c_str(), &(pNameList->namelist), FilterFunc, alphasort); if (num < 0) { HILOG_ERROR("RecursiveFunc: Failed to scan dir"); @@ -158,7 +157,6 @@ static napi_value CreateObjectArray(napi_env env, vector result) static string FindSourceFilePath(const string &path) { - HILOG_INFO("FindSourceFilePath: curFilePath = %{public}s", path.c_str()); size_t slashSize = 1; // 获取/trash目录位置 size_t trashPathPrefixPos = path.find(TRASH_PATH); @@ -186,13 +184,12 @@ static string FindSourceFilePath(const string &path) string realFileName = realFilePath.substr(pos + TRASH_SUB_DIR.length() + timeSlot.length() + slashSize); realFilePath = "/" + realFilePathPrefix + realFileName; - HILOG_INFO("FindSourceFilePath: realFilePath After = %{public}s", realFilePath.c_str()); return realFilePath; } -static bool Mkdirs(const string &path, bool isDir, string &newRecoveredPath) +static bool Mkdirs(const string &path, bool isDir) { - HILOG_INFO("Mkdirs: path = %{public}s", path.c_str()); + HILOG_INFO("Mkdirs start"); string recoveredPath = path; string folderName = ""; size_t lastPos = 0; @@ -213,7 +210,7 @@ static bool Mkdirs(const string &path, bool isDir, string &newRecoveredPath) lastPos = i; auto [isExist, ret] = Access(recoveredPath); if (!isExist && !Mkdir(recoveredPath)) { - HILOG_ERROR("Mkdirs fail for %{public}s ", recoveredPath.c_str()); + HILOG_ERROR("Mkdir fails"); return false; } recoveredPath[i] = '/'; @@ -252,7 +249,7 @@ static string GenerateNewFileNameNoSuffix(const string &destFile, int32_t distin return ""; } -static bool MoveFile(const string &srcFile, const string &destFile) +static int MoveFile(const string &srcFile, const string &destFile) { // 判断目的文件是否存在 auto [isExist, ret] = Access(destFile); @@ -262,11 +259,14 @@ static bool MoveFile(const string &srcFile, const string &destFile) size_t slashPos = destFile.find_last_of("/"); if (slashPos == string::npos) { HILOG_ERROR("MoveFile: : Invalid Path"); - return false; + return E_INVAL; + } + // 识别文件后缀分隔符 + size_t suffixPos = destFile.find_last_of('.'); + if (suffixPos < slashPos) { + // 识别的文件后缀分隔符必须在文件部分 + suffixPos = string::npos; } - size_t suffixPos = destFile.find_first_of('.', slashPos); - HILOG_DEBUG("MoveFile: slashPos = %{public}zu", slashPos); - HILOG_DEBUG("MoveFile: suffixPos = %{public}zu", suffixPos); string newDestFile = destFile; int32_t distinctSuffixIndex = 1; if (suffixPos == string::npos) { @@ -288,21 +288,19 @@ static bool MoveFile(const string &srcFile, const string &destFile) return RenameFile(srcFile, destFile); } HILOG_ERROR("MoveFile: : Invalid Path"); - return false; + return E_INVAL; } static string RecurCheckIfOnlyContentInDir(const string &path, size_t trashWithTimePos, const string &trashWithTimePath) { - HILOG_INFO("RecurCheckIfOnlyContentInDir: path = %{public}s", path.c_str()); + HILOG_INFO("RecurCheckIfOnlyContentInDir start"); size_t slashPos = path.find_last_of("/"); if (slashPos <= trashWithTimePos) { HILOG_DEBUG("RecurCheckIfOnlyContentInDir: slashPos = %{public}zu", slashPos); return trashWithTimePath; } string parentPath = path.substr(0, slashPos); - HILOG_DEBUG("RecurCheckIfOnlyContentInDir: parentPath = %{public}s", parentPath.c_str()); int num = ScanDir(parentPath); - HILOG_DEBUG("RecurCheckIfOnlyContentInDir: num = %{public}d", num); if (num > 1) { // 同一时间戳目录下存在多个删除项,则不论是还原后的删除还是彻底删除,仅需删除该项 HILOG_DEBUG("RecurCheckIfOnlyContentInDir: find other items in current dir"); @@ -311,14 +309,14 @@ static string RecurCheckIfOnlyContentInDir(const string &path, size_t trashWithT // 需要向上一层目录判断 return RecurCheckIfOnlyContentInDir(parentPath, trashWithTimePos, trashWithTimePath); } else { - HILOG_ERROR("RecurCheckIfOnlyContentInDir: invalid path = %{public}s", path.c_str()); + HILOG_ERROR("RecurCheckIfOnlyContentInDir: invalid path"); } return nullptr; } static string GetToDeletePath(const string &toDeletePath, napi_env env) { - HILOG_INFO("GetToDeletePath: toDeletePath = %{public}s", toDeletePath.c_str()); + HILOG_INFO("GetToDeletePath start"); // 判断是否为有效回收站路径 size_t slashSize = 1; // 获取/Trash目录位置 @@ -434,10 +432,11 @@ napi_value FileTrashNExporter::ListFile(napi_env env, napi_callback_info info) static napi_value RecoverFile(napi_env env, const string &filePath) { string sourceFilePath = FindSourceFilePath(filePath); - HILOG_INFO("RecoverFile: sourceFilePath = %{public}s", sourceFilePath.c_str()); - string newDestPath = sourceFilePath; - if (newDestPath.length() != 0 && Mkdirs(sourceFilePath, false, newDestPath)) { - MoveFile(filePath, newDestPath); + HILOG_INFO("RecoverFile start"); + if (!Mkdirs(sourceFilePath, false) || (MoveFile(filePath, sourceFilePath) != ERRNO_NOERR)) { + HILOG_ERROR("RecoverFile: Failed to Mkdirs or MoveFile."); + NError(EINVAL).ThrowErr(env); + return nullptr; } // 文件已被移动,则如果前一层目录包含其他内容,则直接返回; @@ -455,76 +454,29 @@ static napi_value RecoverFile(napi_env env, const string &filePath) return NVal::CreateUndefined(env).val_; } -static void RecoverFilePart(vector filePathList, map dirPath2UpdatedNameMap) +static void RecoverFilePart(vector filePathList) { // 处理文件 for (size_t j = 0; j < filePathList.size(); j++) { string filePath = filePathList[j]; - HILOG_INFO("RecoverFilePart: filePath = %{public}s", filePath.c_str()); string sourceFilePath = FindSourceFilePath(filePath); - HILOG_INFO("RecoverFilePart: sourceFilePath = %{public}s", sourceFilePath.c_str()); - - size_t lastSlashPos = sourceFilePath.find_last_of("/"); - string fileName = sourceFilePath.substr(lastSlashPos + 1); - string sourceFilePathOnly = sourceFilePath.substr(0, lastSlashPos); - map::iterator iter = dirPath2UpdatedNameMap.find(sourceFilePathOnly); - if (iter != dirPath2UpdatedNameMap.end()) { - sourceFilePath = iter->second + "/" + fileName; - } MoveFile(filePath, sourceFilePath); } } -static vector FilterDirsNoContains(vector dirPathList) -{ - //先处理目录,仅保留不互相包含的目录(取子目录较深的) - vector filterDirPathList; - for (size_t j = 0; j < dirPathList.size(); j++) { - string dirPath = dirPathList[j]; - bool isIncluded = false; - for (size_t k = 0; k < filterDirPathList.size(); k++) { - string filterDirPath = filterDirPathList[k]; - if (StartsWith(filterDirPath, dirPath)) { - isIncluded = true; - break; - } - } - if (!isIncluded) { - filterDirPathList.emplace_back(dirPath); - } - } - return filterDirPathList; -} - -static map MakeAndFindUpdateNameDir(vector filterDirPathList) -{ - map dirPath2UpdatedNameMap; - for (size_t j = 0; j < filterDirPathList.size(); j++) { - string dirPath = filterDirPathList[j]; - string sourceFilePath = FindSourceFilePath(dirPath); - HILOG_DEBUG("MakeAndFindUpdateNameDir: sourceFilePath = %{public}s", sourceFilePath.c_str()); - string newDestPath = sourceFilePath; - if (Mkdirs(sourceFilePath, true, newDestPath)) { - HILOG_DEBUG("MakeAndFindUpdateNameDir: newDestPath = %{public}s", newDestPath.c_str()); - if (newDestPath != sourceFilePath) { - dirPath2UpdatedNameMap.insert(make_pair(sourceFilePath, newDestPath)); - } - } - } - return dirPath2UpdatedNameMap; -} - static napi_value RecoverDir(napi_env env, const string &dirPath) { vector dirents; unique_ptr pNameList = { new (nothrow) struct NameListArg, Deleter }; if (!pNameList) { HILOG_ERROR("RecoverDir: Failed to request heap memory."); + NError(ENOMEM).ThrowErr(env); return nullptr; } int ret = RecursiveFunc(dirPath, dirents); if (ret != ERRNO_NOERR) { HILOG_ERROR("RecoverDir: Failed to Recursive Dir."); + NError(ret).ThrowErr(env); return nullptr; } dirents.emplace_back(dirPath); @@ -540,24 +492,35 @@ static napi_value RecoverDir(napi_env env, const string &dirPath) filePathList.emplace_back(dirent); } } - // 目录从长到短排序 - sort(dirPathList.begin(), dirPathList.end(), [&](const string &a, const string &b) { - return a.length() > b.length(); - }); - // 先处理目录,仅保留不互相包含的目录(取子目录较深的) - vector filterDirPathList = FilterDirsNoContains(dirPathList); - if (filterDirPathList.size() == 0) { - HILOG_ERROR("RecoverDir: NO valid dirs found"); - return nullptr; - } + // 记录还原前目录时间 + map> dir2Times; - // 新建目录并获取因为存在同名目录修改过名称的目录 - map dirPath2UpdatedNameMap = MakeAndFindUpdateNameDir(filterDirPathList); + // 新建目录 + for (size_t j = 0; j < dirPathList.size(); j++) { + string sourceFilePath = FindSourceFilePath(dirPathList[j]); + // 获取还原前目录时间 + auto[atime, mtime, retGetTime] = GetFileTime(dirPathList[j]); + if (!Mkdirs(sourceFilePath, true)) { + HILOG_ERROR("RecoverDir: NO valid dirs found"); + NError(EINVAL).ThrowErr(env); + return nullptr; + } + // 修改还原后目录时间 + if (retGetTime == ERRNO_NOERR) { + dir2Times.insert(make_pair(sourceFilePath, make_tuple(atime, mtime))); + } + } // 处理文件部分 - RecoverFilePart(filePathList, dirPath2UpdatedNameMap); - + RecoverFilePart(filePathList); + + // 更新新增目录时间 + for (auto &item : dir2Times) { + auto [oldAtime, oldMtime] = item.second; + UpdateFileTime(oldAtime, oldMtime, item.first); + } + // 删除目录 auto err = RmDirent(GetToDeletePath(dirPath, env)); if (err) { @@ -590,7 +553,6 @@ napi_value FileTrashNExporter::Recover(napi_env env, napi_callback_info info) return nullptr; } string uriStr = uriPtr.get(); - HILOG_DEBUG("Recover: uriPtr.get() = %{public}s", uriStr.c_str()); // 获取沙箱目录地址 AppFileService::ModuleFileUri::FileUri fileUri(uriStr); @@ -601,12 +563,11 @@ napi_value FileTrashNExporter::Recover(napi_env env, napi_callback_info info) HILOG_ERROR("Recover: Invalid Path"); return nullptr; } - HILOG_DEBUG("Recover: path = %{public}s", path.c_str()); // 判断是否是回收站路径 if (path.find(TRASH_PATH) == string::npos) { NError(EINVAL).ThrowErr(env); - HILOG_ERROR("Recover: path = %{public}s is not Trash path", path.c_str()); + HILOG_ERROR("Recover: Not Trash path"); return nullptr; } @@ -614,7 +575,7 @@ napi_value FileTrashNExporter::Recover(napi_env env, napi_callback_info info) auto [isExist, ret] = Access(path); if (!isExist) { NError(EINVAL).ThrowErr(env); - HILOG_ERROR("Recover: Path is not exist"); + HILOG_ERROR("Recover: path is not Trash path"); return nullptr; } @@ -659,12 +620,11 @@ napi_value FileTrashNExporter::CompletelyDelete(napi_env env, napi_callback_info HILOG_ERROR("Recover: Invalid Path"); return nullptr; } - HILOG_DEBUG("Recover: path = %{public}s", path.c_str()); // 判断是否是回收站路径 if (path.find(TRASH_PATH) == string::npos) { NError(EINVAL).ThrowErr(env); - HILOG_ERROR("Recover: path = %{public}s is not Trash path", path.c_str()); + HILOG_ERROR("Recover: Not Trash path"); return nullptr; } diff --git a/utils/file_util.h b/utils/file_util.h index d7c36e08..2138e3ed 100644 --- a/utils/file_util.h +++ b/utils/file_util.h @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -46,11 +47,6 @@ struct StatEntity { uv_stat_t stat_; }; -static bool StartsWith(const string& str, const string prefix) -{ - return (str.rfind(prefix, 0) == 0); -} - static void Deleter(struct NameListArg *arg) { for (int i = 0; i < arg->direntNum; i++) { @@ -148,6 +144,33 @@ static bool Mkdir(const string &path) return false; } +static tuple GetFileTime(const string &src) +{ + // 获取源文件时间 + StatEntity statEntity; + if (!GetStat(src, statEntity)) { + HILOG_ERROR("Failed to get file stat."); + return {0, 0, EINVAL}; + } + // 拼接秒数和纳秒数 + uint64_t acTimeLong = static_cast(statEntity.stat_.st_atim.tv_sec * TIME_CONVERT_BASE + + statEntity.stat_.st_atim.tv_nsec); + uint64_t modTimeLong = static_cast(statEntity.stat_.st_mtim.tv_sec * TIME_CONVERT_BASE + + statEntity.stat_.st_mtim.tv_nsec); + double acTime = static_cast(acTimeLong) / TIME_CONVERT_BASE; + double modTime = static_cast(modTimeLong) / TIME_CONVERT_BASE; + + return {acTime, modTime, ERRNO_NOERR}; +} + +static void UpdateFileTime(double acTime, double modTime, const string &dest) +{ + // 设置目标文件时间 + uv_fs_t utime_req; + uv_fs_utime(nullptr, &utime_req, dest.c_str(), acTime, modTime, nullptr); + uv_fs_req_cleanup(&utime_req); +} + static int CopyAndDeleteFile(const string &src, const string &dest) { // 获取源文件时间 -- Gitee