diff --git a/base/src/directory_ex.cpp b/base/src/directory_ex.cpp index 2ef101b7aef0e8bc408af51f191c668293150fb5..7df00e01e44c3bfdd051fc28937242bb41bbcad0 100644 --- a/base/src/directory_ex.cpp +++ b/base/src/directory_ex.cpp @@ -322,12 +322,11 @@ bool ChangeModeFile(const string& fileName, const mode_t& mode) return ChangeMode(fileName, mode); } -bool ChangeModeDirectory(const string& path, const mode_t& mode) +bool ChangeModeDirectoryInternal(DIR *dir,const mode_t& mode) { - string subPath; bool ret = true; - DIR *dir = opendir(path.c_str()); - if (dir == nullptr) { + int rootFd = dirfd(dir); + if (rootFd < 0) { return false; } @@ -336,24 +335,62 @@ bool ChangeModeDirectory(const string& path, const mode_t& mode) if (ptr == nullptr) { break; } + const char *name = ptr->d_name; // current dir or parent dir - if (strcmp(ptr->d_name, ".") == 0 || strcmp(ptr->d_name, "..") == 0) { + if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) { continue; } - subPath = IncludeTrailingPathDelimiter(path) + string(ptr->d_name); + if (ptr->d_type == DT_DIR) { - ret = ChangeModeDirectory(subPath, mode); + 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; + continue; + } + DIR *subDir = fdopendir(subFd); + if (subDir == nullptr) { + close(subFd); + UTILS_LOGD("Failed in fdopendir: %{public}s", strerror(errno)); + ret = false; + continue; + } + ret = ChangeModeDirectoryInternal(subDir, mode); + closedir(subDir); + if (fchmodat(rootFd, name, mode, 0) < 0) { + UTILS_LOGD("Couldn't fchmodat subDir %{public}s: %{public}s", name, strerror(errno)); + ret = false; + continue; + } } else { - if (access(subPath.c_str(), F_OK) == 0) { - if (!ChangeMode(subPath, mode)) { - UTILS_LOGD("Failed to exec ChangeMode"); - closedir(dir); + if (faccessat(rootFd, name, F_OK, AT_SYMLINK_NOFOLLOW) == 0) { + if (fchmodat(rootFd, name, mode, 0) < 0) { + UTILS_LOGD("Couldn't fchmodat subFile %{public}s: %{public}s", name, strerror(errno)); return false; } + } else { + UTILS_LOGD("Access to file: %{public}s is failed", name); + return false; } } } + + return ret; +} + +bool ChangeModeDirectory(const string& path, const mode_t& mode) +{ + 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 = ChangeModeDirectoryInternal(dir, mode); + if (!ret) { + UTILS_LOGD("Failed to ChangeMode some subfile under path: %{public}s", path.c_str()); + } closedir(dir); string currentPath = ExcludeTrailingPathDelimiter(path); if (access(currentPath.c_str(), F_OK) == 0) {