mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v2 0/3] nolibc: Add fread() and fseek()
@ 2026-01-05  2:36 Daniel Palmer
  2026-01-05  2:36 ` [PATCH v2 1/3] tools/nolibc: Add fread() to stdio.h Daniel Palmer
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Daniel Palmer @ 2026-01-05  2:36 UTC (permalink / raw)
  To: w, linux; +Cc: david.laight.linux, linux-kernel, Daniel Palmer

v1 blurb:

Using nolibc on nommu 68000, something I'm trying to build[0] wanted fread() and fseek()
so I added them, they seem to work so I'm sharing them. Not sure if I need to add
tests or something? Maybe there is a reason these weren't implemented in the first place...

0 - https://github.com/FrenkelS/Doom8088ST/issues/21

Changelog:
v2:
- A few style clean ups in fread() requested by Thomas.
- Added a basic test that exercises the new functions. This isn't a complete POSIX
  testsuite, just a very basic smoke test. I couldn't think of proper error numbers
  for different failure cases (Suggested by Thomas), any ideas appreciated.

Daniel Palmer (3):
  tools/nolibc: Add fread() to stdio.h
  tools/nolibc: Add fseek() to stdio.h
  tools/nolibc: Add a simple test for writing to a FILE and reading it
    back

 tools/include/nolibc/stdio.h                 | 53 +++++++++++++++++++-
 tools/testing/selftests/nolibc/nolibc-test.c | 53 ++++++++++++++++++++
 2 files changed, 105 insertions(+), 1 deletion(-)

-- 
2.51.0


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH v2 1/3] tools/nolibc: Add fread() to stdio.h
  2026-01-05  2:36 [PATCH v2 0/3] nolibc: Add fread() and fseek() Daniel Palmer
@ 2026-01-05  2:36 ` Daniel Palmer
  2026-01-05  2:36 ` [PATCH v2 2/3] tools/nolibc: Add fseek() " Daniel Palmer
  2026-01-05  2:36 ` [PATCH v2 3/3] tools/nolibc: Add a simple test for writing to a FILE and reading it back Daniel Palmer
  2 siblings, 0 replies; 4+ messages in thread
From: Daniel Palmer @ 2026-01-05  2:36 UTC (permalink / raw)
  To: w, linux; +Cc: david.laight.linux, linux-kernel, Daniel Palmer

Add a very basic version of fread() like we already have for fwrite().

Signed-off-by: Daniel Palmer <daniel@thingy.jp>
---
 tools/include/nolibc/stdio.h | 34 +++++++++++++++++++++++++++++++++-
 1 file changed, 33 insertions(+), 1 deletion(-)

diff --git a/tools/include/nolibc/stdio.h b/tools/include/nolibc/stdio.h
index 1f16dab2ac88..6904252df97d 100644
--- a/tools/include/nolibc/stdio.h
+++ b/tools/include/nolibc/stdio.h
@@ -170,7 +170,7 @@ int putchar(int c)
 }
 
 
-/* fwrite(), puts(), fputs(). Note that puts() emits '\n' but not fputs(). */
+/* fwrite(), fread(), puts(), fputs(). Note that puts() emits '\n' but not fputs(). */
 
 /* internal fwrite()-like function which only takes a size and returns 0 on
  * success or EOF on error. It automatically retries on short writes.
@@ -204,6 +204,38 @@ size_t fwrite(const void *s, size_t size, size_t nmemb, FILE *stream)
 	return written;
 }
 
+/* internal fread()-like function which only takes a size and returns 0 on
+ * success or EOF on error. It automatically retries on short reads.
+ */
+static __attribute__((unused))
+int _fread(void *buf, size_t size, FILE *stream)
+{
+	int fd = fileno(stream);
+	ssize_t ret;
+
+	while (size) {
+		ret = read(fd, buf, size);
+		if (ret <= 0)
+			return EOF;
+		size -= ret;
+		buf += ret;
+	}
+	return 0;
+}
+
+static __attribute__((unused))
+size_t fread(void *s, size_t size, size_t nmemb, FILE *stream)
+{
+	size_t nread;
+
+	for (nread = 0; nread < nmemb; nread++) {
+		if (_fread(s, size, stream) != 0)
+			break;
+		s += size;
+	}
+	return nread;
+}
+
 static __attribute__((unused))
 int fputs(const char *s, FILE *stream)
 {
-- 
2.51.0


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH v2 2/3] tools/nolibc: Add fseek() to stdio.h
  2026-01-05  2:36 [PATCH v2 0/3] nolibc: Add fread() and fseek() Daniel Palmer
  2026-01-05  2:36 ` [PATCH v2 1/3] tools/nolibc: Add fread() to stdio.h Daniel Palmer
@ 2026-01-05  2:36 ` Daniel Palmer
  2026-01-05  2:36 ` [PATCH v2 3/3] tools/nolibc: Add a simple test for writing to a FILE and reading it back Daniel Palmer
  2 siblings, 0 replies; 4+ messages in thread
From: Daniel Palmer @ 2026-01-05  2:36 UTC (permalink / raw)
  To: w, linux; +Cc: david.laight.linux, linux-kernel, Daniel Palmer

A very basic wrapper around lseek() that implements fseek().

Signed-off-by: Daniel Palmer <daniel@thingy.jp>
---
 tools/include/nolibc/stdio.h | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/tools/include/nolibc/stdio.h b/tools/include/nolibc/stdio.h
index 6904252df97d..233318b0d0f0 100644
--- a/tools/include/nolibc/stdio.h
+++ b/tools/include/nolibc/stdio.h
@@ -272,6 +272,25 @@ char *fgets(char *s, int size, FILE *stream)
 }
 
 
+/* fseek */
+static __attribute__((unused))
+int fseek(FILE *stream, long offset, int whence)
+{
+	int fd = fileno(stream);
+	off_t ret;
+
+	ret = lseek(fd, offset, whence);
+
+	/* lseek() and fseek() differ in that lseek returns the new
+	 * position or -1, fseek() returns either 0 or -1.
+	 */
+	if (ret >= 0)
+		return 0;
+
+	return -1;
+}
+
+
 /* minimal printf(). It supports the following formats:
  *  - %[l*]{d,u,c,x,p}
  *  - %s
-- 
2.51.0


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH v2 3/3] tools/nolibc: Add a simple test for writing to a FILE and reading it back
  2026-01-05  2:36 [PATCH v2 0/3] nolibc: Add fread() and fseek() Daniel Palmer
  2026-01-05  2:36 ` [PATCH v2 1/3] tools/nolibc: Add fread() to stdio.h Daniel Palmer
  2026-01-05  2:36 ` [PATCH v2 2/3] tools/nolibc: Add fseek() " Daniel Palmer
@ 2026-01-05  2:36 ` Daniel Palmer
  2 siblings, 0 replies; 4+ messages in thread
