xref: /csrg-svn/lib/libc/stdio/makebuf.c (revision 46611)
146111Sbostic /*-
246111Sbostic  * Copyright (c) 1990 The Regents of the University of California.
346111Sbostic  * 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*46611Sbostic static char sccsid[] = "@(#)makebuf.c	5.2 (Berkeley) 02/24/91";
1346111Sbostic #endif /* LIBC_SCCS and not lint */
1446111Sbostic 
1546111Sbostic #include <sys/types.h>
1646111Sbostic #include <sys/stat.h>
17*46611Sbostic #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
3046111Sbostic __smakebuf(fp)
3146111Sbostic 	register FILE *fp;
3246111Sbostic {
3346111Sbostic 	register size_t size, couldbetty;
3446111Sbostic 	register void *p;
3546111Sbostic 	struct stat st;
3646111Sbostic 
3746111Sbostic 	if (fp->_flags & __SNBF) {
3846111Sbostic 		fp->_bf._base = fp->_p = fp->_nbuf;
3946111Sbostic 		fp->_bf._size = 1;
4046111Sbostic 		return;
4146111Sbostic 	}
4246111Sbostic 	if (fp->_file < 0 || fstat(fp->_file, &st) < 0) {
4346111Sbostic 		couldbetty = 0;
4446111Sbostic 		size = BUFSIZ;
4546111Sbostic 		/* do not try to optimise fseek() */
4646111Sbostic 		fp->_flags |= __SNPT;
4746111Sbostic 	} else {
4846111Sbostic 		couldbetty = (st.st_mode & S_IFMT) == S_IFCHR;
4946111Sbostic 		size = st.st_blksize <= 0 ? BUFSIZ : st.st_blksize;
5046111Sbostic 		/*
5146111Sbostic 		 * Optimise fseek() only if it is a regular file.
5246111Sbostic 		 * (The test for __sseek is mainly paranoia.)
5346111Sbostic 		 */
5446111Sbostic 		if ((st.st_mode & S_IFMT) == S_IFREG &&
5546111Sbostic 		    fp->_seek == __sseek) {
5646111Sbostic 			fp->_flags |= __SOPT;
5746111Sbostic 			fp->_blksize = st.st_blksize;
5846111Sbostic 		} else
5946111Sbostic 			fp->_flags |= __SNPT;
6046111Sbostic 	}
6146111Sbostic 	if ((p = malloc(size)) == NULL) {
6246111Sbostic 		fp->_flags |= __SNBF;
6346111Sbostic 		fp->_bf._base = fp->_p = fp->_nbuf;
6446111Sbostic 		fp->_bf._size = 1;
6546111Sbostic 	} else {
6646111Sbostic 		__cleanup = _cleanup;
6746111Sbostic 		fp->_flags |= __SMBF;
6846111Sbostic 		fp->_bf._base = fp->_p = p;
6946111Sbostic 		fp->_bf._size = size;
7046111Sbostic 		if (couldbetty && isatty(fp->_file))
7146111Sbostic 			fp->_flags |= __SLBF;
7246111Sbostic 	}
7346111Sbostic }
74