makebuf.c revision 249810
1213365Smarcel/*- 2214006Smarcel * Copyright (c) 1990, 1993 3213365Smarcel * The Regents of the University of California. All rights reserved. 4213365Smarcel * 5213365Smarcel * This code is derived from software contributed to Berkeley by 6213365Smarcel * Chris Torek. 7213365Smarcel * 8213365Smarcel * Redistribution and use in source and binary forms, with or without 9213365Smarcel * modification, are permitted provided that the following conditions 10213365Smarcel * are met: 11213365Smarcel * 1. Redistributions of source code must retain the above copyright 12213365Smarcel * notice, this list of conditions and the following disclaimer. 13213365Smarcel * 2. Redistributions in binary form must reproduce the above copyright 14213365Smarcel * notice, this list of conditions and the following disclaimer in the 15213365Smarcel * documentation and/or other materials provided with the distribution. 16213365Smarcel * 3. Neither the name of the University nor the names of its contributors 17213365Smarcel * may be used to endorse or promote products derived from this software 18213365Smarcel * without specific prior written permission. 19213365Smarcel * 20213365Smarcel * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21213365Smarcel * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22213365Smarcel * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23213365Smarcel * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24213365Smarcel * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25213365Smarcel * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26213365Smarcel * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27213365Smarcel * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28213365Smarcel * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29213365Smarcel * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30213365Smarcel * SUCH DAMAGE. 31213365Smarcel */ 32213365Smarcel 33213365Smarcel#if defined(LIBC_SCCS) && !defined(lint) 34213365Smarcelstatic char sccsid[] = "@(#)makebuf.c 8.1 (Berkeley) 6/4/93"; 35213365Smarcel#endif /* LIBC_SCCS and not lint */ 36213365Smarcel#include <sys/cdefs.h> 37213365Smarcel__FBSDID("$FreeBSD: head/lib/libc/stdio/makebuf.c 249810 2013-04-23 14:36:44Z emaste $"); 38214006Smarcel 39214006Smarcel#include "namespace.h" 40213365Smarcel#include <sys/types.h> 41213365Smarcel#include <sys/stat.h> 42213365Smarcel#include <unistd.h> 43213365Smarcel#include <stdio.h> 44213365Smarcel#include <stdlib.h> 45228634Savg#include "un-namespace.h" 46213365Smarcel 47213365Smarcel#include "libc_private.h" 48213365Smarcel#include "local.h" 49213365Smarcel 50214006Smarcel/* 51213365Smarcel * Allocate a file buffer, or switch to unbuffered I/O. 52213365Smarcel * Per the ANSI C standard, ALL tty devices default to line buffered. 53213365Smarcel * 54213365Smarcel * As a side effect, we set __SOPT or __SNPT (en/dis-able fseek 55213365Smarcel * optimisation) right after the _fstat() that finds the buffer size. 56213365Smarcel */ 57213365Smarcelvoid 58223919Sae__smakebuf(FILE *fp) 59214006Smarcel{ 60213365Smarcel void *p; 61213365Smarcel int flags; 62213365Smarcel size_t size; 63213365Smarcel int couldbetty; 64213365Smarcel 65213365Smarcel if (fp->_flags & __SNBF) { 66213365Smarcel fp->_bf._base = fp->_p = fp->_nbuf; 67213365Smarcel fp->_bf._size = 1; 68213365Smarcel return; 69213365Smarcel } 70213365Smarcel flags = __swhatbuf(fp, &size, &couldbetty); 71213365Smarcel if ((p = malloc(size)) == NULL) { 72213365Smarcel fp->_flags |= __SNBF; 73213365Smarcel fp->_bf._base = fp->_p = fp->_nbuf; 74213365Smarcel fp->_bf._size = 1; 75213365Smarcel return; 76213365Smarcel } 77213365Smarcel __cleanup = _cleanup; 78213365Smarcel flags |= __SMBF; 79213365Smarcel fp->_bf._base = fp->_p = p; 80213365Smarcel fp->_bf._size = size; 81213365Smarcel if (couldbetty && isatty(fp->_file)) 82213365Smarcel flags |= __SLBF; 83213365Smarcel fp->_flags |= flags; 84213365Smarcel} 85213365Smarcel 86213365Smarcel/* 87213365Smarcel * Internal routine to determine `proper' buffering for a file. 88213365Smarcel */ 89214006Smarcelint 90214006Smarcel__swhatbuf(FILE *fp, size_t *bufsize, int *couldbetty) 91214006Smarcel{ 92213365Smarcel struct stat st; 93214006Smarcel 94214006Smarcel if (fp->_file < 0 || _fstat(fp->_file, &st) < 0) { 95213365Smarcel *couldbetty = 0; 96214006Smarcel *bufsize = BUFSIZ; 97213365Smarcel return (__SNPT); 98287107Strasz } 99287107Strasz 100287107Strasz /* could be a tty iff it is a character device */ 101287107Strasz *couldbetty = (st.st_mode & S_IFMT) == S_IFCHR; 102287107Strasz if (st.st_blksize <= 0) { 103214006Smarcel *bufsize = BUFSIZ; 104213365Smarcel return (__SNPT); 105267351Smav } 106267351Smav 107267351Smav /* 108213365Smarcel * Optimise fseek() only if it is a regular file. (The test for 109213365Smarcel * __sseek is mainly paranoia.) It is safe to set _blksize 110213365Smarcel * unconditionally; it will only be used if __SOPT is also set. 111213365Smarcel */ 112213365Smarcel *bufsize = st.st_blksize; 113213365Smarcel fp->_blksize = st.st_blksize; 114213365Smarcel return ((st.st_mode & S_IFMT) == S_IFREG && fp->_seek == __sseek ? 115213365Smarcel __SOPT : __SNPT); 116214006Smarcel} 117214006Smarcel