Add support for QNX (untested).
[gnulib.git] / lib / fseterr.c
1 /* Set the error indicator of a stream.
2    Copyright (C) 2007 Free Software Foundation, Inc.
3
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 2, or (at your option)
7    any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License along
15    with this program; if not, write to the Free Software Foundation,
16    Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
17
18 #include <config.h>
19
20 /* Specification.  */
21 #include "fseterr.h"
22
23 #include <errno.h>
24
25 void
26 fseterr (FILE *fp)
27 {
28   /* Most systems provide FILE as a struct and the necessary bitmask in
29      <stdio.h>, because they need it for implementing getc() and putc() as
30      fast macros.  */
31 #if defined _IO_ferror_unlocked     /* GNU libc, BeOS */
32   fp->_flags |= _IO_ERR_SEEN;
33 #elif defined __sferror             /* FreeBSD, NetBSD, OpenBSD, MacOS X, Cygwin */
34   fp->_flags |= __SERR;
35 #elif defined _IOERR                /* AIX, HP-UX, IRIX, OSF/1, Solaris, mingw */
36 # if defined __sun && defined _LP64 /* Solaris/{SPARC,AMD64} 64-bit */
37 #  define fp_ ((struct { unsigned char *_ptr; \
38                          unsigned char *_base; \
39                          unsigned char *_end; \
40                          long _cnt; \
41                          int _file; \
42                          unsigned int _flag; \
43                        } *) fp)
44   fp_->_flag |= _IOERR;
45 # else
46   fp->_flag |= _IOERR;
47 # endif
48 #elif defined __UCLIBC__            /* uClibc */
49   fp->__modeflags |= __FLAG_ERROR;
50 #elif defined __QNX__               /* QNX */
51   fp->_Mode |= _MERR;
52 #elif 0                             /* unknown  */
53   /* Portable fallback, based on an idea by Rich Felker.
54      Wow! 6 system calls for something that is just a bit operation!
55      Not activated on any system, because there is no way to repair FP when
56      the sequence of system calls fails, and library code should not call
57      abort().  */
58   int saved_errno;
59   int fd;
60   int fd2;
61
62   saved_errno = errno;
63   fflush (fp);
64   fd = fileno (fp);
65   fd2 = dup (fd);
66   if (fd2 >= 0)
67     {
68       close (fd);
69       fputc ('\0', fp); /* This should set the error indicator.  */
70       fflush (fp);      /* Or this.  */
71       if (dup2 (fd2, fd) < 0)
72         /* Whee... we botched the stream and now cannot restore it!  */
73         abort ();
74       close (fd2);
75     }
76   errno = saved_errno;
77 #else
78  #error "Please port gnulib fseterr.c to your platform! Look at the definitions of ferror and clearerr on your system, then report this to bug-gnulib."
79 #endif
80 }