summaryrefslogtreecommitdiff
path: root/source/fud_directory.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/fud_directory.cpp')
-rw-r--r--source/fud_directory.cpp158
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