From f9bf0f6ca87f8247d7d7f38245de447e3385bfd5 Mon Sep 17 00:00:00 2001 From: y30045862 Date: Wed, 1 Nov 2023 11:40:22 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=96=87=E4=BB=B6=E5=A4=B9?= =?UTF-8?q?=E5=88=A0=E9=99=A4=E8=BF=98=E5=8E=9F=E6=97=B6=E9=97=B4=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=E9=97=AE=E9=A2=98=20Signed-off-by:=20yangjingbo10=20?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I01ffd99854c4caee69e63bbe52852682ac7d7cd4 --- .../trash/src/file_trash_n_exporter.cpp | 143 +++++++++++------- utils/file_util.h | 29 ++++ 2 files changed, 116 insertions(+), 56 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 e0bfea7b..660b4f2b 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(FileTrashNExporter::trashPath_); @@ -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] = '/'; @@ -296,16 +293,14 @@ static int MoveFile(const string &srcFile, const string &destFile) 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"); @@ -314,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目录位置 @@ -438,14 +433,13 @@ 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)) { + if (!Mkdirs(sourceFilePath, false)) { HILOG_ERROR("RecoverFile: Mkdirs failed"); NError(EINVAL).ThrowErr(env); return nullptr; } - int moveRet = MoveFile(filePath, newDestPath); + int moveRet = MoveFile(filePath, sourceFilePath); if (moveRet != ERRNO_NOERR) { HILOG_ERROR("RecoverFile: MoveFile failed"); NError(moveRet).ThrowErr(env); @@ -467,22 +461,12 @@ static napi_value RecoverFile(napi_env env, const string &filePath) return NVal::CreateUndefined(env).val_; } -static int RecoverFilePart(vector filePathList, map dirPath2UpdatedNameMap) +static int 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; - } int moveRet = MoveFile(filePath, sourceFilePath); if (moveRet != ERRNO_NOERR) { return moveRet; @@ -491,39 +475,34 @@ static int RecoverFilePart(vector filePathList, map dirP return ERRNO_NOERR; } -static map MakeAndFindUpdateNameDir(vector filterDirPathList) +static int MkdirAndSaveTime(vector dirPathList, unordered_map> dir2Times) { - 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)); - } + 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)) { + return EINVAL; + } + // 修改还原后目录时间 + if (retGetTime == ERRNO_NOERR) { + dir2Times.insert(make_pair(sourceFilePath, make_pair(atime, mtime))); } } - return dirPath2UpdatedNameMap; + return ERRNO_NOERR; } 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."); - 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); + dirents.emplace_back(dirPath); // 区分目录和文件 vector dirPathList; vector filePathList; @@ -536,17 +515,72 @@ static napi_value RecoverDir(napi_env env, const string &dirPath) } } - // 新建目录并获取因为存在同名目录修改过名称的目录 - map dirPath2UpdatedNameMap = MakeAndFindUpdateNameDir(dirPathList); + // 记录还原前目录时间 + unordered_map> dir2Times; + + // 新建目录 + auto retMkdir = MkdirAndSaveTime(dirPathList, dir2Times); + if (retMkdir != ERRNO_NOERR) { + HILOG_ERROR("RecoverDir: No valid dirs found"); + NError(retMkdir).ThrowErr(env); + return nullptr; + } // 处理文件部分 - auto retRecoveFilePart = RecoverFilePart(filePathList, dirPath2UpdatedNameMap); + auto retRecoveFilePart = RecoverFilePart(filePathList); if (retRecoveFilePart != ERRNO_NOERR) { NError(retRecoveFilePart).ThrowErr(env); HILOG_ERROR("RecoverFilePart: Failed to Recover File in Dir."); return nullptr; } - + + // 更新新增目录时间 + for (auto &item : dir2Times) { + auto [oldAtime, oldMtime] = item.second; + UpdateFileTime(oldAtime, oldMtime, item.first); + } + + // 删除目录 + auto err = RmDirent(GetToDeletePath(dirPath, env)); + if (err) { + err.ThrowErr(env); + return nullptr; + } + + return NVal::CreateUndefined(env).val_; +} + +static napi_value RenameDir(napi_env env, const string &dirPath) +{ + string sourceFilePath = FindSourceFilePath(dirPath); + StatEntity statEntity; + if (!GetStat(dirPath, statEntity)) { + HILOG_ERROR("RecoverDir: Failed to get stat of dir."); + return nullptr; + } + unique_ptr rename_req = { + new uv_fs_t, fs_req_cleanup }; + if (!rename_req) { + HILOG_ERROR("RenameFile: Failed to request heap memory."); + NError(ENOMEM).ThrowErr(env); + return nullptr; + } + int ret = uv_fs_rename(nullptr, rename_req.get(), dirPath.c_str(), sourceFilePath.c_str(), nullptr); + if (ret < 0 && (string_view(uv_err_name(ret)) == "EXDEV")) { + return RecoverDir(env, dirPath); + } else if (ret) { + HILOG_ERROR("RenameFile: Failed to rename src, error: %{public}d", ret); + NError(ret).ThrowErr(env); + return nullptr; + } + + 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; + UpdateFileTime(acTime, modTime, sourceFilePath); // 删除目录 auto err = RmDirent(GetToDeletePath(dirPath, env)); if (err) { @@ -579,7 +613,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); @@ -590,12 +623,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(FileTrashNExporter::trashPath_) == 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; } @@ -603,14 +635,14 @@ 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; } if (!CheckDir(path)) { return RecoverFile(env, path); } - return RecoverDir(env, path); + return RenameDir(env, path); } napi_value FileTrashNExporter::CompletelyDelete(napi_env env, napi_callback_info info) @@ -648,12 +680,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(FileTrashNExporter::trashPath_) == 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 20de0023..cb016f83 100644 --- a/utils/file_util.h +++ b/utils/file_util.h @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -143,6 +144,34 @@ 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