On Wed, 04 Oct 2023 11:53:51 -0600, Todd C. Miller wrote:
> Yes, this should be fixed. One difference is that in FreeBSD,
> __swsetup() sets errno whereas in OpenBSD we set errno in the caller
> when cantwrite() is true. I think it makes sense to set both errno
> and the __SERR flag in the same place. We just need to decide which
> place that is :-)
I decided that it is simplest to set errno and __SERR in __swsetup()
like FreeBSD has done instead of in the callers. This is consistent
with how fread(3) relies on __srefill() to set both errno and the
error flag.
We have an additional check in __swsetup() where we return EOF on
error that also needs to set errno and __SERR. There is no actual
fd in that case so I've set errno to EINVAL.
- todd
Index: lib/libc/stdio/fvwrite.c
===================================================================
RCS file: /cvs/src/lib/libc/stdio/fvwrite.c,v
retrieving revision 1.20
diff -u -p -u -r1.20 fvwrite.c
--- lib/libc/stdio/fvwrite.c 17 Mar 2017 16:06:33 -0000 1.20
+++ lib/libc/stdio/fvwrite.c 4 Oct 2023 18:28:33 -0000
@@ -34,7 +34,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <errno.h>
#include <unistd.h>
#include "local.h"
#include "fvwrite.h"
@@ -58,10 +57,8 @@ __sfvwrite(FILE *fp, struct __suio *uio)
if ((len = uio->uio_resid) == 0)
return (0);
/* make sure we can write */
- if (cantwrite(fp)) {
- errno = EBADF;
+ if (cantwrite(fp))
return (EOF);
- }
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define COPY(n) (void)memcpy(fp->_p, p, n)
Index: lib/libc/stdio/putc.c
===================================================================
RCS file: /cvs/src/lib/libc/stdio/putc.c,v
retrieving revision 1.13
diff -u -p -u -r1.13 putc.c
--- lib/libc/stdio/putc.c 31 Aug 2015 02:53:57 -0000 1.13
+++ lib/libc/stdio/putc.c 4 Oct 2023 18:28:37 -0000
@@ -32,7 +32,6 @@
*/
#include <stdio.h>
-#include <errno.h>
#include "local.h"
/*
@@ -43,10 +42,8 @@
int
putc_unlocked(int c, FILE *fp)
{
- if (cantwrite(fp)) {
- errno = EBADF;
+ if (cantwrite(fp))
return (EOF);
- }
_SET_ORIENTATION(fp, -1);
return (__sputc(c, fp));
}
Index: lib/libc/stdio/vfprintf.c
===================================================================
RCS file: /cvs/src/lib/libc/stdio/vfprintf.c,v
retrieving revision 1.81
diff -u -p -u -r1.81 vfprintf.c
--- lib/libc/stdio/vfprintf.c 8 Sep 2021 15:57:27 -0000 1.81
+++ lib/libc/stdio/vfprintf.c 4 Oct 2023 16:40:18 -0000
@@ -457,10 +457,8 @@ __vfprintf(FILE *fp, const char *fmt0, _
_SET_ORIENTATION(fp, -1);
/* sorry, fprintf(read_only_file, "") returns EOF, not 0 */
- if (cantwrite(fp)) {
- errno = EBADF;
+ if (cantwrite(fp))
return (EOF);
- }
/* optimise fprintf(stderr) (and other unbuffered Unix files) */
if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
Index: lib/libc/stdio/vfwprintf.c
===================================================================
RCS file: /cvs/src/lib/libc/stdio/vfwprintf.c,v
retrieving revision 1.22
diff -u -p -u -r1.22 vfwprintf.c
--- lib/libc/stdio/vfwprintf.c 8 Sep 2021 15:57:27 -0000 1.22
+++ lib/libc/stdio/vfwprintf.c 4 Oct 2023 16:40:18 -0000
@@ -451,10 +451,8 @@ __vfwprintf(FILE * __restrict fp, const
_SET_ORIENTATION(fp, 1);
/* sorry, fwprintf(read_only_file, "") returns EOF, not 0 */
- if (cantwrite(fp)) {
- errno = EBADF;
+ if (cantwrite(fp))
return (EOF);
- }
/* optimise fwprintf(stderr) (and other unbuffered Unix files) */
if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
Index: lib/libc/stdio/wbuf.c
===================================================================
RCS file: /cvs/src/lib/libc/stdio/wbuf.c,v
retrieving revision 1.13
diff -u -p -u -r1.13 wbuf.c
--- lib/libc/stdio/wbuf.c 31 Aug 2015 02:53:57 -0000 1.13
+++ lib/libc/stdio/wbuf.c 4 Oct 2023 18:28:45 -0000
@@ -32,7 +32,6 @@
*/
#include <stdio.h>
-#include <errno.h>
#include "local.h"
/*
@@ -54,10 +53,8 @@ __swbuf(int c, FILE *fp)
* calls might wrap _w from negative to positive.
*/
fp->_w = fp->_lbfsize;
- if (cantwrite(fp)) {
- errno = EBADF;
+ if (cantwrite(fp))
return (EOF);
- }
c = (unsigned char)c;
/*
Index: lib/libc/stdio/wsetup.c
===================================================================
RCS file: /cvs/src/lib/libc/stdio/wsetup.c,v
retrieving revision 1.7
diff -u -p -u -r1.7 wsetup.c
--- lib/libc/stdio/wsetup.c 8 Aug 2005 08:05:36 -0000 1.7
+++ lib/libc/stdio/wsetup.c 4 Oct 2023 18:23:48 -0000
@@ -31,6 +31,7 @@
* SUCH DAMAGE.
*/
+#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include "local.h"
@@ -38,7 +39,7 @@
/*
* Various output routines call wsetup to be sure it is safe to write,
* because either _flags does not include __SWR, or _buf is NULL.
- * _wsetup returns 0 if OK to write, nonzero otherwise.
+ * __swsetup returns 0 if OK to write, nonzero otherwise, setting errno.
*/
int
__swsetup(FILE *fp)
@@ -51,8 +52,11 @@ __swsetup(FILE *fp)
* If we are not writing, we had better be reading and writing.
*/
if ((fp->_flags & __SWR) == 0) {
- if ((fp->_flags & __SRW) == 0)
+ if ((fp->_flags & __SRW) == 0) {
+ errno = EBADF;
+ fp->_flags |= __SERR;
return (EOF);
+ }
if (fp->_flags & __SRD) {
/* clobber any ungetc data */
if (HASUB(fp))
@@ -68,8 +72,11 @@ __swsetup(FILE *fp)
* Make a buffer if necessary, then set _w.
*/
if (fp->_bf._base == NULL) {
- if ((fp->_flags & (__SSTR | __SALC)) == __SSTR)
+ if ((fp->_flags & (__SSTR | __SALC)) == __SSTR) {
+ errno = EINVAL;
+ fp->_flags |= __SERR;
return (EOF);
+ }
__smakebuf(fp);
}
if (fp->_flags & __SLBF) {