From a98ae8f35704737e37920b7ddb516ea703a3dca7 Mon Sep 17 00:00:00 2001 From: Sam Atkins Date: Thu, 2 Mar 2023 15:39:07 +0000 Subject: [PATCH] LibCore: Expose file type from DirIterator Our `find` utility makes use of the `dirent::d_type` field for filtering results, which `Core::DirIterator` didn't expose. So, now it does. :^) We now store the name and type of the entry as the "next" value instead of just the name. The type is exposed as a `DirectoryEntry::Type` instead of a `DT_FOO` constant, so that we're not tied to posixy systems, and because proper enums are nice. :^) --- Userland/Libraries/LibCore/CMakeLists.txt | 1 + Userland/Libraries/LibCore/DirIterator.cpp | 35 +++++++++------ Userland/Libraries/LibCore/DirIterator.h | 5 ++- Userland/Libraries/LibCore/DirectoryEntry.cpp | 45 +++++++++++++++++++ Userland/Libraries/LibCore/DirectoryEntry.h | 34 ++++++++++++++ 5 files changed, 106 insertions(+), 14 deletions(-) create mode 100644 Userland/Libraries/LibCore/DirectoryEntry.cpp create mode 100644 Userland/Libraries/LibCore/DirectoryEntry.h diff --git a/Userland/Libraries/LibCore/CMakeLists.txt b/Userland/Libraries/LibCore/CMakeLists.txt index f75c9a2068..6dee12a65c 100644 --- a/Userland/Libraries/LibCore/CMakeLists.txt +++ b/Userland/Libraries/LibCore/CMakeLists.txt @@ -6,6 +6,7 @@ set(SOURCES DateTime.cpp DeprecatedFile.cpp Directory.cpp + DirectoryEntry.cpp DirIterator.cpp ElapsedTimer.cpp Event.cpp diff --git a/Userland/Libraries/LibCore/DirIterator.cpp b/Userland/Libraries/LibCore/DirIterator.cpp index fb17a82f05..3b58467397 100644 --- a/Userland/Libraries/LibCore/DirIterator.cpp +++ b/Userland/Libraries/LibCore/DirIterator.cpp @@ -1,5 +1,6 @@ /* * Copyright (c) 2018-2020, Andreas Kling + * Copyright (c) 2023, Sam Atkins * * SPDX-License-Identifier: BSD-2-Clause */ @@ -7,7 +8,6 @@ #include #include #include -#include namespace Core { @@ -49,40 +49,49 @@ bool DirIterator::advance_next() auto* de = readdir(m_dir); if (!de) { m_error = errno; - m_next = DeprecatedString(); + m_next.clear(); return false; } - m_next = de->d_name; - if (m_next.is_null()) + m_next = DirectoryEntry::from_dirent(*de); + + if (m_next->name.is_empty()) return false; - if (m_flags & Flags::SkipDots && m_next.starts_with('.')) + if (m_flags & Flags::SkipDots && m_next->name.starts_with('.')) continue; - if (m_flags & Flags::SkipParentAndBaseDir && (m_next == "." || m_next == "..")) + if (m_flags & Flags::SkipParentAndBaseDir && (m_next->name == "." || m_next->name == "..")) continue; - return !m_next.is_empty(); + return !m_next->name.is_empty(); } } bool DirIterator::has_next() { - if (!m_next.is_null()) + if (m_next.has_value()) return true; return advance_next(); } -DeprecatedString DirIterator::next_path() +Optional DirIterator::next() { - if (m_next.is_null()) + if (!m_next.has_value()) advance_next(); - auto tmp = m_next; - m_next = DeprecatedString(); - return tmp; + auto result = m_next; + m_next.clear(); + return result; +} + +DeprecatedString DirIterator::next_path() +{ + auto entry = next(); + if (entry.has_value()) + return entry->name; + return ""; } DeprecatedString DirIterator::next_full_path() diff --git a/Userland/Libraries/LibCore/DirIterator.h b/Userland/Libraries/LibCore/DirIterator.h index dd6c88141a..b1eb618505 100644 --- a/Userland/Libraries/LibCore/DirIterator.h +++ b/Userland/Libraries/LibCore/DirIterator.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2018-2020, Andreas Kling + * Copyright (c) 2023, Sam Atkins * * SPDX-License-Identifier: BSD-2-Clause */ @@ -7,6 +8,7 @@ #pragma once #include +#include #include #include @@ -30,6 +32,7 @@ public: int error() const { return m_error; } char const* error_string() const { return strerror(m_error); } bool has_next(); + Optional next(); DeprecatedString next_path(); DeprecatedString next_full_path(); int fd() const; @@ -37,7 +40,7 @@ public: private: DIR* m_dir = nullptr; int m_error = 0; - DeprecatedString m_next; + Optional m_next; DeprecatedString m_path; int m_flags; diff --git a/Userland/Libraries/LibCore/DirectoryEntry.cpp b/Userland/Libraries/LibCore/DirectoryEntry.cpp new file mode 100644 index 0000000000..a9c8d63c27 --- /dev/null +++ b/Userland/Libraries/LibCore/DirectoryEntry.cpp @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2023, Sam Atkins + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include "DirectoryEntry.h" +#include + +namespace Core { + +static DirectoryEntry::Type directory_entry_type_from_posix(unsigned char dt_constant) +{ + switch (dt_constant) { + case DT_UNKNOWN: + return DirectoryEntry::Type::Unknown; + case DT_FIFO: + return DirectoryEntry::Type::NamedPipe; + case DT_CHR: + return DirectoryEntry::Type::CharacterDevice; + case DT_DIR: + return DirectoryEntry::Type::Directory; + case DT_BLK: + return DirectoryEntry::Type::BlockDevice; + case DT_REG: + return DirectoryEntry::Type::File; + case DT_LNK: + return DirectoryEntry::Type::SymbolicLink; + case DT_SOCK: + return DirectoryEntry::Type::Socket; + case DT_WHT: + return DirectoryEntry::Type::Whiteout; + } + VERIFY_NOT_REACHED(); +} + +DirectoryEntry DirectoryEntry::from_dirent(dirent const& de) +{ + return DirectoryEntry { + .type = directory_entry_type_from_posix(de.d_type), + .name = de.d_name, + }; +}; + +} diff --git a/Userland/Libraries/LibCore/DirectoryEntry.h b/Userland/Libraries/LibCore/DirectoryEntry.h new file mode 100644 index 0000000000..266c79bf0d --- /dev/null +++ b/Userland/Libraries/LibCore/DirectoryEntry.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2023, Sam Atkins + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include + +struct dirent; + +namespace Core { + +struct DirectoryEntry { + enum class Type { + BlockDevice, + CharacterDevice, + Directory, + File, + NamedPipe, + Socket, + SymbolicLink, + Unknown, + Whiteout, + }; + Type type; + // FIXME: Once we have a special Path string class, use that. + DeprecatedString name; + + static DirectoryEntry from_dirent(dirent const&); +}; + +}