]> git.saurik.com Git - apple/libc.git/blob - stdio/FreeBSD/fflush.c
Libc-1353.11.2.tar.gz
[apple/libc.git] / stdio / FreeBSD / fflush.c
1 /*-
2 * Copyright (c) 1990, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Chris Torek.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 4. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33 #if defined(LIBC_SCCS) && !defined(lint)
34 static char sccsid[] = "@(#)fflush.c 8.1 (Berkeley) 6/4/93";
35 #endif /* LIBC_SCCS and not lint */
36 #include <sys/cdefs.h>
37 __FBSDID("$FreeBSD: src/lib/libc/stdio/fflush.c,v 1.14 2007/01/09 00:28:06 imp Exp $");
38
39 #include "namespace.h"
40 #include <errno.h>
41 #include <stdio.h>
42 #include <string.h>
43 #include "un-namespace.h"
44 #include "libc_private.h"
45 #include "local.h"
46
47 static int sflush_locked(FILE *);
48
49 /*
50 * Flush a single file, or (if fp is NULL) all files.
51 * MT-safe version
52 */
53 int
54 fflush(FILE *fp)
55 {
56 int retval = 0;
57
58 if (fp == NULL) {
59 return (_fwalk(sflush_locked));
60 }
61
62 FLOCKFILE(fp);
63 retval = __sflush(fp);
64 FUNLOCKFILE(fp);
65 return (retval);
66 }
67
68 /*
69 * Flush a single file, or (if fp is NULL) all files.
70 * Non-MT-safe version
71 */
72 int
73 __fflush(FILE *fp)
74 {
75 int retval;
76
77 if (fp == NULL)
78 return (_fwalk(sflush_locked));
79 if ((fp->_flags & (__SWR | __SRW)) == 0) {
80 retval = 0;
81 } else
82 retval = __sflush(fp);
83 return (retval);
84 }
85
86 int
87 __sflush(FILE *fp)
88 {
89 unsigned char *p;
90 int n, t;
91
92 t = fp->_flags;
93
94 if ((p = fp->_bf._base) == NULL)
95 return (0);
96
97 /*
98 * SUSv3 requires that fflush() on a seekable input stream updates the file
99 * position indicator with the underlying seek function. Use a dumb fseek
100 * for this (don't attempt to preserve the buffers).
101 */
102 if ((t & __SRD) != 0) {
103 if (fp->_seek == NULL) {
104 /*
105 * No way to seek this file -- just return "success."
106 */
107 return (0);
108 }
109
110 n = fp->_r;
111
112 if (n > 0) {
113 /*
114 * See _fseeko's dumb path.
115 */
116 if (_sseek(fp, (fpos_t)-n, SEEK_CUR) == -1) {
117 if (errno == ESPIPE) {
118 /*
119 * Ignore ESPIPE errors, since there's no way to put the bytes
120 * back into the pipe.
121 */
122 return (0);
123 }
124 return (EOF);
125 }
126
127 if (HASUB(fp)) {
128 FREEUB(fp);
129 }
130 fp->_p = fp->_bf._base;
131 fp->_r = 0;
132 fp->_flags &= ~__SEOF;
133 memset(&fp->_mbstate, 0, sizeof(mbstate_t));
134 }
135 return (0);
136 }
137
138 if ((t & __SWR) != 0) {
139 n = fp->_p - p; /* write this much */
140
141 /*
142 * Set these immediately to avoid problems with longjmp and to allow
143 * exchange buffering (via setvbuf) in user write function.
144 */
145 fp->_p = p;
146 fp->_w = t & (__SLBF|__SNBF) ? 0 : fp->_bf._size;
147
148 for (; n > 0; n -= t, p += t) {
149 t = _swrite(fp, (char *)p, n);
150 if (t <= 0) {
151 /* 5340694: reset _p and _w on EAGAIN */
152 if (t < 0 && errno == EAGAIN) {
153 if (p > fp->_p) {
154 /* some was written */
155 memmove(fp->_p, p, n);
156 fp->_p += n;
157 if (!(fp->_flags & (__SLBF|__SNBF)))
158 fp->_w -= n;
159 }
160 }
161 fp->_flags |= __SERR;
162 return (EOF);
163 }
164 }
165 }
166 return (0);
167 }
168
169 static int
170 sflush_locked(FILE *fp)
171 {
172 int ret;
173
174 FLOCKFILE(fp);
175 ret = __sflush(fp);
176 FUNLOCKFILE(fp);
177 return (ret);
178 }