makebuf.c revision 249808
1272343Sngie/*- 2272343Sngie * Copyright (c) 1990, 1993 3272343Sngie * The Regents of the University of California. All rights reserved. 4272343Sngie * 5272343Sngie * This code is derived from software contributed to Berkeley by 6272343Sngie * Chris Torek. 7272343Sngie * 8272343Sngie * Redistribution and use in source and binary forms, with or without 9272343Sngie * modification, are permitted provided that the following conditions 10272343Sngie * are met: 11272343Sngie * 1. Redistributions of source code must retain the above copyright 12272343Sngie * notice, this list of conditions and the following disclaimer. 13272343Sngie * 2. Redistributions in binary form must reproduce the above copyright 14272343Sngie * notice, this list of conditions and the following disclaimer in the 15272343Sngie * documentation and/or other materials provided with the distribution. 16272343Sngie * 3. Neither the name of the University nor the names of its contributors 17272343Sngie * may be used to endorse or promote products derived from this software 18272343Sngie * without specific prior written permission. 19272343Sngie * 20272343Sngie * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21272343Sngie * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22272343Sngie * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23272343Sngie * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24272343Sngie * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25272343Sngie * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26272343Sngie * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27272343Sngie * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28272343Sngie * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29272343Sngie * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30272343Sngie * SUCH DAMAGE. 31272343Sngie */ 32272343Sngie 33272343Sngie#if defined(LIBC_SCCS) && !defined(lint) 34272343Sngiestatic char sccsid[] = "@(#)makebuf.c 8.1 (Berkeley) 6/4/93"; 35272343Sngie#endif /* LIBC_SCCS and not lint */ 36272343Sngie#include <sys/cdefs.h> 37272343Sngie__FBSDID("$FreeBSD: head/lib/libc/stdio/makebuf.c 249808 2013-04-23 13:33:13Z emaste $"); 38272343Sngie 39272343Sngie#include "namespace.h" 40272343Sngie#include <sys/types.h> 41272343Sngie#include <sys/stat.h> 42272343Sngie#include <unistd.h> 43272343Sngie#include <stdio.h> 44272343Sngie#include <stdlib.h> 45272343Sngie#include "un-namespace.h" 46272343Sngie 47272343Sngie#include "libc_private.h" 48272343Sngie#include "local.h" 49272343Sngie 50272343Sngie/* 51272343Sngie * Allocate a file buffer, or switch to unbuffered I/O. 52272343Sngie * Per the ANSI C standard, ALL tty devices default to line buffered. 53272343Sngie * 54272343Sngie * As a side effect, we set __SOPT or __SNPT (en/dis-able fseek 55272343Sngie * optimisation) right after the _fstat() that finds the buffer size. 56272343Sngie */ 57272343Sngievoid 58272343Sngie__smakebuf(fp) 59272343Sngie FILE *fp; 60272343Sngie{ 61272343Sngie void *p; 62272343Sngie int flags; 63272343Sngie size_t size; 64272343Sngie int couldbetty; 65272343Sngie 66272343Sngie if (fp->_flags & __SNBF) { 67272343Sngie fp->_bf._base = fp->_p = fp->_nbuf; 68272343Sngie fp->_bf._size = 1; 69272343Sngie return; 70272343Sngie } 71272343Sngie flags = __swhatbuf(fp, &size, &couldbetty); 72272343Sngie if ((p = malloc(size)) == NULL) { 73272343Sngie fp->_flags |= __SNBF; 74272343Sngie fp->_bf._base = fp->_p = fp->_nbuf; 75272343Sngie fp->_bf._size = 1; 76272343Sngie return; 77272343Sngie } 78272343Sngie __cleanup = _cleanup; 79272343Sngie flags |= __SMBF; 80272343Sngie fp->_bf._base = fp->_p = p; 81272343Sngie fp->_bf._size = size; 82272343Sngie if (couldbetty && isatty(fp->_file)) 83272343Sngie flags |= __SLBF; 84272343Sngie fp->_flags |= flags; 85272343Sngie} 86272343Sngie 87272343Sngie/* 88272343Sngie * Internal routine to determine `proper' buffering for a file. 89272343Sngie */ 90272343Sngieint 91272343Sngie__swhatbuf(fp, bufsize, couldbetty) 92272343Sngie FILE *fp; 93272343Sngie size_t *bufsize; 94272343Sngie int *couldbetty; 95272343Sngie{ 96272343Sngie struct stat st; 97272343Sngie 98272343Sngie if (fp->_file < 0 || _fstat(fp->_file, &st) < 0) { 99272343Sngie *couldbetty = 0; 100272343Sngie *bufsize = BUFSIZ; 101272343Sngie return (__SNPT); 102272343Sngie } 103272343Sngie 104272343Sngie /* could be a tty iff it is a character device */ 105272343Sngie *couldbetty = (st.st_mode & S_IFMT) == S_IFCHR; 106272343Sngie if (st.st_blksize <= 0) { 107272343Sngie *bufsize = BUFSIZ; 108272343Sngie return (__SNPT); 109272343Sngie } 110272343Sngie 111272343Sngie /* 112272343Sngie * Optimise fseek() only if it is a regular file. (The test for 113272343Sngie * __sseek is mainly paranoia.) It is safe to set _blksize 114272343Sngie * unconditionally; it will only be used if __SOPT is also set. 115272343Sngie */ 116272343Sngie *bufsize = st.st_blksize; 117272343Sngie fp->_blksize = st.st_blksize; 118272343Sngie return ((st.st_mode & S_IFMT) == S_IFREG && fp->_seek == __sseek ? 119272343Sngie __SOPT : __SNPT); 120272343Sngie} 121272343Sngie