Bash  5.0-beta2
Bash - Bourne Again shell
fpurge.c
Go to the documentation of this file.
1 /* fpurge - Flushing buffers of a FILE stream. */
2 
3 /* Copyright (C) 2007-2010 Free Software Foundation, Inc.
4 
5  This file is part of GNU Bash, the Bourne Again SHell.
6 
7  Bash is free software: you can redistribute it and/or modify
8  it under the terms of the GNU General Public License as published by
9  the Free Software Foundation, either version 3 of the License, or
10  (at your option) any later version.
11 
12  Bash is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with Bash. If not, see <http://www.gnu.org/licenses/>.
19 */
20 
21 #include <config.h>
22 
23 #include "stdc.h"
24 
25 #include <stdio.h>
26 
27 /* Specification. Same as in ../../externs.h. */
28 #define NEED_FPURGE_DECL
29 #if HAVE_FPURGE
30 # define fpurge _bash_fpurge
31 #endif
32 extern int fpurge __P((FILE *stream));
33 
34 #if HAVE___FPURGE /* glibc >= 2.2, Haiku, Solaris >= 7 */
35 # include <stdio_ext.h>
36 #endif
37 #include <stdlib.h>
38 
39 /* Inline contents of gnulib:stdio-impl.h */
40 
41 /* Many stdio implementations have the same logic and therefore can share
42  the same implementation of stdio extension API, except that some fields
43  have different naming conventions, or their access requires some casts. */
44 
45 /* BSD stdio derived implementations. */
46 
47 #if defined __NetBSD__ /* NetBSD */
48 /* Get __NetBSD_Version__. */
49 # include <sys/param.h>
50 #endif
51 
52 #if defined __sferror || defined __DragonFly__ /* FreeBSD, NetBSD, OpenBSD, DragonFly, MacOS X, Cygwin */
53 
54 # if defined __DragonFly__ /* DragonFly */
55  /* See <http://www.dragonflybsd.org/cvsweb/src/lib/libc/stdio/priv_stdio.h?rev=HEAD&content-type=text/x-cvsweb-markup>. */
56 # define fp_ ((struct { struct __FILE_public pub; \
57  struct { unsigned char *_base; int _size; } _bf; \
58  void *cookie; \
59  void *_close; \
60  void *_read; \
61  void *_seek; \
62  void *_write; \
63  struct { unsigned char *_base; int _size; } _ub; \
64  int _ur; \
65  unsigned char _ubuf[3]; \
66  unsigned char _nbuf[1]; \
67  struct { unsigned char *_base; int _size; } _lb; \
68  int _blksize; \
69  fpos_t _offset; \
70  /* More fields, not relevant here. */ \
71  } *) fp)
72  /* See <http://www.dragonflybsd.org/cvsweb/src/include/stdio.h?rev=HEAD&content-type=text/x-cvsweb-markup>. */
73 # define _p pub._p
74 # define _flags pub._flags
75 # define _r pub._r
76 # define _w pub._w
77 # else
78 # define fp_ fp
79 # endif
80 
81 # if (defined __NetBSD__ && __NetBSD_Version__ >= 105270000) || defined __OpenBSD__ /* NetBSD >= 1.5ZA, OpenBSD */
82  /* See <http://cvsweb.netbsd.org/bsdweb.cgi/src/lib/libc/stdio/fileext.h?rev=HEAD&content-type=text/x-cvsweb-markup>
83  and <http://www.openbsd.org/cgi-bin/cvsweb/src/lib/libc/stdio/fileext.h?rev=HEAD&content-type=text/x-cvsweb-markup> */
84  struct __sfileext
85  {
86  struct __sbuf _ub; /* ungetc buffer */
87  /* More fields, not relevant here. */
88  };
89 # define fp_ub ((struct __sfileext *) fp->_ext._base)->_ub
90 # else /* FreeBSD, NetBSD <= 1.5Z, DragonFly, MacOS X, Cygwin */
91 # define fp_ub fp_->_ub
92 # endif
93 
94 # define HASUB(fp) (fp_ub._base != NULL)
95 
96 #endif
97 
98 /* SystemV derived implementations. */
99 
100 #if defined _IOERR
101 
102 # if defined __sun && defined _LP64 /* Solaris/{SPARC,AMD64} 64-bit */
103 # define fp_ ((struct { unsigned char *_ptr; \
104  unsigned char *_base; \
105  unsigned char *_end; \
106  long _cnt; \
107  int _file; \
108  unsigned int _flag; \
109  } *) fp)
110 # else
111 # define fp_ fp
112 # endif
113 
114 # if defined _SCO_DS /* OpenServer */
115 # define _cnt __cnt
116 # define _ptr __ptr
117 # define _base __base
118 # define _flag __flag
119 # endif
120 
121 #endif
122 
123 int
124 fpurge (FILE *fp)
125 {
126 #if HAVE___FPURGE /* glibc >= 2.2, Haiku, Solaris >= 7 */
127 
128  __fpurge (fp);
129  /* The __fpurge function does not have a return value. */
130  return 0;
131 
132 #elif HAVE_FPURGE /* FreeBSD, NetBSD, OpenBSD, DragonFly, MacOS X, Cygwin 1.7 */
133 
134  /* Call the system's fpurge function. */
135 # undef fpurge
136 # if !HAVE_DECL_FPURGE
137  extern int fpurge (FILE *);
138 # endif
139  int result = fpurge (fp);
140 # if defined __sferror || defined __DragonFly__ /* FreeBSD, NetBSD, OpenBSD, DragonFly, MacOS X, Cygwin */
141  if (result == 0)
142  /* Correct the invariants that fpurge broke.
143  <stdio.h> on BSD systems says:
144  "The following always hold: if _flags & __SRD, _w is 0."
145  If this invariant is not fulfilled and the stream is read-write but
146  currently reading, subsequent putc or fputc calls will write directly
147  into the buffer, although they shouldn't be allowed to. */
148  if ((fp_->_flags & __SRD) != 0)
149  fp_->_w = 0;
150 # endif
151  return result;
152 
153 #else
154 
155  /* Most systems provide FILE as a struct and the necessary bitmask in
156  <stdio.h>, because they need it for implementing getc() and putc() as
157  fast macros. */
158 # if defined _IO_ftrylockfile || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, Linux libc5 */
159  fp->_IO_read_end = fp->_IO_read_ptr;
160  fp->_IO_write_ptr = fp->_IO_write_base;
161  /* Avoid memory leak when there is an active ungetc buffer. */
162  if (fp->_IO_save_base != NULL)
163  {
164  free (fp->_IO_save_base);
165  fp->_IO_save_base = NULL;
166  }
167  return 0;
168 # elif defined __sferror || defined __DragonFly__ /* FreeBSD, NetBSD, OpenBSD, DragonFly, MacOS X, Cygwin */
169  fp_->_p = fp_->_bf._base;
170  fp_->_r = 0;
171  fp_->_w = ((fp_->_flags & (__SLBF | __SNBF | __SRD)) == 0 /* fully buffered and not currently reading? */
172  ? fp_->_bf._size
173  : 0);
174  /* Avoid memory leak when there is an active ungetc buffer. */
175  if (fp_ub._base != NULL)
176  {
177  if (fp_ub._base != fp_->_ubuf)
178  free (fp_ub._base);
179  fp_ub._base = NULL;
180  }
181  return 0;
182 # elif defined __EMX__ /* emx+gcc */
183  fp->_ptr = fp->_buffer;
184  fp->_rcount = 0;
185  fp->_wcount = 0;
186  fp->_ungetc_count = 0;
187  return 0;
188 # elif defined _IOERR || defined __TANDEM /* AIX, HP-UX, IRIX, OSF/1, Solaris, OpenServer, mingw */
189  fp->_ptr = fp->_base;
190  if (fp->_ptr != NULL)
191  fp->_cnt = 0;
192  return 0;
193 # elif defined __UCLIBC__ /* uClibc */
194 # ifdef __STDIO_BUFFERS
195  if (fp->__modeflags & __FLAG_WRITING)
196  fp->__bufpos = fp->__bufstart;
197  else if (fp->__modeflags & (__FLAG_READONLY | __FLAG_READING))
198  fp->__bufpos = fp->__bufread;
199 # endif
200  return 0;
201 # elif defined __QNX__ /* QNX */
202  fp->_Rback = fp->_Back + sizeof (fp->_Back);
203  fp->_Rsave = NULL;
204  if (fp->_Mode & 0x2000 /* _MWRITE */)
205  /* fp->_Buf <= fp->_Next <= fp->_Wend */
206  fp->_Next = fp->_Buf;
207  else
208  /* fp->_Buf <= fp->_Next <= fp->_Rend */
209  fp->_Rend = fp->_Next;
210  return 0;
211 # elif defined __MINT__ /* Atari FreeMiNT */
212  if (fp->__pushed_back)
213  {
214  fp->__bufp = fp->__pushback_bufp;
215  fp->__pushed_back = 0;
216  }
217  /* Preserve the current file position. */
218  if (fp->__target != -1)
219  fp->__target += fp->__bufp - fp->__buffer;
220  fp->__bufp = fp->__buffer;
221  /* Nothing in the buffer, next getc is nontrivial. */
222  fp->__get_limit = fp->__bufp;
223  /* Nothing in the buffer, next putc is nontrivial. */
224  fp->__put_limit = fp->__buffer;
225  return 0;
226 # else
227 # warning "Please port gnulib fpurge.c to your platform! Look at the definitions of fflush, setvbuf and ungetc on your system, then report this to bug-gnulib."
228  return 0;
229 # endif
230 
231 #endif
232 }
int fpurge __P((FILE *stream))
void free()
#define NULL
Definition: general.h:53
int fpurge(FILE *fp)
Definition: fpurge.c:124