Cygwin: mmap: allow remapping part of an existing anonymous mapping
[newlib-cygwin.git] / newlib / libc / stdio / fflush.c
blobd51e90153790a430478019d6be28f9f32f262b98
1 /*
2 * Copyright (c) 1990 The Regents of the University of California.
3 * All rights reserved.
5 * Redistribution and use in source and binary forms are permitted
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * and/or other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * by the University of California, Berkeley. The name of the
11 * University may not be used to endorse or promote products derived
12 * from this software without specific prior written permission.
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19 FUNCTION
20 <<fflush>>, <<fflush_unlocked>>---flush buffered file output
22 INDEX
23 fflush
24 INDEX
25 fflush_unlocked
26 INDEX
27 _fflush_r
28 INDEX
29 _fflush_unlocked_r
31 SYNOPSIS
32 #include <stdio.h>
33 int fflush(FILE *<[fp]>);
35 #define _BSD_SOURCE
36 #include <stdio.h>
37 int fflush_unlocked(FILE *<[fp]>);
39 #include <stdio.h>
40 int _fflush_r(struct _reent *<[reent]>, FILE *<[fp]>);
42 #define _BSD_SOURCE
43 #include <stdio.h>
44 int _fflush_unlocked_r(struct _reent *<[reent]>, FILE *<[fp]>);
46 DESCRIPTION
47 The <<stdio>> output functions can buffer output before delivering it
48 to the host system, in order to minimize the overhead of system calls.
50 Use <<fflush>> to deliver any such pending output (for the file
51 or stream identified by <[fp]>) to the host system.
53 If <[fp]> is <<NULL>>, <<fflush>> delivers pending output from all
54 open files.
56 Additionally, if <[fp]> is a seekable input stream visiting a file
57 descriptor, set the position of the file descriptor to match next
58 unread byte, useful for obeying POSIX semantics when ending a process
59 without consuming all input from the stream.
61 <<fflush_unlocked>> is a non-thread-safe version of <<fflush>>.
62 <<fflush_unlocked>> may only safely be used within a scope
63 protected by flockfile() (or ftrylockfile()) and funlockfile(). This
64 function may safely be used in a multi-threaded program if and only
65 if they are called while the invoking thread owns the (FILE *)
66 object, as is the case after a successful call to the flockfile() or
67 ftrylockfile() functions. If threads are disabled, then
68 <<fflush_unlocked>> is equivalent to <<fflush>>.
70 The alternate functions <<_fflush_r>> and <<_fflush_unlocked_r>> are
71 reentrant versions, where the extra argument <[reent]> is a pointer to
72 a reentrancy structure, and <[fp]> must not be NULL.
74 RETURNS
75 <<fflush>> returns <<0>> unless it encounters a write error; in that
76 situation, it returns <<EOF>>.
78 PORTABILITY
79 ANSI C requires <<fflush>>. The behavior on input streams is only
80 specified by POSIX, and not all implementations follow POSIX rules.
82 <<fflush_unlocked>> is a BSD extension also provided by GNU libc.
84 No supporting OS subroutines are required.
87 #include <_ansi.h>
88 #include <stdio.h>
89 #include <errno.h>
90 #include "local.h"
92 #ifdef __IMPL_UNLOCKED__
93 #define _fflush_r _fflush_unlocked_r
94 #define fflush fflush_unlocked
95 #endif
97 #ifndef __IMPL_UNLOCKED__
98 /* Flush a single file, or (if fp is NULL) all files. */
100 /* Core function which does not lock file pointer. This gets called
101 directly from __srefill. */
103 __sflush_r (struct _reent *ptr,
104 register FILE * fp)
106 register unsigned char *p;
107 register _READ_WRITE_BUFSIZE_TYPE n;
108 register _READ_WRITE_RETURN_TYPE t;
109 short flags;
111 flags = fp->_flags;
112 if ((flags & __SWR) == 0)
114 #ifdef _FSEEK_OPTIMIZATION
115 /* For a read stream, an fflush causes the next seek to be
116 unoptimized (i.e. forces a system-level seek). This conforms
117 to the POSIX and SUSv3 standards. */
118 fp->_flags |= __SNPT;
119 #endif
121 /* For a seekable stream with buffered read characters, we will attempt
122 a seek to the current position now. A subsequent read will then get
123 the next byte from the file rather than the buffer. This conforms
124 to the POSIX and SUSv3 standards. Note that the standards allow
125 this seek to be deferred until necessary, but we choose to do it here
126 to make the change simpler, more contained, and less likely
127 to miss a code scenario. */
128 if ((fp->_r > 0 || fp->_ur > 0) && fp->_seek != NULL)
130 int tmp_errno;
131 #ifdef __LARGE64_FILES
132 _fpos64_t curoff;
133 #else
134 _fpos_t curoff;
135 #endif
137 /* Save last errno and set errno to 0, so we can check if a device
138 returns with a valid position -1. We restore the last errno if
139 no other error condition has been encountered. */
140 tmp_errno = _REENT_ERRNO(ptr);
141 _REENT_ERRNO(ptr) = 0;
142 /* Get the physical position we are at in the file. */
143 if (fp->_flags & __SOFF)
144 curoff = fp->_offset;
145 else
147 /* We don't know current physical offset, so ask for it.
148 Only ESPIPE and EINVAL are ignorable. */
149 #ifdef __LARGE64_FILES
150 if (fp->_flags & __SL64)
151 curoff = fp->_seek64 (ptr, fp->_cookie, 0, SEEK_CUR);
152 else
153 #endif
154 curoff = fp->_seek (ptr, fp->_cookie, 0, SEEK_CUR);
155 if (curoff == -1L && _REENT_ERRNO(ptr) != 0)
157 int result = EOF;
158 if (_REENT_ERRNO(ptr) == ESPIPE || _REENT_ERRNO(ptr) == EINVAL)
160 result = 0;
161 _REENT_ERRNO(ptr) = tmp_errno;
163 else
164 fp->_flags |= __SERR;
165 return result;
168 if (fp->_flags & __SRD)
170 /* Current offset is at end of buffer. Compensate for
171 characters not yet read. */
172 curoff -= fp->_r;
173 if (HASUB (fp))
174 curoff -= fp->_ur;
176 /* Now physically seek to after byte last read. */
177 #ifdef __LARGE64_FILES
178 if (fp->_flags & __SL64)
179 curoff = fp->_seek64 (ptr, fp->_cookie, curoff, SEEK_SET);
180 else
181 #endif
182 curoff = fp->_seek (ptr, fp->_cookie, curoff, SEEK_SET);
183 if (curoff != -1 || _REENT_ERRNO(ptr) == 0
184 || _REENT_ERRNO(ptr) == ESPIPE || _REENT_ERRNO(ptr) == EINVAL)
186 /* Seek successful or ignorable error condition.
187 We can clear read buffer now. */
188 #ifdef _FSEEK_OPTIMIZATION
189 fp->_flags &= ~__SNPT;
190 #endif
191 fp->_r = 0;
192 fp->_p = fp->_bf._base;
193 if ((fp->_flags & __SOFF) && (curoff != -1 || _REENT_ERRNO(ptr) == 0))
194 fp->_offset = curoff;
195 _REENT_ERRNO(ptr) = tmp_errno;
196 if (HASUB (fp))
197 FREEUB (ptr, fp);
199 else
201 fp->_flags |= __SERR;
202 return EOF;
205 return 0;
207 if ((p = fp->_bf._base) == NULL)
209 /* Nothing to flush. */
210 return 0;
212 n = fp->_p - p; /* write this much */
215 * Set these immediately to avoid problems with longjmp
216 * and to allow exchange buffering (via setvbuf) in user
217 * write function.
219 fp->_p = p;
220 fp->_w = flags & (__SLBF | __SNBF) ? 0 : fp->_bf._size;
222 while (n > 0)
224 t = fp->_write (ptr, fp->_cookie, (char *) p, n);
225 if (t <= 0)
227 fp->_flags |= __SERR;
228 return EOF;
230 p += t;
231 n -= t;
233 return 0;
236 #ifdef _STDIO_BSD_SEMANTICS
237 /* Called from cleanup_stdio(). At exit time, we don't need file locking,
238 and we don't want to move the underlying file pointer unless we're
239 writing. */
241 __sflushw_r (struct _reent *ptr,
242 register FILE *fp)
244 return (fp->_flags & __SWR) ? __sflush_r (ptr, fp) : 0;
246 #endif
248 #endif /* __IMPL_UNLOCKED__ */
251 _fflush_r (struct _reent *ptr,
252 register FILE * fp)
254 int ret;
256 #ifdef _REENT_SMALL
257 /* For REENT_SMALL platforms, it is possible we are being
258 called for the first time on a std stream. This std
259 stream can belong to a reentrant struct that is not
260 _REENT. If CHECK_INIT gets called below based on _REENT,
261 we will end up changing said file pointers to the equivalent
262 std stream off of _REENT. This causes unexpected behavior if
263 there is any data to flush on the _REENT std stream. There
264 are two alternatives to fix this: 1) make a reentrant fflush
265 or 2) simply recognize that this file has nothing to flush
266 and return immediately before performing a CHECK_INIT. Choice
267 2 is implemented here due to its simplicity. */
268 if (fp->_bf._base == NULL)
269 return 0;
270 #endif /* _REENT_SMALL */
272 CHECK_INIT (ptr, fp);
274 if (!fp->_flags)
275 return 0;
277 _newlib_flockfile_start (fp);
278 ret = __sflush_r (ptr, fp);
279 _newlib_flockfile_end (fp);
280 return ret;
283 #ifndef _REENT_ONLY
286 fflush (register FILE * fp)
288 if (fp == NULL)
289 return _fwalk_sglue (_GLOBAL_REENT, _fflush_r, &__sglue);
291 return _fflush_r (_REENT, fp);
294 #endif /* _REENT_ONLY */