xref: /csrg-svn/lib/libc/stdio/makebuf.c (revision 61180)
146111Sbostic /*-
2*61180Sbostic  * Copyright (c) 1990, 1993
3*61180Sbostic  *	The Regents of the University of California.  All rights reserved.
446111Sbostic  *
546111Sbostic  * This code is derived from software contributed to Berkeley by
646111Sbostic  * Chris Torek.
746111Sbostic  *
846111Sbostic  * %sccs.include.redist.c%
946111Sbostic  */
1046111Sbostic 
1146111Sbostic #if defined(LIBC_SCCS) && !defined(lint)
12*61180Sbostic static char sccsid[] = "@(#)makebuf.c	8.1 (Berkeley) 06/04/93";
1346111Sbostic #endif /* LIBC_SCCS and not lint */
1446111Sbostic 
1546111Sbostic #include <sys/types.h>
1646111Sbostic #include <sys/stat.h>
1746611Sbostic #include <unistd.h>
1846111Sbostic #include <stdio.h>
1946111Sbostic #include <stdlib.h>
2046111Sbostic #include "local.h"
2146111Sbostic 
2246111Sbostic /*
2346111Sbostic  * Allocate a file buffer, or switch to unbuffered I/O.
2446111Sbostic  * Per the ANSI C standard, ALL tty devices default to line buffered.
2546111Sbostic  *
2646111Sbostic  * As a side effect, we set __SOPT or __SNPT (en/dis-able fseek
2746111Sbostic  * optimisation) right after the fstat() that finds the buffer size.
2846111Sbostic  */
2946111Sbostic void
__smakebuf(fp)3046111Sbostic __smakebuf(fp)
3146111Sbostic 	register FILE *fp;
3246111Sbostic {
3346111Sbostic 	register void *p;
3459777Storek 	register int flags;
3559777Storek 	size_t size;
3659777Storek 	int couldbetty;
3746111Sbostic 
3846111Sbostic 	if (fp->_flags & __SNBF) {
3946111Sbostic 		fp->_bf._base = fp->_p = fp->_nbuf;
4046111Sbostic 		fp->_bf._size = 1;
4146111Sbostic 		return;
4246111Sbostic 	}
4359777Storek 	flags = __swhatbuf(fp, &size, &couldbetty);
4446111Sbostic 	if ((p = malloc(size)) == NULL) {
4546111Sbostic 		fp->_flags |= __SNBF;
4646111Sbostic 		fp->_bf._base = fp->_p = fp->_nbuf;
4746111Sbostic 		fp->_bf._size = 1;
4859777Storek 		return;
4946111Sbostic 	}
5059777Storek 	__cleanup = _cleanup;
5159777Storek 	flags |= __SMBF;
5259777Storek 	fp->_bf._base = fp->_p = p;
5359777Storek 	fp->_bf._size = size;
5459777Storek 	if (couldbetty && isatty(fp->_file))
5559777Storek 		flags |= __SLBF;
5659777Storek 	fp->_flags |= flags;
5746111Sbostic }
5859777Storek 
5959777Storek /*
6059777Storek  * Internal routine to determine `proper' buffering for a file.
6159777Storek  */
6259777Storek int
__swhatbuf(fp,bufsize,couldbetty)6359777Storek __swhatbuf(fp, bufsize, couldbetty)
6459777Storek 	register FILE *fp;
6559777Storek 	size_t *bufsize;
6659777Storek 	int *couldbetty;
6759777Storek {
6859777Storek 	struct stat st;
6959777Storek 
7059777Storek 	if (fp->_file < 0 || fstat(fp->_file, &st) < 0) {
7159777Storek 		*couldbetty = 0;
7259777Storek 		*bufsize = BUFSIZ;
7359777Storek 		return (__SNPT);
7459777Storek 	}
7559777Storek 
7659777Storek 	/* could be a tty iff it is a character device */
7759777Storek 	*couldbetty = (st.st_mode & S_IFMT) == S_IFCHR;
7859777Storek 	if (st.st_blksize <= 0) {
7959777Storek 		*bufsize = BUFSIZ;
8059777Storek 		return (__SNPT);
8159777Storek 	}
8259777Storek 
8359777Storek 	/*
8459777Storek 	 * Optimise fseek() only if it is a regular file.  (The test for
8559777Storek 	 * __sseek is mainly paranoia.)  It is safe to set _blksize
8659777Storek 	 * unconditionally; it will only be used if __SOPT is also set.
8759777Storek 	 */
8859777Storek 	*bufsize = st.st_blksize;
8959777Storek 	fp->_blksize = st.st_blksize;
9059777Storek 	return ((st.st_mode & S_IFMT) == S_IFREG && fp->_seek == __sseek ?
9159777Storek 	    __SOPT : __SNPT);
9259777Storek }
93