[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
Fri Sep 11 05:11:02 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/41] 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/41] 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/41] 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/41] 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/41] 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/41] 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/41] 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/41] 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/41] 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/41] 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/41] 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/41] 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/41] 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/41] 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/41] 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/41] 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)) {

>From 16a0050b32c7eabc2ecb5870daf4f224dda8dc12 Mon Sep 17 00:00:00 2001
From: tdadadavid <davidtofunmidada at gmail.com>
Date: Wed, 9 Sep 2026 21:13:14 +0100
Subject: [PATCH 17/41] fix the same error missed

Signed-off-by: tdadadavid <davidtofunmidada at gmail.com>
---
 libc/src/__support/File/linux/file.cpp     | 6 +++---
 libc/test/src/__support/File/file_test.cpp | 3 ++-
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/libc/src/__support/File/linux/file.cpp b/libc/src/__support/File/linux/file.cpp
index 08eb7c6d733fd..b16724fcb61f4 100644
--- a/libc/src/__support/File/linux/file.cpp
+++ b/libc/src/__support/File/linux/file.cpp
@@ -255,10 +255,10 @@ int LinuxFile::reopen_unlocked(const char *path, const char *mode) {
     return EBADF;
   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.write_allowed() || file_mode.is_plus();
 
   if (((fd_flags & O_ACCMODE) == O_RDONLY && REQUIRES_WRITE) ||
       ((fd_flags & O_ACCMODE) == O_WRONLY && REQUIRES_READ)) {
diff --git a/libc/test/src/__support/File/file_test.cpp b/libc/test/src/__support/File/file_test.cpp
index 5af36a2e65a3e..81677529ebc32 100644
--- a/libc/test/src/__support/File/file_test.cpp
+++ b/libc/test/src/__support/File/file_test.cpp
@@ -10,12 +10,13 @@
 #include "hdr/wchar_macros.h"
 #include "src/__support/CPP/new.h"
 #include "src/__support/File/file.h"
+#include "src/__support/File/file_mode.h"
 #include "src/__support/alloc-checker.h"
 #include "src/__support/error_or.h"
+#include "src/__support/macros/config.h"
 #include "test/UnitTest/MemoryMatcher.h"
 #include "test/UnitTest/Test.h"
 
-using ModeFlags = LIBC_NAMESPACE::File::ModeFlags;
 using MemoryView = LIBC_NAMESPACE::testing::MemoryView;
 using LIBC_NAMESPACE::ErrorOr;
 using LIBC_NAMESPACE::File;

>From 18a9152af194edd3fba04e869749534d9cfec345 Mon Sep 17 00:00:00 2001
From: David Dada <davidtofunmidada at gmail.com>
Date: Wed, 9 Sep 2026 21:26:01 +0100
Subject: [PATCH 18/41] Update libc/src/__support/File/file_mode.h

Co-authored-by: Michael Jones <michaelrj at google.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 88ca0f5a2aa21..0a85002943520 100644
--- a/libc/src/__support/File/file_mode.h
+++ b/libc/src/__support/File/file_mode.h
@@ -7,7 +7,7 @@
 
 namespace LIBC_NAMESPACE_DECL {
 
-// FileMode class handles everything regarding the mode of the file, be it's
+// FileMode class handles everything regarding the mode of the file, be it
 // opening mode or content type.
 class FileMode {
 public:

>From c72870590987afe1980e077853fdd327e97ca9b6 Mon Sep 17 00:00:00 2001
From: tdadadavid <davidtofunmidada at gmail.com>
Date: Wed, 9 Sep 2026 21:31:01 +0100
Subject: [PATCH 19/41] chore: add lincense headers to file mode class

Signed-off-by: tdadadavid <davidtofunmidada at gmail.com>
---
 libc/src/__support/File/file_mode.h | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/libc/src/__support/File/file_mode.h b/libc/src/__support/File/file_mode.h
index 88ca0f5a2aa21..b61207c497fb3 100644
--- a/libc/src/__support/File/file_mode.h
+++ b/libc/src/__support/File/file_mode.h
@@ -1,3 +1,10 @@
+//===--- A platform independent File mode class -------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
 
 #ifndef LLVM_LIBC_SRC___SUPPORT_FILE_FILE_MODE_H
 #define LLVM_LIBC_SRC___SUPPORT_FILE_FILE_MODE_H

>From b1cb3f254b39ccbc23456465a0e8e7c109a2f374 Mon Sep 17 00:00:00 2001
From: tdadadavid <davidtofunmidada at gmail.com>
Date: Wed, 9 Sep 2026 21:32:51 +0100
Subject: [PATCH 20/41] rename FileMode methods for better DevX

Signed-off-by: tdadadavid <davidtofunmidada at gmail.com>
---
 libc/src/__support/File/file_mode.h | 17 +++++------------
 1 file changed, 5 insertions(+), 12 deletions(-)

diff --git a/libc/src/__support/File/file_mode.h b/libc/src/__support/File/file_mode.h
index b61207c497fb3..6d8cf09139588 100644
--- a/libc/src/__support/File/file_mode.h
+++ b/libc/src/__support/File/file_mode.h
@@ -65,30 +65,23 @@ class FileMode {
 
   bool is_valid() const { return file_mode_ != 0; }
 
-  // helper function to show if file allows writing
-  bool write_allowed() const {
+  bool is_write() const {
     return (file_mode_ & static_cast<Mode>(OpenMode::WRITE)) != 0;
   }
 
-  // helper function to show if file allows reading
-  bool read_allowed() const {
+  bool is_read() const {
     return (file_mode_ & static_cast<Mode>(OpenMode::READ)) != 0;
   }
 
-  // helper function to show if file allows appending
-  bool append_allowed() const {
+  bool is_append() 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 {
+  bool is_update() const {
     return (file_mode_ & static_cast<Mode>(OpenMode::PLUS)) != 0;
   }
 
@@ -129,7 +122,7 @@ class FileMode {
 
   // This property tracks the mode for the particular file instance (i.e
   // currently opened file)
-  int file_mode_;
+  Mode file_mode_;
 };
 
 } // namespace LIBC_NAMESPACE_DECL

>From c905ad67285c974096f00c0df5aabe648695e8cb Mon Sep 17 00:00:00 2001
From: tdadadavid <davidtofunmidada at gmail.com>
Date: Wed, 9 Sep 2026 21:36:32 +0100
Subject: [PATCH 21/41] improve comment to capture what is actually going on

Signed-off-by: tdadadavid <davidtofunmidada at gmail.com>
---
 libc/src/__support/File/file_mode.h | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/libc/src/__support/File/file_mode.h b/libc/src/__support/File/file_mode.h
index 6d8cf09139588..4e4b114040db8 100644
--- a/libc/src/__support/File/file_mode.h
+++ b/libc/src/__support/File/file_mode.h
@@ -28,7 +28,8 @@ class FileMode {
 
     // 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;
+    // we will consider |mode| as incorrect and set the file's mode to zero
+    // meaning the file's mode is in an invalid state.;
     int main_mode_count = 0;
 
     for (; *mode != '\0'; ++mode) {

>From ca1671af0f844a2b81f8399439619d3665149fd3 Mon Sep 17 00:00:00 2001
From: tdadadavid <davidtofunmidada at gmail.com>
Date: Wed, 9 Sep 2026 21:38:56 +0100
Subject: [PATCH 22/41] fix typo in comment

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 4e4b114040db8..589c83e234d41 100644
--- a/libc/src/__support/File/file_mode.h
+++ b/libc/src/__support/File/file_mode.h
@@ -111,7 +111,7 @@ class FileMode {
   };
 
   // Denotes a file opened in binary mode (which is specified by including
-  // the 'b' character in teh mode string.)
+  // the 'b' character in the mode string.)
   enum class ContentType : Mode {
     BINARY = 0x10,
   };

>From 285681af9b4bf609449738f02b958408122da64b Mon Sep 17 00:00:00 2001
From: tdadadavid <davidtofunmidada at gmail.com>
Date: Wed, 9 Sep 2026 21:41:45 +0100
Subject: [PATCH 23/41] update file to use new FileMode api

Signed-off-by: tdadadavid <davidtofunmidada at gmail.com>
---
 libc/src/__support/File/file.h | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/libc/src/__support/File/file.h b/libc/src/__support/File/file.h
index a0ea9b7e9d156..c55fc7e4f828f 100644
--- a/libc/src/__support/File/file.h
+++ b/libc/src/__support/File/file.h
@@ -130,13 +130,11 @@ class File {
 
 protected:
   constexpr bool write_allowed() const {
-    return mode.write_allowed() || mode.append_allowed() ||
-           mode.is_plus(); // TODO: if micheal agrees for me to convert it
-                           // change it here
+    return mode.is_write() || mode.is_append() || mode.is_update();
   }
 
   constexpr bool read_allowed() const {
-    return mode.read_allowed() || mode.is_plus();
+    return mode.is_read() || mode.is_update();
   }
 
   void reset_stream_state_unlocked(FileMode new_mode) {

>From a1b426925aef87fd1d358fc962052c023b4e753f Mon Sep 17 00:00:00 2001
From: tdadadavid <davidtofunmidada at gmail.com>
Date: Wed, 9 Sep 2026 21:49:40 +0100
Subject: [PATCH 24/41] refactor FileMode class methods

Signed-off-by: tdadadavid <davidtofunmidada at gmail.com>
---
 libc/src/__support/File/file_mode.h | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/libc/src/__support/File/file_mode.h b/libc/src/__support/File/file_mode.h
index 589c83e234d41..5ab9f10d98966 100644
--- a/libc/src/__support/File/file_mode.h
+++ b/libc/src/__support/File/file_mode.h
@@ -64,6 +64,13 @@ class FileMode {
       file_mode_ = 0;
   }
 
+  bool write_allowed() const {
+    return is_write() || is_append() || is_update();
+  }
+
+  bool read_allowed() const { return is_read() || is_update(); }
+
+protected:
   bool is_valid() const { return file_mode_ != 0; }
 
   bool is_write() const {

>From 4020a0c647edaec19633b4de0d24a6188b096fe3 Mon Sep 17 00:00:00 2001
From: tdadadavid <davidtofunmidada at gmail.com>
Date: Wed, 9 Sep 2026 21:50:24 +0100
Subject: [PATCH 25/41] use FileMode public API's

Signed-off-by: tdadadavid <davidtofunmidada at gmail.com>
---
 libc/src/__support/File/file.h | 8 ++------
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/libc/src/__support/File/file.h b/libc/src/__support/File/file.h
index c55fc7e4f828f..4a74221f9dddc 100644
--- a/libc/src/__support/File/file.h
+++ b/libc/src/__support/File/file.h
@@ -129,13 +129,9 @@ class File {
   internal::mbstate mbstate;
 
 protected:
-  constexpr bool write_allowed() const {
-    return mode.is_write() || mode.is_append() || mode.is_update();
-  }
+  constexpr bool write_allowed() const { return mode.write_allowed(); }
 
-  constexpr bool read_allowed() const {
-    return mode.is_read() || mode.is_update();
-  }
+  constexpr bool read_allowed() const { return mode.read_allowed(); }
 
   void reset_stream_state_unlocked(FileMode new_mode) {
     mode = new_mode;

>From d062f36425c87bc7ddefff3cb5739a8df50c939c Mon Sep 17 00:00:00 2001
From: tdadadavid <davidtofunmidada at gmail.com>
Date: Wed, 9 Sep 2026 21:51:36 +0100
Subject: [PATCH 26/41] add comment for mode

Signed-off-by: tdadadavid <davidtofunmidada at gmail.com>
---
 libc/src/__support/File/file.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/libc/src/__support/File/file.h b/libc/src/__support/File/file.h
index 4a74221f9dddc..072f5d38c7c95 100644
--- a/libc/src/__support/File/file.h
+++ b/libc/src/__support/File/file.h
@@ -110,6 +110,7 @@ class File {
   // free-ed when close method is called on the stream.
   bool own_buf;
 
+  // Used to handle the File's mode
   FileMode mode;
 
   // Current read or write pointer.

>From 3283d1d0f5a667ac52e9f367969417eea358724d Mon Sep 17 00:00:00 2001
From: tdadadavid <davidtofunmidada at gmail.com>
Date: Wed, 9 Sep 2026 22:09:25 +0100
Subject: [PATCH 27/41] remove protected and make all methods public

Signed-off-by: tdadadavid <davidtofunmidada at gmail.com>
---
 libc/src/__support/File/file_mode.h | 17 ++++++++---------
 1 file changed, 8 insertions(+), 9 deletions(-)

diff --git a/libc/src/__support/File/file_mode.h b/libc/src/__support/File/file_mode.h
index 5ab9f10d98966..176b8f919ccf4 100644
--- a/libc/src/__support/File/file_mode.h
+++ b/libc/src/__support/File/file_mode.h
@@ -70,9 +70,16 @@ class FileMode {
 
   bool read_allowed() const { return is_read() || is_update(); }
 
-protected:
   bool is_valid() const { return file_mode_ != 0; }
 
+  bool is_append() const {
+    return (file_mode_ & static_cast<Mode>(OpenMode::APPEND)) != 0;
+  }
+
+  bool is_update() const {
+    return (file_mode_ & static_cast<Mode>(OpenMode::PLUS)) != 0;
+  }
+
   bool is_write() const {
     return (file_mode_ & static_cast<Mode>(OpenMode::WRITE)) != 0;
   }
@@ -81,18 +88,10 @@ class FileMode {
     return (file_mode_ & static_cast<Mode>(OpenMode::READ)) != 0;
   }
 
-  bool is_append() const {
-    return (file_mode_ & static_cast<Mode>(OpenMode::APPEND)) != 0;
-  }
-
   bool is_binary_format() const {
     return (file_mode_ & static_cast<Mode>(ContentType::BINARY)) != 0;
   }
 
-  bool is_update() 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;

>From 3aa5d5cb5282f65aa6039d15ba59e7dee5dd4834 Mon Sep 17 00:00:00 2001
From: tdadadavid <davidtofunmidada at gmail.com>
Date: Wed, 9 Sep 2026 22:34:41 +0100
Subject: [PATCH 28/41] refactor file_mode's use in linux File implementation

Signed-off-by: tdadadavid <davidtofunmidada at gmail.com>
---
 libc/src/__support/File/linux/file.cpp | 48 +++++++++++++++-----------
 1 file changed, 28 insertions(+), 20 deletions(-)

diff --git a/libc/src/__support/File/linux/file.cpp b/libc/src/__support/File/linux/file.cpp
index b16724fcb61f4..c0156c617c11c 100644
--- a/libc/src/__support/File/linux/file.cpp
+++ b/libc/src/__support/File/linux/file.cpp
@@ -74,20 +74,20 @@ static int map_c_mode_flags_to_linux_open_flags(FileMode mode) {
 
   int open_flags = 0;
 
-  if (file_mode.append_allowed()) {
+  if (file_mode.is_append()) {
     open_flags = O_CREAT | O_APPEND;
-    if (file_mode.is_plus())
+    if (file_mode.is_update())
       open_flags |= O_RDWR;
     else
       open_flags |= O_WRONLY;
-  } else if (file_mode.write_allowed()) {
+  } else if (file_mode.is_write()) {
     open_flags = O_CREAT | O_TRUNC;
-    if (file_mode.is_plus())
+    if (file_mode.is_update())
       open_flags |= O_RDWR;
     else
       open_flags |= O_WRONLY;
   } else {
-    if (file_mode.is_plus())
+    if (file_mode.is_update())
       open_flags |= O_RDWR;
     else
       open_flags |= O_RDONLY;
@@ -140,18 +140,26 @@ ErrorOr<LinuxFile *> create_file_from_fd(int fd, const char *mode) {
   }
   int fd_flags = result.value();
 
-  const bool REQUIRES_WRITE = file_mode.write_allowed() ||
-                              file_mode.append_allowed() || file_mode.is_plus();
+  // constants to check whether a file descriptor was opened in read or write
+  // only mode
+  const bool FD_OPENED_IN_READ_ONLY = (fd_flags & O_ACCMODE) == O_RDONLY;
+  const bool FD_OPENED_IN_WRITE_ONLY = (fd_flags & O_ACCMODE) == O_WRONLY;
 
-  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)) {
+  if ((FD_OPENED_IN_READ_ONLY && file_mode.write_allowed()) ||
+      (FD_OPENED_IN_WRITE_ONLY && file_mode.read_allowed())) {
     return Error(EINVAL);
   }
 
   bool do_seek = false;
-  if (file_mode.append_allowed() && !(fd_flags & O_APPEND)) {
+
+  // TODO: Ask Michael if this explicit value is better. I think it is more
+  // readable in the conditional statements than the bit manipulations.
+  //
+  // TODO<me>: If he agrees check for conditional statements with bit checking
+  // and rework their use.
+  const bool APPEND_MODE_IS_ENABLED_IN_FD = fd_flags & O_APPEND;
+
+  if (file_mode.is_append() && !APPEND_MODE_IS_ENABLED_IN_FD) {
     do_seek = true;
     if (!linux_syscalls::fcntl(fd, F_SETFL,
                                reinterpret_cast<void *>(fd_flags | O_APPEND))
@@ -255,27 +263,27 @@ int LinuxFile::reopen_unlocked(const char *path, const char *mode) {
     return EBADF;
   int fd_flags = result.value();
 
-  const bool REQUIRES_WRITE = file_mode.write_allowed() ||
-                              file_mode.append_allowed() || file_mode.is_plus();
-
-  const bool REQUIRES_READ = file_mode.write_allowed() || file_mode.is_plus();
+  // constants to check whether a file descriptor was opened in read or write
+  // only mode
+  const bool FD_OPENED_IN_READ_ONLY = (fd_flags & O_ACCMODE) == O_RDONLY;
+  const bool FD_OPENED_IN_WRITE_ONLY = (fd_flags & O_ACCMODE) == O_WRONLY;
 
-  if (((fd_flags & O_ACCMODE) == O_RDONLY && REQUIRES_WRITE) ||
-      ((fd_flags & O_ACCMODE) == O_WRONLY && REQUIRES_READ)) {
+  if ((FD_OPENED_IN_READ_ONLY && file_mode.write_allowed()) ||
+      (FD_OPENED_IN_WRITE_ONLY && file_mode.read_allowed())) {
     return EBADF;
   }
 
   bool do_seek = false;
   bool has_append_flag = fd_flags & O_APPEND;
 
-  if (file_mode.append_allowed() && !has_append_flag) {
+  if (file_mode.is_append() && !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 (!file_mode.append_allowed() && has_append_flag) {
+  } else if (!file_mode.is_append() && has_append_flag) {
     if (!linux_syscalls::fcntl(fd, F_SETFL,
                                reinterpret_cast<void *>(fd_flags & ~O_APPEND))
              .has_value()) {

>From 3ee4635b0dc3b59e7a409a50d801d49dfd8335b1 Mon Sep 17 00:00:00 2001
From: tdadadavid <davidtofunmidada at gmail.com>
Date: Wed, 9 Sep 2026 22:39:23 +0100
Subject: [PATCH 29/41] convert to lowercase to follow convention for constants

Signed-off-by: tdadadavid <davidtofunmidada at gmail.com>
---
 libc/src/__support/File/linux/file.cpp | 26 ++++++++++----------------
 1 file changed, 10 insertions(+), 16 deletions(-)

diff --git a/libc/src/__support/File/linux/file.cpp b/libc/src/__support/File/linux/file.cpp
index c0156c617c11c..f85af6b525fb7 100644
--- a/libc/src/__support/File/linux/file.cpp
+++ b/libc/src/__support/File/linux/file.cpp
@@ -142,24 +142,18 @@ ErrorOr<LinuxFile *> create_file_from_fd(int fd, const char *mode) {
 
   // constants to check whether a file descriptor was opened in read or write
   // only mode
-  const bool FD_OPENED_IN_READ_ONLY = (fd_flags & O_ACCMODE) == O_RDONLY;
-  const bool FD_OPENED_IN_WRITE_ONLY = (fd_flags & O_ACCMODE) == O_WRONLY;
+  const bool fd_opened_in_read_only = (fd_flags & O_ACCMODE) == O_RDONLY;
+  const bool fd_opened_in_write_only = (fd_flags & O_ACCMODE) == O_WRONLY;
 
-  if ((FD_OPENED_IN_READ_ONLY && file_mode.write_allowed()) ||
-      (FD_OPENED_IN_WRITE_ONLY && file_mode.read_allowed())) {
+  if ((fd_opened_in_read_only && file_mode.write_allowed()) ||
+      (fd_opened_in_write_only && file_mode.read_allowed())) {
     return Error(EINVAL);
   }
 
   bool do_seek = false;
+  const bool has_append_flag = fd_flags & O_APPEND;
 
-  // TODO: Ask Michael if this explicit value is better. I think it is more
-  // readable in the conditional statements than the bit manipulations.
-  //
-  // TODO<me>: If he agrees check for conditional statements with bit checking
-  // and rework their use.
-  const bool APPEND_MODE_IS_ENABLED_IN_FD = fd_flags & O_APPEND;
-
-  if (file_mode.is_append() && !APPEND_MODE_IS_ENABLED_IN_FD) {
+  if (file_mode.is_append() && !has_append_flag) {
     do_seek = true;
     if (!linux_syscalls::fcntl(fd, F_SETFL,
                                reinterpret_cast<void *>(fd_flags | O_APPEND))
@@ -265,11 +259,11 @@ int LinuxFile::reopen_unlocked(const char *path, const char *mode) {
 
   // constants to check whether a file descriptor was opened in read or write
   // only mode
-  const bool FD_OPENED_IN_READ_ONLY = (fd_flags & O_ACCMODE) == O_RDONLY;
-  const bool FD_OPENED_IN_WRITE_ONLY = (fd_flags & O_ACCMODE) == O_WRONLY;
+  const bool fd_opened_in_read_only = (fd_flags & O_ACCMODE) == O_RDONLY;
+  const bool fd_opened_in_write_only = (fd_flags & O_ACCMODE) == O_WRONLY;
 
-  if ((FD_OPENED_IN_READ_ONLY && file_mode.write_allowed()) ||
-      (FD_OPENED_IN_WRITE_ONLY && file_mode.read_allowed())) {
+  if ((fd_opened_in_read_only && file_mode.write_allowed()) ||
+      (fd_opened_in_write_only && file_mode.read_allowed())) {
     return EBADF;
   }
 

>From bea8e9694d72d07e5a759ec9ab9de152d7cff654 Mon Sep 17 00:00:00 2001
From: tdadadavid <davidtofunmidada at gmail.com>
Date: Wed, 9 Sep 2026 23:01:33 +0100
Subject: [PATCH 30/41] refactor c-to-linux flags mapper for better clarity and
 understanding

Signed-off-by: tdadadavid <davidtofunmidada at gmail.com>
---
 libc/src/__support/File/linux/file.cpp | 45 ++++++++++++++------------
 1 file changed, 24 insertions(+), 21 deletions(-)

diff --git a/libc/src/__support/File/linux/file.cpp b/libc/src/__support/File/linux/file.cpp
index f85af6b525fb7..71b7046886730 100644
--- a/libc/src/__support/File/linux/file.cpp
+++ b/libc/src/__support/File/linux/file.cpp
@@ -69,29 +69,32 @@ int linux_file_close(File *f) {
   return retval;
 }
 
-static int map_c_mode_flags_to_linux_open_flags(FileMode mode) {
-  FileMode file_mode(mode);
-
+// helper methods for manipulating linux file flags
+static constexpr int create_and_append() { return O_CREAT | O_APPEND; }
+static constexpr int read_and_write() { return O_RDWR; }
+static constexpr int write_only() { return O_WRONLY; }
+static constexpr int read_only() { return O_RDONLY; }
+static constexpr int create_or_truncate() { return O_CREAT | O_TRUNC; }
+
+static int map_c_mode_flags_to_linux_open_flags(FileMode file_mode) {
   int open_flags = 0;
 
-  if (file_mode.is_append()) {
-    open_flags = O_CREAT | O_APPEND;
-    if (file_mode.is_update())
-      open_flags |= O_RDWR;
-    else
-      open_flags |= O_WRONLY;
-  } else if (file_mode.is_write()) {
-    open_flags = O_CREAT | O_TRUNC;
-    if (file_mode.is_update())
-      open_flags |= O_RDWR;
-    else
-      open_flags |= O_WRONLY;
-  } else {
-    if (file_mode.is_update())
-      open_flags |= O_RDWR;
-    else
-      open_flags |= O_RDONLY;
-  }
+  // handle access patterns i.e whether the file should be in
+  // only read, write modes or both.
+  if (file_mode.is_update())
+    open_flags |= read_and_write();
+  else if (file_mode.is_append() || file_mode.is_write())
+    open_flags |= write_only();
+  else
+    open_flags = write_only();
+
+  // handle the behaviour of the file when accessed i.e should the file
+  // be appended to or truncate when created.
+  if (file_mode.is_append())
+    open_flags |= create_and_append();
+  else if (file_mode.is_write())
+    open_flags |= create_or_truncate();
+
   return open_flags;
 }
 

>From 305c2bdb61167efce31f40efd7e6ee20a44211ad Mon Sep 17 00:00:00 2001
From: tdadadavid <davidtofunmidada at gmail.com>
Date: Wed, 9 Sep 2026 23:03:45 +0100
Subject: [PATCH 31/41] make file_mode in mapper a constant since it's state is
 not altered within the function

Signed-off-by: tdadadavid <davidtofunmidada at gmail.com>
---
 libc/src/__support/File/linux/file.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libc/src/__support/File/linux/file.cpp b/libc/src/__support/File/linux/file.cpp
index 71b7046886730..cb65f02b00ccc 100644
--- a/libc/src/__support/File/linux/file.cpp
+++ b/libc/src/__support/File/linux/file.cpp
@@ -76,7 +76,7 @@ static constexpr int write_only() { return O_WRONLY; }
 static constexpr int read_only() { return O_RDONLY; }
 static constexpr int create_or_truncate() { return O_CREAT | O_TRUNC; }
 
-static int map_c_mode_flags_to_linux_open_flags(FileMode file_mode) {
+static int map_c_mode_flags_to_linux_open_flags(const FileMode &file_mode) {
   int open_flags = 0;
 
   // handle access patterns i.e whether the file should be in

>From 7a685ae577fb244878879e5e7bbeb2a07f074629 Mon Sep 17 00:00:00 2001
From: tdadadavid <davidtofunmidada at gmail.com>
Date: Wed, 9 Sep 2026 23:13:11 +0100
Subject: [PATCH 32/41] fix some errors

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 cb65f02b00ccc..7c2ddc3445dae 100644
--- a/libc/src/__support/File/linux/file.cpp
+++ b/libc/src/__support/File/linux/file.cpp
@@ -82,11 +82,11 @@ static int map_c_mode_flags_to_linux_open_flags(const FileMode &file_mode) {
   // handle access patterns i.e whether the file should be in
   // only read, write modes or both.
   if (file_mode.is_update())
-    open_flags |= read_and_write();
+    open_flags = read_and_write();
   else if (file_mode.is_append() || file_mode.is_write())
-    open_flags |= write_only();
-  else
     open_flags = write_only();
+  else
+    open_flags = read_only();
 
   // handle the behaviour of the file when accessed i.e should the file
   // be appended to or truncate when created.

>From 7693389777b50cabe69dc177e19c0a42e9073f92 Mon Sep 17 00:00:00 2001
From: tdadadavid <davidtofunmidada at gmail.com>
Date: Wed, 9 Sep 2026 23:22:12 +0100
Subject: [PATCH 33/41] restrict file mode instances from being updated or
 changed

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 7c2ddc3445dae..675ab34c85310 100644
--- a/libc/src/__support/File/linux/file.cpp
+++ b/libc/src/__support/File/linux/file.cpp
@@ -99,7 +99,7 @@ static int map_c_mode_flags_to_linux_open_flags(const FileMode &file_mode) {
 }
 
 ErrorOr<File *> openfile(const char *path, const char *mode) {
-  FileMode file_mode(mode);
+  const FileMode file_mode(mode);
 
   if (!file_mode.is_valid()) {
     return Error(EINVAL);
@@ -131,7 +131,7 @@ ErrorOr<File *> openfile(const char *path, const char *mode) {
 }
 
 ErrorOr<LinuxFile *> create_file_from_fd(int fd, const char *mode) {
-  FileMode file_mode(mode);
+  const FileMode file_mode(mode);
 
   if (!file_mode.is_valid()) {
     return Error(EINVAL);
@@ -192,7 +192,7 @@ ErrorOr<LinuxFile *> create_file_from_fd(int fd, const char *mode) {
 }
 
 int LinuxFile::reopen_unlocked(const char *path, const char *mode) {
-  FileMode file_mode(mode);
+  const FileMode *file_mode(mode);
 
   if (path != nullptr) {
     int old_fd = get_fd();

>From ff08a7ad6867187bd4b42d45e60251e6403abbd3 Mon Sep 17 00:00:00 2001
From: tdadadavid <davidtofunmidada at gmail.com>
Date: Wed, 9 Sep 2026 23:30:50 +0100
Subject: [PATCH 34/41] remove  const pointer reference

Signed-off-by: tdadadavid <davidtofunmidada at gmail.com>
---
 libc/src/__support/File/linux/file.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libc/src/__support/File/linux/file.cpp b/libc/src/__support/File/linux/file.cpp
index 675ab34c85310..6d5586ab4150c 100644
--- a/libc/src/__support/File/linux/file.cpp
+++ b/libc/src/__support/File/linux/file.cpp
@@ -192,7 +192,7 @@ ErrorOr<LinuxFile *> create_file_from_fd(int fd, const char *mode) {
 }
 
 int LinuxFile::reopen_unlocked(const char *path, const char *mode) {
-  const FileMode *file_mode(mode);
+  const FileMode file_mode(mode);
 
   if (path != nullptr) {
     int old_fd = get_fd();

>From 07f666c50eab498b69be8ad195acd250df758f48 Mon Sep 17 00:00:00 2001
From: tdadadavid <davidtofunmidada at gmail.com>
Date: Thu, 10 Sep 2026 11:46:34 +0100
Subject: [PATCH 35/41] make all method constexpr because FileMode is used in
 static initialization of StdOut, StdIn and StdErr

Signed-off-by: tdadadavid <davidtofunmidada at gmail.com>
---
 libc/src/__support/File/file_mode.h | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/libc/src/__support/File/file_mode.h b/libc/src/__support/File/file_mode.h
index 176b8f919ccf4..b93bb0c53483a 100644
--- a/libc/src/__support/File/file_mode.h
+++ b/libc/src/__support/File/file_mode.h
@@ -64,36 +64,36 @@ class FileMode {
       file_mode_ = 0;
   }
 
-  bool write_allowed() const {
+  constexpr bool write_allowed() const {
     return is_write() || is_append() || is_update();
   }
 
-  bool read_allowed() const { return is_read() || is_update(); }
+  constexpr bool read_allowed() const { return is_read() || is_update(); }
 
-  bool is_valid() const { return file_mode_ != 0; }
+  constexpr bool is_valid() const { return file_mode_ != 0; }
 
-  bool is_append() const {
+  constexpr bool is_append() const {
     return (file_mode_ & static_cast<Mode>(OpenMode::APPEND)) != 0;
   }
 
-  bool is_update() const {
+  constexpr bool is_update() const {
     return (file_mode_ & static_cast<Mode>(OpenMode::PLUS)) != 0;
   }
 
-  bool is_write() const {
+  constexpr bool is_write() const {
     return (file_mode_ & static_cast<Mode>(OpenMode::WRITE)) != 0;
   }
 
-  bool is_read() const {
+  constexpr bool is_read() const {
     return (file_mode_ & static_cast<Mode>(OpenMode::READ)) != 0;
   }
 
-  bool is_binary_format() const {
+  constexpr bool is_binary_format() const {
     return (file_mode_ & static_cast<Mode>(ContentType::BINARY)) != 0;
   }
 
   // checks if a file was created for writing
-  bool is_exclusive_create() const {
+  constexpr bool is_exclusive_create() const {
     return (file_mode_ & static_cast<Mode>(CreateType::EXCLUSIVE)) != 0;
   }
 

>From 4efd40ccad6f93e507295af60b904f620739f835 Mon Sep 17 00:00:00 2001
From: tdadadavid <davidtofunmidada at gmail.com>
Date: Thu, 10 Sep 2026 11:47:31 +0100
Subject: [PATCH 36/41] refactor StdIn,StdOut and StdErr to use FileMode
 instead of ModeFlags

Signed-off-by: tdadadavid <davidtofunmidada at gmail.com>
---
 libc/src/stdio/linux/stderr.cpp | 4 +++-
 libc/src/stdio/linux/stdin.cpp  | 4 +++-
 libc/src/stdio/linux/stdout.cpp | 4 +++-
 3 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/libc/src/stdio/linux/stderr.cpp b/libc/src/stdio/linux/stderr.cpp
index b1eaeaaf19834..2c9f35861211f 100644
--- a/libc/src/stdio/linux/stderr.cpp
+++ b/libc/src/stdio/linux/stderr.cpp
@@ -9,6 +9,7 @@
 #include "src/stdio/stderr.h"
 
 #include "hdr/types/FILE.h"
+#include "src/__support/File/file_mode.h"
 
 #ifdef LIBC_FULL_BUILD
 
@@ -19,8 +20,9 @@
 namespace LIBC_NAMESPACE_DECL {
 
 constexpr size_t STDERR_BUFFER_SIZE = 0;
+constexpr FileMode append_mode("a");
 static LinuxFile StdErr(2, nullptr, STDERR_BUFFER_SIZE, _IONBF, false,
-                        File::ModeFlags(File::OpenMode::APPEND));
+                        append_mode);
 
 LLVM_LIBC_VARIABLE(FILE *, stderr) = reinterpret_cast<FILE *>(&StdErr);
 
diff --git a/libc/src/stdio/linux/stdin.cpp b/libc/src/stdio/linux/stdin.cpp
index 629772714923e..78ce9a6c4ad9d 100644
--- a/libc/src/stdio/linux/stdin.cpp
+++ b/libc/src/stdio/linux/stdin.cpp
@@ -9,6 +9,7 @@
 #include "src/stdio/stdin.h"
 
 #include "hdr/types/FILE.h"
+#include "src/__support/File/file_mode.h"
 
 #ifdef LIBC_FULL_BUILD
 
@@ -20,8 +21,9 @@ namespace LIBC_NAMESPACE_DECL {
 
 constexpr size_t STDIN_BUFFER_SIZE = 512;
 uint8_t stdin_buffer[STDIN_BUFFER_SIZE];
+constexpr FileMode read_mode("r");
 static LinuxFile StdIn(0, stdin_buffer, STDIN_BUFFER_SIZE, _IOFBF, false,
-                       File::ModeFlags(File::OpenMode::READ));
+                       read_mode);
 
 LLVM_LIBC_VARIABLE(FILE *, stdin) = reinterpret_cast<FILE *>(&StdIn);
 
diff --git a/libc/src/stdio/linux/stdout.cpp b/libc/src/stdio/linux/stdout.cpp
index d0731c9a218f3..30c9dc45083a2 100644
--- a/libc/src/stdio/linux/stdout.cpp
+++ b/libc/src/stdio/linux/stdout.cpp
@@ -9,6 +9,7 @@
 #include "src/stdio/stdout.h"
 
 #include "hdr/types/FILE.h"
+#include "src/__support/File/file_mode.h"
 
 #ifdef LIBC_FULL_BUILD
 
@@ -20,8 +21,9 @@ namespace LIBC_NAMESPACE_DECL {
 
 constexpr size_t STDOUT_BUFFER_SIZE = 1024;
 uint8_t stdout_buffer[STDOUT_BUFFER_SIZE];
+constexpr FileMode append_mode("a");
 static LinuxFile StdOut(1, stdout_buffer, STDOUT_BUFFER_SIZE, _IOLBF, false,
-                        File::ModeFlags(File::OpenMode::APPEND));
+                        append_mode);
 
 LLVM_LIBC_VARIABLE(FILE *, stdout) = reinterpret_cast<FILE *>(&StdOut);
 

>From 10934dc9a547849726699219a378271622be7fca Mon Sep 17 00:00:00 2001
From: tdadadavid <davidtofunmidada at gmail.com>
Date: Thu, 10 Sep 2026 11:48:45 +0100
Subject: [PATCH 37/41] test: setup initial test for FileMode (testing initial
 mode characters

Signed-off-by: tdadadavid <davidtofunmidada at gmail.com>
---
 libc/test/src/__support/File/CMakeLists.txt   | 10 +++
 .../src/__support/File/file_mode_test.cpp     | 66 +++++++++++++++++++
 libc/test/src/__support/File/file_test.cpp    | 12 ++--
 3 files changed, 82 insertions(+), 6 deletions(-)
 create mode 100644 libc/test/src/__support/File/file_mode_test.cpp

diff --git a/libc/test/src/__support/File/CMakeLists.txt b/libc/test/src/__support/File/CMakeLists.txt
index 070ce4a9aed89..bd5fe622fede0 100644
--- a/libc/test/src/__support/File/CMakeLists.txt
+++ b/libc/test/src/__support/File/CMakeLists.txt
@@ -22,6 +22,16 @@ add_libc_test(
     libc.test.UnitTest.MemoryMatcher
 )
 
+add_libc_test(
+  file_mode_test
+  SUITE
+    libc-support-tests
+  SRCS
+    file_mode_test.cpp
+  DEPENDS
+    libc.src.__support.File.file
+)
+
 add_libc_test(
   platform_file_test
   SUITE
diff --git a/libc/test/src/__support/File/file_mode_test.cpp b/libc/test/src/__support/File/file_mode_test.cpp
new file mode 100644
index 0000000000000..213d418bc9b89
--- /dev/null
+++ b/libc/test/src/__support/File/file_mode_test.cpp
@@ -0,0 +1,66 @@
+//===-- Unittests for file mode class//---------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/__support/File/file_mode.h"
+#include "src/__support/macros/config.h"
+#include "test/UnitTest/Test.h"
+
+using LIBC_NAMESPACE::FileMode;
+
+TEST(LlvmLibcFileModeTest, FirstCharacterMustBeAValidMode) {
+  // creates a table structure to group tests
+  struct TestCase {
+    const char *test_name;
+    const char *mode;
+    bool expects;
+  };
+
+  constexpr TestCase valid_modes[] = {
+      {.test_name = "valid append mode", .mode = "a", .expects = true},
+      {.test_name = "valid read mode", .mode = "r", .expects = true},
+      {.test_name = "valid write mode", .mode = "w", .expects = true},
+  };
+
+  for (const TestCase &tc : valid_modes) {
+    const FileMode mode(tc.mode);
+    EXPECT_EQ(mode.is_valid(), tc.expects);
+  };
+
+  constexpr TestCase invalid_first_char_modes[] = {
+      {.test_name = "update mode set as the first character",
+       .mode = "+",
+       .expects = false},
+      {.test_name = "binary content set as the first character",
+       .mode = "b",
+       .expects = false},
+      {.test_name = "exclusive create set as the first character",
+       .mode = "x",
+       .expects = false},
+  };
+
+  for (const TestCase &tc : invalid_first_char_modes) {
+    const FileMode mode(tc.mode);
+    EXPECT_EQ(mode.is_valid(), tc.expects);
+  };
+}
+
+// Test(LlvmLibcFileModeTest, OnlyOneMainModeAllowed) {}
+//
+// Test(LlvmLibcFileModeTest, WriteAllowedMode) {}
+//
+// Test(LlvmLibcFileModeTest, FileModeIsReadAllowed) {}
+//
+// Test(LlvmLibcFileModeTest, WriteOnlyAllowed) {}
+//
+// Test(LlvmLibcFileModeTest, ReadOnlyAllowed) {}
+//
+// Test(LlvmLibcFileModeTest, AppendAllowed) {}
+//
+// Test(LlvmLibcFileModeTest, BinaryContentBitIsSet) {}
+//
+// Test(LlvmLibcFileModeTest, ExclusiveCreateBitIsSet) {}
diff --git a/libc/test/src/__support/File/file_test.cpp b/libc/test/src/__support/File/file_test.cpp
index 81677529ebc32..c3222c06541e7 100644
--- a/libc/test/src/__support/File/file_test.cpp
+++ b/libc/test/src/__support/File/file_test.cpp
@@ -21,6 +21,7 @@ using MemoryView = LIBC_NAMESPACE::testing::MemoryView;
 using LIBC_NAMESPACE::ErrorOr;
 using LIBC_NAMESPACE::File;
 using LIBC_NAMESPACE::FileIOResult;
+using LIBC_NAMESPACE::FileMode;
 
 class StringFile : public File {
   static constexpr size_t SIZE = 512;
@@ -41,13 +42,12 @@ class StringFile : public File {
 
 public:
   explicit StringFile(char *buffer, size_t buflen, int bufmode, bool owned,
-                      ModeFlags modeflags)
+                      FileMode mode)
       : LIBC_NAMESPACE::File(&str_write, &str_read, &str_seek, &str_close,
                              reinterpret_cast<uint8_t *>(buffer), buflen,
-                             bufmode, owned, modeflags),
+                             bufmode, owned, mode),
         pos(0), eof_marker(0), write_append(false) {
-    if (modeflags &
-        static_cast<ModeFlags>(LIBC_NAMESPACE::File::OpenMode::APPEND))
+    if (mode.is_append())
       write_append = true;
   }
 
@@ -109,10 +109,10 @@ ErrorOr<off_t> StringFile::str_seek(LIBC_NAMESPACE::File *f, off_t offset,
 StringFile *new_string_file(char *buffer, size_t buflen, int bufmode,
                             bool owned, const char *mode) {
   LIBC_NAMESPACE::AllocChecker ac;
+  const FileMode file_mode(mode);
   // We will just assume the allocation succeeds. We cannot test anything
   // otherwise.
-  return new (ac) StringFile(buffer, buflen, bufmode, owned,
-                             LIBC_NAMESPACE::File::mode_flags(mode));
+  return new (ac) StringFile(buffer, buflen, bufmode, owned, file_mode);
 }
 
 TEST(LlvmLibcFileTest, WriteOnly) {

>From c0c579a38291ea2bce973fd209e303168f01cbc0 Mon Sep 17 00:00:00 2001
From: tdadadavid <davidtofunmidada at gmail.com>
Date: Thu, 10 Sep 2026 12:37:32 +0100
Subject: [PATCH 38/41] add tests for only main mode allowed when creating a
 file mode

Signed-off-by: tdadadavid <davidtofunmidada at gmail.com>
---
 .../src/__support/File/file_mode_test.cpp     | 123 +++++++++++++++---
 1 file changed, 102 insertions(+), 21 deletions(-)

diff --git a/libc/test/src/__support/File/file_mode_test.cpp b/libc/test/src/__support/File/file_mode_test.cpp
index 213d418bc9b89..cdaab21d0f3d2 100644
--- a/libc/test/src/__support/File/file_mode_test.cpp
+++ b/libc/test/src/__support/File/file_mode_test.cpp
@@ -15,42 +15,123 @@ using LIBC_NAMESPACE::FileMode;
 TEST(LlvmLibcFileModeTest, FirstCharacterMustBeAValidMode) {
   // creates a table structure to group tests
   struct TestCase {
-    const char *test_name;
+    const char *test_description;
     const char *mode;
     bool expects;
   };
 
-  constexpr TestCase valid_modes[] = {
-      {.test_name = "valid append mode", .mode = "a", .expects = true},
-      {.test_name = "valid read mode", .mode = "r", .expects = true},
-      {.test_name = "valid write mode", .mode = "w", .expects = true},
-  };
-
-  for (const TestCase &tc : valid_modes) {
-    const FileMode mode(tc.mode);
-    EXPECT_EQ(mode.is_valid(), tc.expects);
-  };
-
-  constexpr TestCase invalid_first_char_modes[] = {
-      {.test_name = "update mode set as the first character",
+  // testing for first character to be valid mode
+  constexpr TestCase first_char_modes[] = {
+      {.test_description = "valid append mode", .mode = "a", .expects = true},
+      {.test_description = "valid read mode", .mode = "r", .expects = true},
+      {.test_description = "valid write mode", .mode = "w", .expects = true},
+      {.test_description = "update mode set as the first character",
        .mode = "+",
        .expects = false},
-      {.test_name = "binary content set as the first character",
+      {.test_description = "binary content set as the first character",
        .mode = "b",
        .expects = false},
-      {.test_name = "exclusive create set as the first character",
+      {.test_description = "exclusive create set as the first character",
        .mode = "x",
-       .expects = false},
-  };
+       .expects = false}};
 
-  for (const TestCase &tc : invalid_first_char_modes) {
+  for (const TestCase &tc : first_char_modes) {
     const FileMode mode(tc.mode);
     EXPECT_EQ(mode.is_valid(), tc.expects);
   };
 }
 
-// Test(LlvmLibcFileModeTest, OnlyOneMainModeAllowed) {}
-//
+TEST(LlvmLibcFileModeTest, OnlyOneMainModeAllowed) {
+  struct TestCase {
+    const char *test_description;
+    const char *mode;
+    bool expects;
+    const char *message = "";
+  };
+
+  // This tracks all possible valid combinations for a file mode with a main
+  // mode both the ones that are allowed and the ones not allowed. The list is
+  // exhaustive
+  //
+  // These are the valid main mode combinations
+  //  read(r) = [update(+), binary(b)]
+  //  write(w) = [update(+), binary(b), exclusive(x)]
+  //  append(a) = [update(+), binary(b)]
+  //
+  // Invalid main mode combinations are
+  //  read(r) = [write(w), append(a)]
+  //  apppend(a) = [read(r), write(w)]
+  constexpr TestCase modes_combination[] = {
+      // read(r) = [update(+), binary(b)]
+      {.test_description = "read and update", .mode = "r+", .expects = true},
+      {.test_description = "read binary", .mode = "rb", .expects = true},
+
+      // write(w) = [update(+), binary(b), exclusive(x)]
+      {.test_description = "write and update", .mode = "w+", .expects = true},
+      {.test_description = "write binary", .mode = "wb", .expects = true},
+      {.test_description = "write exclusive", .mode = "wx", .expects = true},
+
+      // append(a) = [update(+), binary(b)]
+      {.test_description = "append and update", .mode = "a+", .expects = true},
+      {.test_description = "append binary", .mode = "ab", .expects = true},
+
+      // invalid main mode = read
+      {
+          .test_description = "read and write",
+          .mode = "rw",
+          .expects = false,
+          .message = "read and write are both main modes and there can be only "
+                     "one main mode",
+      },
+      {
+          .test_description = "read and append",
+          .mode = "ra",
+          .expects = false,
+          .message =
+              "read and append are both main modes and there can be only "
+              "one main mode",
+      },
+
+      // invalid main mode = write
+      {
+          .test_description = "write and read",
+          .mode = "wr",
+          .expects = false,
+          .message = "write and read are all main modes and there can be only "
+                     "one main mode",
+      },
+      {
+          .test_description = "write and append",
+          .mode = "wr",
+          .expects = false,
+          .message = "write and read are all main modes and there can be only "
+                     "one main mode",
+      },
+      {
+          .test_description = "append and read",
+          .mode = "wr",
+          .expects = false,
+          .message = "append and read are all main modes and there can be only "
+                     "one main mode",
+      },
+      {
+          .test_description = "read,write and append",
+          .mode = "rwa",
+          .expects = false,
+          .message =
+              "read, write and append are all main modes and there can be only "
+              "one main mode",
+      },
+  };
+
+  for (const TestCase &tc : modes_combination) {
+    const FileMode mode(tc.mode);
+    EXPECT_EQ(mode.is_valid(), tc.expects) << tc.message;
+  };
+}
+
+// TEST(LlvmLibcFileModeTest, AllPossibleValidModes) {}
+
 // Test(LlvmLibcFileModeTest, WriteAllowedMode) {}
 //
 // Test(LlvmLibcFileModeTest, FileModeIsReadAllowed) {}

>From 877b9169d1c742584a68602f001f8200c7171914 Mon Sep 17 00:00:00 2001
From: tdadadavid <davidtofunmidada at gmail.com>
Date: Thu, 10 Sep 2026 12:57:46 +0100
Subject: [PATCH 39/41] test: add tests for all possible valid combinations of
 c file modes

Signed-off-by: tdadadavid <davidtofunmidada at gmail.com>
---
 .../src/__support/File/file_mode_test.cpp     | 110 +++++++++++++++---
 1 file changed, 96 insertions(+), 14 deletions(-)

diff --git a/libc/test/src/__support/File/file_mode_test.cpp b/libc/test/src/__support/File/file_mode_test.cpp
index cdaab21d0f3d2..48094e69acd98 100644
--- a/libc/test/src/__support/File/file_mode_test.cpp
+++ b/libc/test/src/__support/File/file_mode_test.cpp
@@ -63,10 +63,12 @@ TEST(LlvmLibcFileModeTest, OnlyOneMainModeAllowed) {
   //  apppend(a) = [read(r), write(w)]
   constexpr TestCase modes_combination[] = {
       // read(r) = [update(+), binary(b)]
+      {.test_description = "read only", .mode = "r", .expects = true},
       {.test_description = "read and update", .mode = "r+", .expects = true},
       {.test_description = "read binary", .mode = "rb", .expects = true},
 
       // write(w) = [update(+), binary(b), exclusive(x)]
+      {.test_description = "write only", .mode = "w", .expects = true},
       {.test_description = "write and update", .mode = "w+", .expects = true},
       {.test_description = "write binary", .mode = "wb", .expects = true},
       {.test_description = "write exclusive", .mode = "wx", .expects = true},
@@ -130,18 +132,98 @@ TEST(LlvmLibcFileModeTest, OnlyOneMainModeAllowed) {
   };
 }
 
-// TEST(LlvmLibcFileModeTest, AllPossibleValidModes) {}
+TEST(LlvmLibcFileModeTest, AllValidModes) {
+  struct TestCase {
+    const char *test_description;
+    const char *mode;
+    bool expects;
+  };
 
-// Test(LlvmLibcFileModeTest, WriteAllowedMode) {}
-//
-// Test(LlvmLibcFileModeTest, FileModeIsReadAllowed) {}
-//
-// Test(LlvmLibcFileModeTest, WriteOnlyAllowed) {}
-//
-// Test(LlvmLibcFileModeTest, ReadOnlyAllowed) {}
-//
-// Test(LlvmLibcFileModeTest, AppendAllowed) {}
-//
-// Test(LlvmLibcFileModeTest, BinaryContentBitIsSet) {}
-//
-// Test(LlvmLibcFileModeTest, ExclusiveCreateBitIsSet) {}
+  constexpr TestCase valid_modes[] = {
+      // Read
+      {.test_description = "read", .mode = "r", .expects = true},
+      {.test_description = "read binary", .mode = "rb", .expects = true},
+      {.test_description = "read update", .mode = "r+", .expects = true},
+      {.test_description = "read update binary",
+       .mode = "r+b",
+       .expects = true},
+      {.test_description = "read binary update",
+       .mode = "rb+",
+       .expects = true},
+
+      // Write
+      {.test_description = "write", .mode = "w", .expects = true},
+      {.test_description = "write binary", .mode = "wb", .expects = true},
+      {.test_description = "write exclusive", .mode = "wx", .expects = true},
+      {.test_description = "write binary exclusive",
+       .mode = "wbx",
+       .expects = true},
+      {.test_description = "write update", .mode = "w+", .expects = true},
+      {.test_description = "write update binary",
+       .mode = "w+b",
+       .expects = true},
+      {.test_description = "write binary update",
+       .mode = "wb+",
+       .expects = true},
+      {.test_description = "write update exclusive",
+       .mode = "w+x",
+       .expects = true},
+      {.test_description = "write update binary exclusive",
+       .mode = "w+bx",
+       .expects = true},
+      {.test_description = "write binary update exclusive",
+       .mode = "wb+x",
+       .expects = true},
+
+      // Append
+      {.test_description = "append", .mode = "a", .expects = true},
+      {.test_description = "append binary", .mode = "ab", .expects = true},
+      {.test_description = "append update", .mode = "a+", .expects = true},
+      {.test_description = "append update binary",
+       .mode = "a+b",
+       .expects = true},
+      {.test_description = "append binary update",
+       .mode = "ab+",
+       .expects = true},
+  };
+
+  for (const TestCase &tc : valid_modes) {
+    const FileMode mode(tc.mode);
+
+    EXPECT_TRUE(mode.is_valid());
+  }
+}
+
+TEST(LlvmLibcFileModeTest, WriteAllowedMode) {
+  const FileMode mode("w+");
+
+  EXPECT_TRUE(mode.is_valid());
+  EXPECT_TRUE(mode.write_allowed());
+}
+
+TEST(LlvmLibcFileModeTest, FileModeIsReadAllowed) {
+  const FileMode mode("r+");
+
+  EXPECT_TRUE(mode.is_valid());
+  EXPECT_TRUE(mode.read_allowed());
+  EXPECT_TRUE(mode.is_update());
+}
+
+TEST(LlvmLibcFileModeTest, FileContentIsBinary) {
+  struct TestCase {
+    const char *mode;
+  };
+
+  constexpr TestCase binary_modes[] = {
+      {.mode = "wb"},
+      {.mode = "rb"},
+      {.mode = "ab"},
+  };
+
+  for (const TestCase &tc : binary_modes) {
+    const FileMode mode(tc.mode);
+
+    EXPECT_TRUE(mode.is_valid());
+    EXPECT_TRUE(mode.is_binary_format());
+  }
+}

>From 5a7425d8ff31e033ae9d51c2243356428daa3dd7 Mon Sep 17 00:00:00 2001
From: tdadadavid <davidtofunmidada at gmail.com>
Date: Thu, 10 Sep 2026 13:00:33 +0100
Subject: [PATCH 40/41] improve comments

Signed-off-by: tdadadavid <davidtofunmidada at gmail.com>
---
 libc/test/src/__support/File/file_mode_test.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/libc/test/src/__support/File/file_mode_test.cpp b/libc/test/src/__support/File/file_mode_test.cpp
index 48094e69acd98..367473ed4b05b 100644
--- a/libc/test/src/__support/File/file_mode_test.cpp
+++ b/libc/test/src/__support/File/file_mode_test.cpp
@@ -151,7 +151,7 @@ TEST(LlvmLibcFileModeTest, AllValidModes) {
        .mode = "rb+",
        .expects = true},
 
-      // Write
+      // Write combinations
       {.test_description = "write", .mode = "w", .expects = true},
       {.test_description = "write binary", .mode = "wb", .expects = true},
       {.test_description = "write exclusive", .mode = "wx", .expects = true},
@@ -175,7 +175,7 @@ TEST(LlvmLibcFileModeTest, AllValidModes) {
        .mode = "wb+x",
        .expects = true},
 
-      // Append
+      // Append combinations
       {.test_description = "append", .mode = "a", .expects = true},
       {.test_description = "append binary", .mode = "ab", .expects = true},
       {.test_description = "append update", .mode = "a+", .expects = true},

>From a904a92bfea28bfda224aa94ad48cb132abb3cc1 Mon Sep 17 00:00:00 2001
From: tdadadavid <davidtofunmidada at gmail.com>
Date: Thu, 10 Sep 2026 13:09:06 +0100
Subject: [PATCH 41/41] update ModeFlags implementation to FileMode

Signed-off-by: tdadadavid <davidtofunmidada at gmail.com>
---
 libc/src/stdio/fopencookie.cpp             |  7 ++++---
 libc/test/src/__support/File/file_test.cpp | 10 +++++-----
 2 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/libc/src/stdio/fopencookie.cpp b/libc/src/stdio/fopencookie.cpp
index dafc7823e5fd9..a67f8ca4c1e43 100644
--- a/libc/src/stdio/fopencookie.cpp
+++ b/libc/src/stdio/fopencookie.cpp
@@ -13,6 +13,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/alloc-checker.h"
 
 #include "src/__support/libc_errno.h"
@@ -33,7 +34,7 @@ class CookieFile : public LIBC_NAMESPACE::File {
 
 public:
   CookieFile(void *c, cookie_io_functions_t cops, uint8_t *buffer,
-             size_t bufsize, File::ModeFlags mode)
+             size_t bufsize, FileMode mode)
       : File(&cookie_write, &cookie_read, &CookieFile::cookie_seek,
              &cookie_close, buffer, bufsize, 0 /* default buffering mode */,
              true /* File owns buffer */, mode),
@@ -92,8 +93,8 @@ LLVM_LIBC_FUNCTION(::FILE *, fopencookie,
       return nullptr;
   }
   AllocChecker ac;
-  auto *file = new (ac) CookieFile(
-      cookie, ops, buffer, File::DEFAULT_BUFFER_SIZE, File::mode_flags(mode));
+  auto *file = new (ac) CookieFile(cookie, ops, buffer,
+                                   File::DEFAULT_BUFFER_SIZE, FileMode(mode));
   if (!ac)
     return nullptr;
   return reinterpret_cast<::FILE *>(file);
diff --git a/libc/test/src/__support/File/file_test.cpp b/libc/test/src/__support/File/file_test.cpp
index c3222c06541e7..db475b946c7df 100644
--- a/libc/test/src/__support/File/file_test.cpp
+++ b/libc/test/src/__support/File/file_test.cpp
@@ -830,10 +830,10 @@ class ShortWriteFile : public File {
 
 public:
   explicit ShortWriteFile(char *buffer, size_t buflen, int bufmode, bool owned,
-                          ModeFlags modeflags, size_t max_write_bytes)
+                          FileMode mode, size_t max_write_bytes)
       : LIBC_NAMESPACE::File(&short_write, &short_read, &short_seek,
                              &short_close, reinterpret_cast<uint8_t *>(buffer),
-                             buflen, bufmode, owned, modeflags),
+                             buflen, bufmode, owned, mode),
         pos(0), max_write(max_write_bytes) {}
 
   void reset() { pos = 0; }
@@ -848,9 +848,9 @@ class ShortWriteFile : public File {
 TEST(LlvmLibcFileTest, PartialWideCharWriteDetected) {
   LIBC_NAMESPACE::AllocChecker ac;
   // Unbuffered so writes go directly to platform_write, limited to 2 bytes.
-  ShortWriteFile *f = new (ac) ShortWriteFile(
-      nullptr, 0, _IONBF, true, LIBC_NAMESPACE::File::mode_flags("w"),
-      /*max_write_bytes=*/2);
+  ShortWriteFile *f =
+      new (ac) ShortWriteFile(nullptr, 0, _IONBF, true, FileMode("w"),
+                              /*max_write_bytes=*/2);
   ASSERT_FALSE(f == nullptr);
 
   // € (U+20AC) encodes to 3 UTF-8 bytes: 0xE2 0x82 0xAC.



More information about the libc-commits mailing list