stdio.c revision 82838
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 82838 2001-09-03 02:24:37Z 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
130	if ((fp->_flags & __SAPP) && _sseek(fp, (fpos_t)0, SEEK_END) == -1)
131		return (-1);
132	ret = (*fp->_write)(fp->_cookie, buf, n);
133	/* __SOFF removed even on success in case O_APPEND mode is set. */
134	if (ret >= 0) {
135		if ((fp->_flags & (__SAPP|__SOFF)) == (__SAPP|__SOFF) &&
136		    fp->_offset <= OFF_MAX - ret)
137			fp->_offset += ret;
138		else
139			fp->_flags &= ~__SOFF;
140
141	} else if (ret < 0)
142		fp->_flags &= ~__SOFF;
143	return (ret);
144}
145
146fpos_t
147_sseek(fp, offset, whence)
148	FILE *fp;
149	fpos_t offset;
150	int whence;
151{
152	fpos_t ret;
153	int serrno, errret;
154
155	serrno = errno;
156	errno = 0;
157	ret = (*fp->_seek)(fp->_cookie, offset, whence);
158	errret = errno;
159	if (errno == 0)
160		errno = serrno;
161	/*
162	 * Disallow negative seeks per POSIX.
163	 * It is needed here to help upper level caller
164	 * in the cases it can't detect.
165	 */
166	if (ret < 0) {
167		if (errret == 0) {
168			fp->_flags |= __SERR;
169			errno = EINVAL;
170		}
171		fp->_flags &= ~__SOFF;
172		ret = -1;
173	} else if (fp->_flags & __SOPT) {
174		fp->_flags |= __SOFF;
175		fp->_offset = ret;
176	}
177	return (ret);
178}
179