From: Daniel Palmer @ 2026-01-05  2:36 UTC (permalink / raw)
  To: w, linux; +Cc: david.laight.linux, linux-kernel, Daniel Palmer

Add a test that exercises create->write->seek->read to check that using the
stream functions (fwrite() etc) is not totally broken.

The only edge cases this is testing for are:
- Reading the file after writing but without rewinding reads nothing.
- Trying to read more items than the file contains returns the count of
  fully read items.

Signed-off-by: Daniel Palmer <daniel@thingy.jp>
---
 tools/testing/selftests/nolibc/nolibc-test.c | 53 ++++++++++++++++++++
 1 file changed, 53 insertions(+)

diff --git a/tools/testing/selftests/nolibc/nolibc-test.c b/tools/testing/selftests/nolibc/nolibc-test.c
index 3c5a226dad3a..6d99698005c4 100644
--- a/tools/testing/selftests/nolibc/nolibc-test.c
+++ b/tools/testing/selftests/nolibc/nolibc-test.c
@@ -877,6 +877,58 @@ int test_file_stream(void)
 	return 0;
 }
 
+int test_file_stream_wsr(void)
+{
+	const char dataout[] = "foo";
+	const size_t datasz = sizeof(dataout);
+	char datain[datasz];
+	int fd, r;
+	FILE *f;
+
+	fd = open("/tmp", O_TMPFILE | O_RDWR, 0644);
+	if (fd == -1)
+		return -1;
+
+	f = fdopen(fd, "w+");
+	if (!f)
+		return -1;
+
+	errno = 0;
+	r = fwrite(dataout, 1, datasz, f);
+	if (r != datasz)
+		return -1;
+
+	/* Attempt to read from the file without rewinding,
+	 * we should read 0 items.
+	 */
+	r = fread(datain, 1, datasz, f);
+	if (r)
+		return -1;
+
+	/* Rewind the file to the start */
+	r = fseek(f, 0, SEEK_SET);
+	if (r)
+		return -1;
+
+	/* Attempt to read back more than was written to
+	 * make sure we handle short reads properly.
+	 * fread() should return the number of complete items.
+	 */
+	r = fread(datain, 1, datasz + 1, f);
+	if (r != datasz)
+		return -1;
+
+	/* Data we read should match the data we just wrote */
+	if (memcmp(datain, dataout, datasz) != 0)
+		return -1;
+
+	r = fclose(f);
+	if (r)
+		return -1;
+
+	return 0;
+}
+
 enum fork_type {
 	FORK_STANDARD,
 	FORK_VFORK,
@@ -1351,6 +1403,7 @@ int run_syscall(int min, int max)
 		CASE_TEST(fchdir_stdin);      EXPECT_SYSER(1, fchdir(STDIN_FILENO), -1, ENOTDIR); break;
 		CASE_TEST(fchdir_badfd);      EXPECT_SYSER(1, fchdir(-1), -1, EBADF); break;
 		CASE_TEST(file_stream);       EXPECT_SYSZR(1, test_file_stream()); break;
+		CASE_TEST(file_stream_wsr);   EXPECT_SYSZR(1, test_file_stream_wsr()); break;
 		CASE_TEST(fork);              EXPECT_SYSZR(1, test_fork(FORK_STANDARD)); 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;
-- 
2.51.0


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2026-01-05  2:36 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-01-05  2:36 [PATCH v2 0/3] nolibc: Add fread() and fseek() Daniel Palmer
2026-01-05  2:36 ` [PATCH v2 1/3] tools/nolibc: Add fread() to stdio.h Daniel Palmer
2026-01-05  2:36 ` [PATCH v2 2/3] tools/nolibc: Add fseek() " Daniel Palmer
2026-01-05  2:36 ` [PATCH v2 3/3] tools/nolibc: Add a simple test for writing to a FILE and reading it back Daniel Palmer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®