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
This commit is contained in:
2026-07-04 19:13:26 +03:00
parent a41a3eeb66
commit 2957206718

View File

@@ -170,21 +170,49 @@ int fclose(FILE* file)
static mode_t parse_mode_string(const char* mode_str) static mode_t parse_mode_string(const char* mode_str)
{ {
size_t len = strlen(mode_str); mode_t mode = 0;
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] == '+');
switch (mode_str[0]) switch (mode_str[0])
{ {
case 'r': return plus ? O_RDWR : O_RDONLY; case 'r':
case 'w': return plus ? O_RDWR | O_CREAT | O_TRUNC : O_WRONLY | O_CREAT | O_TRUNC; break;
case 'a': return plus ? O_RDWR | O_CREAT | O_APPEND : O_WRONLY | O_CREAT | O_APPEND; 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) FILE* fdopen(int fd, const char* mode_str)