blob: 2c0efc98687f1e855bb132a2380e8bc1c3f5568d [file] [log] [blame]
lh9ed821d2023-04-07 01:36:19 -07001/* Copyright (C) 2004-2005 Manuel Novoa III <mjn3@codepoet.org>
2 *
3 * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
4 *
5 * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details.
6 */
7
8#include <features.h>
9#include <assert.h>
10#include <errno.h>
11#include <fcntl.h>
12#include <limits.h>
13#include <signal.h>
14#include <stdint.h>
15#include <stdio.h>
16#include <stdlib.h>
17#include <string.h>
18#include <stdarg.h>
19#include <unistd.h>
20#ifdef __UCLIBC_HAS_WCHAR__
21#include <wchar.h>
22#endif
23
24#include <bits/uClibc_mutex.h>
25
26#define __STDIO_THREADLOCK_OPENLIST_ADD \
27 __UCLIBC_IO_MUTEX_LOCK(_stdio_openlist_add_lock)
28
29#define __STDIO_THREADUNLOCK_OPENLIST_ADD \
30 __UCLIBC_IO_MUTEX_UNLOCK(_stdio_openlist_add_lock)
31
32#ifdef __STDIO_BUFFERS
33
34#define __STDIO_THREADLOCK_OPENLIST_DEL \
35 __UCLIBC_IO_MUTEX_LOCK(_stdio_openlist_del_lock)
36
37#define __STDIO_THREADUNLOCK_OPENLIST_DEL \
38 __UCLIBC_IO_MUTEX_UNLOCK(_stdio_openlist_del_lock)
39
40
41#ifdef __UCLIBC_HAS_THREADS__
42#define __STDIO_OPENLIST_INC_USE \
43do { \
44 __STDIO_THREADLOCK_OPENLIST_DEL; \
45 ++_stdio_openlist_use_count; \
46 __STDIO_THREADUNLOCK_OPENLIST_DEL; \
47} while (0)
48
49extern void _stdio_openlist_dec_use(void) attribute_hidden;
50
51#define __STDIO_OPENLIST_DEC_USE \
52 _stdio_openlist_dec_use()
53
54#define __STDIO_OPENLIST_INC_DEL_CNT \
55do { \
56 __STDIO_THREADLOCK_OPENLIST_DEL; \
57 ++_stdio_openlist_del_count; \
58 __STDIO_THREADUNLOCK_OPENLIST_DEL; \
59} while (0)
60
61#define __STDIO_OPENLIST_DEC_DEL_CNT \
62do { \
63 __STDIO_THREADLOCK_OPENLIST_DEL; \
64 --_stdio_openlist_del_count; \
65 __STDIO_THREADUNLOCK_OPENLIST_DEL; \
66} while (0)
67
68#endif /* __UCLIBC_HAS_THREADS__ */
69#endif /* __STDIO_BUFFERS */
70
71#ifndef __STDIO_THREADLOCK_OPENLIST_DEL
72#define __STDIO_THREADLOCK_OPENLIST_DEL ((void)0)
73#endif
74#ifndef __STDIO_THREADUNLOCK_OPENLIST_DEL
75#define __STDIO_THREADUNLOCK_OPENLIST_DEL ((void)0)
76#endif
77#ifndef __STDIO_OPENLIST_INC_USE
78#define __STDIO_OPENLIST_INC_USE ((void)0)
79#endif
80#ifndef __STDIO_OPENLIST_DEC_USE
81#define __STDIO_OPENLIST_DEC_USE ((void)0)
82#endif
83#ifndef __STDIO_OPENLIST_INC_DEL_CNT
84#define __STDIO_OPENLIST_INC_DEL_CNT ((void)0)
85#endif
86#ifndef __STDIO_OPENLIST_DEC_DEL_CNT
87#define __STDIO_OPENLIST_DEC_DEL_CNT ((void)0)
88#endif
89
90#define __UNDEFINED_OR_NONPORTABLE ((void)0)
91
92/**********************************************************************/
93#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__
94
95extern __ssize_t _cs_read(void *cookie, char *buf, size_t bufsize) attribute_hidden;
96extern __ssize_t _cs_write(void *cookie, const char *buf, size_t bufsize) attribute_hidden;
97extern int _cs_seek(void *cookie, __offmax_t *pos, int whence) attribute_hidden;
98extern int _cs_close(void *cookie) attribute_hidden;
99
100#define __STDIO_STREAM_RESET_GCS(S) \
101 (S)->__cookie = &((S)->__filedes); \
102 (S)->__gcs.read = _cs_read; \
103 (S)->__gcs.write = _cs_write; \
104 (S)->__gcs.seek = _cs_seek; \
105 (S)->__gcs.close = _cs_close
106
107
108#define __READ(STREAMPTR,BUF,SIZE) \
109 ((((STREAMPTR)->__gcs.read) == NULL) ? -1 : \
110 (((STREAMPTR)->__gcs.read)((STREAMPTR)->__cookie,(BUF),(SIZE))))
111#define __WRITE(STREAMPTR,BUF,SIZE) \
112 ((((STREAMPTR)->__gcs.write) == NULL) ? -1 : \
113 (((STREAMPTR)->__gcs.write)((STREAMPTR)->__cookie,(BUF),(SIZE))))
114#define __SEEK(STREAMPTR,PPOS,WHENCE) \
115 ((((STREAMPTR)->__gcs.seek) == NULL) ? -1 : \
116 (((STREAMPTR)->__gcs.seek)((STREAMPTR)->__cookie,(PPOS),(WHENCE))))
117#define __CLOSE(STREAMPTR) \
118 ((((STREAMPTR)->__gcs.close) == NULL) ? 0 : \
119 (((STREAMPTR)->__gcs.close)((STREAMPTR)->__cookie)))
120
121#else /* __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ */
122
123extern int __stdio_seek(FILE *stream, register __offmax_t *pos, int whence) attribute_hidden;
124
125#define __STDIO_STREAM_RESET_GCS(S) ((void)0)
126
127#define __READ(STREAMPTR,BUF,SIZE) \
128 (read((STREAMPTR)->__filedes,(BUF),(SIZE)))
129#define __WRITE(STREAMPTR,BUF,SIZE) \
130 (write((STREAMPTR)->__filedes,(BUF),(SIZE)))
131#define __SEEK(STREAMPTR,PPOS,WHENCE) \
132 (__stdio_seek((STREAMPTR),(PPOS),(WHENCE)))
133#define __CLOSE(STREAMPTR) \
134 (close((STREAMPTR)->__filedes))
135
136#endif /* __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ */
137
138/**********************************************************************/
139#ifdef __UCLIBC_HAS_WCHAR__
140
141#define __STDIO_STREAM_TRANS_TO_WRITE(S,O) __stdio_trans2w_o((S), (O))
142#define __STDIO_STREAM_TRANS_TO_READ(S,O) __stdio_trans2r_o((S), (O))
143
144#else
145
146#define __STDIO_STREAM_TRANS_TO_WRITE(S,O) __stdio_trans2w((S))
147#define __STDIO_STREAM_TRANS_TO_READ(S,O) __stdio_trans2r((S))
148
149#endif
150/**********************************************************************/
151
152#define __STDIO_STREAM_IS_READING(S) ((S)->__modeflags & __MASK_READING)
153#define __STDIO_STREAM_IS_WRITING(S) ((S)->__modeflags & __FLAG_WRITING)
154
155#define __STDIO_STREAM_SET_READING(S) ((S)->__modeflags |= __FLAG_READING)
156#define __STDIO_STREAM_SET_WRITING(S) ((S)->__modeflags |= __FLAG_WRITING)
157
158#define __STDIO_STREAM_IS_READING_OR_READONLY(S) \
159 ((S)->__modeflags & (__MASK_READING|__FLAG_READONLY))
160
161#define __STDIO_STREAM_IS_WRITING_OR_WRITEONLY(S) \
162 ((S)->__modeflags & (__FLAG_WRITING|__FLAG_WRITEONLY))
163
164#define __STDIO_STREAM_IS_READONLY(S) ((S)->__modeflags & __FLAG_READONLY)
165#define __STDIO_STREAM_IS_WRITEONLY(S) ((S)->__modeflags & __FLAG_WRITEONLY)
166
167
168/**********************************************************************/
169#ifdef __UCLIBC_HAS_WCHAR__
170
171#define __STDIO_STREAM_IS_NARROW_WRITING(S) \
172 (((S)->__modeflags & (__FLAG_WRITING|__FLAG_NARROW)) \
173 == (__FLAG_WRITING|__FLAG_NARROW))
174
175#define __STDIO_STREAM_IS_WIDE_WRITING(S) \
176 (((S)->__modeflags & (__FLAG_WRITING|__FLAG_WIDE)) \
177 == (__FLAG_WRITING|__FLAG_WIDE))
178
179#if (__FLAG_NARROW <= __MASK_READING)
180#error assumption violated regarding __FLAG_NARROW
181#endif
182
183#define __STDIO_STREAM_IS_NARROW_READING(S) \
184 (((S)->__modeflags & (__MASK_READING|__FLAG_NARROW)) > __FLAG_NARROW)
185
186#define __STDIO_STREAM_IS_WIDE_READING(S) \
187 (((S)->__modeflags & (__MASK_READING|__FLAG_WIDE)) > __FLAG_WIDE)
188
189#define __STDIO_STREAM_IS_NARROW(S) ((S)->__modeflags & __FLAG_NARROW)
190#define __STDIO_STREAM_IS_WIDE(S) ((S)->__modeflags & __FLAG_WIDE)
191
192#define __STDIO_STREAM_SET_NARROW(S) \
193 ((void)((S)->__modeflags |= __FLAG_NARROW))
194#define __STDIO_STREAM_SET_WIDE(S) \
195 ((void)((S)->__modeflags |= __FLAG_WIDE))
196
197#else
198
199#define __STDIO_STREAM_IS_NARROW_WRITING(S) __STDIO_STREAM_IS_WRITING(S)
200
201#define __STDIO_STREAM_IS_NARROW_READING(S) __STDIO_STREAM_IS_READING(S)
202
203#define __STDIO_STREAM_IS_NARROW(S) (1)
204#define __STDIO_STREAM_IS_WIDE(S) (0)
205
206#define __STDIO_STREAM_SET_NARROW(S) ((void)0)
207#define __STDIO_STREAM_SET_WIDE(S) ((void)0)
208
209#endif
210/**********************************************************************/
211
212#define __STDIO_STREAM_SET_EOF(S) \
213 ((void)((S)->__modeflags |= __FLAG_EOF))
214#define __STDIO_STREAM_SET_ERROR(S) \
215 ((void)((S)->__modeflags |= __FLAG_ERROR))
216
217#define __STDIO_STREAM_CLEAR_EOF(S) \
218 ((void)((S)->__modeflags &= ~__FLAG_EOF))
219#define __STDIO_STREAM_CLEAR_ERROR(S) \
220 ((void)((S)->__modeflags &= ~__FLAG_ERROR))
221
222#define __STDIO_STREAM_CLEAR_READING_AND_UNGOTS(S) \
223 ((void)((S)->__modeflags &= ~__MASK_READING))
224#define __STDIO_STREAM_CLEAR_WRITING(S) \
225 ((void)((S)->__modeflags &= ~__FLAG_WRITING))
226
227#ifdef __UCLIBC_HAS_STDIO_GETC_MACRO__
228# define __STDIO_STREAM_DISABLE_GETC(S) \
229 ((void)((S)->__bufgetc_u = (S)->__bufstart))
230# define __STDIO_STREAM_ENABLE_GETC(S) \
231 ((void)((S)->__bufgetc_u = (S)->__bufread))
232# define __STDIO_STREAM_CAN_USE_BUFFER_GET(S) \
233 ((S)->__bufpos < (S)->__bufgetc_u)
234#else
235# define __STDIO_STREAM_DISABLE_GETC(S) ((void)0)
236# define __STDIO_STREAM_ENABLE_GETC(S) ((void)0)
237# define __STDIO_STREAM_CAN_USE_BUFFER_GET(S) (0)
238#endif
239
240#ifdef __UCLIBC_HAS_STDIO_PUTC_MACRO__
241# define __STDIO_STREAM_DISABLE_PUTC(S) \
242 ((void)((S)->__bufputc_u = (S)->__bufstart))
243# define __STDIO_STREAM_ENABLE_PUTC(S) \
244 ((void)((S)->__bufputc_u = (S)->__bufend))
245# define __STDIO_STREAM_CAN_USE_BUFFER_ADD(S) \
246 ((S)->__bufpos < (S)->__bufputc_u)
247#else
248# define __STDIO_STREAM_DISABLE_PUTC(S) ((void)0)
249# define __STDIO_STREAM_ENABLE_PUTC(S) ((void)0)
250# define __STDIO_STREAM_CAN_USE_BUFFER_ADD(S) (0)
251#endif
252
253#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__
254#define __STDIO_STREAM_IS_CUSTOM(S) ((S)->__cookie != &((S)->__filedes))
255#else
256#define __STDIO_STREAM_IS_CUSTOM(S) (0)
257#endif
258
259/**********************************************************************/
260
261#ifdef __STDIO_BUFFERS
262#define __STDIO_STREAM_FREE_BUFFER(S) \
263 do { if ((S)->__modeflags & __FLAG_FREEBUF) \
264 free((S)->__bufstart); } while (0)
265#else
266#define __STDIO_STREAM_FREE_BUFFER(S) ((void)0)
267#endif
268
269#define __STDIO_STREAM_FREE_FILE(S) \
270 do { if ((S)->__modeflags & __FLAG_FREEFILE) \
271 free((S)); } while (0)
272
273
274#ifdef __UCLIBC_HAS_LFS__
275#define __STDIO_WHEN_LFS(E) E
276#else
277#define __STDIO_WHEN_LFS(E) ((void)0)
278#endif
279
280/**********************************************************************/
281/* The following return 0 on success. */
282
283#ifdef __STDIO_BUFFERS
284/* Assume stream in valid writing state. Do not reset writing flag
285 * or disble putc macro unless error. */
286/* Should we assume that buffer is not empty to avoid a check? */
287extern size_t __stdio_wcommit(FILE *__restrict stream) attribute_hidden;
288
289/* Remember to fail if at EOF! */
290extern size_t __stdio_rfill(FILE *__restrict stream) attribute_hidden;
291
292extern size_t __stdio_fwrite(const unsigned char *__restrict buffer,
293 size_t bytes, FILE *__restrict stream) attribute_hidden;
294#else
295
296#define __stdio_fwrite(B,N,S) __stdio_WRITE((S),(B),(N))
297
298#endif
299
300extern size_t __stdio_WRITE(FILE *stream, const unsigned char *buf,
301 size_t bufsize) attribute_hidden;
302extern size_t __stdio_READ(FILE *stream, unsigned char *buf,
303 size_t bufsize) attribute_hidden;
304
305extern int __stdio_trans2r(FILE *__restrict stream) attribute_hidden;
306extern int __stdio_trans2w(FILE *__restrict stream) attribute_hidden;
307
308extern int __stdio_trans2r_o(FILE *__restrict stream, int oflag) attribute_hidden;
309extern int __stdio_trans2w_o(FILE *__restrict stream, int oflag) attribute_hidden;
310
311/**********************************************************************/
312#ifdef __STDIO_BUFFERS
313
314#define __STDIO_STREAM_IS_FBF(S) (!((S)->__modeflags & __MASK_BUFMODE))
315#define __STDIO_STREAM_IS_LBF(S) ((S)->__modeflags & __FLAG_LBF)
316#define __STDIO_STREAM_IS_NBF(S) ((S)->__modeflags & __FLAG_NBF)
317
318#define __STDIO_STREAM_BUFFER_SIZE(S) ((S)->__bufend - (S)->__bufstart)
319
320/* Valid when writing... */
321#define __STDIO_STREAM_BUFFER_ADD(S,C) (*(S)->__bufpos++ = (C))
322#define __STDIO_STREAM_BUFFER_UNADD(S) (--(S)->__bufpos)
323#define __STDIO_STREAM_BUFFER_WAVAIL(S) ((S)->__bufend - (S)->__bufpos)
324#define __STDIO_STREAM_BUFFER_WUSED(S) ((S)->__bufpos - (S)->__bufstart)
325#define __STDIO_COMMIT_WRITE_BUFFER(S) __stdio_wcommit((S))
326#ifdef __UCLIBC_HAS_WCHAR__
327#define __STDIO_STREAM_IS_NARROW_FBF(S) \
328 (!((S)->__modeflags & (__MASK_BUFMODE|__FLAG_WIDE)))
329#else
330#define __STDIO_STREAM_IS_NARROW_FBF(S) __STDIO_STREAM_IS_FBF((S))
331#endif
332
333/* Valid when reading... */
334#define __STDIO_STREAM_BUFFER_RAVAIL(S) ((S)->__bufread - (S)->__bufpos)
335#define __STDIO_STREAM_BUFFER_GET(S) (*(S)->__bufpos++)
336#define __STDIO_FILL_READ_BUFFER(S) __stdio_rfill((S))
337
338#define __STDIO_STREAM_INIT_BUFREAD_BUFPOS(S) \
339 (S)->__bufread = (S)->__bufpos = (S)->__bufstart
340
341
342#define __STDIO_STREAM_FAKE_VSNPRINTF_FILEDES (-2)
343#define __STDIO_STREAM_FAKE_VSSCANF_FILEDES (-2)
344#define __STDIO_STREAM_FAKE_VSWPRINTF_FILEDES (-3)
345#define __STDIO_STREAM_FAKE_VSWSCANF_FILEDES (-3)
346
347#define __STDIO_STREAM_IS_FAKE_VSNPRINTF(S) \
348 ((S)->__filedes == __STDIO_STREAM_FAKE_VSNPRINTF_FILEDES)
349#define __STDIO_STREAM_IS_FAKE_VSSCANF(S) \
350 ((S)->__filedes == __STDIO_STREAM_FAKE_VSSCANF_FILEDES)
351#define __STDIO_STREAM_IS_FAKE_VSWPRINTF(S) \
352 ((S)->__filedes == __STDIO_STREAM_FAKE_VSWPRINTF_FILEDES)
353#define __STDIO_STREAM_IS_FAKE_VSWSCANF(S) \
354 ((S)->__filedes == __STDIO_STREAM_FAKE_VSWSCANF_FILEDES)
355
356#else /* __STDIO_BUFFERS */
357
358#define __STDIO_STREAM_IS_FBF(S) (0)
359#define __STDIO_STREAM_IS_LBF(S) (0)
360#define __STDIO_STREAM_IS_NBF(S) (1)
361
362#define __STDIO_STREAM_BUFFER_SIZE(S) (0)
363#define __STDIO_STREAM_BUFFER_ADD(S,C) ((void)0)
364#define __STDIO_STREAM_BUFFER_UNADD(S) ((void)0)
365#define __STDIO_STREAM_BUFFER_WAVAIL(S) (0)
366#define __STDIO_STREAM_BUFFER_WUSED(S) (0)
367#define __STDIO_COMMIT_WRITE_BUFFER(S) (0)
368#define __STDIO_STREAM_IS_NARROW_FBF(S) (0)
369
370#define __STDIO_STREAM_BUFFER_RAVAIL(S) (0)
371#define __STDIO_STREAM_BUFFER_GET(S) (EOF)
372#define __STDIO_FILL_READ_BUFFER(S) (0)
373#define __STDIO_STREAM_INIT_BUFREAD_BUFPOS(S) ((void)0)
374
375#undef __STDIO_STREAM_FAKE_VSNPRINTF_FILEDES
376#undef __STDIO_STREAM_FAKE_VSSCANF_FILEDES
377#undef __STDIO_STREAM_FAKE_VSWPRINTF_FILEDES
378
379#define __STDIO_STREAM_IS_FAKE_VSNPRINTF(S) (0)
380#define __STDIO_STREAM_IS_FAKE_VSSCANF(S) (0)
381#undef __STDIO_STREAM_IS_FAKE_VSWPRINTF
382
383# ifdef __USE_OLD_VFPRINTF__
384# define __STDIO_STREAM_FAKE_VSNPRINTF_FILEDES_NB (-2)
385# define __STDIO_STREAM_IS_FAKE_VSNPRINTF_NB(S) \
386 ((S)->__filedes == __STDIO_STREAM_FAKE_VSNPRINTF_FILEDES_NB)
387# endif
388
389# ifndef __UCLIBC_HAS_WCHAR__
390# define __STDIO_STREAM_FAKE_VSSCANF_FILEDES_NB (-2)
391# define __STDIO_STREAM_IS_FAKE_VSSCANF_NB(S) \
392 ((S)->__filedes == __STDIO_STREAM_FAKE_VSSCANF_FILEDES_NB)
393# endif
394
395#endif /* __STDIO_BUFFERS */
396/**********************************************************************/
397
398extern int __stdio_adjust_position(FILE *__restrict stream, __offmax_t *pos) attribute_hidden;
399
400#ifdef __STDIO_HAS_OPENLIST
401 /* Uses an implementation hack!!! */
402#define __STDIO_FLUSH_LBF_STREAMS \
403 fflush_unlocked((FILE *) &_stdio_openlist)
404#else
405#define __STDIO_FLUSH_LBF_STREAMS ((void)0)
406#endif
407
408#ifdef NDEBUG
409#define __STDIO_STREAM_VALIDATE(S) ((void)0)
410#else
411extern void _stdio_validate_FILE(const FILE *stream) attribute_hidden;
412#define __STDIO_STREAM_VALIDATE(S) _stdio_validate_FILE((S))
413#endif
414
415#ifdef __STDIO_MBSTATE
416#define __COPY_MBSTATE(dest,src) \
417 ((void)((dest)->__mask = (src)->__mask, (dest)->__wc = (src)->__wc))
418#define __INIT_MBSTATE(dest) ((void)((dest)->__mask = 0))
419#else
420#define __COPY_MBSTATE(dest,src) ((void)0)
421#define __INIT_MBSTATE(dest) ((void)0)
422#endif
423
424/**********************************************************************/
425
426extern FILE *_stdio_fopen(intptr_t fname_or_mode, const char *__restrict mode,
427 FILE *__restrict stream, int filedes) attribute_hidden;
428
429#ifdef __UCLIBC_HAS_WCHAR__
430extern size_t _wstdio_fwrite(const wchar_t *__restrict ws,
431 size_t n, FILE *__restrict stream) attribute_hidden;
432#endif
433
434/**********************************************************************/
435
436extern int _vfprintf_internal (FILE * __restrict stream,
437 const char * __restrict format,
438 va_list arg) attribute_hidden;
439
440#ifdef __UCLIBC_HAS_WCHAR__
441extern int _vfwprintf_internal (FILE * __restrict stream,
442 const wchar_t * __restrict format,
443 va_list arg) attribute_hidden;
444#endif
445
446/**********************************************************************/
447/* Only use the macro below if you know fp is a valid FILE for a valid fd.
448 * This is _not_ true for custom streams! */
449#define __FILENO_UNLOCKED(fp) ((fp)->__filedes)
450
451#define __FEOF_OR_FERROR_UNLOCKED(stream) \
452 ((stream)->__modeflags & (__FLAG_EOF|__FLAG_ERROR))
453
454#if defined(__STDIO_BUFFERS) || defined(__USE_OLD_VFPRINTF__) || defined(__UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__)
455#define __STDIO_HAS_VSNPRINTF 1
456#endif