1 /*-
2 * Copyright (c) 1990, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Chris Torek.
7 *
8 * %sccs.include.redist.c%
9 */
10
11 #if defined(LIBC_SCCS) && !defined(lint)
12 static char sccsid[] = "@(#)makebuf.c 8.1 (Berkeley) 06/04/93";
13 #endif /* LIBC_SCCS and not lint */
14
15 #include <sys/types.h>
16 #include <sys/stat.h>
17 #include <unistd.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include "local.h"
21
22 /*
23 * Allocate a file buffer, or switch to unbuffered I/O.
24 * Per the ANSI C standard, ALL tty devices default to line buffered.
25 *
26 * As a side effect, we set __SOPT or __SNPT (en/dis-able fseek
27 * optimisation) right after the fstat() that finds the buffer size.
28 */
29 void
__smakebuf(fp)30 __smakebuf(fp)
31 register FILE *fp;
32 {
33 register void *p;
34 register int flags;
35 size_t size;
36 int couldbetty;
37
38 if (fp->_flags & __SNBF) {
39 fp->_bf._base = fp->_p = fp->_nbuf;
40 fp->_bf._size = 1;
41 return;
42 }
43 flags = __swhatbuf(fp, &size, &couldbetty);
44 if ((p = malloc(size)) == NULL) {
45 fp->_flags |= __SNBF;
46 fp->_bf._base = fp->_p = fp->_nbuf;
47 fp->_bf._size = 1;
48 return;
49 }
50 __cleanup = _cleanup;
51 flags |= __SMBF;
52 fp->_bf._base = fp->_p = p;
53 fp->_bf._size = size;
54 if (couldbetty && isatty(fp->_file))
55 flags |= __SLBF;
56 fp->_flags |= flags;
57 }
58
59 /*
60 * Internal routine to determine `proper' buffering for a file.
61 */
62 int
__swhatbuf(fp,bufsize,couldbetty)63 __swhatbuf(fp, bufsize, couldbetty)
64 register FILE *fp;
65 size_t *bufsize;
66 int *couldbetty;
67 {
68 struct stat st;
69
70 if (fp->_file < 0 || fstat(fp->_file, &st) < 0) {
71 *couldbetty = 0;
72 *bufsize = BUFSIZ;
73 return (__SNPT);
74 }
75
76 /* could be a tty iff it is a character device */
77 *couldbetty = (st.st_mode & S_IFMT) == S_IFCHR;
78 if (st.st_blksize <= 0) {
79 *bufsize = BUFSIZ;
80 return (__SNPT);
81 }
82
83 /*
84 * Optimise fseek() only if it is a regular file. (The test for
85 * __sseek is mainly paranoia.) It is safe to set _blksize
86 * unconditionally; it will only be used if __SOPT is also set.
87 */
88 *bufsize = st.st_blksize;
89 fp->_blksize = st.st_blksize;
90 return ((st.st_mode & S_IFMT) == S_IFREG && fp->_seek == __sseek ?
91 __SOPT : __SNPT);
92 }
93