Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit

Permalink
Duplicate the directory fd in fml::VisitFiles
Browse files Browse the repository at this point in the history
The fd passed to fdopendir will be unusable afterward.  Using a duplicate
preserves the validity of the original directory fd passed to VisitFiles.

Fixes flutter/flutter#43844
  • Loading branch information
jason-simmons committed Oct 31, 2019
1 parent 6f44e9f commit 652edce
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 7 deletions.
21 changes: 14 additions & 7 deletions fml/platform/posix/file_posix.cc
Original file line number Diff line number Diff line change
Expand Up @@ -223,27 +223,34 @@ 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)) {
return false;
}
}
}

return true;
}

Expand Down
4 changes: 4 additions & 0 deletions fml/unique_fd.cc
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ void UniqueFDTraits::Free(int fd) {
close(fd);
}

void UniqueDirTraits::Free(DIR* dir) {
closedir(dir);
}

} // namespace os_unix

#endif // OS_WIN
Expand Down
8 changes: 8 additions & 0 deletions fml/unique_fd.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

#else // OS_WIN

#include <dirent.h>
#include <unistd.h>

#endif // OS_WIN
Expand Down Expand Up @@ -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
Expand All @@ -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

Expand Down

0 comments on commit 652edce

Please sign in to comment.