commit a06980e91b715ab72c56024930712c5af8390da5
parent cae1735f86d590f9d71b407e895d81e60fb2bba1
Author: Michael Forney <mforney@mforney.org>
Date: Sun, 3 Oct 2021 01:27:57 -0700
libc: Fix fopen with mode "r"
On all supported platforms, O_RDONLY is 0, so flags & O_RDONLY is
never true and the FILE does not get marked as _IOREAD, causing all
read operations to fail with EBADF.
To fix this, introduce O_ACCMODE in sys.h, containing a mask of the
bits used for the file access mode. Then, in _fpopen, switch on
access mode.
Diffstat:
6 files changed, 13 insertions(+), 3 deletions(-)
diff --git a/include/bits/darwin/sys.h b/include/bits/darwin/sys.h
@@ -1,6 +1,7 @@
#define O_RDONLY 0x00000000
#define O_WRONLY 0x00000001
#define O_RDWR 0x00000002
+#define O_ACCMODE 0x00000003
#define O_TRUNC 0x00000400
#define O_APPEND 0x00000008
diff --git a/include/bits/dragonfly/sys.h b/include/bits/dragonfly/sys.h
@@ -1,6 +1,7 @@
#define O_RDONLY 0x00000000
#define O_WRONLY 0x00000001
#define O_RDWR 0x00000002
+#define O_ACCMODE 0x00000003
#define O_TRUNC 0x00000400
#define O_APPEND 0x00000008
diff --git a/include/bits/linux/sys.h b/include/bits/linux/sys.h
@@ -1,6 +1,7 @@
#define O_RDONLY 0x00000000
#define O_WRONLY 0x00000001
#define O_RDWR 0x00000002
+#define O_ACCMODE 0x00000003
#define O_TRUNC 0x00000200
#define O_APPEND 0x00000400
diff --git a/include/bits/netbsd/sys.h b/include/bits/netbsd/sys.h
@@ -1,6 +1,7 @@
#define O_RDONLY 0x00000000
#define O_WRONLY 0x00000001
#define O_RDWR 0x00000002
+#define O_ACCMODE 0x00000003
#define O_TRUNC 0x00000400
#define O_APPEND 0x00000008
diff --git a/include/bits/openbsd/sys.h b/include/bits/openbsd/sys.h
@@ -1,6 +1,7 @@
#define O_RDONLY 0x00000000
#define O_WRONLY 0x00000001
#define O_RDWR 0x00000002
+#define O_ACCMODE 0x00000003
#define O_TRUNC 0x00000400
#define O_APPEND 0x00000008
diff --git a/src/libc/stdio/_fpopen.c b/src/libc/stdio/_fpopen.c
@@ -63,12 +63,17 @@ _fpopen(const char *restrict fname,
if (!bin)
fp->flags |= _IOTXT;
- if (flags & O_RDWR)
+ switch (flags & O_ACCMODE) {
+ case O_RDWR:
fp->flags |= _IORW;
- else if (flags & O_RDONLY)
+ break;
+ case O_RDONLY:
fp->flags |= _IOREAD;
- else
+ break;
+ case O_WRONLY:
fp->flags |= _IOWRITE;
+ break;
+ }
fp->lp = fp->rp = fp->wp = NULL;