source: trunk/libs/newlib/src/newlib/libc/stdio/fflush.c @ 577

Last change on this file since 577 was 444, checked in by satin@…, 6 years ago

add newlib,libalmos-mkh, restructure shared_syscalls.h and mini-libc

File size: 8.4 KB
Line 
1/*
2 * Copyright (c) 1990 The Regents of the University of California.
3 * All rights reserved.
4 *
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 * advertising materials, and 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.
16 */
17
18/*
19FUNCTION
20<<fflush>>, <<fflush_unlocked>>---flush buffered file output
21
22INDEX
23        fflush
24INDEX
25        fflush_unlocked
26INDEX
27        _fflush_r
28INDEX
29        _fflush_unlocked_r
30
31SYNOPSIS
32        #include <stdio.h>
33        int fflush(FILE *<[fp]>);
34
35        #define _BSD_SOURCE
36        #include <stdio.h>
37        int fflush_unlocked(FILE *<[fp]>);
38
39        #include <stdio.h>
40        int _fflush_r(struct _reent *<[reent]>, FILE *<[fp]>);
41
42        #define _BSD_SOURCE
43        #include <stdio.h>
44        int _fflush_unlocked_r(struct _reent *<[reent]>, FILE *<[fp]>);
45
46DESCRIPTION
47The <<stdio>> output functions can buffer output before delivering it
48to the host system, in order to minimize the overhead of system calls.
49
50Use <<fflush>> to deliver any such pending output (for the file
51or stream identified by <[fp]>) to the host system.
52
53If <[fp]> is <<NULL>>, <<fflush>> delivers pending output from all
54open files.
55
56Additionally, if <[fp]> is a seekable input stream visiting a file
57descriptor, set the position of the file descriptor to match next
58unread byte, useful for obeying POSIX semantics when ending a process
59without consuming all input from the stream.
60
61<<fflush_unlocked>> is a non-thread-safe version of <<fflush>>.
62<<fflush_unlocked>> may only safely be used within a scope
63protected by flockfile() (or ftrylockfile()) and funlockfile().  This
64function may safely be used in a multi-threaded program if and only
65if they are called while the invoking thread owns the (FILE *)
66object, as is the case after a successful call to the flockfile() or
67ftrylockfile() functions.  If threads are disabled, then
68<<fflush_unlocked>> is equivalent to <<fflush>>.
69
70The alternate functions <<_fflush_r>> and <<_fflush_unlocked_r>> are
71reentrant versions, where the extra argument <[reent]> is a pointer to
72a reentrancy structure, and <[fp]> must not be NULL.
73
74RETURNS
75<<fflush>> returns <<0>> unless it encounters a write error; in that
76situation, it returns <<EOF>>.
77
78PORTABILITY
79ANSI C requires <<fflush>>.  The behavior on input streams is only
80specified by POSIX, and not all implementations follow POSIX rules.
81
82<<fflush_unlocked>> is a BSD extension also provided by GNU libc.
83
84No supporting OS subroutines are required.
85*/
86
87#include <_ansi.h>
88#include <stdio.h>
89#include <errno.h>
90#include "local.h"
91
92#ifdef __IMPL_UNLOCKED__
93#define _fflush_r _fflush_unlocked_r
94#define fflush fflush_unlocked
95#endif
96
97#ifndef __IMPL_UNLOCKED__
98/* Flush a single file, or (if fp is NULL) all files.  */
99
100/* Core function which does not lock file pointer.  This gets called
101   directly from __srefill. */
102int
103__sflush_r (struct _reent *ptr,
104       register FILE * fp)
105{
106  register unsigned char *p;
107  register _READ_WRITE_BUFSIZE_TYPE n;
108  register _READ_WRITE_RETURN_TYPE t;
109  short flags;
110
111  flags = fp->_flags;
112  if ((flags & __SWR) == 0)
113    {
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
120
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)
129        {
130          int tmp_errno;
131#ifdef __LARGE64_FILES
132          _fpos64_t curoff;
133#else
134          _fpos_t curoff;
135#endif
136
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 = ptr->_errno;
141          ptr->_errno = 0;
142          /* Get the physical position we are at in the file.  */
143          if (fp->_flags & __SOFF)
144            curoff = fp->_offset;
145          else
146            {
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 && ptr->_errno != 0)
156                {
157                  int result = EOF;
158                  if (ptr->_errno == ESPIPE || ptr->_errno == EINVAL)
159                    {
160                      result = 0;
161                      ptr->_errno = tmp_errno;
162                    }
163                  else
164                    fp->_flags |= __SERR;
165                  return result;
166                }
167            }
168          if (fp->_flags & __SRD)
169            {
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;
175            }
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 || ptr->_errno == 0
184              || ptr->_errno == ESPIPE || ptr->_errno == EINVAL)
185            {
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 || ptr->_errno == 0))
194                fp->_offset = curoff;
195              ptr->_errno = tmp_errno;
196              if (HASUB (fp))
197                FREEUB (ptr, fp);
198            }
199          else
200            {
201              fp->_flags |= __SERR;
202              return EOF;
203            }
204        }
205      return 0;
206    }
207  if ((p = fp->_bf._base) == NULL)
208    {
209      /* Nothing to flush.  */
210      return 0;
211    }
212  n = fp->_p - p;               /* write this much */
213
214  /*
215   * Set these immediately to avoid problems with longjmp
216   * and to allow exchange buffering (via setvbuf) in user
217   * write function.
218   */
219  fp->_p = p;
220  fp->_w = flags & (__SLBF | __SNBF) ? 0 : fp->_bf._size;
221
222  while (n > 0)
223    {
224      t = fp->_write (ptr, fp->_cookie, (char *) p, n);
225      if (t <= 0)
226        {
227          fp->_flags |= __SERR;
228          return EOF;
229        }
230      p += t;
231      n -= t;
232    }
233  return 0;
234}
235
236#ifdef _STDIO_BSD_SEMANTICS
237/* Called from _cleanup_r.  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. */
240int
241__sflushw_r (struct _reent *ptr,
242       register FILE *fp)
243{
244  return (fp->_flags & __SWR) ?  __sflush_r (ptr, fp) : 0;
245}
246#endif
247
248#endif /* __IMPL_UNLOCKED__ */
249
250int
251_fflush_r (struct _reent *ptr,
252       register FILE * fp)
253{
254  int ret;
255
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  */
271
272  CHECK_INIT (ptr, fp);
273
274  if (!fp->_flags)
275    return 0;
276
277  _newlib_flockfile_start (fp);
278  ret = __sflush_r (ptr, fp);
279  _newlib_flockfile_end (fp);
280  return ret;
281}
282
283#ifndef _REENT_ONLY
284
285int
286fflush (register FILE * fp)
287{
288  if (fp == NULL)
289    return _fwalk_reent (_GLOBAL_REENT, _fflush_r);
290
291  return _fflush_r (_REENT, fp);
292}
293
294#endif /* _REENT_ONLY */
Note: See TracBrowser for help on using the repository browser.