From 82be76b5a2c069c6d5039f28c63831a639163dfb Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Thu, 22 Sep 2022 23:47:42 +0000 Subject: [PATCH] Add __freadahead. At the time I added , I just added what was on the man page (which matched glibc), not realizing that musl and glibc had slightly different functionality in their headers. The toybox maintainer came up with a legitimate use case for this, for which there is no portable workaround, so I'm adding it here. I'm not adding the other functions that are in musl but not glibc for lack of a motivating use case. Bug: http://lists.landley.net/htdig.cgi/toybox-landley.net/2022-April/020864.html Test: treehugger Change-Id: I073baa86ff0271064d4e2f20a584d38787ead6b0 --- docs/status.md | 1 + libc/include/stdio_ext.h | 10 +++++++++- libc/libc.map.txt | 1 + libc/stdio/stdio_ext.cpp | 6 ++++++ tests/stdio_ext_test.cpp | 18 ++++++++++++++++++ 5 files changed, 35 insertions(+), 1 deletion(-) diff --git a/docs/status.md b/docs/status.md index ef60ce202..20a1309e8 100644 --- a/docs/status.md +++ b/docs/status.md @@ -54,6 +54,7 @@ Current libc symbols: https://android.googlesource.com/platform/bionic/+/master/ New libc functions in U (API level 34): * `close_range` and `copy_file_range` (Linux-specific GNU extensions). * `memset_explicit` in (C23 addition). + * `__freadahead` in (in musl but not glibc). New libc behavior in U (API level 34): * Support for `%b` and `%B` in the printf/wprintf family, `%b` in the diff --git a/libc/include/stdio_ext.h b/libc/include/stdio_ext.h index 3aa183d48..eda591905 100644 --- a/libc/include/stdio_ext.h +++ b/libc/include/stdio_ext.h @@ -96,12 +96,20 @@ void __fpurge(FILE* __fp) __INTRODUCED_IN(23); /** * [__fpending(3)](http://man7.org/linux/man-pages/man3/__fpending.3.html) returns the number of - * bytes in the output buffer. + * bytes in the output buffer. See __freadahead() for the input buffer. * * Available since API level 23. */ size_t __fpending(FILE* __fp) __INTRODUCED_IN(23); +/** + * __freadahead(3) returns the number of bytes in the input buffer. + * See __fpending() for the output buffer. + * + * Available since API level 34. + */ +size_t __freadahead(FILE* __fp) __INTRODUCED_IN(34); + /** * [_flushlbf(3)](http://man7.org/linux/man-pages/man3/_flushlbf.3.html) flushes all * line-buffered streams. diff --git a/libc/libc.map.txt b/libc/libc.map.txt index 0f4187882..e8d03b9ee 100644 --- a/libc/libc.map.txt +++ b/libc/libc.map.txt @@ -1578,6 +1578,7 @@ LIBC_T { # introduced=Tiramisu LIBC_U { # introduced=UpsideDownCake global: + __freadahead; close_range; copy_file_range; memset_explicit; diff --git a/libc/stdio/stdio_ext.cpp b/libc/stdio/stdio_ext.cpp index 945813e10..99a8af75f 100644 --- a/libc/stdio/stdio_ext.cpp +++ b/libc/stdio/stdio_ext.cpp @@ -67,6 +67,12 @@ size_t __fpending(FILE* fp) { return fp->_p - fp->_bf._base; } +size_t __freadahead(FILE* fp) { + // Normally _r is the amount of input already available. + // When there's ungetc() data, _r counts that and _ur is the previous _r. + return fp->_r + (HASUB(fp) ? fp->_ur : 0); +} + void _flushlbf() { // If we flush all streams, we know we've flushed all the line-buffered streams. fflush(nullptr); diff --git a/tests/stdio_ext_test.cpp b/tests/stdio_ext_test.cpp index fce600aa6..dce1a662f 100644 --- a/tests/stdio_ext_test.cpp +++ b/tests/stdio_ext_test.cpp @@ -78,6 +78,24 @@ TEST(stdio_ext, __fpending) { fclose(fp); } +TEST(stdio_ext, __freadahead) { +#if defined(__GLIBC__) + GTEST_SKIP() << "glibc doesn't have __freadahead"; +#else + FILE* fp = tmpfile(); + ASSERT_NE(EOF, fputs("hello", fp)); + rewind(fp); + + ASSERT_EQ('h', fgetc(fp)); + ASSERT_EQ(4u, __freadahead(fp)); + + ASSERT_EQ('H', ungetc('H', fp)); + ASSERT_EQ(5u, __freadahead(fp)); + + fclose(fp); +#endif +} + TEST(stdio_ext, __fpurge) { FILE* fp = tmpfile();