diff --git a/Userland/Libraries/LibCore/DirIterator.cpp b/Userland/Libraries/LibCore/DirIterator.cpp index 1151bf7b71..ea64c4e38e 100644 --- a/Userland/Libraries/LibCore/DirIterator.cpp +++ b/Userland/Libraries/LibCore/DirIterator.cpp @@ -8,6 +8,8 @@ #include #include #include +#include +#include namespace Core { @@ -60,6 +62,18 @@ bool DirIterator::advance_next() m_next = DirectoryEntry::from_stat(m_dir, *de); #else m_next = DirectoryEntry::from_dirent(*de); + + // dirent structures from readdir aren't guaranteed to contain valid file types, + // as it is possible that the underlying filesystem doesn't keep track of those. + if (m_next->type == DirectoryEntry::Type::Unknown && !m_next->name.is_empty()) { + struct stat statbuf; + if (fstatat(dirfd(m_dir), de->d_name, &statbuf, AT_SYMLINK_NOFOLLOW) < 0) { + m_error = Error::from_errno(errno); + dbgln("DirIteration error: {}", m_error.value()); + return false; + } + m_next->type = DirectoryEntry::directory_entry_type_from_stat(statbuf.st_mode); + } #endif if (m_next->name.is_empty()) diff --git a/Userland/Libraries/LibCore/DirectoryEntry.cpp b/Userland/Libraries/LibCore/DirectoryEntry.cpp index 8790c8ef6a..c0f9391683 100644 --- a/Userland/Libraries/LibCore/DirectoryEntry.cpp +++ b/Userland/Libraries/LibCore/DirectoryEntry.cpp @@ -9,7 +9,7 @@ namespace Core { -static DirectoryEntry::Type directory_entry_type_from_stat(mode_t st_mode) +DirectoryEntry::Type DirectoryEntry::directory_entry_type_from_stat(mode_t st_mode) { switch (st_mode & S_IFMT) { case S_IFIFO: diff --git a/Userland/Libraries/LibCore/DirectoryEntry.h b/Userland/Libraries/LibCore/DirectoryEntry.h index 7244ec83dd..c2927435ce 100644 --- a/Userland/Libraries/LibCore/DirectoryEntry.h +++ b/Userland/Libraries/LibCore/DirectoryEntry.h @@ -28,6 +28,7 @@ struct DirectoryEntry { ByteString name; ino_t inode_number; + static Type directory_entry_type_from_stat(mode_t st_mode); static DirectoryEntry from_dirent(dirent const&); static DirectoryEntry from_stat(DIR*, dirent const&); };