summaryrefslogtreecommitdiff
path: root/tools/include/nolibc/stdio.h
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2023-06-27 20:56:41 +0300
committerLinus Torvalds <torvalds@linux-foundation.org>2023-06-27 20:56:41 +0300
commitb19edac5992da0188be98454ca592621d3d89844 (patch)
tree57ebeb5f3583c172e6d4aa64a33841086e7cc5db /tools/include/nolibc/stdio.h
parentaf96134dc8562f9fcbb8358af36f6086619a29ab (diff)
parentdd58d666ac08eb5eb81e4956172fc52b3bf0ab38 (diff)
downloadlinux-b19edac5992da0188be98454ca592621d3d89844.tar.xz
Merge tag 'nolibc.2023.06.22a' of git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-rcu
Pull nolibc updates from Paul McKenney: - Add stackprotector support - Fix RISC-V load-store instruction syntax to support 32-bit binaries, plus fixes for generic 32-bit support - Fix use of s390 sys_fork() - Add my_syscall6() for ARM - Support different platforms having different errno definitions - Fix ppoll/ppoll_time64 arguments (add the fifth argument) - Force use of little endian on MIPS - Improved testing, for example, better handling of different compilers and compiler versions, comparing nolibc behavior to that of libc, and additional test cases - Improve syntax and header ordering - Use existing <linux/reboot.h> instead of redefining constants - Add syscall() * tag 'nolibc.2023.06.22a' of git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-rcu: (53 commits) selftests/nolibc: make sure gcc always use little endian on MIPS selftests/nolibc: also count skipped and failed tests in output selftests/nolibc: add new gettimeofday test cases selftests/nolibc: remove gettimeofday_bad1/2 completely selftests/nolibc: support two errnos with EXPECT_SYSER2() tools/nolibc: open: fix up compile warning for arm tools/nolibc: arm: add missing my_syscall6 selftests/nolibc: use INT_MAX instead of __INT_MAX__ selftests/nolibc: not include limits.h for nolibc selftests/nolibc: fix up compile warning with glibc on x86_64 selftests/nolibc: allow specify extra arguments for qemu selftests/nolibc: remove test gettimeofday_null tools/nolibc: ensure fast64 integer types have 64 bits selftests/nolibc: test_fork: fix up duplicated print tools/nolibc: ppoll/ppoll_time64: add a missing argument selftests/nolibc: remove the duplicated gettimeofday_bad2 selftests/nolibc: print name instead of number for EOVERFLOW tools/nolibc: support nanoseconds in stat() selftests/nolibc: prevent coredumps during test execution tools/nolibc: add support for prctl() ...
Diffstat (limited to 'tools/include/nolibc/stdio.h')
-rw-r--r--tools/include/nolibc/stdio.h95
1 files changed, 68 insertions, 27 deletions
diff --git a/tools/include/nolibc/stdio.h b/tools/include/nolibc/stdio.h
index 6cbbb52836a0..0eef91daf289 100644
--- a/tools/include/nolibc/stdio.h
+++ b/tools/include/nolibc/stdio.h
@@ -21,17 +21,75 @@
#define EOF (-1)
#endif
-/* just define FILE as a non-empty type */
+/* just define FILE as a non-empty type. The value of the pointer gives
+ * the FD: FILE=~fd for fd>=0 or NULL for fd<0. This way positive FILE
+ * are immediately identified as abnormal entries (i.e. possible copies
+ * of valid pointers to something else).
+ */
typedef struct FILE {
char dummy[1];
} FILE;
-/* We define the 3 common stdio files as constant invalid pointers that
- * are easily recognized.
- */
-static __attribute__((unused)) FILE* const stdin = (FILE*)-3;
-static __attribute__((unused)) FILE* const stdout = (FILE*)-2;
-static __attribute__((unused)) FILE* const stderr = (FILE*)-1;
+static __attribute__((unused)) FILE* const stdin = (FILE*)(intptr_t)~STDIN_FILENO;
+static __attribute__((unused)) FILE* const stdout = (FILE*)(intptr_t)~STDOUT_FILENO;
+static __attribute__((unused)) FILE* const stderr = (FILE*)(intptr_t)~STDERR_FILENO;
+
+/* provides a FILE* equivalent of fd. The mode is ignored. */
+static __attribute__((unused))
+FILE *fdopen(int fd, const char *mode __attribute__((unused)))
+{
+ if (fd < 0) {
+ SET_ERRNO(EBADF);
+ return NULL;
+ }
+ return (FILE*)(intptr_t)~fd;
+}
+
+/* provides the fd of stream. */
+static __attribute__((unused))
+int fileno(FILE *stream)
+{
+ intptr_t i = (intptr_t)stream;
+
+ if (i >= 0) {
+ SET_ERRNO(EBADF);
+ return -1;
+ }
+ return ~i;
+}
+
+/* flush a stream. */
+static __attribute__((unused))
+int fflush(FILE *stream)
+{
+ intptr_t i = (intptr_t)stream;
+
+ /* NULL is valid here. */
+ if (i > 0) {
+ SET_ERRNO(EBADF);
+ return -1;
+ }
+
+ /* Don't do anything, nolibc does not support buffering. */
+ return 0;
+}
+
+/* flush a stream. */
+static __attribute__((unused))
+int fclose(FILE *stream)
+{
+ intptr_t i = (intptr_t)stream;
+
+ if (i >= 0) {
+ SET_ERRNO(EBADF);
+ return -1;
+ }
+
+ if (close(~i))
+ return EOF;
+
+ return 0;
+}
/* getc(), fgetc(), getchar() */
@@ -41,14 +99,8 @@ static __attribute__((unused))
int fgetc(FILE* stream)
{
unsigned char ch;
- int fd;
- if (stream < stdin || stream > stderr)
- return EOF;
-
- fd = 3 + (long)stream;
-
- if (read(fd, &ch, 1) <= 0)
+ if (read(fileno(stream), &ch, 1) <= 0)
return EOF;
return ch;
}
@@ -68,14 +120,8 @@ static __attribute__((unused))
int fputc(int c, FILE* stream)
{
unsigned char ch = c;
- int fd;
-
- if (stream < stdin || stream > stderr)
- return EOF;
-
- fd = 3 + (long)stream;
- if (write(fd, &ch, 1) <= 0)
+ if (write(fileno(stream), &ch, 1) <= 0)
return EOF;
return ch;
}
@@ -96,12 +142,7 @@ static __attribute__((unused))
int _fwrite(const void *buf, size_t size, FILE *stream)
{
ssize_t ret;
- int fd;
-
- if (stream < stdin || stream > stderr)
- return EOF;
-
- fd = 3 + (long)stream;
+ int fd = fileno(stream);
while (size) {
ret = write(fd, buf, size);