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