diff options
author | Dominick Allen <djallen@librehumanitas.org> | 2024-09-28 11:14:31 -0500 |
---|---|---|
committer | Dominick Allen <djallen@librehumanitas.org> | 2024-09-28 11:14:31 -0500 |
commit | b6967c8a9190efa4e9128850fa723fe3ea3140f7 (patch) | |
tree | 101be12055abd27968fce2666d573c80f8afe22d /source/fud_directory.cpp | |
parent | 987466c74332025fae74d196ff680a57ccb247a2 (diff) |
Expand directory interface, remove FileStatus for FudStatus.
Diffstat (limited to 'source/fud_directory.cpp')
-rw-r--r-- | source/fud_directory.cpp | 158 |
1 files changed, 100 insertions, 58 deletions
diff --git a/source/fud_directory.cpp b/source/fud_directory.cpp index 39f2e10..99f3600 100644 --- a/source/fud_directory.cpp +++ b/source/fud_directory.cpp @@ -23,6 +23,57 @@ namespace fud { +using CStat = struct stat; +struct Stat : public CStat {}; + +Result<DirectoryEntry, FudStatus> DirectoryEntry::fromStat(const String& name, const Stat& statBuffer) +{ + using RetType = Result<DirectoryEntry, FudStatus>; + static_assert(std::is_same_v<decltype(statBuffer.st_size), long>); + static_assert(sizeof(decltype(statBuffer.st_size)) <= sizeof(size_t)); + + static_assert(std::is_same_v<decltype(statBuffer.st_nlink), unsigned long>); + static_assert(sizeof(decltype(statBuffer.st_nlink)) <= sizeof(size_t)); + + size_t size{0}; + if (statBuffer.st_size < 0) { + return RetType::error(FudStatus::Failure); + } else { + size = static_cast<size_t>(statBuffer.st_size); + } + + DirectoryEntryType entryType; + switch (statBuffer.st_mode & S_IFMT) { + case S_IFBLK: + entryType = DirectoryEntryType::Block; + break; + case S_IFCHR: + entryType = DirectoryEntryType::Character; + break; + case S_IFDIR: + entryType = DirectoryEntryType::Directory; + break; + case S_IFIFO: + entryType = DirectoryEntryType::NamedPipe; + break; + case S_IFLNK: + entryType = DirectoryEntryType::SymbolicLink; + break; + case S_IFREG: + entryType = DirectoryEntryType::RegularFile; + break; + case S_IFSOCK: + entryType = DirectoryEntryType::UnixSocket; + break; + default: + entryType = DirectoryEntryType::Unknown; + break; + } + + return RetType::okay( + DirectoryEntry{name, size, static_cast<size_t>(statBuffer.st_nlink), statBuffer.st_mtime, entryType}); +} + Directory::Directory(String name) : m_name{name} { if (!m_name.valid()) { @@ -81,11 +132,45 @@ Directory::~Directory() } } +bool Directory::valid() const +{ + return m_directory != nullptr && m_dirFd != -1; +} + +Result<DirectoryEntry, FudStatus> Directory::info() +{ + using RetType = Result<DirectoryEntry, FudStatus>; + + if (!valid()) { + m_status = FudStatus::ObjectInvalid; + return RetType::error(m_status); + } + + Stat statBuffer{}; + auto status = fstat(m_dirFd, &statBuffer); + if (status == -1) { + m_errorCode = errno; + m_status = FudStatus::Failure; + return RetType::error(m_status); + } + + auto retValue = DirectoryEntry::fromStat(m_name, statBuffer); + + if (retValue.isOkay()) { + m_errorCode = 0; + m_status = FudStatus::Success; + } else { + m_status = retValue.getError(); + } + + return retValue; +} + Result<std::optional<DirectoryEntry>, FudStatus> Directory::getNextEntry() { using RetType = Result<std::optional<DirectoryEntry>, FudStatus>; - if (m_directory == nullptr || m_dirFd == -1) { + if (!valid()) { m_status = FudStatus::ObjectInvalid; return RetType::error(m_status); } @@ -102,8 +187,8 @@ Result<std::optional<DirectoryEntry>, FudStatus> Directory::getNextEntry() } } - const char* entryName = dirEntry->d_name; - if (entryName == nullptr) { + const char* entryNameCString = dirEntry->d_name; + if (entryNameCString == nullptr) { m_errorCode = -1; m_status = FudStatus::NullPointer; return RetType::error(m_status); @@ -111,82 +196,39 @@ Result<std::optional<DirectoryEntry>, FudStatus> Directory::getNextEntry() m_errorCode = 0; - using Stat = struct stat; Stat statBuffer{}; auto flags = 0; - auto status = fstatat(m_dirFd, entryName, &statBuffer, flags); + auto status = fstatat(m_dirFd, entryNameCString, &statBuffer, flags); if (status == -1) { m_errorCode = errno; m_status = FudStatus::Failure; return RetType::error(m_status); } - DirectoryEntryType entryType; - switch (statBuffer.st_mode & S_IFMT) { - case S_IFBLK: - entryType = DirectoryEntryType::Block; - break; - case S_IFCHR: - entryType = DirectoryEntryType::Character; - break; - case S_IFDIR: - entryType = DirectoryEntryType::Directory; - break; - case S_IFIFO: - entryType = DirectoryEntryType::NamedPipe; - break; - case S_IFLNK: - entryType = DirectoryEntryType::SymbolicLink; - break; - case S_IFREG: - entryType = DirectoryEntryType::RegularFile; - break; - case S_IFSOCK: - entryType = DirectoryEntryType::UnixSocket; - break; - default: - entryType = DirectoryEntryType::Unknown; - break; - } - - static_assert(std::is_same_v<decltype(statBuffer.st_size), long>); - static_assert(sizeof(decltype(statBuffer.st_size)) <= sizeof(size_t)); + auto entryName = String{entryNameCString}; + auto retValue = DirectoryEntry::fromStat(entryName, statBuffer); - size_t size{0}; - if (statBuffer.st_size < 0) { - size = SIZE_MAX; - } else { - size = static_cast<size_t>(statBuffer.st_size); + if (retValue.isOkay()) { + m_errorCode = 0; + m_status = FudStatus::Success; + return RetType::okay(retValue.getOkay()); } - static_assert(std::is_same_v<decltype(statBuffer.st_nlink), unsigned long>); - static_assert(sizeof(decltype(statBuffer.st_nlink)) <= sizeof(size_t)); - - DirectoryEntry entry{ - String{dirEntry->d_name}, - size, - static_cast<size_t>(statBuffer.st_nlink), - statBuffer.st_mtime, - entryType}; - - if (!entry.name.valid()) { - m_status = FudStatus::StringInvalid; - return RetType::error(m_status); - } - - m_status = FudStatus::Success; - return RetType::okay(std::move(entry)); + m_status = retValue.getError(); + return RetType::error(retValue.getError()); } FudStatus Directory::reset() { + if (!valid()) { + } if (m_directory != nullptr) { rewinddir(m_directory); } else { m_status = FudStatus::ObjectInvalid; return m_status; } - return FudStatus::NotImplemented; + return FudStatus::Success; } } // namespace fud |