From 37180227bbfb7d4a85ca646398e70816f74e9bc9 Mon Sep 17 00:00:00 2001 From: wujianlin Date: Fri, 11 Oct 2024 10:06:43 +0800 Subject: [PATCH] Added the ForceRemoveDirectoryBMS interface Issue:https://gitee.com/openharmony/commonlibrary_c_utils/issues/IAW75H?from=project-issue Signed-off-by: wujianlin --- base/include/directory_ex.h | 2 + base/src/directory_ex.cpp | 81 +++++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+) diff --git a/base/include/directory_ex.h b/base/include/directory_ex.h index 7cf9482..df529b2 100644 --- a/base/include/directory_ex.h +++ b/base/include/directory_ex.h @@ -123,6 +123,8 @@ bool ForceCreateDirectory(const std::string& path); */ bool ForceRemoveDirectory(const std::string& path); +bool ForceRemoveDirectoryBMS(const std::string& path); + /** * @brief Removes the file specified by fileName. * diff --git a/base/src/directory_ex.cpp b/base/src/directory_ex.cpp index bac6356..22958e4 100644 --- a/base/src/directory_ex.cpp +++ b/base/src/directory_ex.cpp @@ -324,6 +324,87 @@ bool ForceRemoveDirectory(const string& path) return faccessat(AT_FDCWD, path.c_str(), F_OK, AT_SYMLINK_NOFOLLOW) != 0; } +bool ForceRemoveDirectoryInternal(DIR *dir) +{ + bool ret = true; + int rootFd = dirfd(dir); + if (rootFd < 0) { + UTILS_LOGE("BMS: Failed to get dirfd, fd: %{public}d: %{public}s ", rootFd, strerror(errno)); + return false; + } + + while (true) { + struct dirent *ptr = readdir(dir); + if (ptr == nullptr) { + break; + } + const char *name = ptr -> d_name; + + // current dir or parent dir + if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) { + continue; + } + + if (ptr->d_type == DT_DIR) { + int subFd = openat(rootFd, name, O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC); + if (subFd < 0) { + UTILS_LOGE("BMS: Failed in subFd openat: %{public}s, errno: %{public}s ", name, strerror(errno)); + ret = false; + continue; + } + DIR *subDir = fdopendir(subFd); + if (subDir == nullptr) { + close(subFd); + UTILS_LOGE("BMS: Failed in fdopendir: %{public}s", strerror(errno)); + ret = false; + continue; + } + ret = ForceRemoveDirectoryInternal(subDir); + closedir(subDir); + if (unlinkat(rootFd, name, AT_REMOVEDIR) < 0) { + UTILS_LOGE("BMS: Couldn't unlinkat subDir %{public}s: %{public}s", name, strerror(errno)); + ret = false; + continue; + } + } else { + if (faccessat(rootFd, name, F_OK, AT_SYMLINK_NOFOLLOW) == 0) { + if (unlinkat(rootFd, name, 0) < 0) { + UTILS_LOGE("BMS: Couldn't unlinkat subFile %{public}s: %{public}s", name, strerror(errno)); + return false; + } + } else { + UTILS_LOGE("BMS: Access to file: %{public}s is failed, errno: %{public}s", name, strerror(errno)); + return false; + } + } + } + + return ret; +} + +bool ForceRemoveDirectoryBMS(const std::string& path) +{ + bool ret = true; + DIR *dir = opendir(path.c_str()); + if (dir == nullptr) { + UTILS_LOGE("BMS: Failed to open root dir: %{public}s: %{public}s ", path.c_str(), strerror(errno)); + return false; + } + ret = ForceRemoveDirectoryInternal(dir); + if (!ret) { + UTILS_LOGE("BMS: Failed to remove some subfile under path: %{public}s", path.c_str()); + } + closedir(dir); + if (faccessat(AT_FDCWD, path.c_str(), F_OK, AT_SYMLINK_NOFOLLOW) == 0) { + if (remove(path.c_str()) != 0) { + UTILS_LOGE("BMS: Failed to remove root dir: %{public}s: %{public}s ", path.c_str(), strerror(errno)); + return false; + } + } + + return faccessat(AT_FDCWD, path.c_str(), F_OK, AT_SYMLINK_NOFOLLOW) != 0; +} + bool RemoveFile(const string& fileName) { if (access(fileName.c_str(), F_OK) == 0) { -- Gitee