From f0141dfab10a4b332769d52fa76631a64741297a Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Mon, 12 Oct 2015 12:44:23 -0700 Subject: [PATCH] Make struct FILE opaque. Bug: http://b/24807045 Change-Id: I3cb4e436325a65bef3b203e3970e4d967101fcce --- libc/include/stdio.h | 97 +-------------------------------------- libc/stdio/fileext.h | 80 -------------------------------- libc/stdio/findfp.c | 7 ++- libc/stdio/local.h | 107 +++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 111 insertions(+), 180 deletions(-) delete mode 100644 libc/stdio/fileext.h diff --git a/libc/include/stdio.h b/libc/include/stdio.h index c4bfb4fdf..1df4b54f2 100644 --- a/libc/include/stdio.h +++ b/libc/include/stdio.h @@ -38,14 +38,6 @@ #ifndef _STDIO_H_ #define _STDIO_H_ -/* - * This file must contain a reference to __gnuc_va_list so that GCC's - * fixincludes knows that that's what's being used for va_list, and so - * to leave our alone. (fixincludes gets in the way of pointing - * one toolchain at various different sets of platform headers.) - * If you alter this comment, be sure to keep "__gnuc_va_list" in it! - */ - #include #include @@ -59,94 +51,9 @@ __BEGIN_DECLS typedef off_t fpos_t; /* stdio file position type */ -/* - * NB: to fit things in six character monocase externals, the stdio - * code uses the prefix `__s' for stdio objects, typically followed - * by a three-character attempt at a mnemonic. - */ +struct __sFILE; +typedef struct __sFILE FILE; -/* stdio buffers */ -#if defined(__LP64__) -struct __sbuf { - unsigned char* _base; - size_t _size; -}; -#else -struct __sbuf { - unsigned char *_base; - int _size; -}; -#endif - -/* - * stdio state variables. - * - * The following always hold: - * - * if (_flags&(__SLBF|__SWR)) == (__SLBF|__SWR), - * _lbfsize is -_bf._size, else _lbfsize is 0 - * if _flags&__SRD, _w is 0 - * if _flags&__SWR, _r is 0 - * - * This ensures that the getc and putc macros (or inline functions) never - * try to write or read from a file that is in `read' or `write' mode. - * (Moreover, they can, and do, automatically switch from read mode to - * write mode, and back, on "r+" and "w+" files.) - * - * _lbfsize is used only to make the inline line-buffered output stream - * code as compact as possible. - * - * _ub, _up, and _ur are used when ungetc() pushes back more characters - * than fit in the current _bf, or when ungetc() pushes back a character - * that does not match the previous one in _bf. When this happens, - * _ub._base becomes non-nil (i.e., a stream has ungetc() data iff - * _ub._base!=NULL) and _up and _ur save the current values of _p and _r. - * - * NOTE: if you change this structure, you also need to update the - * std() initializer in findfp.c. - */ -typedef struct __sFILE { - unsigned char *_p; /* current position in (some) buffer */ - int _r; /* read space left for getc() */ - int _w; /* write space left for putc() */ -#if defined(__LP64__) - int _flags; /* flags, below; this FILE is free if 0 */ - int _file; /* fileno, if Unix descriptor, else -1 */ -#else - short _flags; /* flags, below; this FILE is free if 0 */ - short _file; /* fileno, if Unix descriptor, else -1 */ -#endif - struct __sbuf _bf; /* the buffer (at least 1 byte, if !NULL) */ - int _lbfsize; /* 0 or -_bf._size, for inline putc */ - - /* operations */ - void *_cookie; /* cookie passed to io functions */ - int (*_close)(void *); - int (*_read)(void *, char *, int); - fpos_t (*_seek)(void *, fpos_t, int); - int (*_write)(void *, const char *, int); - - /* extension data, to avoid further ABI breakage */ - struct __sbuf _ext; - /* data for long sequences of ungetc() */ - unsigned char *_up; /* saved _p when _p is doing ungetc data */ - int _ur; /* saved _r when _r is counting ungetc data */ - - /* tricks to meet minimum requirements even when malloc() fails */ - unsigned char _ubuf[3]; /* guarantee an ungetc() buffer */ - unsigned char _nbuf[1]; /* guarantee a getc() buffer */ - - /* separate buffer for fgetln() when line crosses buffer boundary */ - struct __sbuf _lb; /* buffer for fgetln() */ - - /* Unix stdio files get aligned to block boundaries on fseek() */ - int _blksize; /* stat.st_blksize (may be != _bf._size) */ - fpos_t _offset; /* current lseek offset */ -} FILE; - -/* Legacy BSD implementation of stdin/stdout/stderr. */ -extern FILE __sF[]; -/* More obvious implementation. */ extern FILE* stdin; extern FILE* stdout; extern FILE* stderr; diff --git a/libc/stdio/fileext.h b/libc/stdio/fileext.h deleted file mode 100644 index 6cacc0f84..000000000 --- a/libc/stdio/fileext.h +++ /dev/null @@ -1,80 +0,0 @@ -/* $OpenBSD: fileext.h,v 1.2 2005/06/17 20:40:32 espie Exp $ */ -/* $NetBSD: fileext.h,v 1.5 2003/07/18 21:46:41 nathanw Exp $ */ - -/*- - * Copyright (c)2001 Citrus Project, - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $Citrus$ - */ - -#ifndef _FILEEXT_H_ -#define _FILEEXT_H_ - -#include -#include - -__BEGIN_DECLS - -/* - * file extension - */ -struct __sfileext { - struct __sbuf _ub; /* ungetc buffer */ - struct wchar_io_data _wcio; /* wide char io status */ - pthread_mutex_t _lock; /* file lock */ - bool _stdio_handles_locking; /* __fsetlocking support */ -}; - -#if defined(__cplusplus) -#define _EXT(fp) reinterpret_cast<__sfileext*>((fp)->_ext._base) -#else -#define _EXT(fp) ((struct __sfileext *)((fp)->_ext._base)) -#endif - -#define _UB(fp) _EXT(fp)->_ub -#define _FLOCK(fp) _EXT(fp)->_lock - -#define _FILEEXT_INIT(fp) \ -do { \ - _UB(fp)._base = NULL; \ - _UB(fp)._size = 0; \ - WCIO_INIT(fp); \ - pthread_mutexattr_t attr; \ - pthread_mutexattr_init(&attr); \ - pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); \ - pthread_mutex_init(&_FLOCK(fp), &attr); \ - pthread_mutexattr_destroy(&attr); \ - _EXT(fp)->_stdio_handles_locking = true; \ -} while (0) - -#define _FILEEXT_SETUP(f, fext) \ -do { \ - (f)->_ext._base = (unsigned char *)(fext); \ - _FILEEXT_INIT(f); \ -} while (0) - -__END_DECLS - -#endif /* _FILEEXT_H_ */ diff --git a/libc/stdio/findfp.c b/libc/stdio/findfp.c index 5e51198a7..2696cfd25 100644 --- a/libc/stdio/findfp.c +++ b/libc/stdio/findfp.c @@ -60,15 +60,20 @@ static struct glue *lastglue = &uglue; _THREAD_PRIVATE_MUTEX(__sfp_mutex); static struct __sfileext __sFext[3]; + +// __sF is exported for backwards compatibility. Until M, we didn't have symbols +// for stdin/stdout/stderr; they were macros accessing __sF. FILE __sF[3] = { std(__SRD, STDIN_FILENO), /* stdin */ std(__SWR, STDOUT_FILENO), /* stdout */ std(__SWR|__SNBF, STDERR_FILENO) /* stderr */ }; + +struct glue __sglue = { &uglue, 3, __sF }; + FILE* stdin = &__sF[0]; FILE* stdout = &__sF[1]; FILE* stderr = &__sF[2]; -struct glue __sglue = { &uglue, 3, __sF }; static struct glue * moreglue(int n) diff --git a/libc/stdio/local.h b/libc/stdio/local.h index ce0414129..749de7b87 100644 --- a/libc/stdio/local.h +++ b/libc/stdio/local.h @@ -32,17 +32,114 @@ * SUCH DAMAGE. */ +#ifndef __BIONIC_STDIO_LOCAL_H__ +#define __BIONIC_STDIO_LOCAL_H__ + +#include +#include +#include +#include "wcio.h" + /* * Information local to this implementation of stdio, * in particular, macros and private variables. */ -#include -#include "wcio.h" -#include "fileext.h" - __BEGIN_DECLS +struct __sbuf { + unsigned char* _base; +#if defined(__LP64__) + size_t _size; +#else + int _size; +#endif +}; + +struct __sFILE { + unsigned char *_p; /* current position in (some) buffer */ + int _r; /* read space left for getc() */ + int _w; /* write space left for putc() */ +#if defined(__LP64__) + int _flags; /* flags, below; this FILE is free if 0 */ + int _file; /* fileno, if Unix descriptor, else -1 */ +#else + short _flags; /* flags, below; this FILE is free if 0 */ + short _file; /* fileno, if Unix descriptor, else -1 */ +#endif + struct __sbuf _bf; /* the buffer (at least 1 byte, if !NULL) */ + int _lbfsize; /* 0 or -_bf._size, for inline putc */ + + /* operations */ + void *_cookie; /* cookie passed to io functions */ + int (*_close)(void *); + int (*_read)(void *, char *, int); + fpos_t (*_seek)(void *, fpos_t, int); + int (*_write)(void *, const char *, int); + + /* extension data, to avoid further ABI breakage */ + struct __sbuf _ext; + /* data for long sequences of ungetc() */ + unsigned char *_up; /* saved _p when _p is doing ungetc data */ + int _ur; /* saved _r when _r is counting ungetc data */ + + /* tricks to meet minimum requirements even when malloc() fails */ + unsigned char _ubuf[3]; /* guarantee an ungetc() buffer */ + unsigned char _nbuf[1]; /* guarantee a getc() buffer */ + + /* separate buffer for fgetln() when line crosses buffer boundary */ + struct __sbuf _lb; /* buffer for fgetln() */ + + /* Unix stdio files get aligned to block boundaries on fseek() */ + int _blksize; /* stat.st_blksize (may be != _bf._size) */ + fpos_t _offset; /* current lseek offset */ +}; + +/* + * file extension + */ +struct __sfileext { + /* ungetc buffer */ + struct __sbuf _ub; + + /* wide char io status */ + struct wchar_io_data _wcio; + + /* file lock */ + pthread_mutex_t _lock; + + /* __fsetlocking support */ + bool _stdio_handles_locking; +}; + +#if defined(__cplusplus) +#define _EXT(fp) reinterpret_cast<__sfileext*>((fp)->_ext._base) +#else +#define _EXT(fp) ((struct __sfileext *)((fp)->_ext._base)) +#endif + +#define _UB(fp) _EXT(fp)->_ub +#define _FLOCK(fp) _EXT(fp)->_lock + +#define _FILEEXT_INIT(fp) \ +do { \ + _UB(fp)._base = NULL; \ + _UB(fp)._size = 0; \ + WCIO_INIT(fp); \ + pthread_mutexattr_t attr; \ + pthread_mutexattr_init(&attr); \ + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); \ + pthread_mutex_init(&_FLOCK(fp), &attr); \ + pthread_mutexattr_destroy(&attr); \ + _EXT(fp)->_stdio_handles_locking = true; \ +} while (0) + +#define _FILEEXT_SETUP(f, fext) \ +do { \ + (f)->_ext._base = (unsigned char *)(fext); \ + _FILEEXT_INIT(f); \ +} while (0) + /* * Android <= KitKat had getc/putc macros in that referred * to __srget/__swbuf, so those symbols need to be public for LP32 @@ -143,3 +240,5 @@ wint_t __fputwc_unlock(wchar_t wc, FILE *fp); #pragma GCC visibility pop __END_DECLS + +#endif