[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:20:57 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/54] 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/54] 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/54] 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/54] 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/54] 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/54] 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/54] 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/54] 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/54] 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/54] 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/54] 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/54] 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/54] 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/54] 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/54] 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/54] 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/54] 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/54] 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/54] 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/54] 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/54] 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/54] 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/54] 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/54] 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/54] 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/54] 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/54] 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/54] 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/54] 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/54] 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/54] 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/54] 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/54] 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/54] 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/54] 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/54] 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/54] 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/54] 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/54] 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/54] 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/54] 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.
>From ecb3aa7d0eb30972576726b62a87b40cd3398b36 Mon Sep 17 00:00:00 2001
From: tdadadavid <davidtofunmidada at gmail.com>
Date: Thu, 10 Sep 2026 21:10:25 +0100
Subject: [PATCH 42/54] rework the file license to use updated format
Signed-off-by: tdadadavid <davidtofunmidada at gmail.com>
---
libc/src/__support/File/file_mode.h | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/libc/src/__support/File/file_mode.h b/libc/src/__support/File/file_mode.h
index 4d3d4a21c4887..a7f3c1e294615 100644
--- a/libc/src/__support/File/file_mode.h
+++ b/libc/src/__support/File/file_mode.h
@@ -1,15 +1,22 @@
-//===--- 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
//
//===----------------------------------------------------------------------===//
+///
+/// file_mode.h
+/// This file contains the implementation of FileMode class. This is the class
+/// that handles everything related to a file's mode.
+///
+//===----------------------------------------------------------------------===//
#ifndef LLVM_LIBC_SRC___SUPPORT_FILE_FILE_MODE_H
#define LLVM_LIBC_SRC___SUPPORT_FILE_FILE_MODE_H
#include "hdr/stdint_proxy.h"
+#include "src/__support/File/file.h"
#include "src/__support/macros/config.h"
namespace LIBC_NAMESPACE_DECL {
>From a5fb48894eadeeb9d5223e3b617182f9344f2e92 Mon Sep 17 00:00:00 2001
From: tdadadavid <davidtofunmidada at gmail.com>
Date: Thu, 10 Sep 2026 21:10:56 +0100
Subject: [PATCH 43/54] create constexpr constant modes
Signed-off-by: tdadadavid <davidtofunmidada at gmail.com>
---
libc/src/__support/File/file_mode.h | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/libc/src/__support/File/file_mode.h b/libc/src/__support/File/file_mode.h
index a7f3c1e294615..b60d2fbb45cd7 100644
--- a/libc/src/__support/File/file_mode.h
+++ b/libc/src/__support/File/file_mode.h
@@ -71,6 +71,10 @@ class FileMode {
file_mode_ = 0;
}
+ static const FileMode APPEND_MODE;
+ static const FileMode READ_MODE;
+ static const FileMode WRITE_MODE;
+
constexpr bool write_allowed() const {
return is_write() || is_append() || is_update();
}
@@ -139,6 +143,10 @@ class FileMode {
Mode file_mode_;
};
+inline constexpr FileMode FileMode::APPEND_MODE("a");
+inline constexpr FileMode FileMode::READ_MODE("r");
+inline constexpr FileMode FileMode::WRITE_MODE("w");
+
} // namespace LIBC_NAMESPACE_DECL
#endif // LLVM_LIBC_SRC___SUPPORT_FILE_FILE_MODE_H
>From 33cf7f3e2290ca0d3ef10403675aa911af4bf4b9 Mon Sep 17 00:00:00 2001
From: tdadadavid <davidtofunmidada at gmail.com>
Date: Thu, 10 Sep 2026 21:14:25 +0100
Subject: [PATCH 44/54] refactor and use FileMode's constexpr modes
Signed-off-by: tdadadavid <davidtofunmidada at gmail.com>
---
libc/src/stdio/linux/stderr.cpp | 3 +--
libc/src/stdio/linux/stdin.cpp | 3 +--
libc/src/stdio/linux/stdout.cpp | 3 +--
3 files changed, 3 insertions(+), 6 deletions(-)
diff --git a/libc/src/stdio/linux/stderr.cpp b/libc/src/stdio/linux/stderr.cpp
index 2c9f35861211f..34a47f93a3c96 100644
--- a/libc/src/stdio/linux/stderr.cpp
+++ b/libc/src/stdio/linux/stderr.cpp
@@ -20,9 +20,8 @@
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,
- append_mode);
+ FileMode::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 78ce9a6c4ad9d..472653aa95d4e 100644
--- a/libc/src/stdio/linux/stdin.cpp
+++ b/libc/src/stdio/linux/stdin.cpp
@@ -21,9 +21,8 @@ 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,
- read_mode);
+ FileMode::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 30c9dc45083a2..56bbe2f5a0683 100644
--- a/libc/src/stdio/linux/stdout.cpp
+++ b/libc/src/stdio/linux/stdout.cpp
@@ -21,9 +21,8 @@ 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,
- append_mode);
+ FileMode::APPEND_MODE);
LLVM_LIBC_VARIABLE(FILE *, stdout) = reinterpret_cast<FILE *>(&StdOut);
>From 79a37e5ee39e418239f30929e99da4e9f76ff434 Mon Sep 17 00:00:00 2001
From: tdadadavid <davidtofunmidada at gmail.com>
Date: Thu, 10 Sep 2026 22:01:39 +0100
Subject: [PATCH 45/54] feat: add class for handling linux file flags
Signed-off-by: tdadadavid <davidtofunmidada at gmail.com>
---
libc/src/__support/File/linux/file_flags.h | 42 ++++++++++++++++++++++
1 file changed, 42 insertions(+)
create mode 100644 libc/src/__support/File/linux/file_flags.h
diff --git a/libc/src/__support/File/linux/file_flags.h b/libc/src/__support/File/linux/file_flags.h
new file mode 100644
index 0000000000000..abc6769ac2856
--- /dev/null
+++ b/libc/src/__support/File/linux/file_flags.h
@@ -0,0 +1,42 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+///
+/// file_flags.h
+/// This file contains the defualt constants of Linux file open flags.
+///
+//===----------------------------------------------------------------------===//
+
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+class LinuxFileFlags {
+public:
+ static constexpr int CREATE_AND_APPEND = O_CREAT | O_APPEND;
+ static constexpr int READ_AND_WRITE = O_RDWR;
+ static constexpr int WRITE_ONLY = O_WRONLY;
+ static constexpr int READ_ONLY = O_RDONLY;
+ static constexpr int CREATE_OR_TRUNCATE = O_CREAT | O_TRUNC;
+
+ // File created will have 0666 permissions.
+ static constexpr mode_t OPEN_MODE =
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+
+ static constexpr int is_file_descriptor_opened_in_read_only(int flag) {
+ return (flag & O_ACCMODE) == O_RDONLY;
+ }
+
+ static constexpr int is_file_descriptor_opened_in_write_only(int flag) {
+ return (flag & O_ACCMODE) == O_WRONLY;
+ }
+
+ static constexpr int file_has_append_flag(int flag) {
+ return flag & O_APPEND;
+ }
+};
+} // namespace LIBC_NAMESPACE_DECL
>From e2b25cca7c7591a1f2d766cc2eb2b2d13782f3d4 Mon Sep 17 00:00:00 2001
From: tdadadavid <davidtofunmidada at gmail.com>
Date: Thu, 10 Sep 2026 22:05:49 +0100
Subject: [PATCH 46/54] replace static flag methods with linux flags constants
Signed-off-by: tdadadavid <davidtofunmidada at gmail.com>
---
libc/src/__support/File/linux/file.cpp | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/libc/src/__support/File/linux/file.cpp b/libc/src/__support/File/linux/file.cpp
index 6d5586ab4150c..7093bc71c7429 100644
--- a/libc/src/__support/File/linux/file.cpp
+++ b/libc/src/__support/File/linux/file.cpp
@@ -7,7 +7,7 @@
//===----------------------------------------------------------------------===//
#include "file.h"
-
+#include "file_flags.h"
#include "hdr/fcntl_macros.h" // For mode_t and other flags to the open syscall
#include "hdr/stdio_macros.h"
#include "hdr/sys_stat_macros.h" // For S_IS*, S_IF*, and S_IR* flags.
@@ -82,18 +82,18 @@ 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 = LinuxFileFlags::READ_AND_WRITE;
else if (file_mode.is_append() || file_mode.is_write())
- open_flags = write_only();
+ open_flags = LinuxFileFlags::WRITE_ONLY;
else
- open_flags = read_only();
+ open_flags = LinuxFileFlags::READ_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();
+ open_flags |= LinuxFileFlags::CREATE_AND_APPEND;
else if (file_mode.is_write())
- open_flags |= create_or_truncate();
+ open_flags |= LinuxFileFlags::CREATE_OR_TRUNCATE;
return open_flags;
}
>From c5727ffed118f819370d1798f822b1097a398f81 Mon Sep 17 00:00:00 2001
From: tdadadavid <davidtofunmidada at gmail.com>
Date: Thu, 10 Sep 2026 22:16:26 +0100
Subject: [PATCH 47/54] refactor bit manipulation with linux file flags
Signed-off-by: tdadadavid <davidtofunmidada at gmail.com>
---
libc/src/__support/File/linux/file.cpp | 49 ++++++++------------------
1 file changed, 15 insertions(+), 34 deletions(-)
diff --git a/libc/src/__support/File/linux/file.cpp b/libc/src/__support/File/linux/file.cpp
index 7093bc71c7429..b757ad9a4bb07 100644
--- a/libc/src/__support/File/linux/file.cpp
+++ b/libc/src/__support/File/linux/file.cpp
@@ -69,13 +69,6 @@ int linux_file_close(File *f) {
return retval;
}
-// 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(const FileMode &file_mode) {
int open_flags = 0;
@@ -106,11 +99,8 @@ ErrorOr<File *> openfile(const char *path, const char *mode) {
}
int open_flags = map_c_mode_flags_to_linux_open_flags(file_mode);
- // File created will have 0666 permissions.
- constexpr mode_t OPEN_MODE =
- S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
-
- ErrorOr<int> fd = linux_syscalls::open(path, open_flags, OPEN_MODE);
+ ErrorOr<int> fd =
+ linux_syscalls::open(path, open_flags, LinuxFileFlags::OPEN_MODE);
if (!fd)
return Error(fd.error());
@@ -143,20 +133,16 @@ ErrorOr<LinuxFile *> create_file_from_fd(int fd, const char *mode) {
}
int fd_flags = result.value();
- // 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_opened_in_read_only && file_mode.write_allowed()) ||
- (fd_opened_in_write_only && file_mode.read_allowed())) {
+ if ((LinuxFileFlags::is_file_descriptor_opened_in_read_only(fd_flags) &&
+ file_mode.write_allowed()) ||
+ (LinuxFileFlags::is_file_descriptor_opened_in_write_only(fd_flags) &&
+ file_mode.read_allowed())) {
return Error(EINVAL);
}
bool do_seek = false;
- const bool has_append_flag = fd_flags & O_APPEND;
-
- if (file_mode.is_append() && !has_append_flag) {
+ if (file_mode.is_append() &&
+ !LinuxFileFlags::file_has_append_flag(fd_flags)) {
do_seek = true;
if (!linux_syscalls::fcntl(fd, F_SETFL,
reinterpret_cast<void *>(fd_flags | O_APPEND))
@@ -208,10 +194,8 @@ int LinuxFile::reopen_unlocked(const char *path, const char *mode) {
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;
-
- ErrorOr<int> new_fd = linux_syscalls::open(path, open_flags, OPEN_MODE);
+ ErrorOr<int> new_fd =
+ linux_syscalls::open(path, open_flags, LinuxFileFlags::OPEN_MODE);
// If the new file fails to open, POSIX says we still have to close the old
// file.
@@ -260,18 +244,15 @@ int LinuxFile::reopen_unlocked(const char *path, const char *mode) {
return EBADF;
int fd_flags = result.value();
- // 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_opened_in_read_only && file_mode.write_allowed()) ||
- (fd_opened_in_write_only && file_mode.read_allowed())) {
+ if ((LinuxFileFlags::is_file_descriptor_opened_in_read_only(fd_flags) &&
+ file_mode.write_allowed()) ||
+ (LinuxFileFlags::is_file_descriptor_opened_in_write_only(fd_flags) &&
+ file_mode.read_allowed())) {
return EBADF;
}
bool do_seek = false;
- bool has_append_flag = fd_flags & O_APPEND;
+ bool has_append_flag = LinuxFileFlags::file_has_append_flag(fd_flags);
if (file_mode.is_append() && !has_append_flag) {
if (!linux_syscalls::fcntl(fd, F_SETFL,
>From 251125fd2b1a5a210db2b0107c92ef822daacfc4 Mon Sep 17 00:00:00 2001
From: tdadadavid <davidtofunmidada at gmail.com>
Date: Thu, 10 Sep 2026 23:25:16 +0100
Subject: [PATCH 48/54] remove wrong imports
Signed-off-by: tdadadavid <davidtofunmidada at gmail.com>
---
libc/src/__support/File/file_mode.h | 1 -
1 file changed, 1 deletion(-)
diff --git a/libc/src/__support/File/file_mode.h b/libc/src/__support/File/file_mode.h
index b60d2fbb45cd7..72af260467c07 100644
--- a/libc/src/__support/File/file_mode.h
+++ b/libc/src/__support/File/file_mode.h
@@ -16,7 +16,6 @@
#define LLVM_LIBC_SRC___SUPPORT_FILE_FILE_MODE_H
#include "hdr/stdint_proxy.h"
-#include "src/__support/File/file.h"
#include "src/__support/macros/config.h"
namespace LIBC_NAMESPACE_DECL {
>From 5057b4e83f61a6ce24b017e58cfa13752251520a Mon Sep 17 00:00:00 2001
From: tdadadavid <davidtofunmidada at gmail.com>
Date: Fri, 11 Sep 2026 00:14:44 +0100
Subject: [PATCH 49/54] refactor linux files to use LinuxFileFlags class
Signed-off-by: tdadadavid <davidtofunmidada at gmail.com>
---
libc/src/__support/File/linux/CMakeLists.txt | 1 +
libc/src/__support/File/linux/file.cpp | 1 -
libc/src/__support/File/linux/file_flags.h | 4 ++++
3 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/libc/src/__support/File/linux/CMakeLists.txt b/libc/src/__support/File/linux/CMakeLists.txt
index 336854d4429dd..d0e1df252895c 100644
--- a/libc/src/__support/File/linux/CMakeLists.txt
+++ b/libc/src/__support/File/linux/CMakeLists.txt
@@ -8,6 +8,7 @@ add_object_library(
DEPENDS
libc.hdr.fcntl_macros
libc.hdr.stdio_macros
+ libc.hdr.types.mode_t
libc.hdr.sys_stat_macros
libc.hdr.types.FILE
libc.hdr.types.off_t
diff --git a/libc/src/__support/File/linux/file.cpp b/libc/src/__support/File/linux/file.cpp
index b757ad9a4bb07..a414c9a878347 100644
--- a/libc/src/__support/File/linux/file.cpp
+++ b/libc/src/__support/File/linux/file.cpp
@@ -8,7 +8,6 @@
#include "file.h"
#include "file_flags.h"
-#include "hdr/fcntl_macros.h" // For mode_t and other flags to the open syscall
#include "hdr/stdio_macros.h"
#include "hdr/sys_stat_macros.h" // For S_IS*, S_IF*, and S_IR* flags.
#include "hdr/types/off_t.h"
diff --git a/libc/src/__support/File/linux/file_flags.h b/libc/src/__support/File/linux/file_flags.h
index abc6769ac2856..59b41310a9ebb 100644
--- a/libc/src/__support/File/linux/file_flags.h
+++ b/libc/src/__support/File/linux/file_flags.h
@@ -11,6 +11,10 @@
///
//===----------------------------------------------------------------------===//
+#include "hdr/fcntl_macros.h" // For mode_t and other flags to the open syscall
+#include "hdr/sys_stat_macros.h" // For S_IS*, S_IF*, and S_IR* flags.
+#include "hdr/types/mode_t.h"
+#include "src/__support/OSUtil/linux/syscall_wrappers/fcntl.h"
#include "src/__support/macros/config.h"
namespace LIBC_NAMESPACE_DECL {
>From 432cabd8bb838a2ebe44c9504d3075d89498bd86 Mon Sep 17 00:00:00 2001
From: tdadadavid <davidtofunmidada at gmail.com>
Date: Fri, 11 Sep 2026 00:29:55 +0100
Subject: [PATCH 50/54] refactor FirstCharacterMustBeValidMode test case
Signed-off-by: tdadadavid <davidtofunmidada at gmail.com>
---
.../src/__support/File/file_mode_test.cpp | 434 +++++++++---------
1 file changed, 222 insertions(+), 212 deletions(-)
diff --git a/libc/test/src/__support/File/file_mode_test.cpp b/libc/test/src/__support/File/file_mode_test.cpp
index 367473ed4b05b..0f2c28018f70c 100644
--- a/libc/test/src/__support/File/file_mode_test.cpp
+++ b/libc/test/src/__support/File/file_mode_test.cpp
@@ -13,217 +13,227 @@
using LIBC_NAMESPACE::FileMode;
TEST(LlvmLibcFileModeTest, FirstCharacterMustBeAValidMode) {
- // creates a table structure to group tests
- struct TestCase {
- const char *test_description;
- const char *mode;
- bool expects;
- };
-
- // 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_description = "binary content set as the first character",
- .mode = "b",
- .expects = false},
- {.test_description = "exclusive create set as the first character",
- .mode = "x",
- .expects = false}};
-
- for (const TestCase &tc : first_char_modes) {
- const FileMode mode(tc.mode);
- EXPECT_EQ(mode.is_valid(), tc.expects);
- };
+ // valid append mode
+ constexpr FileMode append_only("a");
+ EXPECT_TRUE(append_only.is_valid());
+ EXPECT_TRUE(append_only.is_append());
+
+ // valid read mode
+ constexpr FileMode read_only("r");
+ EXPECT_TRUE(read_only.is_valid());
+ EXPECT_TRUE(read_only.is_read());
+
+ // valid write mode
+ constexpr FileMode write_only("w");
+ EXPECT_TRUE(write_only.is_valid());
+ EXPECT_TRUE(write_only.is_write());
+
+ // update set as first character => invalid
+ constexpr FileMode update_mode("+");
+ EXPECT_FALSE(update_mode.is_valid());
+ EXPECT_FALSE(update_mode.is_update());
+
+ // binary bit flag set as first character => invalid
+ constexpr FileMode binary_mode("b");
+ EXPECT_FALSE(binary_mode.is_valid());
+ EXPECT_FALSE(binary_mode.is_binary_format());
+
+ // exclusive create set as first character => invalid
+ constexpr FileMode exclusive_create("x");
+ EXPECT_FALSE(exclusive_create.is_valid());
+ EXPECT_FALSE(exclusive_create.is_exclusive_create());
}
-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 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},
-
- // 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, AllValidModes) {
- struct TestCase {
- const char *test_description;
- const char *mode;
- bool expects;
- };
-
- 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 combinations
- {.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 combinations
- {.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());
- }
-}
+// 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 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},
+
+// // 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, AllValidModes) {
+// struct TestCase {
+// const char *test_description;
+// const char *mode;
+// bool expects;
+// };
+
+// 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 combinations
+// {.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 combinations
+// {.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 aaed0549a39cd3b64136f9fa82c0f4b16d20ef2b Mon Sep 17 00:00:00 2001
From: tdadadavid <davidtofunmidada at gmail.com>
Date: Fri, 11 Sep 2026 01:03:11 +0100
Subject: [PATCH 51/54] refactor: remove table tests formats for
OnlyOneMainModeAllowed
Signed-off-by: tdadadavid <davidtofunmidada at gmail.com>
---
.../src/__support/File/file_mode_test.cpp | 212 ++++++++++--------
1 file changed, 120 insertions(+), 92 deletions(-)
diff --git a/libc/test/src/__support/File/file_mode_test.cpp b/libc/test/src/__support/File/file_mode_test.cpp
index 0f2c28018f70c..5fbd0531d74f0 100644
--- a/libc/test/src/__support/File/file_mode_test.cpp
+++ b/libc/test/src/__support/File/file_mode_test.cpp
@@ -44,103 +44,131 @@ TEST(LlvmLibcFileModeTest, FirstCharacterMustBeAValidMode) {
EXPECT_FALSE(exclusive_create.is_exclusive_create());
}
-// TEST(LlvmLibcFileModeTest, OnlyOneMainModeAllowed) {
-// struct TestCase {
-// const char *test_description;
-// const char *mode;
-// bool expects;
-// const char *message = "";
-// };
+TEST(LlvmLibcFileModeTest, OnlyOneMainModeAllowed) {
+ // 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)]
-// // 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 only", .mode = "r", .expects = true},
-// {.test_description = "read and update", .mode = "r+", .expects = true},
-// {.test_description = "read binary", .mode = "rb", .expects = true},
+ // 1. Read: possible valid read combination modes
-// // 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},
+ // a. Read only
+ constexpr FileMode readonly("r");
+ EXPECT_TRUE(readonly.is_valid());
+ EXPECT_TRUE(readonly.is_read());
+ EXPECT_TRUE(readonly.read_allowed());
-// // append(a) = [update(+), binary(b)]
-// {.test_description = "append and update", .mode = "a+", .expects =
-// true},
-// {.test_description = "append binary", .mode = "ab", .expects = true},
+ // b. Read and Update mode
+ constexpr FileMode read_and_update("r+");
+ EXPECT_TRUE(read_and_update.is_valid());
+ EXPECT_TRUE(read_and_update.is_read());
+ EXPECT_TRUE(read_and_update.is_update());
+ EXPECT_TRUE(read_and_update.read_allowed());
-// // 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",
-// },
-// };
+ // c. Read Binary
+ constexpr FileMode read_binary("rb");
+ EXPECT_TRUE(read_binary.is_valid());
+ EXPECT_TRUE(read_binary.is_read());
+ EXPECT_TRUE(read_binary.is_binary_format());
+ EXPECT_TRUE(read_binary.read_allowed());
-// for (const TestCase &tc : modes_combination) {
-// const FileMode mode(tc.mode);
-// EXPECT_EQ(mode.is_valid(), tc.expects) << tc.message;
-// };
-// }
+ // 2. Write: possible valid write combinations
+
+ // a. Write only
+ constexpr FileMode writeonly("w");
+ EXPECT_TRUE(writeonly.is_valid());
+ EXPECT_TRUE(writeonly.is_write());
+ EXPECT_TRUE(writeonly.write_allowed());
+
+ // b. Write and Update mode
+ constexpr FileMode write_and_update("w+");
+ EXPECT_TRUE(write_and_update.is_valid());
+ EXPECT_TRUE(write_and_update.is_write());
+ EXPECT_TRUE(write_and_update.is_update());
+ EXPECT_TRUE(write_and_update.write_allowed());
+
+ // c. Write Binary
+ constexpr FileMode write_binary("wb");
+ EXPECT_TRUE(write_binary.is_valid());
+ EXPECT_TRUE(write_binary.is_write());
+ EXPECT_TRUE(write_binary.is_binary_format());
+ EXPECT_TRUE(write_binary.write_allowed());
+
+ // d. Write Exclusive
+ constexpr FileMode write_exclusive("wx");
+ EXPECT_TRUE(write_exclusive.is_valid());
+ EXPECT_TRUE(write_exclusive.is_write());
+ EXPECT_TRUE(write_exclusive.is_exclusive_create());
+ EXPECT_TRUE(write_exclusive.write_allowed());
+
+ // 3. Append: possible valid append mode combinations
+
+ // a. Append only
+ constexpr FileMode appendonly("a");
+ EXPECT_TRUE(appendonly.is_valid());
+ EXPECT_TRUE(appendonly.is_append());
+ EXPECT_TRUE(appendonly.write_allowed());
+
+ // b. Append and Update
+ constexpr FileMode append_and_update("a+");
+ EXPECT_TRUE(append_and_update.is_valid());
+ EXPECT_TRUE(append_and_update.is_append());
+ EXPECT_TRUE(append_and_update.is_update());
+ EXPECT_TRUE(append_and_update.write_allowed());
+
+ // c. Append Binary
+ constexpr FileMode append_binary("ab");
+ EXPECT_TRUE(append_binary.is_valid());
+ EXPECT_TRUE(append_binary.is_append());
+ EXPECT_TRUE(append_binary.is_binary_format());
+ EXPECT_TRUE(append_binary.write_allowed());
+
+ // Invalid mode combinations
+
+ // 1. Read and Write as main modes
+ constexpr FileMode read_and_write("rw");
+ EXPECT_FALSE(read_and_write.is_valid())
+ << "read and write are both main modes and there can be only "
+ "one main mode";
+
+ // 2. Read and Append as main modes
+ constexpr FileMode read_and_append("ra");
+ EXPECT_FALSE(read_and_append.is_valid())
+ << "read and append are both main modes and there can be only "
+ "one main mode";
+
+ // 3. Write and Append as main modes
+ constexpr FileMode write_and_read("wr");
+ EXPECT_FALSE(write_and_read.is_valid())
+ << "write and read are both main modes and there can be only "
+ "one main mode";
+
+ // 4. Write and Append as main modes
+ constexpr FileMode write_and_append("wa");
+ EXPECT_FALSE(write_and_append.is_valid())
+ << "write and append are both main modes and there can be only "
+ "one main mode";
+
+ // 5. Append and Read as main modes
+ constexpr FileMode append_and_read("ar");
+ EXPECT_FALSE(append_and_read.is_valid())
+ << "append and read are both main modes and there can be only "
+ "one main mode";
+
+ // 6. Read, Write and Append as main modes
+ constexpr FileMode read_write_append("rwa");
+ EXPECT_FALSE(read_write_append.is_valid())
+ << "read, write and append are both main modes and there can be only "
+ "one main mode";
+}
// TEST(LlvmLibcFileModeTest, AllValidModes) {
// struct TestCase {
>From 317fdb5cab20b31e13ddb6fe79e75d55df02f325 Mon Sep 17 00:00:00 2001
From: tdadadavid <davidtofunmidada at gmail.com>
Date: Fri, 11 Sep 2026 01:11:05 +0100
Subject: [PATCH 52/54] update license
Signed-off-by: tdadadavid <davidtofunmidada at gmail.com>
---
libc/test/src/__support/File/file_mode_test.cpp | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/libc/test/src/__support/File/file_mode_test.cpp b/libc/test/src/__support/File/file_mode_test.cpp
index 5fbd0531d74f0..d2c4364d4a066 100644
--- a/libc/test/src/__support/File/file_mode_test.cpp
+++ b/libc/test/src/__support/File/file_mode_test.cpp
@@ -1,10 +1,15 @@
-//===-- 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
//
//===----------------------------------------------------------------------===//
+///
+/// file_mode_test.cpp
+/// This file contains possible test cases for FileMode class.
+///
+//===----------------------------------------------------------------------===//
#include "src/__support/File/file_mode.h"
#include "src/__support/macros/config.h"
>From e7e056a1a85d822c7377eae68bb065d6b3881c76 Mon Sep 17 00:00:00 2001
From: tdadadavid <davidtofunmidada at gmail.com>
Date: Fri, 11 Sep 2026 01:50:52 +0100
Subject: [PATCH 53/54] refactor tests and add invalid mode tests
Signed-off-by: tdadadavid <davidtofunmidada at gmail.com>
---
.../src/__support/File/file_mode_test.cpp | 170 +++++++-----------
1 file changed, 60 insertions(+), 110 deletions(-)
diff --git a/libc/test/src/__support/File/file_mode_test.cpp b/libc/test/src/__support/File/file_mode_test.cpp
index d2c4364d4a066..92f58bd154ee3 100644
--- a/libc/test/src/__support/File/file_mode_test.cpp
+++ b/libc/test/src/__support/File/file_mode_test.cpp
@@ -49,19 +49,8 @@ TEST(LlvmLibcFileModeTest, FirstCharacterMustBeAValidMode) {
EXPECT_FALSE(exclusive_create.is_exclusive_create());
}
-TEST(LlvmLibcFileModeTest, OnlyOneMainModeAllowed) {
- // 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)]
+TEST(LlvmLibcFileModeTest, AllPossibleValidCombinations) {
+ // This tracks all possible valid combinations
// 1. Read: possible valid read combination modes
@@ -76,6 +65,7 @@ TEST(LlvmLibcFileModeTest, OnlyOneMainModeAllowed) {
EXPECT_TRUE(read_and_update.is_valid());
EXPECT_TRUE(read_and_update.is_read());
EXPECT_TRUE(read_and_update.is_update());
+ EXPECT_TRUE(read_and_update.write_allowed());
EXPECT_TRUE(read_and_update.read_allowed());
// c. Read Binary
@@ -85,6 +75,15 @@ TEST(LlvmLibcFileModeTest, OnlyOneMainModeAllowed) {
EXPECT_TRUE(read_binary.is_binary_format());
EXPECT_TRUE(read_binary.read_allowed());
+ // d. Read Update Binary
+ constexpr FileMode read_update_binary("r+b");
+ EXPECT_TRUE(read_update_binary.is_valid());
+ EXPECT_TRUE(read_update_binary.is_read());
+ EXPECT_TRUE(read_update_binary.is_update());
+ EXPECT_TRUE(read_update_binary.is_binary_format());
+ EXPECT_TRUE(read_update_binary.write_allowed());
+ EXPECT_TRUE(read_update_binary.read_allowed());
+
// 2. Write: possible valid write combinations
// a. Write only
@@ -99,6 +98,7 @@ TEST(LlvmLibcFileModeTest, OnlyOneMainModeAllowed) {
EXPECT_TRUE(write_and_update.is_write());
EXPECT_TRUE(write_and_update.is_update());
EXPECT_TRUE(write_and_update.write_allowed());
+ EXPECT_TRUE(write_and_update.read_allowed());
// c. Write Binary
constexpr FileMode write_binary("wb");
@@ -114,6 +114,42 @@ TEST(LlvmLibcFileModeTest, OnlyOneMainModeAllowed) {
EXPECT_TRUE(write_exclusive.is_exclusive_create());
EXPECT_TRUE(write_exclusive.write_allowed());
+ // e. Write Binary Exclusive
+ constexpr FileMode write_binary_exclusive("wbx");
+ EXPECT_TRUE(write_binary_exclusive.is_valid());
+ EXPECT_TRUE(write_binary_exclusive.is_write());
+ EXPECT_TRUE(write_binary_exclusive.is_binary_format());
+ EXPECT_TRUE(write_binary_exclusive.is_exclusive_create());
+ EXPECT_TRUE(write_binary_exclusive.write_allowed());
+
+ // f. Write Binary Update
+ constexpr FileMode write_binary_update("wb+");
+ EXPECT_TRUE(write_binary_update.is_valid());
+ EXPECT_TRUE(write_binary_update.is_write());
+ EXPECT_TRUE(write_binary_update.is_binary_format());
+ EXPECT_TRUE(write_binary_update.is_update());
+ EXPECT_TRUE(write_binary_update.write_allowed());
+ EXPECT_TRUE(write_binary_update.read_allowed());
+
+ // g. Write Update Exclusive
+ constexpr FileMode write_update_exclusive("w+x");
+ EXPECT_TRUE(write_update_exclusive.is_valid());
+ EXPECT_TRUE(write_update_exclusive.is_write());
+ EXPECT_TRUE(write_update_exclusive.is_update());
+ EXPECT_TRUE(write_update_exclusive.is_exclusive_create());
+ EXPECT_TRUE(write_update_exclusive.write_allowed());
+ EXPECT_TRUE(write_update_exclusive.read_allowed());
+
+ // h. Write Update Binary Exclusive
+ constexpr FileMode write_update_binary_exclusive("w+bx");
+ EXPECT_TRUE(write_update_binary_exclusive.is_valid());
+ EXPECT_TRUE(write_update_binary_exclusive.is_write());
+ EXPECT_TRUE(write_update_binary_exclusive.is_update());
+ EXPECT_TRUE(write_update_binary_exclusive.is_binary_format());
+ EXPECT_TRUE(write_update_binary_exclusive.is_exclusive_create());
+ EXPECT_TRUE(write_update_binary_exclusive.write_allowed());
+ EXPECT_TRUE(write_update_binary_exclusive.read_allowed());
+
// 3. Append: possible valid append mode combinations
// a. Append only
@@ -128,6 +164,7 @@ TEST(LlvmLibcFileModeTest, OnlyOneMainModeAllowed) {
EXPECT_TRUE(append_and_update.is_append());
EXPECT_TRUE(append_and_update.is_update());
EXPECT_TRUE(append_and_update.write_allowed());
+ EXPECT_TRUE(append_and_update.read_allowed());
// c. Append Binary
constexpr FileMode append_binary("ab");
@@ -136,8 +173,17 @@ TEST(LlvmLibcFileModeTest, OnlyOneMainModeAllowed) {
EXPECT_TRUE(append_binary.is_binary_format());
EXPECT_TRUE(append_binary.write_allowed());
- // Invalid mode combinations
+ // d. Append Update Binary
+ constexpr FileMode append_update_binary("a+b");
+ EXPECT_TRUE(append_update_binary.is_valid());
+ EXPECT_TRUE(append_update_binary.is_append());
+ EXPECT_TRUE(append_update_binary.is_update());
+ EXPECT_TRUE(append_update_binary.is_binary_format());
+ EXPECT_TRUE(append_update_binary.write_allowed());
+ EXPECT_TRUE(append_update_binary.read_allowed());
+}
+TEST(LlvmLibcFileModeTest, InvalidCombinations) {
// 1. Read and Write as main modes
constexpr FileMode read_and_write("rw");
EXPECT_FALSE(read_and_write.is_valid())
@@ -174,99 +220,3 @@ TEST(LlvmLibcFileModeTest, OnlyOneMainModeAllowed) {
<< "read, write and append are both main modes and there can be only "
"one main mode";
}
-
-// TEST(LlvmLibcFileModeTest, AllValidModes) {
-// struct TestCase {
-// const char *test_description;
-// const char *mode;
-// bool expects;
-// };
-
-// 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 combinations
-// {.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 combinations
-// {.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 1b2d29154a08d7bd8bb04ab89ce9fa08de1e4600 Mon Sep 17 00:00:00 2001
From: tdadadavid <davidtofunmidada at gmail.com>
Date: Fri, 11 Sep 2026 13:18:33 +0100
Subject: [PATCH 54/54] fix lincense format
Signed-off-by: tdadadavid <davidtofunmidada at gmail.com>
---
libc/src/__support/File/file_mode.h | 2 +-
libc/src/__support/File/linux/file_flags.h | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/libc/src/__support/File/file_mode.h b/libc/src/__support/File/file_mode.h
index 72af260467c07..6ba7b9d01f0de 100644
--- a/libc/src/__support/File/file_mode.h
+++ b/libc/src/__support/File/file_mode.h
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
///
-/// file_mode.h
+/// \file
/// This file contains the implementation of FileMode class. This is the class
/// that handles everything related to a file's mode.
///
diff --git a/libc/src/__support/File/linux/file_flags.h b/libc/src/__support/File/linux/file_flags.h
index 59b41310a9ebb..a13cf74a9a59f 100644
--- a/libc/src/__support/File/linux/file_flags.h
+++ b/libc/src/__support/File/linux/file_flags.h
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
///
-/// file_flags.h
+/// \file
/// This file contains the defualt constants of Linux file open flags.
///
//===----------------------------------------------------------------------===//
More information about the libc-commits
mailing list