未验证 提交 7fe505ca 编写于 作者: J Jason Simmons 提交者: GitHub

Duplicate the directory fd in fml::VisitFiles (#13448)

The fd passed to fdopendir will be unusable afterward.  Using a duplicate
preserves the validity of the original directory fd passed to VisitFiles.

Fixes https://github.com/flutter/flutter/issues/43844
上级 c63aefd2
......@@ -223,20 +223,26 @@ bool WriteAtomically(const fml::UniqueFD& base_directory,
}
bool VisitFiles(const fml::UniqueFD& directory, FileVisitor visitor) {
// We cannot call closedir(dir) because it will also close the corresponding
// UniqueFD, and later reference to that UniqueFD will fail. Also, we don't
// have to call closedir because UniqueFD will call close on its destructor.
DIR* dir = ::fdopendir(directory.get());
if (dir == nullptr) {
fml::UniqueFD dup_fd(dup(directory.get()));
if (!dup_fd.is_valid()) {
FML_DLOG(ERROR) << "Can't dup the directory fd. Error: " << strerror(errno);
return true; // continue to visit other files
}
fml::UniqueDir dir(::fdopendir(dup_fd.get()));
if (!dir.is_valid()) {
FML_DLOG(ERROR) << "Can't open the directory. Error: " << strerror(errno);
return true; // continue to visit other files
}
// The directory fd will be closed by `closedir`.
(void)dup_fd.release();
// Without `rewinddir`, `readir` will directly return NULL (end of dir is
// reached) after a previuos `VisitFiles` call for the same `const
// fml::UniqueFd& directory`.
rewinddir(dir);
while (dirent* ent = readdir(dir)) {
rewinddir(dir.get());
while (dirent* ent = readdir(dir.get())) {
std::string filename = ent->d_name;
if (filename != "." && filename != "..") {
if (!visitor(directory, filename)) {
......@@ -244,6 +250,7 @@ bool VisitFiles(const fml::UniqueFD& directory, FileVisitor visitor) {
}
}
}
return true;
}
......
......@@ -27,6 +27,10 @@ void UniqueFDTraits::Free(int fd) {
close(fd);
}
void UniqueDirTraits::Free(DIR* dir) {
closedir(dir);
}
} // namespace os_unix
#endif // OS_WIN
......
......@@ -14,6 +14,7 @@
#else // OS_WIN
#include <dirent.h>
#include <unistd.h>
#endif // OS_WIN
......@@ -43,6 +44,12 @@ struct UniqueFDTraits {
static void Free(int fd);
};
struct UniqueDirTraits {
static DIR* InvalidValue() { return nullptr; }
static bool IsValid(DIR* value) { return value != nullptr; }
static void Free(DIR* dir);
};
} // namespace os_unix
#endif // OS_WIN
......@@ -56,6 +63,7 @@ using UniqueFD = UniqueObject<HANDLE, internal::os_win::UniqueFDTraits>;
#else // OS_WIN
using UniqueFD = UniqueObject<int, internal::os_unix::UniqueFDTraits>;
using UniqueDir = UniqueObject<DIR*, internal::os_unix::UniqueDirTraits>;
#endif // OS_WIN
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册