Commit a009a0c6 authored by Thomas Weißschuh's avatar Thomas Weißschuh Committed by Thomas Weißschuh
Browse files

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: default avatarThomas Weißschuh <thomas.weissschuh@linutronix.de>
Acked-by: default avatarWilly Tarreau <w@1wt.eu>
Link: https://lore.kernel.org/r/20250428-nolibc-misc-v2-13-3c043eeab06c@linutronix.de


Signed-off-by: default avatarThomas Weißschuh <linux@weissschuh.net>
parent 256dc733
Loading
Loading
Loading
Loading
+27 −0
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@
#include "std.h"
#include "arch.h"
#include "errno.h"
#include "fcntl.h"
#include "types.h"
#include "sys.h"
#include "stdarg.h"
@@ -55,6 +56,32 @@ FILE *fdopen(int fd, const char *mode __attribute__((unused)))
	return (FILE*)(intptr_t)~fd;
}

static __attribute__((unused))
FILE *fopen(const char *pathname, const char *mode)
{
	int flags, fd;

	switch (*mode) {
	case 'r':
		flags = O_RDONLY;
		break;
	case 'w':
		flags = O_WRONLY | O_CREAT | O_TRUNC;
		break;
	case 'a':
		flags = O_WRONLY | O_CREAT | O_APPEND;
		break;
	default:
		SET_ERRNO(EINVAL); return NULL;
	}

	if (mode[1] == '+')
		flags = (flags & ~(O_RDONLY | O_WRONLY)) | O_RDWR;

	fd = open(pathname, flags, 0666);
	return fdopen(fd, mode);
}

/* provides the fd of stream. */
static __attribute__((unused))
int fileno(FILE *stream)
+24 −0
Original line number Diff line number Diff line
@@ -859,6 +859,29 @@ int test_getpagesize(void)
	return !c;
}

int test_file_stream(void)
{
	FILE *f;
	int r;

	f = fopen("/dev/null", "r");
	if (!f)
		return -1;

	errno = 0;
	r = fwrite("foo", 1, 3, f);
	if (r != 0 || errno != EBADF) {
		fclose(f);
		return -1;
	}

	r = fclose(f);
	if (r == EOF)
		return -1;

	return 0;
}

int test_fork(void)
{
	int status;
@@ -1311,6 +1334,7 @@ int run_syscall(int min, int max)
		CASE_TEST(dup3_0);            tmp = dup3(0, 100, 0);  EXPECT_SYSNE(1, tmp, -1); close(tmp); break;
		CASE_TEST(dup3_m1);           tmp = dup3(-1, 100, 0); EXPECT_SYSER(1, tmp, -1, EBADF); if (tmp != -1) close(tmp); break;
		CASE_TEST(execve_root);       EXPECT_SYSER(1, execve("/", (char*[]){ [0] = "/", [1] = NULL }, NULL), -1, EACCES); break;
		CASE_TEST(file_stream);       EXPECT_SYSZR(1, test_file_stream()); break;
		CASE_TEST(fork);              EXPECT_SYSZR(1, test_fork()); break;
		CASE_TEST(getdents64_root);   EXPECT_SYSNE(1, test_getdents64("/"), -1); break;
		CASE_TEST(getdents64_null);   EXPECT_SYSER(1, test_getdents64("/dev/null"), -1, ENOTDIR); break;