POSIX requires that ferror() and errno reflect any failed attempt to
write to a read-only stream, but newlib wasn't reliably doing this:
#include<stdio.h>
#include<errno.h>
int main()
{
FILE *f = fopen ("f", "w");
if (!f)
return 1;
if (freopen ("f", "r", f) != f)
return 2;
if (setvbuf (f, NULL, _IONBF, BUFSIZ))
return 3;
if (ferror (f))
return 4;
errno = -1;
if (fprintf (f, "hi") != EOF)
return 5;
if (errno<= 0)
return 6;
if (!ferror (f))
return 7;
if (fclose (f))
return 8;
if (remove (f))
return 9;
return 0;
}
This was mistakenly existing with status 6; comment that line out and it
exited with status 7. This fix mirrors the refill.c setting of errors
on attempts to read a write-only stream.
---
newlib/ChangeLog | 4 ++++
newlib/libc/stdio/wsetup.c | 6 +++++-
2 files changed, 9 insertions(+), 1 deletions(-)
2011-06-07 Eric Blake<eblake@redhat.com>
* libc/stdio/wsetup.c (__swsetup_r): Set errno on failure.
diff --git a/newlib/libc/stdio/wsetup.c b/newlib/libc/stdio/wsetup.c
index dcbda0a..6513e00 100644
--- a/newlib/libc/stdio/wsetup.c
+++ b/newlib/libc/stdio/wsetup.c
@@ -44,7 +44,11 @@ _DEFUN(__swsetup_r, (ptr, fp),
if ((fp->_flags& __SWR) == 0)
{
if ((fp->_flags& __SRW) == 0)
- return EOF;
+ {
+ ptr->_errno = EBADF;
+ fp->_flags |= __SERR;
+ return EOF;
+ }
if (fp->_flags& __SRD)
{
/* clobber any ungetc data */