Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

tools/nolibc: add fopen()

This is used in various selftests and will be handy when integrating
those with nolibc.

Only the standard POSIX modes are supported.
No extensions nor the (noop) "b" from ISO C are accepted.

Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
Acked-by: Willy Tarreau <w@1wt.eu>
Link: https://lore.kernel.org/r/20250428-nolibc-misc-v2-13-3c043eeab06c@linutronix.de
Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>

authored by

Thomas Weißschuh and committed by
Thomas Weißschuh
a009a0c6 256dc733

+51
+27
tools/include/nolibc/stdio.h
··· 13 13 #include "std.h" 14 14 #include "arch.h" 15 15 #include "errno.h" 16 + #include "fcntl.h" 16 17 #include "types.h" 17 18 #include "sys.h" 18 19 #include "stdarg.h" ··· 54 53 return NULL; 55 54 } 56 55 return (FILE*)(intptr_t)~fd; 56 + } 57 + 58 + static __attribute__((unused)) 59 + FILE *fopen(const char *pathname, const char *mode) 60 + { 61 + int flags, fd; 62 + 63 + switch (*mode) { 64 + case 'r': 65 + flags = O_RDONLY; 66 + break; 67 + case 'w': 68 + flags = O_WRONLY | O_CREAT | O_TRUNC; 69 + break; 70 + case 'a': 71 + flags = O_WRONLY | O_CREAT | O_APPEND; 72 + break; 73 + default: 74 + SET_ERRNO(EINVAL); return NULL; 75 + } 76 + 77 + if (mode[1] == '+') 78 + flags = (flags & ~(O_RDONLY | O_WRONLY)) | O_RDWR; 79 + 80 + fd = open(pathname, flags, 0666); 81 + return fdopen(fd, mode); 57 82 } 58 83 59 84 /* provides the fd of stream. */
+24
tools/testing/selftests/nolibc/nolibc-test.c
··· 859 859 return !c; 860 860 } 861 861 862 + int test_file_stream(void) 863 + { 864 + FILE *f; 865 + int r; 866 + 867 + f = fopen("/dev/null", "r"); 868 + if (!f) 869 + return -1; 870 + 871 + errno = 0; 872 + r = fwrite("foo", 1, 3, f); 873 + if (r != 0 || errno != EBADF) { 874 + fclose(f); 875 + return -1; 876 + } 877 + 878 + r = fclose(f); 879 + if (r == EOF) 880 + return -1; 881 + 882 + return 0; 883 + } 884 + 862 885 int test_fork(void) 863 886 { 864 887 int status; ··· 1334 1311 CASE_TEST(dup3_0); tmp = dup3(0, 100, 0); EXPECT_SYSNE(1, tmp, -1); close(tmp); break; 1335 1312 CASE_TEST(dup3_m1); tmp = dup3(-1, 100, 0); EXPECT_SYSER(1, tmp, -1, EBADF); if (tmp != -1) close(tmp); break; 1336 1313 CASE_TEST(execve_root); EXPECT_SYSER(1, execve("/", (char*[]){ [0] = "/", [1] = NULL }, NULL), -1, EACCES); break; 1314 + CASE_TEST(file_stream); EXPECT_SYSZR(1, test_file_stream()); break; 1337 1315 CASE_TEST(fork); EXPECT_SYSZR(1, test_fork()); break; 1338 1316 CASE_TEST(getdents64_root); EXPECT_SYSNE(1, test_getdents64("/"), -1); break; 1339 1317 CASE_TEST(getdents64_null); EXPECT_SYSER(1, test_getdents64("/dev/null"), -1, ENOTDIR); break;