stdio.c revision 85391
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 * 3. All advertising materials mentioning features or use of this software
17 *    must display the following acknowledgement:
18 *	This product includes software developed by the University of
19 *	California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 *    may be used to endorse or promote products derived from this software
22 *    without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36
37#if defined(LIBC_SCCS) && !defined(lint)
38#if 0
39static char sccsid[] = "@(#)stdio.c	8.1 (Berkeley) 6/4/93";
40#endif
41static const char rcsid[] =
42  "$FreeBSD: head/lib/libc/stdio/stdio.c 85391 2001-10-23 22:48:00Z ache $";
43#endif /* LIBC_SCCS and not lint */
44
45#include "namespace.h"
46#include <errno.h>
47#include <fcntl.h>
48#include <limits.h>
49#include <stdio.h>
50#include <unistd.h>
51#include "un-namespace.h"
52#include "local.h"
53
54/*
55 * Small standard I/O/seek/close functions.
56 */
57int
58__sread(cookie, buf, n)
59	void *cookie;
60	char *buf;
61	int n;
62{
63	register FILE *fp = cookie;
64
65	return(_read(fp->_file, buf, (size_t)n));
66}
67
68int
69__swrite(cookie, buf, n)
70	void *cookie;
71	char const *buf;
72	int n;
73{
74	register FILE *fp = cookie;
75
76	return (_write(fp->_file, buf, (size_t)n));
77}
78
79fpos_t
80__sseek(cookie, offset, whence)
81	void *cookie;
82	fpos_t offset;
83	int whence;
84{
85	register FILE *fp = cookie;
86
87	return (lseek(fp->_file, (off_t)offset, whence));
88}
89
90int
91__sclose(cookie)
92	void *cookie;
93{
94
95	return (_close(((FILE *)cookie)->_file));
96}
97
98/*
99 * Higher level wrappers.
100 */
101int
102_sread(fp, buf, n)
103	FILE *fp;
104	char *buf;
105	int n;
106{
107	int ret;
108
109	ret = (*fp->_read)(fp->_cookie, buf, n);
110	if (ret > 0) {
111		if (fp->_flags & __SOFF) {
112			if (fp->_offset <= OFF_MAX - ret)
113				fp->_offset += ret;
114			else
115				fp->_flags &= ~__SOFF;
116		}
117	} else if (ret < 0)
118		fp->_flags &= ~__SOFF;
119	return (ret);
120}
121
122int
123_swrite(fp, buf, n)
124	FILE *fp;
125	char const *buf;
126	int n;
127{
128	int ret;
129	int serrno;
130
131	if (fp->_flags & __SAPP) {
132		serrno = errno;
133		if (_sseek(fp, (fpos_t)0, SEEK_END) == -1 &&
134		    (fp->_flags & __SOPT))
135			return (-1);
136		errno = serrno;
137	}
138	ret = (*fp->_write)(fp->_cookie, buf, n);
139	/* __SOFF removed even on success in case O_APPEND mode is set. */
140	if (ret >= 0) {
141		if ((fp->_flags & (__SAPP|__SOFF)) == (__SAPP|__SOFF) &&
142		    fp->_offset <= OFF_MAX - ret)
143			fp->_offset += ret;
144		else
145			fp->_flags &= ~__SOFF;
146
147	} else if (ret < 0)
148		fp->_flags &= ~__SOFF;
149	return (ret);
150}
151
152fpos_t
153_sseek(fp, offset, whence)
154	FILE *fp;
155	fpos_t offset;
156	int whence;
157{
158	fpos_t ret;
159	int serrno, errret;
160
161	serrno = errno;
162	errno = 0;
163	ret = (*fp->_seek)(fp->_cookie, offset, whence);
164	errret = errno;
165	if (errno == 0)
166		errno = serrno;
167
168	if (errret == 0 && (offset != 0 || whence != SEEK_CUR))
169		/* Disallow fseek() optimization inside read buffer */
170		fp->_flags |= __SMOD;
171
172	/*
173	 * Disallow negative seeks per POSIX.
174	 * It is needed here to help upper level caller
175	 * in the cases it can't detect.
176	 */
177	if (ret < 0) {
178		if (errret == 0) {
179			fp->_flags |= __SERR;
180			errno = EINVAL;
181		} else if (errret == ESPIPE)
182			fp->_flags &= ~__SAPP;
183		fp->_flags &= ~__SOFF;
184		ret = -1;
185	} else if (fp->_flags & __SOPT) {
186		fp->_flags |= __SOFF;
187		fp->_offset = ret;
188	}
189	return (ret);
190}
191