diff options
author | Dominick Allen <djallen@librehumanitas.org> | 2024-10-28 23:49:50 -0500 |
---|---|---|
committer | Dominick Allen <djallen@librehumanitas.org> | 2024-10-28 23:49:50 -0500 |
commit | afc11065bb151349090d8ae89cb61d1c35bdddae (patch) | |
tree | 41a7133a6e143d6333594d899556831b5a914fc1 /source/fud_file.cpp | |
parent | c3cf6df863828798ed8230b0f0966bcf3b2d08dd (diff) |
Prepare for new SSO.
Diffstat (limited to 'source/fud_file.cpp')
-rw-r--r-- | source/fud_file.cpp | 123 |
1 files changed, 114 insertions, 9 deletions
diff --git a/source/fud_file.cpp b/source/fud_file.cpp index e27a46d..8dab031 100644 --- a/source/fud_file.cpp +++ b/source/fud_file.cpp @@ -82,6 +82,7 @@ FileResult RegularFile::open( return FudStatus::Partial; case ENOENT: return FudStatus::NotFound; + case EBADF: case EFBIG: case EOVERFLOW: case EINVAL: @@ -117,17 +118,100 @@ FileResult RegularFile::open( return file; } -/* - static FileResult RegularFile::create( - StringView filename, - FileAccessMode mode, - OpenFlags flags, - bool exclusive, - Option<int> dirFdOption, - Allocator* allocator = &globalFudAllocator); +FileResult RegularFile::create( + StringView filename, + FileAccessMode mode, + OpenFlags flags, + Permissions permissions, + bool exclusive, + Option<int> dirFdOption, + Allocator* allocator) { + if (allocator == nullptr) { + return FudStatus::NullPointer; + } + + if (!filename.nullTerminated()) { + return FudStatus::ArgumentInvalid; + } + + int dirFd = dirFdOption.valueOr(AT_FDCWD); + + RegularFile file{}; + + uint32_t openFlags = 0; + switch (mode) { + case FileAccessMode::Read: + openFlags = O_RDONLY; + break; + case FileAccessMode::Write: + openFlags = O_WRONLY; + break; + case FileAccessMode::ReadWrite: + openFlags = O_RDWR; + break; + default: + return FudStatus::ArgumentInvalid; + } + + if (flags.hasFlag(OpenFlagEnum::Append) && flags.hasFlag(OpenFlagEnum::Truncate)) { + return FudStatus::OperationInvalid; + } + + openFlags |= flags.flags() | O_CREAT | (O_EXCL * static_cast<uint8_t>(exclusive)); + + open_how openHow{}; + zeroObject(openHow); + openHow.flags = openFlags; + openHow.resolve = RESOLVE_NO_SYMLINKS; + openHow.mode = permissions.mode(); + + auto status = syscall(SYS_openat2, dirFd, filename.data(), &openHow, sizeof(openHow)); + if (status == -1) { + if constexpr (EAGAIN != EWOULDBLOCK && status == EWOULDBLOCK) { + return FudStatus::Partial; + } + switch (errno) { + case ETXTBSY: + case EAGAIN: + return FudStatus::Partial; + case EBADF: + case EFBIG: + case EOVERFLOW: + case EINVAL: + case EISDIR: + case ENAMETOOLONG: + return FudStatus::ArgumentInvalid; + case EROFS: + case EACCES: + case EPERM: + return FudStatus::PermissionDenied; + case EDQUOT: + case ENOENT: + case ELOOP: + case EXDEV: + case ENFILE: + case E2BIG: + default: + return FudStatus::Failure; + } + } + fudAssert(status <= std::numeric_limits<decltype(file.m_fd)>::max()); + file.m_fd = static_cast<decltype(file.m_fd)>(status); + + using Stat = struct stat; + Stat sBuffer{}; + auto fStatus = fstat(file.m_fd, &sBuffer); + if (fStatus == -1) { + return FudStatus::Failure; + } + + if ((sBuffer.st_mode & S_IFMT) != S_IFREG) { + return FudStatus::ObjectInvalid; + } + + return file; } -*/ RegularFile::~RegularFile() { @@ -198,4 +282,25 @@ FudStatus RegularFile::close() return status; } +Result<size_t, FudStatus> RegularFile::size() const +{ + auto fileSize = lseek(m_fd, 0, SEEK_END); + if (fileSize == -1) { + switch (errno) { + case EBADF: + case ESPIPE: + return FudStatus::ObjectInvalid; + default: + return FudStatus::Failure; + } + } + + auto seekBegin = lseek(m_fd, 0, SEEK_SET); + if (seekBegin == -1) { + return FudStatus::Failure; + } + + return static_cast<size_t>(fileSize); +} + } // namespace fud |