ref: 2a61dfcd596b6da4d31379663a20e4fe0566cc17
parent: f764b7c8342bd000d43eea624bc6265b8f3a8a7f
author: Michael Forney <mforney@mforney.org>
date: Sat Oct 2 21:27:57 EDT 2021
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.
--- 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
--- 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
--- 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
--- 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
--- 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
--- a/src/libc/stdio/_fpopen.c
+++ b/src/libc/stdio/_fpopen.c
@@ -63,12 +63,17 @@
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;