From 2957206718cffaaab9197e880d812d5f3a5509e8 Mon Sep 17 00:00:00 2001 From: Bananymous Date: Sat, 4 Jul 2026 19:13:26 +0300 Subject: [PATCH] LibC: Fix and cleanup stdio mode string parsing The code is now much cleaner andd we are not as strict with the mode string. Also add support for new 'e' and 'x' modifiers --- userspace/libraries/LibC/stdio.cpp | 52 +++++++++++++++++++++++------- 1 file changed, 40 insertions(+), 12 deletions(-) diff --git a/userspace/libraries/LibC/stdio.cpp b/userspace/libraries/LibC/stdio.cpp index 3e9b506f..2ea0d1e8 100644 --- a/userspace/libraries/LibC/stdio.cpp +++ b/userspace/libraries/LibC/stdio.cpp @@ -170,21 +170,49 @@ int fclose(FILE* file) static mode_t parse_mode_string(const char* mode_str) { - size_t len = strlen(mode_str); - if (len == 0 || len > 3) - return 0; - if (len == 3 && mode_str[1] == mode_str[2]) - return 0; - if (strspn(mode_str + 1, "tb+") != len - 1) - return 0; - bool plus = (mode_str[1] == '+' || mode_str[2] == '+'); + mode_t mode = 0; + switch (mode_str[0]) { - case 'r': return plus ? O_RDWR : O_RDONLY; - case 'w': return plus ? O_RDWR | O_CREAT | O_TRUNC : O_WRONLY | O_CREAT | O_TRUNC; - case 'a': return plus ? O_RDWR | O_CREAT | O_APPEND : O_WRONLY | O_CREAT | O_APPEND; + case 'r': + break; + case 'w': + mode |= O_CREAT | O_TRUNC; + break; + case 'a': + mode |= O_CREAT | O_APPEND; + break; + default: + return 0; } - return 0; + + bool plus = false; + for (size_t i = 1; mode_str[i]; i++) + { + switch (mode_str[i]) + { + case 'b': + case 't': + break; + case 'e': + mode |= O_CLOEXEC; + break; + case 'x': + mode |= O_CREAT | O_EXCL; + break; + case '+': + mode |= O_RDWR; + plus = true; + break; + default: + return 0; + } + } + + if (!plus) + mode |= (mode_str[0] == 'r') ? O_RDONLY : O_WRONLY; + + return mode; } FILE* fdopen(int fd, const char* mode_str)