1 /*
2 * Copyright (c) 1990, 2007 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms are permitted
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * and/or other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * by the University of California, Berkeley. The name of the
11 * University may not be used to endorse or promote products derived
12 * from this software without specific prior written permission.
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16 */
17 /* No user fns here. Pesch 15apr92. */
18
19 #define _DEFAULT_SOURCE
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <sys/stat.h>
23 #include <sys/types.h>
24 #include <sys/unistd.h>
25 #include "local.h"
26
27 #define _DEFAULT_ASPRINTF_BUFSIZE 64
28
29 /*
30 * Allocate a file buffer, or switch to unbuffered I/O.
31 * Per the ANSI C standard, ALL tty devices default to line buffered.
32 *
33 * As a side effect, we set __SOPT or __SNPT (en/dis-able fseek
34 * optimization) right after the _fstat() that finds the buffer size.
35 */
36
37 void
_smakebuf(register FILE * fp)38 _smakebuf (
39 register FILE *fp)
40 {
41 register void *p;
42 int flags;
43 size_t size;
44 int couldbetty;
45
46 if (fp->_flags & __SNBF)
47 {
48 fp->_bf._base = fp->_p = fp->_nbuf;
49 fp->_bf._size = 1;
50 return;
51 }
52 flags = _swhatbuf ( fp, &size, &couldbetty);
53 if ((p = malloc (size)) == NULL)
54 {
55 if (!(fp->_flags & __SSTR))
56 {
57 fp->_flags = (fp->_flags & ~__SLBF) | __SNBF;
58 fp->_bf._base = fp->_p = fp->_nbuf;
59 fp->_bf._size = 1;
60 }
61 }
62 else
63 {
64 fp->_flags |= __SMBF;
65 fp->_bf._base = fp->_p = (unsigned char *) p;
66 fp->_bf._size = size;
67 if (couldbetty && isatty (fp->_file))
68 fp->_flags = (fp->_flags & ~__SNBF) | __SLBF;
69 fp->_flags |= flags;
70 }
71 }
72
73 /*
74 * Internal routine to determine `proper' buffering for a file.
75 */
76 int
_swhatbuf(FILE * fp,size_t * bufsize,int * couldbetty)77 _swhatbuf (
78 FILE *fp,
79 size_t *bufsize,
80 int *couldbetty)
81 {
82 #ifdef _FSEEK_OPTIMIZATION
83 const int snpt = __SNPT;
84 #else
85 const int snpt = 0;
86 #endif
87
88 #ifdef __USE_INTERNAL_STAT64
89 struct stat64 st;
90
91 if (fp->_file < 0 || fstat64 (fp->_file, &st) < 0)
92 #else
93 struct stat st;
94
95 if (fp->_file < 0 || fstat (fp->_file, &st) < 0)
96 #endif
97 {
98 *couldbetty = 0;
99 /* Check if we are be called by asprintf family for initial buffer. */
100 if (fp->_flags & __SMBF)
101 *bufsize = _DEFAULT_ASPRINTF_BUFSIZE;
102 else
103 *bufsize = BUFSIZ;
104 return (0);
105 }
106
107 /* could be a tty iff it is a character device */
108 *couldbetty = S_ISCHR(st.st_mode);
109 #ifdef HAVE_BLKSIZE
110 if (st.st_blksize > 0)
111 {
112 /*
113 * Optimise fseek() only if it is a regular file. (The test for
114 * __sseek is mainly paranoia.) It is safe to set _blksize
115 * unconditionally; it will only be used if __SOPT is also set.
116 */
117 *bufsize = st.st_blksize;
118 fp->_blksize = st.st_blksize;
119 return ((st.st_mode & S_IFMT) == S_IFREG ? __SOPT : snpt);
120 }
121 #endif
122 *bufsize = BUFSIZ;
123 return (snpt);
124 }
125