makebuf.c revision 92986
154359Sroberto/*- 254359Sroberto * Copyright (c) 1990, 1993 354363Sroberto * The Regents of the University of California. All rights reserved. 4132454Sroberto * 5132454Sroberto * This code is derived from software contributed to Berkeley by 654359Sroberto * Chris Torek. 754359Sroberto * 854359Sroberto * Redistribution and use in source and binary forms, with or without 954359Sroberto * modification, are permitted provided that the following conditions 1054359Sroberto * are met: 1154359Sroberto * 1. Redistributions of source code must retain the above copyright 1254359Sroberto * notice, this list of conditions and the following disclaimer. 1354359Sroberto * 2. Redistributions in binary form must reproduce the above copyright 1454359Sroberto * notice, this list of conditions and the following disclaimer in the 1554359Sroberto * documentation and/or other materials provided with the distribution. 16285612Sdelphij * 3. All advertising materials mentioning features or use of this software 17285612Sdelphij * must display the following acknowledgement: 1854359Sroberto * This product includes software developed by the University of 1982505Sroberto * California, Berkeley and its contributors. 20285612Sdelphij * 4. Neither the name of the University nor the names of its contributors 21285612Sdelphij * may be used to endorse or promote products derived from this software 2254359Sroberto * without specific prior written permission. 23285612Sdelphij * 24285612Sdelphij * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2554359Sroberto * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2654359Sroberto * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2754359Sroberto * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28182007Sroberto * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29182007Sroberto * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30182007Sroberto * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31289997Sglebius * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32289997Sglebius * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33182007Sroberto * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34285612Sdelphij * SUCH DAMAGE. 35285612Sdelphij */ 36285612Sdelphij 37285612Sdelphij#if defined(LIBC_SCCS) && !defined(lint) 38285612Sdelphijstatic char sccsid[] = "@(#)makebuf.c 8.1 (Berkeley) 6/4/93"; 39182007Sroberto#endif /* LIBC_SCCS and not lint */ 40289997Sglebius#include <sys/cdefs.h> 41289997Sglebius__FBSDID("$FreeBSD: head/lib/libc/stdio/makebuf.c 92986 2002-03-22 21:53:29Z obrien $"); 42289997Sglebius 43289997Sglebius#include "namespace.h" 44289997Sglebius#include <sys/types.h> 45289997Sglebius#include <sys/stat.h> 46289997Sglebius#include <unistd.h> 47289997Sglebius#include <stdio.h> 48289997Sglebius#include <stdlib.h> 49289997Sglebius#include "local.h" 50289997Sglebius#include "un-namespace.h" 51289997Sglebius 52289997Sglebius/* 53285612Sdelphij * Allocate a file buffer, or switch to unbuffered I/O. 5454359Sroberto * Per the ANSI C standard, ALL tty devices default to line buffered. 55285612Sdelphij * 56285612Sdelphij * As a side effect, we set __SOPT or __SNPT (en/dis-able fseek 57285612Sdelphij * optimisation) right after the _fstat() that finds the buffer size. 58285612Sdelphij */ 59285612Sdelphijvoid 60285612Sdelphij__smakebuf(fp) 61285612Sdelphij FILE *fp; 62285612Sdelphij{ 63285612Sdelphij void *p; 64285612Sdelphij int flags; 65285612Sdelphij size_t size; 66285612Sdelphij int couldbetty; 67285612Sdelphij 68285612Sdelphij if (fp->_flags & __SNBF) { 69285612Sdelphij fp->_bf._base = fp->_p = fp->_nbuf; 70285612Sdelphij fp->_bf._size = 1; 71285612Sdelphij return; 72285612Sdelphij } 73285612Sdelphij flags = __swhatbuf(fp, &size, &couldbetty); 74285612Sdelphij if ((p = malloc(size)) == NULL) { 75285612Sdelphij fp->_flags |= __SNBF; 76285612Sdelphij fp->_bf._base = fp->_p = fp->_nbuf; 77285612Sdelphij fp->_bf._size = 1; 78285612Sdelphij return; 79285612Sdelphij } 80285612Sdelphij __cleanup = _cleanup; 81182007Sroberto flags |= __SMBF; 8282505Sroberto fp->_bf._base = fp->_p = p; 83285612Sdelphij fp->_bf._size = size; 84285612Sdelphij if (couldbetty && isatty(fp->_file)) 85285612Sdelphij flags |= __SLBF; 86285612Sdelphij fp->_flags |= flags; 8754359Sroberto} 88285612Sdelphij 89285612Sdelphij/* 90285612Sdelphij * Internal routine to determine `proper' buffering for a file. 91285612Sdelphij */ 92285612Sdelphijint 9354359Sroberto__swhatbuf(fp, bufsize, couldbetty) 94285612Sdelphij FILE *fp; 95285612Sdelphij size_t *bufsize; 96285612Sdelphij int *couldbetty; 97285612Sdelphij{ 98285612Sdelphij struct stat st; 99285612Sdelphij 100285612Sdelphij if (fp->_file < 0 || _fstat(fp->_file, &st) < 0) { 101285612Sdelphij *couldbetty = 0; 10254359Sroberto *bufsize = BUFSIZ; 103285612Sdelphij return (__SNPT); 104285612Sdelphij } 105285612Sdelphij 106132454Sroberto /* could be a tty iff it is a character device */ 107132454Sroberto *couldbetty = (st.st_mode & S_IFMT) == S_IFCHR; 10854359Sroberto if (st.st_blksize <= 0) { 10954359Sroberto *bufsize = BUFSIZ; 110285612Sdelphij return (__SNPT); 111285612Sdelphij } 112285612Sdelphij 113285612Sdelphij /* 114285612Sdelphij * Optimise fseek() only if it is a regular file. (The test for 115285612Sdelphij * __sseek is mainly paranoia.) It is safe to set _blksize 116285612Sdelphij * unconditionally; it will only be used if __SOPT is also set. 117285612Sdelphij */ 11882505Sroberto *bufsize = st.st_blksize; 11982505Sroberto fp->_blksize = st.st_blksize; 120285612Sdelphij return ((st.st_mode & S_IFMT) == S_IFREG && fp->_seek == __sseek ? 12182505Sroberto __SOPT : __SNPT); 122132454Sroberto} 123285612Sdelphij