xref: /illumos-gate/usr/src/lib/libc/inc/stdiom.h (revision 8459c777fc1aaabb2f7dad05de1313aa169417cd)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*	Copyright (c) 1988 AT&T	*/
28 /*	  All Rights Reserved	*/
29 
30 /*
31  * Copyright 2020 Robert Mustacchi
32  */
33 
34 /*
35  * stdiom.h - shared guts of stdio
36  */
37 
38 #ifndef	_STDIOM_H
39 #define	_STDIOM_H
40 
41 #include <thread.h>
42 #include <synch.h>
43 #include <mtlib.h>
44 #include <stdarg.h>
45 #include "file64.h"
46 #include <wchar.h>
47 #include "mse.h"
48 
49 
50 /*
51  * The following flags, and the macros that manipulate them, operate upon
52  * the FILE structure used by stdio. If new flags are required, they should
53  * be created in this file. The values of the flags must be different from
54  * the currently used values. New macros should be created to use the flags
55  * so that the compilation mode dependencies can be isolated here.
56  */
57 
58 /*
59  * The 32-bit version of the stdio FILE has 8 bits for its flags (see
60  * lib/libc/port/stdio/README.design). These 8 bits are used to determine if the
61  * FILE structure is allocated. We define '_DEF_FLAG_MASK' as a means to
62  * indicate this.
63  */
64 #define	_DEF_FLAG_MASK	0377
65 #ifdef _LP64
66 #define	_BYTE_MODE_FLAG	0400
67 #define	_WC_MODE_FLAG	01000
68 #define	_IONOLOCK	02000
69 #define	_SEEKABLE	04000	/* is it seekable? */
70 #define	SET_IONOLOCK(iop)	((iop)->_flag |= _IONOLOCK)
71 #define	CLEAR_IONOLOCK(iop)	((iop)->_flag &= ~_IONOLOCK)
72 #define	GET_IONOLOCK(iop)	((iop)->_flag & _IONOLOCK)
73 #define	SET_BYTE_MODE(iop)	((iop)->_flag |= _BYTE_MODE_FLAG)
74 #define	CLEAR_BYTE_MODE(iop)	((iop)->_flag &= ~_BYTE_MODE_FLAG)
75 #define	GET_BYTE_MODE(iop)	((iop)->_flag & _BYTE_MODE_FLAG)
76 #define	SET_WC_MODE(iop)	((iop)->_flag |= _WC_MODE_FLAG)
77 #define	CLEAR_WC_MODE(iop)	((iop)->_flag &= ~_WC_MODE_FLAG)
78 #define	GET_WC_MODE(iop)	((iop)->_flag & _WC_MODE_FLAG)
79 #define	GET_NO_MODE(iop)	(!((iop)->_flag & \
80 					(_BYTE_MODE_FLAG | _WC_MODE_FLAG)))
81 #define	SET_SEEKABLE(iop)	((iop)->_flag |=  _SEEKABLE)
82 #define	CLEAR_SEEKABLE(iop)	((iop)->_flag &= ~_SEEKABLE)
83 #define	GET_SEEKABLE(iop)	((iop)->_flag &   _SEEKABLE)
84 #else
85 #define	_BYTE_MODE_FLAG	0001
86 #define	_WC_MODE_FLAG	0002
87 #define	SET_IONOLOCK(iop)	((iop)->__ionolock = 1)
88 #define	CLEAR_IONOLOCK(iop)	((iop)->__ionolock = 0)
89 #define	GET_IONOLOCK(iop)	((iop)->__ionolock)
90 #define	SET_BYTE_MODE(iop)	((iop)->__orientation |= _BYTE_MODE_FLAG)
91 #define	CLEAR_BYTE_MODE(iop)	((iop)->__orientation &= ~_BYTE_MODE_FLAG)
92 #define	GET_BYTE_MODE(iop)	((iop)->__orientation & _BYTE_MODE_FLAG)
93 #define	SET_WC_MODE(iop)	((iop)->__orientation |= _WC_MODE_FLAG)
94 #define	CLEAR_WC_MODE(iop)	((iop)->__orientation &= ~_WC_MODE_FLAG)
95 #define	GET_WC_MODE(iop)	((iop)->__orientation & _WC_MODE_FLAG)
96 #define	GET_NO_MODE(iop)	(!((iop)->__orientation & \
97 					(_BYTE_MODE_FLAG | _WC_MODE_FLAG)))
98 #define	SET_SEEKABLE(iop)	((iop)->__seekable = 1)
99 #define	CLEAR_SEEKABLE(iop)	((iop)->__seekable = 0)
100 #define	GET_SEEKABLE(iop)	((iop)->__seekable)
101 
102 /* Is iop a member of the _iob array? */
103 #define	STDIOP(iop)		((iop) >= &_iob[0] && (iop) < &_iob[_NFILE])
104 
105 /* Compute the index of an _iob array member */
106 #define	IOPIND(iop)		((iop) - &_iob[0])
107 
108 #endif
109 
110 typedef unsigned char	Uchar;
111 
112 #define	_flockrel(rl)		cancel_safe_mutex_unlock(rl)
113 
114 #define	MAXVAL	(MAXINT - (MAXINT % BUFSIZ))
115 
116 /*
117  * The number of actual pushback characters is the value
118  * of PUSHBACK plus the first byte of the buffer. The FILE buffer must,
119  * for performance reasons, start on a word aligned boundry so the value
120  * of PUSHBACK should be a multiple of word.
121  * At least 4 bytes of PUSHBACK are needed. If sizeof (int) = 1 this breaks.
122  */
123 #define	PUSHBACK	(((3 + sizeof (int) - 1) / sizeof (int)) * sizeof (int))
124 
125 /* minimum buffer size must be at least 8 or shared library will break */
126 #define	_SMBFSZ	(((PUSHBACK + 4) < 8) ? 8 : (PUSHBACK + 4))
127 
128 #if BUFSIZ == 1024
129 #define	MULTIBFSZ(SZ)	((SZ) & ~0x3ff)
130 #elif BUFSIZ == 512
131 #define	MULTIBFSZ(SZ)    ((SZ) & ~0x1ff)
132 #else
133 #define	MULTIBFSZ(SZ)    ((SZ) - (SZ % BUFSIZ))
134 #endif
135 
136 #undef _bufend
137 #define	_bufend(iop)	_realbufend(iop)
138 
139 /*
140  * Internal data
141  */
142 extern Uchar _smbuf[][_SMBFSZ];
143 
144 
145 /*
146  * Internal routines from flush.c
147  */
148 extern void	__cleanup(void);
149 extern void	_flushlbf(void);
150 extern FILE	*_findiop(void);
151 
152 /*
153  * this is to be found in <stdio.h> for 32bit mode
154  */
155 #ifdef	_LP64
156 extern int	__filbuf(FILE *);
157 extern int	__flsbuf(int, FILE *);
158 
159 /*
160  * Not needed as a function in 64 bit mode.
161  */
162 #define	_realbufend(iop)	((iop)->_end)
163 #else
164 extern Uchar	*_realbufend(FILE *iop);
165 extern rmutex_t	*_reallock(FILE *iop);
166 #endif	/*	_LP64	*/
167 
168 extern void	_setbufend(FILE *iop, Uchar *end);
169 extern rmutex_t *_flockget(FILE *iop);
170 extern int	_xflsbuf(FILE *iop);
171 extern int	_wrtchk(FILE *iop);
172 extern void	_bufsync(FILE *iop, Uchar *bufend);
173 extern int	_fflush_u(FILE *iop);
174 extern int	close_fd(FILE *iop);
175 extern int	_doscan(FILE *, const char *, va_list);
176 #ifdef	_LP64
177 extern void	close_pid(void);
178 #endif	/*	_LP64	*/
179 
180 /*
181  * Internal routines from flush.c
182  */
183 extern int _get_fd(FILE *);
184 extern int _file_set(FILE *, int, const char *);
185 
186 /*
187  * Macros to aid the extended fd FILE work.
188  * This helps isolate the changes to only the 32-bit code
189  * since 64-bit Solaris is not affected by this.
190  */
191 #ifdef  _LP64
192 #define	SET_FILE(iop, fd)	((iop)->_file = (fd))
193 #else
194 #define	SET_FILE(iop, fd)	(iop)->_magic = (fd); (iop)->__extendedfd = 0
195 #endif
196 
197 /*
198  * Maximum size of the file descriptor stored in the FILE structure.
199  */
200 
201 #ifdef _LP64
202 #define	_FILE_FD_MAX	INT_MAX
203 #else
204 #define	_FILE_FD_MAX	255
205 #endif
206 
207 /*
208  * Internal routines from fileno.c
209  */
210 extern int _fileno(FILE *iop);
211 
212 /*
213  * Internal routines from _findbuf.c
214  */
215 extern Uchar	*_findbuf(FILE *iop);
216 
217 /*
218  * Internal routine used by fopen.c
219  */
220 extern	FILE	*_endopen(const char *, const char *, FILE *, int);
221 
222 /*
223  * Internal routine from fwrite.c
224  */
225 extern size_t _fwrite_unlocked(const void *, size_t, size_t, FILE *);
226 
227 /*
228  * Internal routine from getc.c
229  */
230 int _getc_internal(FILE *);
231 
232 /*
233  * Internal routine from put.c
234  */
235 int _putc_internal(int, FILE *);
236 
237 /*
238  * Internal routine from ungetc.c
239  */
240 int _ungetc_unlocked(int, FILE *);
241 
242 /*
243  * The following macros improve performance of the stdio by reducing the
244  * number of calls to _bufsync and _wrtchk.  _needsync checks whether
245  * or not _bufsync needs to be called.  _WRTCHK has the same effect as
246  * _wrtchk, but often these functions have no effect, and in those cases
247  * the macros avoid the expense of calling the functions.
248  */
249 
250 #define	_needsync(p, bufend)	((bufend - (p)->_ptr) < \
251 				    ((p)->_cnt < 0 ? 0 : (p)->_cnt))
252 
253 #define	_WRTCHK(iop)	((((iop->_flag & (_IOWRT | _IOEOF)) != _IOWRT) || \
254 			    (iop->_base == 0) ||  \
255 			    (iop->_ptr == iop->_base && iop->_cnt == 0 && \
256 			    !(iop->_flag & (_IONBF | _IOLBF)))) \
257 			? _wrtchk(iop) : 0)
258 
259 #ifdef	_LP64
260 #define	IOB_LCK(iop)	(&((iop)->_lock))
261 #else
262 #define	IOB_LCK(iop)	(STDIOP(iop) ? &_xftab[IOPIND(iop)]._lock \
263 					: _reallock(iop))
264 
265 extern struct xFILEdata	_xftab[];
266 
267 #endif	/*	_LP64	*/
268 
269 /*
270  * A set of stdio routines to allow us to have alternate read, write, lseek, and
271  * close implementations.
272  */
273 extern ssize_t	_xread(FILE *iop, void *buf, size_t nbytes);
274 extern ssize_t	_xwrite(FILE *iop, const void *buf, size_t nbytes);
275 extern off_t	_xseek(FILE *iop, off_t off, int whence);
276 extern off64_t	_xseek64(FILE *iop, off64_t off, int whence);
277 extern int	_xclose(FILE *iop);
278 extern void	*_xdata(FILE *iop);
279 extern int	_xassoc(FILE *iop, fread_t readf, fwrite_t writef,
280     fseek_t seekf, fclose_t closef, void *data);
281 extern void	_xunassoc(FILE *iop);
282 
283 /*
284  * Internal functions from _stdio_flags.c.
285  */
286 extern int	_stdio_flags(const char *type, int *oflags, int *fflags);
287 
288 /*
289  * Internal functions from open_memstream.c.
290  */
291 extern boolean_t	memstream_seek(size_t base, off_t off, size_t max,
292     size_t *nposp);
293 extern int	memstream_newsize(size_t pos, size_t alloc, size_t nbytes,
294     size_t *nallocp);
295 
296 /*
297  * Internal function from ftell.o.
298  */
299 extern off64_t	ftell_common(FILE *iop);
300 
301 #endif	/* _STDIOM_H */
302