• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /*	$OpenBSD: local.h,v 1.12 2005/10/10 17:37:44 espie Exp $	*/
2  
3  /*-
4   * Copyright (c) 1990, 1993
5   *	The Regents of the University of California.  All rights reserved.
6   *
7   * This code is derived from software contributed to Berkeley by
8   * Chris Torek.
9   *
10   * Redistribution and use in source and binary forms, with or without
11   * modification, are permitted provided that the following conditions
12   * are met:
13   * 1. Redistributions of source code must retain the above copyright
14   *    notice, this list of conditions and the following disclaimer.
15   * 2. Redistributions in binary form must reproduce the above copyright
16   *    notice, this list of conditions and the following disclaimer in the
17   *    documentation and/or other materials provided with the distribution.
18   * 3. Neither the name of the University nor the names of its contributors
19   *    may be used to endorse or promote products derived from this software
20   *    without specific prior written permission.
21   *
22   * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25   * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28   * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30   * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31   * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32   * SUCH DAMAGE.
33   */
34  
35  #pragma once
36  
37  #include <pthread.h>
38  #include <stdbool.h>
39  #include <wchar.h>
40  
41  #if defined(__cplusplus)  // Until we fork all of stdio...
42  #include "private/bionic_fortify.h"
43  #endif
44  
45  /*
46   * Information local to this implementation of stdio,
47   * in particular, macros and private variables.
48   */
49  
50  __BEGIN_DECLS
51  
52  struct __sbuf {
53    unsigned char* _base;
54  #if defined(__LP64__)
55    size_t _size;
56  #else
57    int _size;
58  #endif
59  };
60  
61  struct __sFILE {
62    unsigned char* _p; /* current position in (some) buffer */
63    int _r;            /* read space left for getc() */
64    int _w;            /* write space left for putc() */
65  #if defined(__LP64__)
66    int _flags; /* flags, below; this FILE is free if 0 */
67    int _file;  /* fileno, if Unix descriptor, else -1 */
68  #else
69    short _flags; /* flags, below; this FILE is free if 0 */
70    short _file;  /* fileno, if Unix descriptor, else -1 */
71  #endif
72    struct __sbuf _bf; /* the buffer (at least 1 byte, if !NULL) */
73    int _lbfsize;      /* 0 or -_bf._size, for inline putc */
74  
75    // Function pointers used by `funopen`.
76    // Note that `_seek` is ignored if `_seek64` (in __sfileext) is set.
77    // TODO: NetBSD has `funopen2` which corrects the `int`s to `size_t`s.
78    // TODO: glibc has `fopencookie` which passes the function pointers in a struct.
79    void* _cookie; /* cookie passed to io functions */
80    int (*_close)(void*);
81    int (*_read)(void*, char*, int);
82    fpos_t (*_seek)(void*, fpos_t, int);
83    int (*_write)(void*, const char*, int);
84  
85    /* extension data, to avoid further ABI breakage */
86    struct __sbuf _ext;
87    /* data for long sequences of ungetc() */
88    unsigned char* _up; /* saved _p when _p is doing ungetc data */
89    int _ur;            /* saved _r when _r is counting ungetc data */
90  
91    /* tricks to meet minimum requirements even when malloc() fails */
92    unsigned char _ubuf[3]; /* guarantee an ungetc() buffer */
93    unsigned char _nbuf[1]; /* guarantee a getc() buffer */
94  
95    /* separate buffer for fgetln() when line crosses buffer boundary */
96    struct __sbuf _lb; /* buffer for fgetln() */
97  
98    /* Unix stdio files get aligned to block boundaries on fseek() */
99    int _blksize; /* stat.st_blksize (may be != _bf._size) */
100  
101    fpos_t _unused_0;  // This was the `_offset` field (see below).
102  
103    // Do not add new fields here. (Or remove or change the size of any above.)
104    // Although bionic currently exports `stdin`, `stdout`, and `stderr` symbols,
105    // that still hasn't made it to the NDK. All NDK-built apps index directly
106    // into an array of this struct (which was in <stdio.h> historically), so if
107    // you need to make any changes, they need to be in the `__sfileext` struct
108    // below, and accessed via `_EXT`.
109  };
110  
111  /* minimal requirement of SUSv2 */
112  #define WCIO_UNGETWC_BUFSIZE 1
113  
114  struct wchar_io_data {
115    mbstate_t wcio_mbstate_in;
116    mbstate_t wcio_mbstate_out;
117  
118    wchar_t wcio_ungetwc_buf[WCIO_UNGETWC_BUFSIZE];
119    size_t wcio_ungetwc_inbuf;
120  
121    int wcio_mode; /* orientation */
122  };
123  
124  struct __sfileext {
125    // ungetc buffer.
126    struct __sbuf _ub;
127  
128    // Wide char io status.
129    struct wchar_io_data _wcio;
130  
131    // File lock.
132    pthread_mutex_t _lock;
133  
134    // __fsetlocking support.
135    bool _caller_handles_locking;
136  
137    // Equivalent to `_seek` but for _FILE_OFFSET_BITS=64.
138    // Callers should use this but fall back to `__sFILE::_seek`.
139    off64_t (*_seek64)(void*, off64_t, int);
140  
141    // The pid of the child if this FILE* is from popen(3).
142    pid_t _popen_pid;
143  };
144  
145  // Values for `__sFILE::_flags`.
146  #define __SLBF 0x0001  // Line buffered.
147  #define __SNBF 0x0002  // Unbuffered.
148  // __SRD and __SWR are mutually exclusive because they indicate what we did last.
149  // If you want to know whether we were opened read-write, check __SRW instead.
150  #define __SRD 0x0004   // Last operation was read.
151  #define __SWR 0x0008   // Last operation was write.
152  #define __SRW 0x0010   // Was opened for reading & writing.
153  #define __SEOF 0x0020  // Found EOF.
154  #define __SERR 0x0040  // Found error.
155  #define __SMBF 0x0080  // `_buf` is from malloc.
156  // #define __SAPP 0x0100 --- historical (fdopen()ed in append mode).
157  #define __SSTR 0x0200  // This is an sprintf/snprintf string.
158  // #define __SOPT 0x0400 --- historical (do fseek() optimization).
159  // #define __SNPT 0x0800 --- historical (do not do fseek() optimization).
160  // #define __SOFF 0x1000 --- historical (set iff _offset is in fact correct).
161  // #define __SMOD 0x2000 --- historical (set iff fgetln modified _p text).
162  #define __SALC 0x4000  // Allocate string space dynamically.
163  #define __SIGN 0x8000  // Ignore this file in _fwalk.
164  
165  // TODO: remove remaining references to these obsolete flags (see above).
166  #define __SMOD 0
167  #define __SNPT 0
168  #define __SOPT 0
169  
170  #define _EXT(fp) __BIONIC_CAST(reinterpret_cast, struct __sfileext*, (fp)->_ext._base)
171  
172  #define _UB(fp) _EXT(fp)->_ub
173  
174  #define _FILEEXT_SETUP(fp, fext)                                              \
175    do {                                                                        \
176      (fp)->_ext._base = __BIONIC_CAST(reinterpret_cast, unsigned char*, fext); \
177      memset(_EXT(fp), 0, sizeof(struct __sfileext));                           \
178      _EXT(fp)->_caller_handles_locking = true;                                 \
179    } while (0)
180  
181  // Android <= 19 had getc/putc macros in <stdio.h> that referred
182  // to __srget/__swbuf, so those symbols need to be public for LP32
183  // but can be hidden for LP64. Moreover, the NDK continued to ship
184  // those macros until r15 made unified headers the default.
185  __LIBC32_LEGACY_PUBLIC__ int __srget(FILE*);
186  __LIBC32_LEGACY_PUBLIC__ int __swbuf(int, FILE*);
187  __LIBC32_LEGACY_PUBLIC__ int __srefill(FILE*);
188  
189  /* This was referenced by the apportable middleware for LP32. */
190  __LIBC32_LEGACY_PUBLIC__ int __swsetup(FILE*);
191  
192  /* These were referenced by a couple of different pieces of middleware and the Crystax NDK. */
193  __LIBC32_LEGACY_PUBLIC__ int __sflags(const char*, int*);
194  __LIBC32_LEGACY_PUBLIC__ FILE* __sfp(void);
195  __LIBC32_LEGACY_PUBLIC__ void __smakebuf(FILE*);
196  
197  /* These are referenced by the Greed for Glory franchise. */
198  __LIBC32_LEGACY_PUBLIC__ int __sflush(FILE*);
199  __LIBC32_LEGACY_PUBLIC__ int __sread(void*, char*, int);
200  __LIBC32_LEGACY_PUBLIC__ int __swrite(void*, const char*, int);
201  __LIBC32_LEGACY_PUBLIC__ fpos_t __sseek(void*, fpos_t, int);
202  __LIBC32_LEGACY_PUBLIC__ int __sclose(void*);
203  __LIBC32_LEGACY_PUBLIC__ int _fwalk(int (*)(FILE*));
204  
205  off64_t __sseek64(void*, off64_t, int);
206  int __sflush_locked(FILE*);
207  int __swhatbuf(FILE*, size_t*, int*);
208  wint_t __fgetwc_unlock(FILE*);
209  wint_t __ungetwc(wint_t, FILE*);
210  int __vfprintf(FILE*, const char*, va_list);
211  int __svfscanf(FILE*, const char*, va_list);
212  int __vfwprintf(FILE*, const wchar_t*, va_list);
213  int __vfwscanf(FILE*, const wchar_t*, va_list);
214  
215  /*
216   * Return true if the given FILE cannot be written now.
217   */
218  #define cantwrite(fp) ((((fp)->_flags & __SWR) == 0 || (fp)->_bf._base == NULL) && __swsetup(fp))
219  
220  /*
221   * Test whether the given stdio file has an active ungetc buffer;
222   * release such a buffer, without restoring ordinary unread data.
223   */
224  #define HASUB(fp) (_UB(fp)._base != NULL)
225  #define FREEUB(fp)                                         \
226    {                                                        \
227      if (_UB(fp)._base != (fp)->_ubuf) free(_UB(fp)._base); \
228      _UB(fp)._base = NULL;                                  \
229    }
230  
231  #define FLOCKFILE(fp) \
232    if (!_EXT(fp)->_caller_handles_locking) flockfile(fp)
233  #define FUNLOCKFILE(fp) \
234    if (!_EXT(fp)->_caller_handles_locking) funlockfile(fp)
235  
236  /* OpenBSD exposes these in <stdio.h>, but we only want them exposed to the implementation. */
237  #define __sferror(p) (((p)->_flags & __SERR) != 0)
238  #define __sclearerr(p) ((void)((p)->_flags &= ~(__SERR | __SEOF)))
239  #define __sgetc(p) (--(p)->_r < 0 ? __srget(p) : __BIONIC_CAST(static_cast, int, *(p)->_p++))
240  
241  /* OpenBSD declares these in fvwrite.h, but we share them with C++ parts of the implementation. */
242  struct __siov {
243    void* iov_base;
244    size_t iov_len;
245  };
246  struct __suio {
247    struct __siov* uio_iov;
248    int uio_iovcnt;
249    size_t uio_resid;
250  };
251  int __sfvwrite(FILE*, struct __suio*);
252  wint_t __fputwc_unlock(wchar_t wc, FILE* fp);
253  
254  /* Remove the if (!__sdidinit) __sinit() idiom from untouched upstream stdio code. */
255  extern void __sinit(void);  // Not actually implemented.
256  #define __sdidinit 1
257  
258  size_t parsefloat(FILE*, char*, char*);
259  size_t wparsefloat(FILE*, wchar_t*, wchar_t*);
260  
261  // Check a FILE* isn't nullptr, so we can emit a clear diagnostic message
262  // instead of just crashing with SIGSEGV.
263  #define CHECK_FP(fp) \
264    if (fp == nullptr) __fortify_fatal("%s: null FILE*", __FUNCTION__)
265  
266  /*
267   * Floating point scanf/printf (input/output) definitions.
268   */
269  
270  /* 11-bit exponent (VAX G floating point) is 308 decimal digits */
271  #define MAXEXP 308
272  /* 128 bit fraction takes up 39 decimal digits; max reasonable precision */
273  #define MAXFRACT 39
274  
275  /*
276   * MAXEXPDIG is the maximum number of decimal digits needed to store a
277   * floating point exponent in the largest supported format.  It should
278   * be ceil(log10(LDBL_MAX_10_EXP)) or, if hexadecimal floating point
279   * conversions are supported, ceil(log10(LDBL_MAX_EXP)).  But since it
280   * is presently never greater than 5 in practice, we fudge it.
281   */
282  #define MAXEXPDIG 6
283  #if LDBL_MAX_EXP > 999999
284  #error "floating point buffers too small"
285  #endif
286  
287  char* __hdtoa(double, const char*, int, int*, int*, char**);
288  char* __hldtoa(long double, const char*, int, int*, int*, char**);
289  char* __ldtoa(long double*, int, int, int*, int*, char**);
290  
291  #define WCIO_GET(fp) (_EXT(fp) ? &(_EXT(fp)->_wcio) : NULL)
292  
293  #define ORIENT_BYTES (-1)
294  #define ORIENT_UNKNOWN 0
295  #define ORIENT_CHARS 1
296  
297  #define _SET_ORIENTATION(fp, mode)                                              \
298    do {                                                                          \
299      struct wchar_io_data* _wcio = WCIO_GET(fp);                                 \
300      if (_wcio && _wcio->wcio_mode == ORIENT_UNKNOWN) _wcio->wcio_mode = (mode); \
301    } while (0)
302  
303  #define WCIO_FREE(fp)                           \
304    do {                                          \
305      struct wchar_io_data* _wcio = WCIO_GET(fp); \
306      if (_wcio) {                                \
307        _wcio->wcio_mode = ORIENT_UNKNOWN;        \
308        _wcio->wcio_ungetwc_inbuf = 0;            \
309      }                                           \
310    } while (0)
311  
312  __END_DECLS
313