diff --git a/base/include/directory_ex.h b/base/include/directory_ex.h index 7cf9482e04660a0dbfb6d71f583d3f1d7b808385..df529b2327a3f1218438deb4d952096d8e9f833d 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 bac6356d160f932f8333e50d52f09df9d903eb7f..22958e4ac56d91b271be4e2112e2eed561cea55d 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) {