diff --git a/base/src/directory_ex.cpp b/base/src/directory_ex.cpp index 2ef101b7aef0e8bc408af51f191c668293150fb5..310f60187593552f740481f89e89bb5f8dd0c520 100644 --- a/base/src/directory_ex.cpp +++ b/base/src/directory_ex.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include "securec.h" #include "unistd.h" #include "utils_log.h" @@ -195,76 +196,88 @@ bool ForceCreateDirectory(const string& path) return access(path.c_str(), F_OK) == 0; } -bool ForceRemoveDirectoryInternal(DIR *dir) +struct DirectoryNode { + DIR *dir; + int currentFd; + const char *name; +}; + +bool ForceRemoveDirectory(const string& path) { bool ret = true; - int rootFd = dirfd(dir); - if (rootFd < 0) { - UTILS_LOGD("Failed to get dirfd, fd: %{public}d: %{public}s ", rootFd, strerror(errno)); + DIR *dir = opendir(path.c_str()); + if (dir == nullptr) { + UTILS_LOGD("Failed to open root dir: %{public}s: %{public}s ", path.c_str(), 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) { + stack traversStack; + stack removeStack; + traversStack.push(dir); + while (!traversStack.empty()) { + DIR *currentDir = traversStack.top(); + traversStack.pop(); + DirectoryNode node; + int currentFd = dirfd(currentDir); + if (currentFd < 0) { + UTILS_LOGD("Failed to get dirfd, fd: %{public}d: %{public}s ", currentFd, strerror(errno)); + ret = false; continue; } - - if (ptr->d_type == DT_DIR) { - int subFd = openat(rootFd, name, O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC); - if (subFd < 0) { - UTILS_LOGD("Failed in subFd openat: %{public}s ", name); - ret = false; + struct dirent *ptr = readdir(currentDir); + while (ptr != nullptr) { + struct dirent *currentPtr = ptr; + ptr = readdir(currentDir); + const char *name = currentPtr->d_name; + // current dir or parent dir + if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) { continue; } - DIR *subDir = fdopendir(subFd); - if (subDir == nullptr) { - close(subFd); - UTILS_LOGD("Failed in fdopendir: %{public}s", strerror(errno)); - ret = false; - continue; - } - ret = ForceRemoveDirectoryInternal(subDir); - closedir(subDir); - if (unlinkat(rootFd, name, AT_REMOVEDIR) < 0) { - UTILS_LOGD("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_LOGD("Couldn't unlinkat subFile %{public}s: %{public}s", name, strerror(errno)); - return false; + if (currentPtr->d_type == DT_DIR) { + int subFd = openat(currentFd, name, O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC); + if (subFd < 0) { + UTILS_LOGD("Failed in subFd openat: %{public}s ", name); + ret = false; + continue; + } + DIR *subDir = fdopendir(subFd); + if (subDir == nullptr) { + close(subFd); + UTILS_LOGD("Failed in fdopendir: %{public}s", strerror(errno)); + ret = false; + continue; } + node.dir = subDir; + node.currentFd = currentFd; + node.name = name; + removeStack.push(node); + traversStack.push(subDir); } else { - UTILS_LOGD("Access to file: %{public}s is failed", name); - return false; + if (faccessat(currentFd, name, F_OK, AT_SYMLINK_NOFOLLOW) == 0) { + if (unlinkat(currentFd, name, 0) < 0) { + UTILS_LOGD("Couldn't unlinkat subFile %{public}s: %{public}s", name, strerror(errno)); + ret = false; + break; + } + } else { + UTILS_LOGD("Access to file: %{public}s is failed", name); + ret = false; + break; + } } } } - - return ret; -} - -bool ForceRemoveDirectory(const string& path) -{ - bool ret = true; - DIR *dir = opendir(path.c_str()); - if (dir == nullptr) { - UTILS_LOGD("Failed to open root dir: %{public}s: %{public}s ", path.c_str(), strerror(errno)); - return false; - } - ret = ForceRemoveDirectoryInternal(dir); if (!ret) { UTILS_LOGD("Failed to remove some subfile under path: %{public}s", path.c_str()); } + while (!removeStack.empty()) { + DirectoryNode node = removeStack.top(); + removeStack.pop(); + closedir(node.dir); + if (unlinkat(node.currentFd, node.name, AT_REMOVEDIR) < 0) { + UTILS_LOGD("Couldn't unlinkat subDir %{public}s: %{public}s", node.name, strerror(errno)); + continue; + } + } closedir(dir); if (faccessat(AT_FDCWD, path.c_str(), F_OK, AT_SYMLINK_NOFOLLOW) == 0) { if (remove(path.c_str()) != 0) { @@ -272,7 +285,6 @@ bool ForceRemoveDirectory(const string& path) return false; } } - return faccessat(AT_FDCWD, path.c_str(), F_OK, AT_SYMLINK_NOFOLLOW) != 0; }