[libc-commits] [libc] feat(filemode): implement class and helper functions to handle file modes for an opened file (PR #220906)
David Dada via libc-commits
libc-commits at lists.llvm.org
Wed Sep 9 12:49:17 PDT 2026
https://github.com/obadafidii updated https://github.com/llvm/llvm-project/pull/220906
>From e3dc3a646ef6c422e75810881826e211aebb7a3b Mon Sep 17 00:00:00 2001
From: tdadadavid <davidtofunmidada at gmail.com>
Date: Thu, 3 Sep 2026 13:21:11 +0100
Subject: [PATCH 01/16] feat(filemode): implement class and helper functions to
handle file modes for an opened file
Signed-off-by: tdadadavid <davidtofunmidada at gmail.com>
---
libc/src/__support/File/file_mode.h | 125 ++++++++++++++++++++++++++++
1 file changed, 125 insertions(+)
create mode 100644 libc/src/__support/File/file_mode.h
diff --git a/libc/src/__support/File/file_mode.h b/libc/src/__support/File/file_mode.h
new file mode 100644
index 0000000000000..6b837ea46f652
--- /dev/null
+++ b/libc/src/__support/File/file_mode.h
@@ -0,0 +1,125 @@
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_FILE_FILE_MODE_H
+#define LLVM_LIBC_SRC___SUPPORT_FILE_FILE_MODE_H
+#include <cstdint>
+
+namespace LIBC_NAMESPACE_DECL {
+
+// FileMode class handles everything regarding the mode of the file, be it's opening mode or content type.
+class FileMode {
+public:
+ // FileMode constructor accepts the mode string as an argument.
+ // It performs validation against several rules and records the `file_mode` property to
+ // the specific mode.
+ explicit FileMode(const char *mode) : file_mode_(0) {
+ // First character in |mode| should be 'a', 'r' or 'w'.
+ if (*mode != 'a' && *mode != 'r' && *mode != 'w')
+ return;
+
+ // There should be exactly one main mode ('a', 'r' or 'w') character.
+ // If there are more than one main mode characters listed, then
+ // we will consider |mode| as incorrect and return 0;
+ int main_mode_count = 0;
+
+ for (; *mode != '\0'; ++mode) {
+ switch (*mode) {
+ case 'r':
+ file_mode_ |= static_cast<Mode>(OpenMode::READ);
+ ++main_mode_count;
+ break;
+ case 'w':
+ file_mode_ |= static_cast<Mode>(OpenMode::WRITE);
+ ++main_mode_count;
+ break;
+ case '+':
+ file_mode_ |= static_cast<Mode>(OpenMode::PLUS);
+ break;
+ case 'b':
+ file_mode_ |= static_cast<Mode>(ContentType::BINARY);
+ break;
+ case 'a':
+ file_mode_ |= static_cast<Mode>(OpenMode::APPEND);
+ ++main_mode_count;
+ break;
+ case 'x':
+ file_mode_ |= static_cast<Mode>(CreateType::EXCLUSIVE);
+ break;
+ default:
+ file_mode_ = 0;
+ }
+ }
+
+ if (main_mode_count != 1)
+ file_mode_ = 0;
+ }
+
+ // helper function to show if file allows writing
+ bool write_allowed() const {
+ return (file_mode_ & static_cast<Mode>(OpenMode::WRITE)) != 0;
+ }
+
+ // helper function to show if file allows reading
+ bool read_allowed() const {
+ return (file_mode_ & static_cast<Mode>(OpenMode::READ)) != 0;
+ }
+
+ // helper function to show if file allows appending
+ bool append_allowed() const {
+ return (file_mode_ & static_cast<Mode>(OpenMode::APPEND)) != 0;
+ }
+
+ // helper function to denote if the file is in binary format.
+ bool is_binary_format() const {
+ return (file_mode_ & static_cast<Mode>(ContentType::BINARY)) != 0;
+ }
+
+ // '+' means update is allowed
+ // TODO: ask michael if I need to give it a better name like "update_allowed" or just continue with the
+ // old convention.
+ bool is_plus() const {
+ return (file_mode_ & static_cast<Mode>(OpenMode::PLUS)) != 0;
+ }
+
+ // checks if a file was created for writing
+ bool is_exclusive_create() const {
+ return (file_mode_ & static_cast<Mode>(CreateType::EXCLUSIVE)) != 0;
+ }
+
+private:
+ // Mode is a generic or abstract mode bit for all kinds of modes
+ // (open-mode, 'content-mode', 'create-modes')
+ using Mode = uint32_t;
+
+ // Denotes the mode of the file.
+ //
+ // The three different types of flags below are to be used with '|' operator.
+ // Their values correspond to mutually exclusive bits in a 32-bit unsigned
+ // integer value. A flag set can include both READ and WRITE if the file
+ // is opened in update mode (ie. if the file was opened with a '+' the mode
+ // string.)
+ enum class OpenMode: Mode {
+ READ = 0x1,
+ WRITE = 0x2,
+ APPEND = 0x4,
+ PLUS = 0x8,
+ };
+
+ // Denotes a file opened in binary mode (which is specified by including
+ // the 'b' character in teh mode string.)
+ enum class ContentType: Mode {
+ BINARY = 0x10,
+ };
+
+ // Denotes a file to be created for writing.
+ enum class CreateType: Mode {
+ EXCLUSIVE = 0x100,
+ };
+
+ // This property tracks the mode for the particular file instance (i.e currently opened file)
+ int file_mode_;
+};
+
+
+}
+
+#endif // LLVM_LIBC_SRC___SUPPORT_FILE_FILE_MODE_H
>From b0470fe313766fcb4fac92b63d41d39314a90f75 Mon Sep 17 00:00:00 2001
From: tdadadavid <davidtofunmidada at gmail.com>
Date: Thu, 3 Sep 2026 14:08:49 +0100
Subject: [PATCH 02/16] feat(lint): lint file mode class to conform to
standards
Signed-off-by: tdadadavid <davidtofunmidada at gmail.com>
---
libc/src/__support/File/file_mode.h | 23 ++++++++++++-----------
1 file changed, 12 insertions(+), 11 deletions(-)
diff --git a/libc/src/__support/File/file_mode.h b/libc/src/__support/File/file_mode.h
index 6b837ea46f652..707a448c5955d 100644
--- a/libc/src/__support/File/file_mode.h
+++ b/libc/src/__support/File/file_mode.h
@@ -5,12 +5,13 @@
namespace LIBC_NAMESPACE_DECL {
-// FileMode class handles everything regarding the mode of the file, be it's opening mode or content type.
+// FileMode class handles everything regarding the mode of the file, be it's
+// opening mode or content type.
class FileMode {
public:
// FileMode constructor accepts the mode string as an argument.
- // It performs validation against several rules and records the `file_mode` property to
- // the specific mode.
+ // It performs validation against several rules and records the `file_mode`
+ // property to the specific mode.
explicit FileMode(const char *mode) : file_mode_(0) {
// First character in |mode| should be 'a', 'r' or 'w'.
if (*mode != 'a' && *mode != 'r' && *mode != 'w')
@@ -74,8 +75,8 @@ class FileMode {
}
// '+' means update is allowed
- // TODO: ask michael if I need to give it a better name like "update_allowed" or just continue with the
- // old convention.
+ // TODO: ask michael if I need to give it a better name like "update_allowed"
+ // or just continue with the old convention.
bool is_plus() const {
return (file_mode_ & static_cast<Mode>(OpenMode::PLUS)) != 0;
}
@@ -97,7 +98,7 @@ class FileMode {
// integer value. A flag set can include both READ and WRITE if the file
// is opened in update mode (ie. if the file was opened with a '+' the mode
// string.)
- enum class OpenMode: Mode {
+ enum class OpenMode : Mode {
READ = 0x1,
WRITE = 0x2,
APPEND = 0x4,
@@ -106,20 +107,20 @@ class FileMode {
// Denotes a file opened in binary mode (which is specified by including
// the 'b' character in teh mode string.)
- enum class ContentType: Mode {
+ enum class ContentType : Mode {
BINARY = 0x10,
};
// Denotes a file to be created for writing.
- enum class CreateType: Mode {
+ enum class CreateType : Mode {
EXCLUSIVE = 0x100,
};
- // This property tracks the mode for the particular file instance (i.e currently opened file)
+ // This property tracks the mode for the particular file instance (i.e
+ // currently opened file)
int file_mode_;
};
-
-}
+} // namespace LIBC_NAMESPACE_DECL
#endif // LLVM_LIBC_SRC___SUPPORT_FILE_FILE_MODE_H
>From d208bddb974f3c55dcbcc35a17523eaccff20c79 Mon Sep 17 00:00:00 2001
From: tdadadavid <davidtofunmidada at gmail.com>
Date: Wed, 9 Sep 2026 14:31:48 +0100
Subject: [PATCH 03/16] feat(file_mode): update write_allowed and read_allowed
method to use new api
Signed-off-by: tdadadavid <davidtofunmidada at gmail.com>
---
libc/src/__support/File/file.h | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/libc/src/__support/File/file.h b/libc/src/__support/File/file.h
index 67879e6c9933e..08f8b93b8f215 100644
--- a/libc/src/__support/File/file.h
+++ b/libc/src/__support/File/file.h
@@ -9,6 +9,7 @@
#ifndef LLVM_LIBC_SRC___SUPPORT_FILE_FILE_H
#define LLVM_LIBC_SRC___SUPPORT_FILE_FILE_H
+#include "file_mode.h"
#include "hdr/stdint_proxy.h"
#include "hdr/stdio_macros.h"
#include "hdr/types/off_t.h"
@@ -122,8 +123,12 @@ class File {
bool own_buf;
// The mode in which the file was opened.
+ //TODO: old way of doing things
+ // clean up when totally done with pr
ModeFlags mode;
+ FileMode file_mode;
+
// Current read or write pointer.
size_t pos;
@@ -155,14 +160,13 @@ class File {
protected:
constexpr bool write_allowed() const {
- return mode & (static_cast<ModeFlags>(OpenMode::WRITE) |
- static_cast<ModeFlags>(OpenMode::APPEND) |
- static_cast<ModeFlags>(OpenMode::PLUS));
+ return file_mode.write_allowed() ||
+ file_mode.append_allowed() ||
+ file_mode.is_plus(); //TODO: if micheal agrees for me to convert it change it here
}
constexpr bool read_allowed() const {
- return mode & (static_cast<ModeFlags>(OpenMode::READ) |
- static_cast<ModeFlags>(OpenMode::PLUS));
+ return file_mode.read_allowed() || file_mode.is_plus();
}
void reset_stream_state_unlocked(ModeFlags new_mode) {
>From 91f4a23232fb9d2992a69286e74241002513c86e Mon Sep 17 00:00:00 2001
From: tdadadavid <davidtofunmidada at gmail.com>
Date: Wed, 9 Sep 2026 16:47:57 +0100
Subject: [PATCH 04/16] feat: add method to check validity of a file mode
Signed-off-by: tdadadavid <davidtofunmidada at gmail.com>
---
libc/src/__support/File/file_mode.h | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/libc/src/__support/File/file_mode.h b/libc/src/__support/File/file_mode.h
index 707a448c5955d..92647decd2e76 100644
--- a/libc/src/__support/File/file_mode.h
+++ b/libc/src/__support/File/file_mode.h
@@ -1,7 +1,8 @@
#ifndef LLVM_LIBC_SRC___SUPPORT_FILE_FILE_MODE_H
#define LLVM_LIBC_SRC___SUPPORT_FILE_FILE_MODE_H
-#include <cstdint>
+
+#include "hdr/stdint_proxy.h"
namespace LIBC_NAMESPACE_DECL {
@@ -54,6 +55,8 @@ class FileMode {
file_mode_ = 0;
}
+ bool is_valid() const { return file_mode_ != 0; }
+
// helper function to show if file allows writing
bool write_allowed() const {
return (file_mode_ & static_cast<Mode>(OpenMode::WRITE)) != 0;
>From 86ef8ab5c1b9efc429df6ce9e9dfedb2bfa822e9 Mon Sep 17 00:00:00 2001
From: tdadadavid <davidtofunmidada at gmail.com>
Date: Wed, 9 Sep 2026 16:49:02 +0100
Subject: [PATCH 05/16] add config header for namespace resolution
Signed-off-by: tdadadavid <davidtofunmidada at gmail.com>
---
libc/src/__support/File/file_mode.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/libc/src/__support/File/file_mode.h b/libc/src/__support/File/file_mode.h
index 92647decd2e76..e7f46d6172833 100644
--- a/libc/src/__support/File/file_mode.h
+++ b/libc/src/__support/File/file_mode.h
@@ -3,6 +3,7 @@
#define LLVM_LIBC_SRC___SUPPORT_FILE_FILE_MODE_H
#include "hdr/stdint_proxy.h"
+#include "src/__support/macros/config.h"
namespace LIBC_NAMESPACE_DECL {
>From e97d27a9e2d28d37a0e75790be6b4820e5f0d27e Mon Sep 17 00:00:00 2001
From: tdadadavid <davidtofunmidada at gmail.com>
Date: Wed, 9 Sep 2026 16:50:49 +0100
Subject: [PATCH 06/16] feat: make FileMode constructor a constexpr
Signed-off-by: tdadadavid <davidtofunmidada at gmail.com>
---
libc/src/__support/File/file_mode.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libc/src/__support/File/file_mode.h b/libc/src/__support/File/file_mode.h
index e7f46d6172833..88ca0f5a2aa21 100644
--- a/libc/src/__support/File/file_mode.h
+++ b/libc/src/__support/File/file_mode.h
@@ -14,7 +14,7 @@ class FileMode {
// FileMode constructor accepts the mode string as an argument.
// It performs validation against several rules and records the `file_mode`
// property to the specific mode.
- explicit FileMode(const char *mode) : file_mode_(0) {
+ constexpr FileMode(const char *mode) : file_mode_(0) {
// First character in |mode| should be 'a', 'r' or 'w'.
if (*mode != 'a' && *mode != 'r' && *mode != 'w')
return;
>From 85003b267932ad24be42eff1f569321c7854944d Mon Sep 17 00:00:00 2001
From: tdadadavid <davidtofunmidada at gmail.com>
Date: Wed, 9 Sep 2026 16:53:22 +0100
Subject: [PATCH 07/16] feat(file.h): refactor File class to use FileMode to
handle mode related operations
Signed-off-by: tdadadavid <davidtofunmidada at gmail.com>
---
libc/src/__support/File/file.h | 50 ++++++----------------------------
1 file changed, 8 insertions(+), 42 deletions(-)
diff --git a/libc/src/__support/File/file.h b/libc/src/__support/File/file.h
index 6e06e0d6d28bd..a0ea9b7e9d156 100644
--- a/libc/src/__support/File/file.h
+++ b/libc/src/__support/File/file.h
@@ -68,31 +68,6 @@ class File {
using SeekFunc = ErrorOr<off_t>(File *, off_t, int);
using CloseFunc = int(File *);
- using ModeFlags = uint32_t;
-
- // The three different types of flags below are to be used with '|' operator.
- // Their values correspond to mutually exclusive bits in a 32-bit unsigned
- // integer value. A flag set can include both READ and WRITE if the file
- // is opened in update mode (ie. if the file was opened with a '+' the mode
- // string.)
- enum class OpenMode : ModeFlags {
- READ = 0x1,
- WRITE = 0x2,
- APPEND = 0x4,
- PLUS = 0x8,
- };
-
- // Denotes a file opened in binary mode (which is specified by including
- // the 'b' character in teh mode string.)
- enum class ContentType : ModeFlags {
- BINARY = 0x10,
- };
-
- // Denotes a file to be created for writing.
- enum class CreateType : ModeFlags {
- EXCLUSIVE = 0x100,
- };
-
// This is a convenience RAII class to lock and unlock file objects.
class FileLock {
File *file;
@@ -135,12 +110,7 @@ class File {
// free-ed when close method is called on the stream.
bool own_buf;
- // The mode in which the file was opened.
- //TODO: old way of doing things
- // clean up when totally done with pr
- ModeFlags mode;
-
- FileMode file_mode;
+ FileMode mode;
// Current read or write pointer.
size_t pos;
@@ -160,16 +130,16 @@ class File {
protected:
constexpr bool write_allowed() const {
- return file_mode.write_allowed() ||
- file_mode.append_allowed() ||
- file_mode.is_plus(); //TODO: if micheal agrees for me to convert it change it here
+ return mode.write_allowed() || mode.append_allowed() ||
+ mode.is_plus(); // TODO: if micheal agrees for me to convert it
+ // change it here
}
constexpr bool read_allowed() const {
- return file_mode.read_allowed() || file_mode.is_plus();
+ return mode.read_allowed() || mode.is_plus();
}
- void reset_stream_state_unlocked(ModeFlags new_mode) {
+ void reset_stream_state_unlocked(FileMode new_mode) {
mode = new_mode;
pos = 0;
prev_op = FileOp::NONE;
@@ -191,12 +161,12 @@ class File {
// the set_buffer method and allocate a buffer.
constexpr File(WriteFunc *wf, ReadFunc *rf, SeekFunc *sf, CloseFunc *cf,
uint8_t *buffer, size_t buffer_size, int buffer_mode,
- bool owned, ModeFlags modeflags)
+ bool owned, FileMode mode)
: platform_write(wf), platform_read(rf), platform_seek(sf),
platform_close(cf), mutex(/*timed=*/false, /*recursive=*/false,
/*robust=*/false, /*pshared=*/false),
ungetc_buf{}, buf(buffer), bufsize(buffer_size), bufmode(buffer_mode),
- own_buf(owned), mode(modeflags), pos(0), prev_op(FileOp::NONE),
+ own_buf(owned), mode(mode), pos(0), prev_op(FileOp::NONE),
read_limit(0), eof(false), err(false),
orientation(Orientation::UNORIENTED), mbstate(), prev(nullptr),
next(nullptr) {
@@ -356,10 +326,6 @@ class File {
return try_set_orientation_unlocked(o);
}
- // Returns an bit map of flags corresponding to enumerations of
- // OpenMode, ContentType and CreateType.
- static ModeFlags mode_flags(const char *mode);
-
private:
FileIOResult write_unlocked_impl(const void *data, size_t len);
FileIOResult read_unlocked_impl(void *data, size_t len);
>From 400aa53c132cb130c0187e376d6c5c78ad9b3b22 Mon Sep 17 00:00:00 2001
From: tdadadavid <davidtofunmidada at gmail.com>
Date: Wed, 9 Sep 2026 16:56:51 +0100
Subject: [PATCH 08/16] feat(file.cpp): remove modeFlags function
Signed-off-by: tdadadavid <davidtofunmidada at gmail.com>
---
libc/src/__support/File/file.cpp | 45 --------------------------------
1 file changed, 45 deletions(-)
diff --git a/libc/src/__support/File/file.cpp b/libc/src/__support/File/file.cpp
index fb8268a297a1a..d0366100525ac 100644
--- a/libc/src/__support/File/file.cpp
+++ b/libc/src/__support/File/file.cpp
@@ -510,51 +510,6 @@ int File::set_buffer(void *buffer, size_t size, int buffer_mode) {
return 0;
}
-File::ModeFlags File::mode_flags(const char *mode) {
- // First character in |mode| should be 'a', 'r' or 'w'.
- if (*mode != 'a' && *mode != 'r' && *mode != 'w')
- return 0;
-
- // There should be exaclty one main mode ('a', 'r' or 'w') character.
- // If there are more than one main mode characters listed, then
- // we will consider |mode| as incorrect and return 0;
- int main_mode_count = 0;
-
- ModeFlags flags = 0;
- for (; *mode != '\0'; ++mode) {
- switch (*mode) {
- case 'r':
- flags |= static_cast<ModeFlags>(OpenMode::READ);
- ++main_mode_count;
- break;
- case 'w':
- flags |= static_cast<ModeFlags>(OpenMode::WRITE);
- ++main_mode_count;
- break;
- case '+':
- flags |= static_cast<ModeFlags>(OpenMode::PLUS);
- break;
- case 'b':
- flags |= static_cast<ModeFlags>(ContentType::BINARY);
- break;
- case 'a':
- flags |= static_cast<ModeFlags>(OpenMode::APPEND);
- ++main_mode_count;
- break;
- case 'x':
- flags |= static_cast<ModeFlags>(CreateType::EXCLUSIVE);
- break;
- default:
- return 0;
- }
- }
-
- if (main_mode_count != 1)
- return 0;
-
- return flags;
-}
-
FileIOResult File::write_unlocked(const wchar_t *ws, size_t len) {
switch (orientation) {
case Orientation::BYTE:
>From 5d8d1901a32b77faaf25506c2137c290c22fbecd Mon Sep 17 00:00:00 2001
From: tdadadavid <davidtofunmidada at gmail.com>
Date: Wed, 9 Sep 2026 17:00:04 +0100
Subject: [PATCH 09/16] feat(linux-file): update linux file constructor to
accept FileMode instance instead of ModeFlags
Signed-off-by: tdadadavid <davidtofunmidada at gmail.com>
---
libc/src/__support/File/linux/file.h | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/libc/src/__support/File/linux/file.h b/libc/src/__support/File/linux/file.h
index 700db415156ae..539957b8b22c8 100644
--- a/libc/src/__support/File/linux/file.h
+++ b/libc/src/__support/File/linux/file.h
@@ -8,6 +8,7 @@
#include "hdr/types/off_t.h"
#include "src/__support/File/file.h"
+#include "src/__support/File/file_mode.h"
#include "src/__support/macros/config.h"
namespace LIBC_NAMESPACE_DECL {
@@ -22,10 +23,9 @@ class LinuxFile : public File {
public:
constexpr LinuxFile(int file_descriptor, uint8_t *buffer, size_t buffer_size,
- int buffer_mode, bool owned, File::ModeFlags modeflags)
+ int buffer_mode, bool owned, FileMode mode)
: File(&linux_file_write, &linux_file_read, &linux_file_seek,
- &linux_file_close, buffer, buffer_size, buffer_mode, owned,
- modeflags),
+ &linux_file_close, buffer, buffer_size, buffer_mode, owned, mode),
fd(file_descriptor) {}
int get_fd() const { return fd; }
>From 17152f2ddfb93c338208dacbd7c5fd90bb589f87 Mon Sep 17 00:00:00 2001
From: tdadadavid <davidtofunmidada at gmail.com>
Date: Wed, 9 Sep 2026 17:04:28 +0100
Subject: [PATCH 10/16] feat: create new method to map c-mode flags to linux
open flags
Signed-off-by: tdadadavid <davidtofunmidada at gmail.com>
---
libc/src/__support/File/linux/file.cpp | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)
diff --git a/libc/src/__support/File/linux/file.cpp b/libc/src/__support/File/linux/file.cpp
index 613fadc5b1f3e..ce92ca818a3fb 100644
--- a/libc/src/__support/File/linux/file.cpp
+++ b/libc/src/__support/File/linux/file.cpp
@@ -14,6 +14,7 @@
#include "hdr/types/off_t.h"
#include "src/__support/CPP/new.h"
#include "src/__support/File/file.h"
+#include "src/__support/File/file_mode.h"
#include "src/__support/OSUtil/linux/syscall_wrappers/close.h"
#include "src/__support/OSUtil/linux/syscall_wrappers/dup2.h"
#include "src/__support/OSUtil/linux/syscall_wrappers/fcntl.h"
@@ -68,6 +69,30 @@ int linux_file_close(File *f) {
return retval;
}
+static int map_c_mode_flags_to_linux_open_flags(FileMode mode) {
+ FileMode file_mode(mode);
+
+ if (file_mode.append_allowed()) {
+ open_flags = O_CREAT | O_APPEND;
+ if (file_mode.is_plus())
+ open_flags |= O_RDWR;
+ else
+ open_flags |= O_WRONLY;
+ } else if (file_mode.write_allowed()) {
+ open_flags = O_CREAT | O_TRUNC;
+ if (file_mode.is_plus())
+ open_flags |= O_RDWR;
+ else
+ open_flags |= O_WRONLY;
+ } else {
+ if (file_mode.is_plus())
+ open_flags |= O_RDWR;
+ else
+ open_flags |= O_RDONLY;
+ }
+ return open_flags;
+}
+
static int mode_flags_to_open_flags(File::ModeFlags modeflags) {
using ModeFlags = File::ModeFlags;
int open_flags = 0;
>From 3cc1aed286b95db440ea9a83a795b86c35d40a63 Mon Sep 17 00:00:00 2001
From: tdadadavid <davidtofunmidada at gmail.com>
Date: Wed, 9 Sep 2026 17:08:12 +0100
Subject: [PATCH 11/16] refactor openfile function to work with FileMode
instead of ModeFlags
Signed-off-by: tdadadavid <davidtofunmidada at gmail.com>
---
libc/src/__support/File/linux/file.cpp | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/libc/src/__support/File/linux/file.cpp b/libc/src/__support/File/linux/file.cpp
index ce92ca818a3fb..0b39f2f8e21cb 100644
--- a/libc/src/__support/File/linux/file.cpp
+++ b/libc/src/__support/File/linux/file.cpp
@@ -93,6 +93,7 @@ static int map_c_mode_flags_to_linux_open_flags(FileMode mode) {
return open_flags;
}
+// TODO: clean up
static int mode_flags_to_open_flags(File::ModeFlags modeflags) {
using ModeFlags = File::ModeFlags;
int open_flags = 0;
@@ -118,11 +119,12 @@ static int mode_flags_to_open_flags(File::ModeFlags modeflags) {
}
ErrorOr<File *> openfile(const char *path, const char *mode) {
- auto modeflags = File::mode_flags(mode);
- if (modeflags == 0) {
+ FileMode file_mode(mode);
+
+ if (!file_mode.is_valid()) {
return Error(EINVAL);
}
- int open_flags = mode_flags_to_open_flags(modeflags);
+ int open_flags = map_c_mode_flags_to_linux_open_flags(file_mode);
// File created will have 0666 permissions.
constexpr mode_t OPEN_MODE =
@@ -141,7 +143,7 @@ ErrorOr<File *> openfile(const char *path, const char *mode) {
}
AllocChecker ac;
auto *file = new (ac) LinuxFile(fd.value(), buffer, File::DEFAULT_BUFFER_SIZE,
- _IOFBF, true, modeflags);
+ _IOFBF, true, file_mode);
if (!ac)
return Error(ENOMEM);
File::add_file(file);
>From e28986fb0a868511189fbe9e85a5a260c93b76af Mon Sep 17 00:00:00 2001
From: tdadadavid <davidtofunmidada at gmail.com>
Date: Wed, 9 Sep 2026 17:14:46 +0100
Subject: [PATCH 12/16] refactor create_file_from_fd to use FileMode instance
for handling file mode
Signed-off-by: tdadadavid <davidtofunmidada at gmail.com>
---
libc/src/__support/File/linux/file.cpp | 28 ++++++++++----------------
1 file changed, 11 insertions(+), 17 deletions(-)
diff --git a/libc/src/__support/File/linux/file.cpp b/libc/src/__support/File/linux/file.cpp
index 0b39f2f8e21cb..e5510d931ee4e 100644
--- a/libc/src/__support/File/linux/file.cpp
+++ b/libc/src/__support/File/linux/file.cpp
@@ -151,9 +151,9 @@ ErrorOr<File *> openfile(const char *path, const char *mode) {
}
ErrorOr<LinuxFile *> create_file_from_fd(int fd, const char *mode) {
- using ModeFlags = File::ModeFlags;
- ModeFlags modeflags = File::mode_flags(mode);
- if (modeflags == 0) {
+ FileMode file_mode(mode);
+
+ if (!file_mode.is_valid()) {
return Error(EINVAL);
}
@@ -163,25 +163,19 @@ ErrorOr<LinuxFile *> create_file_from_fd(int fd, const char *mode) {
}
int fd_flags = result.value();
- using OpenMode = File::OpenMode;
- using ModeFlags = File::ModeFlags;
+ constexpr int REQUIRES_WRITE = file_mode.write_allowed() |
+ file_mode.append_allowed() |
+ file_mode.is_plus();
- constexpr ModeFlags REQUIRES_WRITE =
- static_cast<ModeFlags>(OpenMode::WRITE) |
- static_cast<ModeFlags>(OpenMode::APPEND) |
- static_cast<ModeFlags>(OpenMode::PLUS);
+ constexpr int REQUIRES_READ = file_mode.write_allowed() | file_mode.is_plus();
- constexpr ModeFlags REQUIRES_READ = static_cast<ModeFlags>(OpenMode::READ) |
- static_cast<ModeFlags>(OpenMode::PLUS);
-
- if (((fd_flags & O_ACCMODE) == O_RDONLY && (modeflags & REQUIRES_WRITE)) ||
- ((fd_flags & O_ACCMODE) == O_WRONLY && (modeflags & REQUIRES_READ))) {
+ if (((fd_flags & O_ACCMODE) == O_RDONLY && REQUIRES_WRITE) ||
+ ((fd_flags & O_ACCMODE) == O_WRONLY && REQUIRES_READ)) {
return Error(EINVAL);
}
bool do_seek = false;
- if ((modeflags & static_cast<ModeFlags>(OpenMode::APPEND)) &&
- !(fd_flags & O_APPEND)) {
+ if (file_mode.append_allowed() && !(fd_flags & O_APPEND)) {
do_seek = true;
if (!linux_syscalls::fcntl(fd, F_SETFL,
reinterpret_cast<void *>(fd_flags | O_APPEND))
@@ -200,7 +194,7 @@ ErrorOr<LinuxFile *> create_file_from_fd(int fd, const char *mode) {
}
AllocChecker ac;
auto *file = new (ac)
- LinuxFile(fd, buffer, File::DEFAULT_BUFFER_SIZE, _IOFBF, true, modeflags);
+ LinuxFile(fd, buffer, File::DEFAULT_BUFFER_SIZE, _IOFBF, true, file_mode);
if (!ac) {
return Error(ENOMEM);
}
>From 8b11ddd5101184b65abee156d74241c036257c56 Mon Sep 17 00:00:00 2001
From: tdadadavid <davidtofunmidada at gmail.com>
Date: Wed, 9 Sep 2026 17:22:52 +0100
Subject: [PATCH 13/16] refactor reopen_unlocked to use FileMode implementation
and initialize open_flags in c to linux open flags map function
Signed-off-by: tdadadavid <davidtofunmidada at gmail.com>
---
libc/src/__support/File/linux/file.cpp | 46 +++++++++++---------------
1 file changed, 20 insertions(+), 26 deletions(-)
diff --git a/libc/src/__support/File/linux/file.cpp b/libc/src/__support/File/linux/file.cpp
index e5510d931ee4e..95aefa366fab1 100644
--- a/libc/src/__support/File/linux/file.cpp
+++ b/libc/src/__support/File/linux/file.cpp
@@ -72,6 +72,8 @@ int linux_file_close(File *f) {
static int map_c_mode_flags_to_linux_open_flags(FileMode mode) {
FileMode file_mode(mode);
+ int open_flags = 0;
+
if (file_mode.append_allowed()) {
open_flags = O_CREAT | O_APPEND;
if (file_mode.is_plus())
@@ -211,23 +213,21 @@ ErrorOr<LinuxFile *> create_file_from_fd(int fd, const char *mode) {
}
int LinuxFile::reopen_unlocked(const char *path, const char *mode) {
- flush_unlocked();
-
- auto modeflags = File::mode_flags(mode);
+ FileMode file_mode(mode);
if (path != nullptr) {
int old_fd = get_fd();
- if (modeflags == 0) {
+ if (!file_mode.is_valid()) {
if (old_fd >= 0) {
linux_syscalls::close(old_fd);
set_fd(-1);
}
- reset_stream_state_unlocked(modeflags);
+ reset_stream_state_unlocked(file_mode);
return EINVAL;
}
- int open_flags = mode_flags_to_open_flags(modeflags);
+ int open_flags = map_c_mode_flags_to_linux_open_flags(file_mode);
constexpr mode_t OPEN_MODE =
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
@@ -244,7 +244,7 @@ int LinuxFile::reopen_unlocked(const char *path, const char *mode) {
set_fd(-1);
}
- reset_stream_state_unlocked(modeflags);
+ reset_stream_state_unlocked(file_mode);
return new_fd.error();
}
@@ -254,23 +254,23 @@ int LinuxFile::reopen_unlocked(const char *path, const char *mode) {
auto dup_result = linux_syscalls::dup2(new_fd.value(), old_fd);
if (!dup_result) {
linux_syscalls::close(new_fd.value());
- reset_stream_state_unlocked(modeflags);
+ reset_stream_state_unlocked(file_mode);
return dup_result.error();
}
auto close_result = linux_syscalls::close(new_fd.value());
if (!close_result) {
- reset_stream_state_unlocked(modeflags);
+ reset_stream_state_unlocked(file_mode);
return close_result.error();
}
} else {
set_fd(new_fd.value());
}
- reset_stream_state_unlocked(modeflags);
+ reset_stream_state_unlocked(file_mode);
return 0;
}
- if (modeflags == 0)
+ if (!file_mode.is_valid())
return EINVAL;
if (fd < 0)
@@ -281,34 +281,28 @@ int LinuxFile::reopen_unlocked(const char *path, const char *mode) {
return EBADF;
int fd_flags = result.value();
- using OpenMode = File::OpenMode;
- using ModeFlags = File::ModeFlags;
-
- constexpr ModeFlags REQUIRES_WRITE =
- static_cast<ModeFlags>(OpenMode::WRITE) |
- static_cast<ModeFlags>(OpenMode::APPEND) |
- static_cast<ModeFlags>(OpenMode::PLUS);
+ constexpr int REQUIRES_WRITE = file_mode.write_allowed() |
+ file_mode.append_allowed() |
+ file_mode.is_plus();
- constexpr ModeFlags REQUIRES_READ = static_cast<ModeFlags>(OpenMode::READ) |
- static_cast<ModeFlags>(OpenMode::PLUS);
+ constexpr int REQUIRES_READ = file_mode.write_allowed() | file_mode.is_plus();
- if (((fd_flags & O_ACCMODE) == O_RDONLY && (modeflags & REQUIRES_WRITE)) ||
- ((fd_flags & O_ACCMODE) == O_WRONLY && (modeflags & REQUIRES_READ))) {
+ if (((fd_flags & O_ACCMODE) == O_RDONLY && REQUIRES_WRITE) ||
+ ((fd_flags & O_ACCMODE) == O_WRONLY && REQUIRES_READ)) {
return EBADF;
}
bool do_seek = false;
- bool is_append = modeflags & static_cast<ModeFlags>(OpenMode::APPEND);
bool has_append_flag = fd_flags & O_APPEND;
- if (is_append && !has_append_flag) {
+ if (file_mode.append_allowed() && !has_append_flag) {
if (!linux_syscalls::fcntl(fd, F_SETFL,
reinterpret_cast<void *>(fd_flags | O_APPEND))
.has_value()) {
return EBADF;
}
do_seek = true;
- } else if (!is_append && has_append_flag) {
+ } else if (!file_mode.append_allowed() && has_append_flag) {
if (!linux_syscalls::fcntl(fd, F_SETFL,
reinterpret_cast<void *>(fd_flags & ~O_APPEND))
.has_value()) {
@@ -316,7 +310,7 @@ int LinuxFile::reopen_unlocked(const char *path, const char *mode) {
}
}
- reset_stream_state_unlocked(modeflags);
+ reset_stream_state_unlocked(file_mode);
if (do_seek) {
auto seek_result = linux_file_seek(this, 0, SEEK_END);
>From e72c2fc0ca0fffb891acdf4d2e761cc1a6bfa6f8 Mon Sep 17 00:00:00 2001
From: tdadadavid <davidtofunmidada at gmail.com>
Date: Wed, 9 Sep 2026 17:59:37 +0100
Subject: [PATCH 14/16] remove old method
Signed-off-by: tdadadavid <davidtofunmidada at gmail.com>
---
libc/src/__support/File/linux/file.cpp | 25 -------------------------
1 file changed, 25 deletions(-)
diff --git a/libc/src/__support/File/linux/file.cpp b/libc/src/__support/File/linux/file.cpp
index 95aefa366fab1..5e74c2143231f 100644
--- a/libc/src/__support/File/linux/file.cpp
+++ b/libc/src/__support/File/linux/file.cpp
@@ -95,31 +95,6 @@ static int map_c_mode_flags_to_linux_open_flags(FileMode mode) {
return open_flags;
}
-// TODO: clean up
-static int mode_flags_to_open_flags(File::ModeFlags modeflags) {
- using ModeFlags = File::ModeFlags;
- int open_flags = 0;
- if (modeflags & ModeFlags(File::OpenMode::APPEND)) {
- open_flags = O_CREAT | O_APPEND;
- if (modeflags & ModeFlags(File::OpenMode::PLUS))
- open_flags |= O_RDWR;
- else
- open_flags |= O_WRONLY;
- } else if (modeflags & ModeFlags(File::OpenMode::WRITE)) {
- open_flags = O_CREAT | O_TRUNC;
- if (modeflags & ModeFlags(File::OpenMode::PLUS))
- open_flags |= O_RDWR;
- else
- open_flags |= O_WRONLY;
- } else {
- if (modeflags & ModeFlags(File::OpenMode::PLUS))
- open_flags |= O_RDWR;
- else
- open_flags |= O_RDONLY;
- }
- return open_flags;
-}
-
ErrorOr<File *> openfile(const char *path, const char *mode) {
FileMode file_mode(mode);
>From 5084e697f2043595435f08928969f91c214f8241 Mon Sep 17 00:00:00 2001
From: tdadadavid <davidtofunmidada at gmail.com>
Date: Wed, 9 Sep 2026 20:13:26 +0100
Subject: [PATCH 15/16] fix error in getting constant
Signed-off-by: tdadadavid <davidtofunmidada at gmail.com>
---
libc/src/__support/File/linux/file.cpp | 14 ++++++--------
1 file changed, 6 insertions(+), 8 deletions(-)
diff --git a/libc/src/__support/File/linux/file.cpp b/libc/src/__support/File/linux/file.cpp
index 5e74c2143231f..259fc7a87ea3f 100644
--- a/libc/src/__support/File/linux/file.cpp
+++ b/libc/src/__support/File/linux/file.cpp
@@ -140,11 +140,10 @@ ErrorOr<LinuxFile *> create_file_from_fd(int fd, const char *mode) {
}
int fd_flags = result.value();
- constexpr int REQUIRES_WRITE = file_mode.write_allowed() |
- file_mode.append_allowed() |
- file_mode.is_plus();
+ int REQUIRES_WRITE = file_mode.write_allowed() ||
+ file_mode.append_allowed() || file_mode.is_plus();
- constexpr int REQUIRES_READ = file_mode.write_allowed() | file_mode.is_plus();
+ int REQUIRES_READ = file_mode.write_allowed() || file_mode.is_plus();
if (((fd_flags & O_ACCMODE) == O_RDONLY && REQUIRES_WRITE) ||
((fd_flags & O_ACCMODE) == O_WRONLY && REQUIRES_READ)) {
@@ -256,11 +255,10 @@ int LinuxFile::reopen_unlocked(const char *path, const char *mode) {
return EBADF;
int fd_flags = result.value();
- constexpr int REQUIRES_WRITE = file_mode.write_allowed() |
- file_mode.append_allowed() |
- file_mode.is_plus();
+ int REQUIRES_WRITE = file_mode.write_allowed() ||
+ file_mode.append_allowed() || file_mode.is_plus();
- constexpr int REQUIRES_READ = file_mode.write_allowed() | file_mode.is_plus();
+ int REQUIRES_READ = file_mode.write_allowed() || file_mode.is_plus();
if (((fd_flags & O_ACCMODE) == O_RDONLY && REQUIRES_WRITE) ||
((fd_flags & O_ACCMODE) == O_WRONLY && REQUIRES_READ)) {
>From db720c24d27f0ae18e4bbc4dc13878665c47f617 Mon Sep 17 00:00:00 2001
From: tdadadavid <davidtofunmidada at gmail.com>
Date: Wed, 9 Sep 2026 20:48:51 +0100
Subject: [PATCH 16/16] convert int to boolean and fix REQUIRES_READ flag
Signed-off-by: tdadadavid <davidtofunmidada at gmail.com>
---
libc/src/__support/File/linux/file.cpp | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/libc/src/__support/File/linux/file.cpp b/libc/src/__support/File/linux/file.cpp
index 259fc7a87ea3f..08eb7c6d733fd 100644
--- a/libc/src/__support/File/linux/file.cpp
+++ b/libc/src/__support/File/linux/file.cpp
@@ -140,10 +140,10 @@ ErrorOr<LinuxFile *> create_file_from_fd(int fd, const char *mode) {
}
int fd_flags = result.value();
- int REQUIRES_WRITE = file_mode.write_allowed() ||
- file_mode.append_allowed() || file_mode.is_plus();
+ const bool REQUIRES_WRITE = file_mode.write_allowed() ||
+ file_mode.append_allowed() || file_mode.is_plus();
- int REQUIRES_READ = file_mode.write_allowed() || file_mode.is_plus();
+ const bool REQUIRES_READ = file_mode.read_allowed() || file_mode.is_plus();
if (((fd_flags & O_ACCMODE) == O_RDONLY && REQUIRES_WRITE) ||
((fd_flags & O_ACCMODE) == O_WRONLY && REQUIRES_READ)) {
More information about the libc-commits
mailing list