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
110typedef 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 */
142extern Uchar _smbuf[][_SMBFSZ];
143
144
145/*
146 * Internal routines from flush.c
147 */
148extern void	__cleanup(void);
149extern void	_flushlbf(void);
150extern FILE	*_findiop(void);
151
152/*
153 * this is to be found in <stdio.h> for 32bit mode
154 */
155#ifdef	_LP64
156extern int	__filbuf(FILE *);
157extern 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
164extern Uchar	*_realbufend(FILE *iop);
165extern rmutex_t	*_reallock(FILE *iop);
166#endif	/*	_LP64	*/
167
168extern void	_setbufend(FILE *iop, Uchar *end);
169extern rmutex_t *_flockget(FILE *iop);
170extern int	_xflsbuf(FILE *iop);
171extern int	_wrtchk(FILE *iop);
172extern void	_bufsync(FILE *iop, Uchar *bufend);
173extern int	_fflush_u(FILE *iop);
174extern int	close_fd(FILE *iop);
175extern int	_doscan(FILE *, const char *, va_list);
176#ifdef	_LP64
177extern void	close_pid(void);
178#endif	/*	_LP64	*/
179
180/*
181 * Internal routines from flush.c
182 */
183extern int _get_fd(FILE *);
184extern 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 */
210extern int _fileno(FILE *iop);
211
212/*
213 * Internal routines from _findbuf.c
214 */
215extern Uchar	*_findbuf(FILE *iop);
216
217/*
218 * Internal routine used by fopen.c
219 */
220extern	FILE	*_endopen(const char *, const char *, FILE *, int);
221
222/*
223 * Internal routine from fwrite.c
224 */
225extern size_t _fwrite_unlocked(const void *, size_t, size_t, FILE *);
226
227/*
228 * Internal routine from getc.c
229 */
230int _getc_internal(FILE *);
231
232/*
233 * Internal routine from put.c
234 */
235int _putc_internal(int, FILE *);
236
237/*
238 * Internal routine from ungetc.c
239 */
240int _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
265extern 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 */
273extern ssize_t	_xread(FILE *iop, void *buf, size_t nbytes);
274extern ssize_t	_xwrite(FILE *iop, const void *buf, size_t nbytes);
275extern off_t	_xseek(FILE *iop, off_t off, int whence);
276extern off64_t	_xseek64(FILE *iop, off64_t off, int whence);
277extern int	_xclose(FILE *iop);
278extern void	*_xdata(FILE *iop);
279extern int	_xassoc(FILE *iop, fread_t readf, fwrite_t writef,
280    fseek_t seekf, fclose_t closef, void *data);
281extern void	_xunassoc(FILE *iop);
282
283/*
284 * Internal functions from _stdio_flags.c.
285 */
286extern int	_stdio_flags(const char *type, int *oflags, int *fflags);
287
288/*
289 * Internal functions from open_memstream.c.
290 */
291extern boolean_t	memstream_seek(size_t base, off_t off, size_t max,
292    size_t *nposp);
293extern 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 */
299extern off64_t	ftell_common(FILE *iop);
300
301#endif	/* _STDIOM_H */
302