stdio.c revision 330897
119370Spst/*-
219370Spst * SPDX-License-Identifier: BSD-3-Clause
3130803Smarcel *
4130803Smarcel * Copyright (c) 1990, 1993
5130803Smarcel *	The Regents of the University of California.  All rights reserved.
6130803Smarcel *
798944Sobrien * This code is derived from software contributed to Berkeley by
819370Spst * Chris Torek.
998944Sobrien *
1098944Sobrien * Redistribution and use in source and binary forms, with or without
1198944Sobrien * modification, are permitted provided that the following conditions
1298944Sobrien * are met:
1319370Spst * 1. Redistributions of source code must retain the above copyright
1498944Sobrien *    notice, this list of conditions and the following disclaimer.
1598944Sobrien * 2. Redistributions in binary form must reproduce the above copyright
1698944Sobrien *    notice, this list of conditions and the following disclaimer in the
1798944Sobrien *    documentation and/or other materials provided with the distribution.
1819370Spst * 3. Neither the name of the University nor the names of its contributors
1998944Sobrien *    may be used to endorse or promote products derived from this software
2098944Sobrien *    without specific prior written permission.
2198944Sobrien *
2298944Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2319370Spst * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2419370Spst * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2519370Spst * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2619370Spst * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2719370Spst * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2819370Spst * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2919370Spst * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3019370Spst * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3119370Spst * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32130803Smarcel * SUCH DAMAGE.
3319370Spst */
3419370Spst
35130803Smarcel#if defined(LIBC_SCCS) && !defined(lint)
36130803Smarcelstatic char sccsid[] = "@(#)stdio.c	8.1 (Berkeley) 6/4/93";
37130803Smarcel#endif /* LIBC_SCCS and not lint */
3819370Spst#include <sys/cdefs.h>
3919370Spst__FBSDID("$FreeBSD: stable/11/lib/libc/stdio/stdio.c 330897 2018-03-14 03:19:51Z eadler $");
40130803Smarcel
4119370Spst#include "namespace.h"
4219370Spst#include <errno.h>
4319370Spst#include <fcntl.h>
4419370Spst#include <limits.h>
4519370Spst#include <stdio.h>
4619370Spst#include <stdlib.h>
4719370Spst#include <unistd.h>
4819370Spst#include "un-namespace.h"
4919370Spst#include "local.h"
5019370Spst
5119370Spst/*
5219370Spst * Small standard I/O/seek/close functions.
5319370Spst */
5419370Spstint
5519370Spst__sread(void *cookie, char *buf, int n)
5619370Spst{
5719370Spst	FILE *fp = cookie;
5898944Sobrien
5998944Sobrien	return(_read(fp->_file, buf, (size_t)n));
6019370Spst}
6198944Sobrien
6298944Sobrienint
6319370Spst__swrite(void *cookie, char const *buf, int n)
6498944Sobrien{
6519370Spst	FILE *fp = cookie;
6698944Sobrien
6719370Spst	return (_write(fp->_file, buf, (size_t)n));
6898944Sobrien}
6919370Spst
7098944Sobrienfpos_t
7198944Sobrien__sseek(void *cookie, fpos_t offset, int whence)
7219370Spst{
7398944Sobrien	FILE *fp = cookie;
7446283Sdfr
7598944Sobrien	return (lseek(fp->_file, (off_t)offset, whence));
7646283Sdfr}
7798944Sobrien
7898944Sobrienint
7998944Sobrien__sclose(void *cookie)
8098944Sobrien{
8198944Sobrien
8298944Sobrien	return (_close(((FILE *)cookie)->_file));
8319370Spst}
84130803Smarcel
8519370Spst/*
8698944Sobrien * Higher level wrappers.
8798944Sobrien */
8819370Spstint
8919370Spst_sread(FILE *fp, char *buf, int n)
9019370Spst{
91130803Smarcel	int ret;
92130803Smarcel
93130803Smarcel	ret = (*fp->_read)(fp->_cookie, buf, n);
9419370Spst	if (ret > 0) {
9598944Sobrien		if (fp->_flags & __SOFF) {
9619370Spst			if (fp->_offset <= OFF_MAX - ret)
97130803Smarcel				fp->_offset += ret;
98130803Smarcel			else
99130803Smarcel				fp->_flags &= ~__SOFF;
100130803Smarcel		}
10119370Spst	} else if (ret < 0)
102130803Smarcel		fp->_flags &= ~__SOFF;
103130803Smarcel	return (ret);
10419370Spst}
105130803Smarcel
106130803Smarcelint
107130803Smarcel_swrite(FILE *fp, char const *buf, int n)
10819370Spst{
10919370Spst	int ret;
11019370Spst	int serrno;
11119370Spst
11219370Spst	if (fp->_flags & __SAPP) {
11319370Spst		serrno = errno;
11419370Spst		if (_sseek(fp, (fpos_t)0, SEEK_END) == -1 &&
11519370Spst		    (fp->_flags & __SOPT))
11619370Spst			return (-1);
11719370Spst		errno = serrno;
11819370Spst	}
119130803Smarcel	ret = (*fp->_write)(fp->_cookie, buf, n);
12019370Spst	/* __SOFF removed even on success in case O_APPEND mode is set. */
121130803Smarcel	if (ret >= 0) {
122130803Smarcel		if ((fp->_flags & __SOFF) && !(fp->_flags2 & __S2OAP) &&
12319370Spst		    fp->_offset <= OFF_MAX - ret)
12419370Spst			fp->_offset += ret;
12519370Spst		else
12619370Spst			fp->_flags &= ~__SOFF;
12719370Spst
12898944Sobrien	} else if (ret < 0)
12998944Sobrien		fp->_flags &= ~__SOFF;
13019370Spst	return (ret);
13119370Spst}
13219370Spst
13319370Spstfpos_t
13498944Sobrien_sseek(FILE *fp, fpos_t offset, int whence)
13519370Spst{
13619370Spst	fpos_t ret;
13719370Spst	int serrno, errret;
13819370Spst
13998944Sobrien	serrno = errno;
14019370Spst	errno = 0;
141130803Smarcel	ret = (*fp->_seek)(fp->_cookie, offset, whence);
14219370Spst	errret = errno;
14398944Sobrien	if (errno == 0)
14419370Spst		errno = serrno;
145130803Smarcel	/*
14698944Sobrien	 * Disallow negative seeks per POSIX.
14798944Sobrien	 * It is needed here to help upper level caller
14819370Spst	 * in the cases it can't detect.
149130803Smarcel	 */
15019370Spst	if (ret < 0) {
15119370Spst		if (errret == 0) {
15219370Spst			if (offset != 0 || whence != SEEK_CUR) {
15319370Spst				if (HASUB(fp))
154130803Smarcel					FREEUB(fp);
155130803Smarcel				fp->_p = fp->_bf._base;
15619370Spst				fp->_r = 0;
15719370Spst				fp->_flags &= ~__SEOF;
15898944Sobrien			}
159130803Smarcel			fp->_flags |= __SERR;
16098944Sobrien			errno = EINVAL;
16198944Sobrien		} else if (errret == ESPIPE)
16298944Sobrien			fp->_flags &= ~__SAPP;
16398944Sobrien		fp->_flags &= ~__SOFF;
164130803Smarcel		ret = -1;
16519370Spst	} else if (fp->_flags & __SOPT) {
16619370Spst		fp->_flags |= __SOFF;
16719370Spst		fp->_offset = ret;
16898944Sobrien	}
16919370Spst	return (ret);
17019370Spst}
17119370Spst
17219370Spstvoid
17319370Spst__stdio_cancel_cleanup(void * arg)
17498944Sobrien{
17598944Sobrien
176130803Smarcel	if (arg != NULL)
17798944Sobrien		_funlockfile((FILE *)arg);
17819370Spst}
17919370Spst