| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463 | /* Copyright (C) 2004-2005 Manuel Novoa III    <mjn3@codepoet.org> * * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. * * Dedicated to Toni.  See uClibc/DEDICATION.mjn3 for details. */#include <features.h>#include <assert.h>#include <errno.h>#include <fcntl.h>#include <limits.h>#include <signal.h>#include <stdint.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <stdarg.h>#include <unistd.h>#ifdef __UCLIBC_HAS_WCHAR__#include <wchar.h>#endif#include <bits/uClibc_mutex.h>#define __STDIO_THREADLOCK_OPENLIST_ADD			\        __UCLIBC_IO_MUTEX_LOCK(_stdio_openlist_add_lock)#define __STDIO_THREADUNLOCK_OPENLIST_ADD		\        __UCLIBC_IO_MUTEX_UNLOCK(_stdio_openlist_add_lock)#ifdef __STDIO_BUFFERS#define __STDIO_THREADLOCK_OPENLIST_DEL			\        __UCLIBC_IO_MUTEX_LOCK(_stdio_openlist_del_lock)#define __STDIO_THREADUNLOCK_OPENLIST_DEL		\        __UCLIBC_IO_MUTEX_UNLOCK(_stdio_openlist_del_lock)#ifdef __UCLIBC_HAS_THREADS__extern void __stdio_init_mutex(__UCLIBC_MUTEX_TYPE *m) attribute_hidden;extern volatile int _stdio_openlist_use_count attribute_hidden; /* _stdio_openlist_del_lock */#define __STDIO_OPENLIST_INC_USE			\do {							\	__STDIO_THREADLOCK_OPENLIST_DEL;		\	++_stdio_openlist_use_count;			\	__STDIO_THREADUNLOCK_OPENLIST_DEL;		\} while (0)extern void _stdio_openlist_dec_use(void) attribute_hidden;#define __STDIO_OPENLIST_DEC_USE			\	_stdio_openlist_dec_use()extern int _stdio_openlist_del_count attribute_hidden; /* _stdio_openlist_del_lock */#define __STDIO_OPENLIST_INC_DEL_CNT			\do {							\	__STDIO_THREADLOCK_OPENLIST_DEL;		\	++_stdio_openlist_del_count;			\	__STDIO_THREADUNLOCK_OPENLIST_DEL;		\} while (0)#define __STDIO_OPENLIST_DEC_DEL_CNT			\do { \	__STDIO_THREADLOCK_OPENLIST_DEL;		\	--_stdio_openlist_del_count;			\	__STDIO_THREADUNLOCK_OPENLIST_DEL;		\} while (0)#endif /* __UCLIBC_HAS_THREADS__ */#endif /* __STDIO_BUFFERS */#ifndef __STDIO_THREADLOCK_OPENLIST_DEL#define	__STDIO_THREADLOCK_OPENLIST_DEL     ((void)0)#endif#ifndef __STDIO_THREADUNLOCK_OPENLIST_DEL#define	__STDIO_THREADUNLOCK_OPENLIST_DEL   ((void)0)#endif#ifndef __STDIO_OPENLIST_INC_USE#define __STDIO_OPENLIST_INC_USE            ((void)0)#endif#ifndef __STDIO_OPENLIST_DEC_USE#define __STDIO_OPENLIST_DEC_USE            ((void)0)#endif#ifndef __STDIO_OPENLIST_INC_DEL_CNT#define __STDIO_OPENLIST_INC_DEL_CNT        ((void)0)#endif#ifndef __STDIO_OPENLIST_DEC_DEL_CNT#define __STDIO_OPENLIST_DEC_DEL_CNT        ((void)0)#endif#define __UNDEFINED_OR_NONPORTABLE ((void)0)/**********************************************************************/#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__extern __ssize_t _cs_read(void *cookie, char *buf, size_t bufsize) attribute_hidden;extern __ssize_t _cs_write(void *cookie, const char *buf, size_t bufsize) attribute_hidden;extern int _cs_seek(void *cookie, __offmax_t *pos, int whence) attribute_hidden;extern int _cs_close(void *cookie) attribute_hidden;#define __STDIO_STREAM_RESET_GCS(S) \	(S)->__cookie = &((S)->__filedes); \	(S)->__gcs.read = _cs_read; \	(S)->__gcs.write = _cs_write; \	(S)->__gcs.seek = _cs_seek; \	(S)->__gcs.close = _cs_close#define __READ(STREAMPTR,BUF,SIZE) \	((((STREAMPTR)->__gcs.read) == NULL) ? -1 : \	(((STREAMPTR)->__gcs.read)((STREAMPTR)->__cookie,(BUF),(SIZE))))#define __WRITE(STREAMPTR,BUF,SIZE) \	((((STREAMPTR)->__gcs.write) == NULL) ? -1 : \	(((STREAMPTR)->__gcs.write)((STREAMPTR)->__cookie,(BUF),(SIZE))))#define __SEEK(STREAMPTR,PPOS,WHENCE) \	((((STREAMPTR)->__gcs.seek) == NULL) ? -1 : \	(((STREAMPTR)->__gcs.seek)((STREAMPTR)->__cookie,(PPOS),(WHENCE))))#define __CLOSE(STREAMPTR) \	((((STREAMPTR)->__gcs.close) == NULL) ? 0 : \	(((STREAMPTR)->__gcs.close)((STREAMPTR)->__cookie)))#else  /* __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ */extern int __stdio_seek(FILE *stream, register __offmax_t *pos, int whence) attribute_hidden;#define __STDIO_STREAM_RESET_GCS(S) ((void)0)#define __READ(STREAMPTR,BUF,SIZE) \	(read((STREAMPTR)->__filedes,(BUF),(SIZE)))#define __WRITE(STREAMPTR,BUF,SIZE) \	(write((STREAMPTR)->__filedes,(BUF),(SIZE)))#define __SEEK(STREAMPTR,PPOS,WHENCE) \	(__stdio_seek((STREAMPTR),(PPOS),(WHENCE)))#define __CLOSE(STREAMPTR) \	(close((STREAMPTR)->__filedes))#endif /* __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ *//**********************************************************************/#ifdef __UCLIBC_HAS_WCHAR__#define __STDIO_STREAM_TRANS_TO_WRITE(S,O)	__stdio_trans2w_o((S), (O))#define __STDIO_STREAM_TRANS_TO_READ(S,O)	__stdio_trans2r_o((S), (O))#else#define __STDIO_STREAM_TRANS_TO_WRITE(S,O)	__stdio_trans2w((S))#define __STDIO_STREAM_TRANS_TO_READ(S,O)	__stdio_trans2r((S))#endif/**********************************************************************/#define __STDIO_STREAM_IS_READING(S) ((S)->__modeflags & __MASK_READING)#define __STDIO_STREAM_IS_WRITING(S) ((S)->__modeflags & __FLAG_WRITING)#define __STDIO_STREAM_SET_READING(S) ((S)->__modeflags |= __FLAG_READING)#define __STDIO_STREAM_SET_WRITING(S) ((S)->__modeflags |= __FLAG_WRITING)#define __STDIO_STREAM_IS_READING_OR_READONLY(S) \	((S)->__modeflags & (__MASK_READING|__FLAG_READONLY))#define __STDIO_STREAM_IS_WRITING_OR_WRITEONLY(S) \	((S)->__modeflags & (__FLAG_WRITING|__FLAG_WRITEONLY))#define __STDIO_STREAM_IS_READONLY(S) ((S)->__modeflags & __FLAG_READONLY)#define __STDIO_STREAM_IS_WRITEONLY(S) ((S)->__modeflags & __FLAG_WRITEONLY)/**********************************************************************/#ifdef __UCLIBC_HAS_WCHAR__#define __STDIO_STREAM_IS_NARROW_WRITING(S)			\	(((S)->__modeflags & (__FLAG_WRITING|__FLAG_NARROW))	\	 == (__FLAG_WRITING|__FLAG_NARROW))#define __STDIO_STREAM_IS_WIDE_WRITING(S)			\	(((S)->__modeflags & (__FLAG_WRITING|__FLAG_WIDE))	\	 == (__FLAG_WRITING|__FLAG_WIDE))#if (__FLAG_NARROW <= __MASK_READING)#error assumption violated regarding __FLAG_NARROW#endif#define __STDIO_STREAM_IS_NARROW_READING(S)			\	(((S)->__modeflags & (__MASK_READING|__FLAG_NARROW)) > __FLAG_NARROW)#define __STDIO_STREAM_IS_WIDE_READING(S)			\	(((S)->__modeflags & (__MASK_READING|__FLAG_WIDE)) > __FLAG_WIDE)#define __STDIO_STREAM_IS_NARROW(S)		((S)->__modeflags & __FLAG_NARROW)#define __STDIO_STREAM_IS_WIDE(S)		((S)->__modeflags & __FLAG_WIDE)#define __STDIO_STREAM_SET_NARROW(S)				\	((void)((S)->__modeflags |= __FLAG_NARROW))#define __STDIO_STREAM_SET_WIDE(S)				\	((void)((S)->__modeflags |= __FLAG_WIDE))#else#define __STDIO_STREAM_IS_NARROW_WRITING(S)  __STDIO_STREAM_IS_WRITING(S)#define __STDIO_STREAM_IS_NARROW_READING(S)  __STDIO_STREAM_IS_READING(S)#define __STDIO_STREAM_IS_NARROW(S)			(1)#define __STDIO_STREAM_IS_WIDE(S)			(0)#define __STDIO_STREAM_SET_NARROW(S)			((void)0)#define __STDIO_STREAM_SET_WIDE(S)			((void)0)#endif/**********************************************************************/#define __STDIO_STREAM_SET_EOF(S) \	((void)((S)->__modeflags |= __FLAG_EOF))#define __STDIO_STREAM_SET_ERROR(S) \	((void)((S)->__modeflags |= __FLAG_ERROR))#define __STDIO_STREAM_CLEAR_EOF(S) \	((void)((S)->__modeflags &= ~__FLAG_EOF))#define __STDIO_STREAM_CLEAR_ERROR(S) \	((void)((S)->__modeflags &= ~__FLAG_ERROR))#define __STDIO_STREAM_CLEAR_READING_AND_UNGOTS(S) \	((void)((S)->__modeflags &= ~__MASK_READING))#define __STDIO_STREAM_CLEAR_WRITING(S) \	((void)((S)->__modeflags &= ~__FLAG_WRITING))#ifdef __UCLIBC_HAS_STDIO_GETC_MACRO__# define __STDIO_STREAM_DISABLE_GETC(S) \	((void)((S)->__bufgetc_u = (S)->__bufstart))# define __STDIO_STREAM_ENABLE_GETC(S) \	((void)((S)->__bufgetc_u = (S)->__bufread))# define __STDIO_STREAM_CAN_USE_BUFFER_GET(S) \	((S)->__bufpos < (S)->__bufgetc_u)#else# define __STDIO_STREAM_DISABLE_GETC(S)			((void)0)# define __STDIO_STREAM_ENABLE_GETC(S)			((void)0)# define __STDIO_STREAM_CAN_USE_BUFFER_GET(S)		(0)#endif#ifdef __UCLIBC_HAS_STDIO_PUTC_MACRO__# define __STDIO_STREAM_DISABLE_PUTC(S) \	((void)((S)->__bufputc_u = (S)->__bufstart))# define __STDIO_STREAM_ENABLE_PUTC(S) \	((void)((S)->__bufputc_u = (S)->__bufend))# define __STDIO_STREAM_CAN_USE_BUFFER_ADD(S) \	((S)->__bufpos < (S)->__bufputc_u)#else# define __STDIO_STREAM_DISABLE_PUTC(S)			((void)0)# define __STDIO_STREAM_ENABLE_PUTC(S)			((void)0)# define __STDIO_STREAM_CAN_USE_BUFFER_ADD(S)		(0)#endif#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__#define __STDIO_STREAM_IS_CUSTOM(S)		((S)->__cookie != &((S)->__filedes))#else#define __STDIO_STREAM_IS_CUSTOM(S)			(0)#endif/**********************************************************************/#ifdef __STDIO_BUFFERS#define __STDIO_STREAM_FREE_BUFFER(S)			\	do { if ((S)->__modeflags & __FLAG_FREEBUF)	\	free((S)->__bufstart); } while (0)#else#define __STDIO_STREAM_FREE_BUFFER(S) ((void)0)#endif#define __STDIO_STREAM_FREE_FILE(S) \	do { if ((S)->__modeflags & __FLAG_FREEFILE)	\	free((S)); } while (0)#ifdef __UCLIBC_HAS_LFS__#define __STDIO_WHEN_LFS(E) E#else#define __STDIO_WHEN_LFS(E) ((void)0)#endif/**********************************************************************//* The following return 0 on success. */#ifdef __STDIO_BUFFERS/* Assume stream in valid writing state.  Do not reset writing flag * or disble putc macro unless error. *//* Should we assume that buffer is not empty to avoid a check? */extern size_t __stdio_wcommit(FILE *__restrict stream) attribute_hidden;/* Remember to fail if at EOF! */extern size_t __stdio_rfill(FILE *__restrict stream) attribute_hidden;extern size_t __stdio_fwrite(const unsigned char *__restrict buffer,		size_t bytes, FILE *__restrict stream) attribute_hidden;#else#define __stdio_fwrite(B,N,S)  __stdio_WRITE((S),(B),(N))#endifextern size_t __stdio_WRITE(FILE *stream, const unsigned char *buf,		size_t bufsize) attribute_hidden;extern size_t __stdio_READ(FILE *stream, unsigned char *buf,		size_t bufsize) attribute_hidden;extern int __stdio_trans2r(FILE *__restrict stream) attribute_hidden;extern int __stdio_trans2w(FILE *__restrict stream) attribute_hidden;extern int __stdio_trans2r_o(FILE *__restrict stream, int oflag) attribute_hidden;extern int __stdio_trans2w_o(FILE *__restrict stream, int oflag) attribute_hidden;extern uintmax_t _load_inttype(int desttype, register const void *src, int uflag) attribute_hidden;extern void _store_inttype(void *dest, int desttype, uintmax_t val) attribute_hidden;/**********************************************************************/#ifdef __STDIO_BUFFERS#define __STDIO_STREAM_IS_FBF(S)		(!((S)->__modeflags & __MASK_BUFMODE))#define __STDIO_STREAM_IS_LBF(S)		((S)->__modeflags & __FLAG_LBF)#define __STDIO_STREAM_IS_NBF(S)		((S)->__modeflags & __FLAG_NBF)#define __STDIO_STREAM_BUFFER_SIZE(S)		((S)->__bufend - (S)->__bufstart)/* Valid when writing... */#define __STDIO_STREAM_BUFFER_ADD(S,C)		(*(S)->__bufpos++ = (C))#define __STDIO_STREAM_BUFFER_UNADD(S)		(--(S)->__bufpos)#define __STDIO_STREAM_BUFFER_WAVAIL(S)		((S)->__bufend - (S)->__bufpos)#define __STDIO_STREAM_BUFFER_WUSED(S)		((S)->__bufpos - (S)->__bufstart)#define __STDIO_COMMIT_WRITE_BUFFER(S)		__stdio_wcommit((S))#ifdef __UCLIBC_HAS_WCHAR__#define __STDIO_STREAM_IS_NARROW_FBF(S) \	(!((S)->__modeflags & (__MASK_BUFMODE|__FLAG_WIDE)))#else#define __STDIO_STREAM_IS_NARROW_FBF(S)		__STDIO_STREAM_IS_FBF((S))#endif/* Valid when reading... */#define __STDIO_STREAM_BUFFER_RAVAIL(S)		((S)->__bufread - (S)->__bufpos)#define __STDIO_STREAM_BUFFER_GET(S)		(*(S)->__bufpos++)#define __STDIO_FILL_READ_BUFFER(S)		__stdio_rfill((S))#define __STDIO_STREAM_INIT_BUFREAD_BUFPOS(S)		\	(S)->__bufread = (S)->__bufpos = (S)->__bufstart#define __STDIO_STREAM_FAKE_VSNPRINTF_FILEDES		(-2)#define __STDIO_STREAM_FAKE_VSSCANF_FILEDES		(-2)#define __STDIO_STREAM_FAKE_VSWPRINTF_FILEDES		(-3)#define __STDIO_STREAM_FAKE_VSWSCANF_FILEDES		(-3)#define __STDIO_STREAM_IS_FAKE_VSNPRINTF(S) \	((S)->__filedes == __STDIO_STREAM_FAKE_VSNPRINTF_FILEDES)#define __STDIO_STREAM_IS_FAKE_VSSCANF(S) \	((S)->__filedes == __STDIO_STREAM_FAKE_VSSCANF_FILEDES)#define __STDIO_STREAM_IS_FAKE_VSWPRINTF(S) \	((S)->__filedes == __STDIO_STREAM_FAKE_VSWPRINTF_FILEDES)#define __STDIO_STREAM_IS_FAKE_VSWSCANF(S) \	((S)->__filedes == __STDIO_STREAM_FAKE_VSWSCANF_FILEDES)#else  /* __STDIO_BUFFERS */#define __STDIO_STREAM_IS_FBF(S)				(0)#define __STDIO_STREAM_IS_LBF(S)				(0)#define __STDIO_STREAM_IS_NBF(S)				(1)#define __STDIO_STREAM_BUFFER_SIZE(S)				(0)#define __STDIO_STREAM_BUFFER_ADD(S,C)				((void)0)#define __STDIO_STREAM_BUFFER_UNADD(S)				((void)0)#define __STDIO_STREAM_BUFFER_WAVAIL(S)				(0)#define __STDIO_STREAM_BUFFER_WUSED(S)				(0)#define __STDIO_COMMIT_WRITE_BUFFER(S)				(0)#define __STDIO_STREAM_IS_NARROW_FBF(S)				(0)#define __STDIO_STREAM_BUFFER_RAVAIL(S)				(0)#define __STDIO_STREAM_BUFFER_GET(S)				(EOF)#define __STDIO_FILL_READ_BUFFER(S)				(0)#define __STDIO_STREAM_INIT_BUFREAD_BUFPOS(S)			((void)0)#undef __STDIO_STREAM_FAKE_VSNPRINTF_FILEDES#undef __STDIO_STREAM_FAKE_VSSCANF_FILEDES#undef __STDIO_STREAM_FAKE_VSWPRINTF_FILEDES#define __STDIO_STREAM_IS_FAKE_VSNPRINTF(S)			(0)#define __STDIO_STREAM_IS_FAKE_VSSCANF(S)			(0)#undef __STDIO_STREAM_IS_FAKE_VSWPRINTF# ifdef __USE_OLD_VFPRINTF__#  define __STDIO_STREAM_FAKE_VSNPRINTF_FILEDES_NB		(-2)#  define __STDIO_STREAM_IS_FAKE_VSNPRINTF_NB(S)		\	((S)->__filedes == __STDIO_STREAM_FAKE_VSNPRINTF_FILEDES_NB)# endif# ifndef __UCLIBC_HAS_WCHAR__#  define __STDIO_STREAM_FAKE_VSSCANF_FILEDES_NB		(-2)#  define __STDIO_STREAM_IS_FAKE_VSSCANF_NB(S)			\	((S)->__filedes == __STDIO_STREAM_FAKE_VSSCANF_FILEDES_NB)# endif#endif /* __STDIO_BUFFERS *//**********************************************************************/extern int __stdio_adjust_position(FILE *__restrict stream, __offmax_t *pos) attribute_hidden;#ifdef __STDIO_HAS_OPENLIST	/* Uses an implementation hack!!! */#define __STDIO_FLUSH_LBF_STREAMS		\	fflush_unlocked((FILE *) &_stdio_openlist)#else#define __STDIO_FLUSH_LBF_STREAMS		((void)0)#endif#ifdef NDEBUG#define __STDIO_STREAM_VALIDATE(S)		((void)0)#elseextern void _stdio_validate_FILE(const FILE *stream) attribute_hidden;#define __STDIO_STREAM_VALIDATE(S)		_stdio_validate_FILE((S))#endif#ifdef __STDIO_MBSTATE#define __COPY_MBSTATE(dest,src) \	((void)((dest)->__mask = (src)->__mask, (dest)->__wc = (src)->__wc))#define __INIT_MBSTATE(dest)			((void)((dest)->__mask = 0))#else#define __COPY_MBSTATE(dest,src)		((void)0)#define __INIT_MBSTATE(dest)			((void)0)#endif/**********************************************************************/extern FILE *_stdio_fopen(intptr_t fname_or_mode, const char *__restrict mode,		FILE *__restrict stream, int filedes) attribute_hidden;#ifdef __UCLIBC_HAS_WCHAR__extern size_t _wstdio_fwrite(const wchar_t *__restrict ws,		size_t n, FILE *__restrict stream) attribute_hidden;#endif/**********************************************************************/extern int _vfprintf_internal (FILE * __restrict stream,			const char * __restrict format,			va_list arg) attribute_hidden;#ifdef __UCLIBC_HAS_WCHAR__extern int _vfwprintf_internal (FILE * __restrict stream,			const wchar_t * __restrict format,			va_list arg) attribute_hidden;#endif/**********************************************************************//* Only use the macro below if you know fp is a valid FILE for a valid fd. * This is _not_ true for custom streams! */#define __FILENO_UNLOCKED(fp)	((fp)->__filedes)#define __FEOF_OR_FERROR_UNLOCKED(stream) \	((stream)->__modeflags & (__FLAG_EOF|__FLAG_ERROR))#if defined(__STDIO_BUFFERS) || defined(__USE_OLD_VFPRINTF__) || defined(__UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__)#define __STDIO_HAS_VSNPRINTF 1#endif
 |