]> git.ipfire.org Git - thirdparty/glibc.git/blame - libio/genops.c
Update copyright dates with scripts/update-copyrights.
[thirdparty/glibc.git] / libio / genops.c
CommitLineData
04277e02 1/* Copyright (C) 1993-2019 Free Software Foundation, Inc.
41bdb6e2 2 This file is part of the GNU C Library.
40a55d20 3
41bdb6e2
AJ
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
40a55d20 8
41bdb6e2
AJ
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
40a55d20 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41bdb6e2
AJ
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
59ba27a6
PE
15 License along with the GNU C Library; if not, see
16 <http://www.gnu.org/licenses/>.
41bdb6e2
AJ
17
18 As a special exception, if you link the code in this file with
19 files compiled with a GNU compiler to produce an executable,
20 that does not cause the resulting executable to be covered by
21 the GNU Lesser General Public License. This exception does not
22 however invalidate any other reasons why the executable file
23 might be covered by the GNU Lesser General Public License.
24 This exception applies to code released by its copyright holders
25 in files containing the exception. */
96aa2d94
RM
26
27/* Generic or default I/O operations. */
28
29#include "libioP.h"
96aa2d94 30#include <stdlib.h>
96aa2d94 31#include <string.h>
8d24de8b 32#include <stdbool.h>
e2c7e1de 33#include <sched.h>
96aa2d94 34
51e176c2 35#ifdef _IO_MTSAFE_IO
118bad87 36static _IO_lock_t list_all_lock = _IO_lock_initializer;
51e176c2 37#endif
118bad87 38
9964a145 39static FILE *run_fp;
beafb752 40
bea9b193 41#ifdef _IO_MTSAFE_IO
beafb752
UD
42static void
43flush_cleanup (void *not_used)
44{
45 if (run_fp != NULL)
46 _IO_funlockfile (run_fp);
47 _IO_lock_unlock (list_all_lock);
48}
bea9b193 49#endif
beafb752 50
96aa2d94 51void
9d46370c 52_IO_un_link (struct _IO_FILE_plus *fp)
40a55d20 53{
2ca8b1ee 54 if (fp->file._flags & _IO_LINKED)
40a55d20 55 {
9964a145 56 FILE **f;
d328b80b 57#ifdef _IO_MTSAFE_IO
beafb752 58 _IO_cleanup_region_start_noarg (flush_cleanup);
118bad87 59 _IO_lock_lock (list_all_lock);
9964a145
ZW
60 run_fp = (FILE *) fp;
61 _IO_flockfile ((FILE *) fp);
51e176c2 62#endif
d18ea0c5 63 if (_IO_list_all == NULL)
cedb4109 64 ;
d18ea0c5 65 else if (fp == _IO_list_all)
19f82f35 66 _IO_list_all = (struct _IO_FILE_plus *) _IO_list_all->file._chain;
cedb4109 67 else
d18ea0c5 68 for (f = &_IO_list_all->file._chain; *f; f = &(*f)->_chain)
9964a145 69 if (*f == (FILE *) fp)
40a55d20 70 {
cedb4109 71 *f = fp->file._chain;
40a55d20
UD
72 break;
73 }
beafb752 74 fp->file._flags &= ~_IO_LINKED;
51e176c2 75#ifdef _IO_MTSAFE_IO
9964a145 76 _IO_funlockfile ((FILE *) fp);
beafb752 77 run_fp = NULL;
118bad87 78 _IO_lock_unlock (list_all_lock);
beafb752 79 _IO_cleanup_region_end (0);
51e176c2 80#endif
96aa2d94 81 }
96aa2d94 82}
d18ea0c5 83libc_hidden_def (_IO_un_link)
96aa2d94
RM
84
85void
9d46370c 86_IO_link_in (struct _IO_FILE_plus *fp)
96aa2d94 87{
beafb752
UD
88 if ((fp->file._flags & _IO_LINKED) == 0)
89 {
90 fp->file._flags |= _IO_LINKED;
51e176c2 91#ifdef _IO_MTSAFE_IO
beafb752
UD
92 _IO_cleanup_region_start_noarg (flush_cleanup);
93 _IO_lock_lock (list_all_lock);
9964a145
ZW
94 run_fp = (FILE *) fp;
95 _IO_flockfile ((FILE *) fp);
51e176c2 96#endif
9964a145 97 fp->file._chain = (FILE *) _IO_list_all;
d18ea0c5 98 _IO_list_all = fp;
51e176c2 99#ifdef _IO_MTSAFE_IO
9964a145 100 _IO_funlockfile ((FILE *) fp);
beafb752
UD
101 run_fp = NULL;
102 _IO_lock_unlock (list_all_lock);
103 _IO_cleanup_region_end (0);
51e176c2 104#endif
beafb752 105 }
96aa2d94 106}
d18ea0c5 107libc_hidden_def (_IO_link_in)
96aa2d94
RM
108
109/* Return minimum _pos markers
110 Assumes the current get area is the main get area. */
9964a145 111ssize_t _IO_least_marker (FILE *fp, char *end_p);
96aa2d94 112
9964a145
ZW
113ssize_t
114_IO_least_marker (FILE *fp, char *end_p)
96aa2d94 115{
9964a145 116 ssize_t least_so_far = end_p - fp->_IO_read_base;
40a55d20 117 struct _IO_marker *mark;
96aa2d94
RM
118 for (mark = fp->_markers; mark != NULL; mark = mark->_next)
119 if (mark->_pos < least_so_far)
120 least_so_far = mark->_pos;
121 return least_so_far;
122}
123
124/* Switch current get area from backup buffer to (start of) main get area. */
125
126void
9964a145 127_IO_switch_to_main_get_area (FILE *fp)
96aa2d94
RM
128{
129 char *tmp;
130 fp->_flags &= ~_IO_IN_BACKUP;
131 /* Swap _IO_read_end and _IO_save_end. */
40a55d20
UD
132 tmp = fp->_IO_read_end;
133 fp->_IO_read_end = fp->_IO_save_end;
134 fp->_IO_save_end= tmp;
96aa2d94 135 /* Swap _IO_read_base and _IO_save_base. */
40a55d20
UD
136 tmp = fp->_IO_read_base;
137 fp->_IO_read_base = fp->_IO_save_base;
138 fp->_IO_save_base = tmp;
05f732b3
UD
139 /* Set _IO_read_ptr. */
140 fp->_IO_read_ptr = fp->_IO_read_base;
96aa2d94
RM
141}
142
143/* Switch current get area from main get area to (end of) backup area. */
144
145void
9964a145 146_IO_switch_to_backup_area (FILE *fp)
96aa2d94
RM
147{
148 char *tmp;
149 fp->_flags |= _IO_IN_BACKUP;
150 /* Swap _IO_read_end and _IO_save_end. */
40a55d20
UD
151 tmp = fp->_IO_read_end;
152 fp->_IO_read_end = fp->_IO_save_end;
153 fp->_IO_save_end = tmp;
05f732b3 154 /* Swap _IO_read_base and _IO_save_base. */
40a55d20
UD
155 tmp = fp->_IO_read_base;
156 fp->_IO_read_base = fp->_IO_save_base;
157 fp->_IO_save_base = tmp;
05f732b3 158 /* Set _IO_read_ptr. */
96aa2d94
RM
159 fp->_IO_read_ptr = fp->_IO_read_end;
160}
161
162int
9964a145 163_IO_switch_to_get_mode (FILE *fp)
96aa2d94
RM
164{
165 if (fp->_IO_write_ptr > fp->_IO_write_base)
166 if (_IO_OVERFLOW (fp, EOF) == EOF)
167 return EOF;
40a55d20 168 if (_IO_in_backup (fp))
96aa2d94
RM
169 fp->_IO_read_base = fp->_IO_backup_base;
170 else
171 {
172 fp->_IO_read_base = fp->_IO_buf_base;
173 if (fp->_IO_write_ptr > fp->_IO_read_end)
174 fp->_IO_read_end = fp->_IO_write_ptr;
175 }
176 fp->_IO_read_ptr = fp->_IO_write_ptr;
177
178 fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end = fp->_IO_read_ptr;
179
180 fp->_flags &= ~_IO_CURRENTLY_PUTTING;
181 return 0;
182}
d18ea0c5 183libc_hidden_def (_IO_switch_to_get_mode)
96aa2d94
RM
184
185void
9964a145 186_IO_free_backup_area (FILE *fp)
96aa2d94
RM
187{
188 if (_IO_in_backup (fp))
40a55d20 189 _IO_switch_to_main_get_area (fp); /* Just in case. */
96aa2d94
RM
190 free (fp->_IO_save_base);
191 fp->_IO_save_base = NULL;
192 fp->_IO_save_end = NULL;
193 fp->_IO_backup_base = NULL;
194}
d18ea0c5 195libc_hidden_def (_IO_free_backup_area)
96aa2d94 196
96aa2d94 197int
9964a145 198__overflow (FILE *f, int ch)
96aa2d94 199{
6f98fd7e
UD
200 /* This is a single-byte stream. */
201 if (f->_mode == 0)
202 _IO_fwide (f, -1);
96aa2d94
RM
203 return _IO_OVERFLOW (f, ch);
204}
37ba7d66 205libc_hidden_def (__overflow)
96aa2d94 206
05f732b3 207static int
9964a145 208save_for_backup (FILE *fp, char *end_p)
96aa2d94 209{
05f732b3 210 /* Append [_IO_read_base..end_p] to backup area. */
9964a145 211 ssize_t least_mark = _IO_least_marker (fp, end_p);
96aa2d94 212 /* needed_size is how much space we need in the backup area. */
9964a145 213 size_t needed_size = (end_p - fp->_IO_read_base) - least_mark;
05f732b3 214 /* FIXME: Dubious arithmetic if pointers are NULL */
9964a145
ZW
215 size_t current_Bsize = fp->_IO_save_end - fp->_IO_save_base;
216 size_t avail; /* Extra space available for future expansion. */
217 ssize_t delta;
96aa2d94
RM
218 struct _IO_marker *mark;
219 if (needed_size > current_Bsize)
220 {
221 char *new_buffer;
222 avail = 100;
40a55d20 223 new_buffer = (char *) malloc (avail + needed_size);
96aa2d94
RM
224 if (new_buffer == NULL)
225 return EOF; /* FIXME */
226 if (least_mark < 0)
227 {
86187531
UD
228 __mempcpy (__mempcpy (new_buffer + avail,
229 fp->_IO_save_end + least_mark,
230 -least_mark),
231 fp->_IO_read_base,
05f732b3 232 end_p - fp->_IO_read_base);
96aa2d94
RM
233 }
234 else
40a55d20
UD
235 memcpy (new_buffer + avail,
236 fp->_IO_read_base + least_mark,
237 needed_size);
72e6cdfa 238 free (fp->_IO_save_base);
96aa2d94
RM
239 fp->_IO_save_base = new_buffer;
240 fp->_IO_save_end = new_buffer + avail + needed_size;
241 }
242 else
243 {
244 avail = current_Bsize - needed_size;
245 if (least_mark < 0)
246 {
40a55d20
UD
247 memmove (fp->_IO_save_base + avail,
248 fp->_IO_save_end + least_mark,
249 -least_mark);
250 memcpy (fp->_IO_save_base + avail - least_mark,
251 fp->_IO_read_base,
05f732b3 252 end_p - fp->_IO_read_base);
96aa2d94
RM
253 }
254 else if (needed_size > 0)
40a55d20
UD
255 memcpy (fp->_IO_save_base + avail,
256 fp->_IO_read_base + least_mark,
257 needed_size);
96aa2d94 258 }
96aa2d94
RM
259 fp->_IO_backup_base = fp->_IO_save_base + avail;
260 /* Adjust all the streammarkers. */
05f732b3 261 delta = end_p - fp->_IO_read_base;
96aa2d94
RM
262 for (mark = fp->_markers; mark != NULL; mark = mark->_next)
263 mark->_pos -= delta;
264 return 0;
265}
266
267int
9964a145 268__underflow (FILE *fp)
96aa2d94 269{
bbdef797 270 if (_IO_vtable_offset (fp) == 0 && _IO_fwide (fp, -1) != -1)
d64b6ad0
UD
271 return EOF;
272
6f98fd7e
UD
273 if (fp->_mode == 0)
274 _IO_fwide (fp, -1);
40a55d20 275 if (_IO_in_put_mode (fp))
d18ea0c5 276 if (_IO_switch_to_get_mode (fp) == EOF)
40a55d20 277 return EOF;
96aa2d94 278 if (fp->_IO_read_ptr < fp->_IO_read_end)
40a55d20
UD
279 return *(unsigned char *) fp->_IO_read_ptr;
280 if (_IO_in_backup (fp))
96aa2d94 281 {
40a55d20 282 _IO_switch_to_main_get_area (fp);
96aa2d94 283 if (fp->_IO_read_ptr < fp->_IO_read_end)
31f7410f 284 return *(unsigned char *) fp->_IO_read_ptr;
96aa2d94 285 }
40a55d20 286 if (_IO_have_markers (fp))
96aa2d94 287 {
05f732b3 288 if (save_for_backup (fp, fp->_IO_read_end))
96aa2d94
RM
289 return EOF;
290 }
40a55d20 291 else if (_IO_have_backup (fp))
d18ea0c5 292 _IO_free_backup_area (fp);
96aa2d94
RM
293 return _IO_UNDERFLOW (fp);
294}
a20d8dbe 295libc_hidden_def (__underflow)
96aa2d94
RM
296
297int
9964a145 298__uflow (FILE *fp)
96aa2d94 299{
bbdef797 300 if (_IO_vtable_offset (fp) == 0 && _IO_fwide (fp, -1) != -1)
d64b6ad0
UD
301 return EOF;
302
6f98fd7e 303 if (fp->_mode == 0)
1e88bd0f 304 _IO_fwide (fp, -1);
40a55d20 305 if (_IO_in_put_mode (fp))
d18ea0c5 306 if (_IO_switch_to_get_mode (fp) == EOF)
40a55d20 307 return EOF;
96aa2d94 308 if (fp->_IO_read_ptr < fp->_IO_read_end)
40a55d20
UD
309 return *(unsigned char *) fp->_IO_read_ptr++;
310 if (_IO_in_backup (fp))
96aa2d94 311 {
40a55d20 312 _IO_switch_to_main_get_area (fp);
96aa2d94 313 if (fp->_IO_read_ptr < fp->_IO_read_end)
31f7410f 314 return *(unsigned char *) fp->_IO_read_ptr++;
96aa2d94 315 }
40a55d20 316 if (_IO_have_markers (fp))
96aa2d94 317 {
05f732b3 318 if (save_for_backup (fp, fp->_IO_read_end))
96aa2d94
RM
319 return EOF;
320 }
40a55d20 321 else if (_IO_have_backup (fp))
d18ea0c5 322 _IO_free_backup_area (fp);
96aa2d94
RM
323 return _IO_UFLOW (fp);
324}
3ba06713 325libc_hidden_def (__uflow)
96aa2d94
RM
326
327void
9964a145 328_IO_setb (FILE *f, char *b, char *eb, int a)
96aa2d94
RM
329{
330 if (f->_IO_buf_base && !(f->_flags & _IO_USER_BUF))
8a29509d 331 free (f->_IO_buf_base);
96aa2d94
RM
332 f->_IO_buf_base = b;
333 f->_IO_buf_end = eb;
334 if (a)
335 f->_flags &= ~_IO_USER_BUF;
336 else
337 f->_flags |= _IO_USER_BUF;
338}
d18ea0c5 339libc_hidden_def (_IO_setb)
96aa2d94
RM
340
341void
9964a145 342_IO_doallocbuf (FILE *fp)
96aa2d94
RM
343{
344 if (fp->_IO_buf_base)
345 return;
655de5fd 346 if (!(fp->_flags & _IO_UNBUFFERED) || fp->_mode > 0)
96aa2d94
RM
347 if (_IO_DOALLOCATE (fp) != EOF)
348 return;
d18ea0c5 349 _IO_setb (fp, fp->_shortbuf, fp->_shortbuf+1, 0);
96aa2d94 350}
d18ea0c5 351libc_hidden_def (_IO_doallocbuf)
96aa2d94
RM
352
353int
9964a145 354_IO_default_underflow (FILE *fp)
96aa2d94
RM
355{
356 return EOF;
357}
358
359int
9964a145 360_IO_default_uflow (FILE *fp)
96aa2d94
RM
361{
362 int ch = _IO_UNDERFLOW (fp);
363 if (ch == EOF)
364 return EOF;
40a55d20 365 return *(unsigned char *) fp->_IO_read_ptr++;
96aa2d94 366}
d18ea0c5 367libc_hidden_def (_IO_default_uflow)
96aa2d94 368
9964a145
ZW
369size_t
370_IO_default_xsputn (FILE *f, const void *data, size_t n)
96aa2d94 371{
40a55d20 372 const char *s = (char *) data;
9964a145 373 size_t more = n;
96aa2d94
RM
374 if (more <= 0)
375 return 0;
376 for (;;)
377 {
40a55d20 378 /* Space available. */
f7803f51 379 if (f->_IO_write_ptr < f->_IO_write_end)
96aa2d94 380 {
9964a145 381 size_t count = f->_IO_write_end - f->_IO_write_ptr;
f7803f51 382 if (count > more)
96aa2d94
RM
383 count = more;
384 if (count > 20)
385 {
86187531 386 f->_IO_write_ptr = __mempcpy (f->_IO_write_ptr, s, count);
86187531 387 s += count;
f22e1074 388 }
f7803f51 389 else if (count)
96aa2d94 390 {
40a55d20 391 char *p = f->_IO_write_ptr;
9964a145 392 ssize_t i;
40a55d20
UD
393 for (i = count; --i >= 0; )
394 *p++ = *s++;
96aa2d94 395 f->_IO_write_ptr = p;
f22e1074 396 }
96aa2d94 397 more -= count;
f22e1074 398 }
9202ffe3 399 if (more == 0 || _IO_OVERFLOW (f, (unsigned char) *s++) == EOF)
96aa2d94
RM
400 break;
401 more--;
402 }
403 return n - more;
404}
d18ea0c5 405libc_hidden_def (_IO_default_xsputn)
96aa2d94 406
9964a145
ZW
407size_t
408_IO_sgetn (FILE *fp, void *data, size_t n)
96aa2d94
RM
409{
410 /* FIXME handle putback buffer here! */
411 return _IO_XSGETN (fp, data, n);
412}
d18ea0c5 413libc_hidden_def (_IO_sgetn)
96aa2d94 414
9964a145
ZW
415size_t
416_IO_default_xsgetn (FILE *fp, void *data, size_t n)
96aa2d94 417{
9964a145 418 size_t more = n;
40a55d20 419 char *s = (char*) data;
96aa2d94
RM
420 for (;;)
421 {
40a55d20 422 /* Data available. */
f7803f51 423 if (fp->_IO_read_ptr < fp->_IO_read_end)
96aa2d94 424 {
9964a145 425 size_t count = fp->_IO_read_end - fp->_IO_read_ptr;
f7803f51 426 if (count > more)
96aa2d94
RM
427 count = more;
428 if (count > 20)
429 {
86187531 430 s = __mempcpy (s, fp->_IO_read_ptr, count);
96aa2d94
RM
431 fp->_IO_read_ptr += count;
432 }
f7803f51 433 else if (count)
96aa2d94 434 {
40a55d20
UD
435 char *p = fp->_IO_read_ptr;
436 int i = (int) count;
437 while (--i >= 0)
438 *s++ = *p++;
96aa2d94 439 fp->_IO_read_ptr = p;
f22e1074
UD
440 }
441 more -= count;
442 }
40a55d20 443 if (more == 0 || __underflow (fp) == EOF)
96aa2d94
RM
444 break;
445 }
446 return n - more;
447}
d18ea0c5 448libc_hidden_def (_IO_default_xsgetn)
96aa2d94 449
9964a145
ZW
450FILE *
451_IO_default_setbuf (FILE *fp, char *p, ssize_t len)
96aa2d94
RM
452{
453 if (_IO_SYNC (fp) == EOF)
454 return NULL;
455 if (p == NULL || len == 0)
456 {
457 fp->_flags |= _IO_UNBUFFERED;
d18ea0c5 458 _IO_setb (fp, fp->_shortbuf, fp->_shortbuf+1, 0);
96aa2d94
RM
459 }
460 else
461 {
462 fp->_flags &= ~_IO_UNBUFFERED;
d18ea0c5 463 _IO_setb (fp, p, p+len, 0);
96aa2d94
RM
464 }
465 fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end = 0;
466 fp->_IO_read_base = fp->_IO_read_ptr = fp->_IO_read_end = 0;
467 return fp;
468}
469
9964a145
ZW
470off64_t
471_IO_default_seekpos (FILE *fp, off64_t pos, int mode)
96aa2d94 472{
d64b6ad0 473 return _IO_SEEKOFF (fp, pos, 0, mode);
96aa2d94
RM
474}
475
476int
9964a145 477_IO_default_doallocate (FILE *fp)
96aa2d94 478{
f8b87ef0
UD
479 char *buf;
480
9964a145 481 buf = malloc(BUFSIZ);
8a29509d
PP
482 if (__glibc_unlikely (buf == NULL))
483 return EOF;
484
9964a145 485 _IO_setb (fp, buf, buf+BUFSIZ, 1);
96aa2d94
RM
486 return 1;
487}
d18ea0c5 488libc_hidden_def (_IO_default_doallocate)
96aa2d94
RM
489
490void
9964a145 491_IO_init_internal (FILE *fp, int flags)
d64b6ad0
UD
492{
493 _IO_no_init (fp, flags, -1, NULL, NULL);
494}
db3476af
FW
495
496void
9964a145 497_IO_init (FILE *fp, int flags)
db3476af
FW
498{
499 IO_set_accept_foreign_vtables (&_IO_vtable_check);
500 _IO_init_internal (fp, flags);
501}
d64b6ad0 502
d2e04918
SN
503static int stdio_needs_locking;
504
505/* In a single-threaded process most stdio locks can be omitted. After
506 _IO_enable_locks is called, locks are not optimized away any more.
507 It must be first called while the process is still single-threaded.
508
509 This lock optimization can be disabled on a per-file basis by setting
510 _IO_FLAGS2_NEED_LOCK, because a file can have user-defined callbacks
511 or can be locked with flockfile and then a thread may be created
512 between a lock and unlock, so omitting the lock is not valid.
513
514 Here we have to make sure that the flag is set on all existing files
515 and files created later. */
516void
517_IO_enable_locks (void)
518{
519 _IO_ITER i;
520
521 if (stdio_needs_locking)
522 return;
523 stdio_needs_locking = 1;
524 for (i = _IO_iter_begin (); i != _IO_iter_end (); i = _IO_iter_next (i))
525 _IO_iter_file (i)->_flags2 |= _IO_FLAGS2_NEED_LOCK;
526}
527libc_hidden_def (_IO_enable_locks)
528
d64b6ad0 529void
9964a145 530_IO_old_init (FILE *fp, int flags)
96aa2d94
RM
531{
532 fp->_flags = _IO_MAGIC|flags;
dd0ee2e1 533 fp->_flags2 = 0;
d2e04918
SN
534 if (stdio_needs_locking)
535 fp->_flags2 |= _IO_FLAGS2_NEED_LOCK;
96aa2d94
RM
536 fp->_IO_buf_base = NULL;
537 fp->_IO_buf_end = NULL;
538 fp->_IO_read_base = NULL;
539 fp->_IO_read_ptr = NULL;
540 fp->_IO_read_end = NULL;
541 fp->_IO_write_base = NULL;
542 fp->_IO_write_ptr = NULL;
543 fp->_IO_write_end = NULL;
544 fp->_chain = NULL; /* Not necessary. */
545
546 fp->_IO_save_base = NULL;
547 fp->_IO_backup_base = NULL;
548 fp->_IO_save_end = NULL;
549 fp->_markers = NULL;
550 fp->_cur_column = 0;
c15cf13a 551#if _IO_JUMPS_OFFSET
bd355af0
UD
552 fp->_vtable_offset = 0;
553#endif
7c713e28 554#ifdef _IO_MTSAFE_IO
c020d48c
UD
555 if (fp->_lock != NULL)
556 _IO_lock_init (*fp->_lock);
7c713e28 557#endif
14a2bd4b
UD
558}
559
560void
9964a145 561_IO_no_init (FILE *fp, int flags, int orientation,
f63f2bfd 562 struct _IO_wide_data *wd, const struct _IO_jump_t *jmp)
14a2bd4b
UD
563{
564 _IO_old_init (fp, flags);
d64b6ad0
UD
565 fp->_mode = orientation;
566 if (orientation >= 0)
567 {
568 fp->_wide_data = wd;
569 fp->_wide_data->_IO_buf_base = NULL;
570 fp->_wide_data->_IO_buf_end = NULL;
571 fp->_wide_data->_IO_read_base = NULL;
572 fp->_wide_data->_IO_read_ptr = NULL;
573 fp->_wide_data->_IO_read_end = NULL;
574 fp->_wide_data->_IO_write_base = NULL;
575 fp->_wide_data->_IO_write_ptr = NULL;
576 fp->_wide_data->_IO_write_end = NULL;
577 fp->_wide_data->_IO_save_base = NULL;
578 fp->_wide_data->_IO_backup_base = NULL;
579 fp->_wide_data->_IO_save_end = NULL;
580
581 fp->_wide_data->_wide_vtable = jmp;
582 }
bae143d2
OB
583 else
584 /* Cause predictable crash when a wide function is called on a byte
585 stream. */
586 fp->_wide_data = (struct _IO_wide_data *) -1L;
78762723 587 fp->_freeres_list = NULL;
96aa2d94
RM
588}
589
590int
9964a145 591_IO_default_sync (FILE *fp)
96aa2d94
RM
592{
593 return 0;
594}
595
596/* The way the C++ classes are mapped into the C functions in the
597 current implementation, this function can get called twice! */
598
599void
9964a145 600_IO_default_finish (FILE *fp, int dummy)
96aa2d94
RM
601{
602 struct _IO_marker *mark;
603 if (fp->_IO_buf_base && !(fp->_flags & _IO_USER_BUF))
604 {
8a29509d 605 free (fp->_IO_buf_base);
96aa2d94
RM
606 fp->_IO_buf_base = fp->_IO_buf_end = NULL;
607 }
608
609 for (mark = fp->_markers; mark != NULL; mark = mark->_next)
610 mark->_sbuf = NULL;
611
612 if (fp->_IO_save_base)
613 {
614 free (fp->_IO_save_base);
615 fp->_IO_save_base = NULL;
616 }
617
d18ea0c5 618 _IO_un_link ((struct _IO_FILE_plus *) fp);
993a5d66 619
7c713e28 620#ifdef _IO_MTSAFE_IO
c020d48c
UD
621 if (fp->_lock != NULL)
622 _IO_lock_fini (*fp->_lock);
7c713e28 623#endif
96aa2d94 624}
d18ea0c5 625libc_hidden_def (_IO_default_finish)
96aa2d94 626
9964a145
ZW
627off64_t
628_IO_default_seekoff (FILE *fp, off64_t offset, int dir, int mode)
96aa2d94 629{
c020d48c 630 return _IO_pos_BAD;
96aa2d94
RM
631}
632
633int
9964a145 634_IO_sputbackc (FILE *fp, int c)
96aa2d94 635{
19bc17a9 636 int result;
adfa2078 637
96aa2d94
RM
638 if (fp->_IO_read_ptr > fp->_IO_read_base
639 && (unsigned char)fp->_IO_read_ptr[-1] == (unsigned char)c)
640 {
641 fp->_IO_read_ptr--;
40a55d20 642 result = (unsigned char) c;
96aa2d94 643 }
19bc17a9
RM
644 else
645 result = _IO_PBACKFAIL (fp, c);
646
647 if (result != EOF)
648 fp->_flags &= ~_IO_EOF_SEEN;
649
650 return result;
96aa2d94 651}
d18ea0c5 652libc_hidden_def (_IO_sputbackc)
96aa2d94
RM
653
654int
9964a145 655_IO_sungetc (FILE *fp)
96aa2d94 656{
19bc17a9 657 int result;
adfa2078 658
96aa2d94
RM
659 if (fp->_IO_read_ptr > fp->_IO_read_base)
660 {
661 fp->_IO_read_ptr--;
40a55d20 662 result = (unsigned char) *fp->_IO_read_ptr;
96aa2d94
RM
663 }
664 else
19bc17a9
RM
665 result = _IO_PBACKFAIL (fp, EOF);
666
667 if (result != EOF)
668 fp->_flags &= ~_IO_EOF_SEEN;
669
670 return result;
96aa2d94
RM
671}
672
96aa2d94 673unsigned
9d46370c 674_IO_adjust_column (unsigned start, const char *line, int count)
96aa2d94 675{
40a55d20 676 const char *ptr = line + count;
96aa2d94
RM
677 while (ptr > line)
678 if (*--ptr == '\n')
679 return line + count - ptr - 1;
680 return start + count;
681}
d18ea0c5 682libc_hidden_def (_IO_adjust_column)
96aa2d94 683
96aa2d94 684int
c6baa867 685_IO_flush_all_lockp (int do_lock)
96aa2d94
RM
686{
687 int result = 0;
9964a145 688 FILE *fp;
3afd9491
UD
689
690#ifdef _IO_MTSAFE_IO
19f82f35
AS
691 _IO_cleanup_region_start_noarg (flush_cleanup);
692 _IO_lock_lock (list_all_lock);
3afd9491
UD
693#endif
694
9964a145 695 for (fp = (FILE *) _IO_list_all; fp != NULL; fp = fp->_chain)
3afd9491
UD
696 {
697 run_fp = fp;
c6baa867
UD
698 if (do_lock)
699 _IO_flockfile (fp);
3afd9491
UD
700
701 if (((fp->_mode <= 0 && fp->_IO_write_ptr > fp->_IO_write_base)
bbdef797 702 || (_IO_vtable_offset (fp) == 0
3afd9491
UD
703 && fp->_mode > 0 && (fp->_wide_data->_IO_write_ptr
704 > fp->_wide_data->_IO_write_base))
3afd9491
UD
705 )
706 && _IO_OVERFLOW (fp, EOF) == EOF)
707 result = EOF;
708
c6baa867
UD
709 if (do_lock)
710 _IO_funlockfile (fp);
3afd9491 711 run_fp = NULL;
3afd9491
UD
712 }
713
714#ifdef _IO_MTSAFE_IO
19f82f35
AS
715 _IO_lock_unlock (list_all_lock);
716 _IO_cleanup_region_end (0);
3afd9491
UD
717#endif
718
96aa2d94
RM
719 return result;
720}
721
c6baa867
UD
722
723int
60d2f8f3 724_IO_flush_all (void)
c6baa867
UD
725{
726 /* We want locking. */
727 return _IO_flush_all_lockp (1);
728}
d18ea0c5 729libc_hidden_def (_IO_flush_all)
c6baa867 730
96aa2d94 731void
60d2f8f3 732_IO_flush_all_linebuffered (void)
96aa2d94 733{
9964a145 734 FILE *fp;
3afd9491
UD
735
736#ifdef _IO_MTSAFE_IO
737 _IO_cleanup_region_start_noarg (flush_cleanup);
738 _IO_lock_lock (list_all_lock);
739#endif
740
9964a145 741 for (fp = (FILE *) _IO_list_all; fp != NULL; fp = fp->_chain)
3afd9491
UD
742 {
743 run_fp = fp;
744 _IO_flockfile (fp);
745
746 if ((fp->_flags & _IO_NO_WRITES) == 0 && fp->_flags & _IO_LINE_BUF)
747 _IO_OVERFLOW (fp, EOF);
748
749 _IO_funlockfile (fp);
750 run_fp = NULL;
3afd9491
UD
751 }
752
753#ifdef _IO_MTSAFE_IO
754 _IO_lock_unlock (list_all_lock);
755 _IO_cleanup_region_end (0);
756#endif
96aa2d94 757}
d18ea0c5 758libc_hidden_def (_IO_flush_all_linebuffered)
a91d3cd3 759weak_alias (_IO_flush_all_linebuffered, _flushlbf)
96aa2d94 760
78762723
UD
761
762/* The following is a bit tricky. In general, we want to unbuffer the
763 streams so that all output which follows is seen. If we are not
764 looking for memory leaks it does not make much sense to free the
765 actual buffer because this will happen anyway once the program
766 terminated. If we do want to look for memory leaks we have to free
767 the buffers. Whether something is freed is determined by the
768 function sin the libc_freeres section. Those are called as part of
769 the atexit routine, just like _IO_cleanup. The problem is we do
770 not know whether the freeres code is called first or _IO_cleanup.
771 if the former is the case, we set the DEALLOC_BUFFER variable to
18d26750
PP
772 true and _IO_unbuffer_all will take care of the rest. If
773 _IO_unbuffer_all is called first we add the streams to a list
78762723 774 which the freeres function later can walk through. */
18d26750 775static void _IO_unbuffer_all (void);
40a55d20 776
78762723 777static bool dealloc_buffers;
9964a145 778static FILE *freeres_list;
78762723 779
40a55d20 780static void
18d26750 781_IO_unbuffer_all (void)
96aa2d94 782{
9964a145 783 FILE *fp;
19f82f35
AS
784
785#ifdef _IO_MTSAFE_IO
786 _IO_cleanup_region_start_noarg (flush_cleanup);
787 _IO_lock_lock (list_all_lock);
788#endif
789
9964a145 790 for (fp = (FILE *) _IO_list_all; fp; fp = fp->_chain)
6906cea4
UD
791 {
792 if (! (fp->_flags & _IO_UNBUFFERED)
6906cea4
UD
793 /* Iff stream is un-orientated, it wasn't used. */
794 && fp->_mode != 0)
78762723 795 {
b2e1c562 796#ifdef _IO_MTSAFE_IO
af047cff
UD
797 int cnt;
798#define MAXTRIES 2
799 for (cnt = 0; cnt < MAXTRIES; ++cnt)
f22e1074 800 if (fp->_lock == NULL || _IO_lock_trylock (*fp->_lock) == 0)
af047cff
UD
801 break;
802 else
803 /* Give the other thread time to finish up its use of the
804 stream. */
805 __sched_yield ();
b2e1c562 806#endif
af047cff 807
78762723
UD
808 if (! dealloc_buffers && !(fp->_flags & _IO_USER_BUF))
809 {
810 fp->_flags |= _IO_USER_BUF;
811
812 fp->_freeres_list = freeres_list;
813 freeres_list = fp;
814 fp->_freeres_buf = fp->_IO_buf_base;
78762723
UD
815 }
816
817 _IO_SETBUF (fp, NULL, 0);
af047cff 818
a601b74d
PP
819 if (fp->_mode > 0)
820 _IO_wsetb (fp, NULL, NULL, 0);
821
b2e1c562 822#ifdef _IO_MTSAFE_IO
f22e1074 823 if (cnt < MAXTRIES && fp->_lock != NULL)
af047cff 824 _IO_lock_unlock (*fp->_lock);
b2e1c562 825#endif
78762723 826 }
6906cea4
UD
827
828 /* Make sure that never again the wide char functions can be
829 used. */
830 fp->_mode = -1;
831 }
19f82f35
AS
832
833#ifdef _IO_MTSAFE_IO
834 _IO_lock_unlock (list_all_lock);
835 _IO_cleanup_region_end (0);
836#endif
96aa2d94
RM
837}
838
78762723
UD
839
840libc_freeres_fn (buffer_free)
841{
842 dealloc_buffers = true;
843
844 while (freeres_list != NULL)
845 {
8a29509d 846 free (freeres_list->_freeres_buf);
78762723
UD
847
848 freeres_list = freeres_list->_freeres_list;
849 }
850}
851
852
310b3460 853int
60d2f8f3 854_IO_cleanup (void)
96aa2d94 855{
64f01020 856 /* We do *not* want locking. Some threads might use streams but
78762723 857 that is their problem, we flush them underneath them. */
64f01020 858 int result = _IO_flush_all_lockp (0);
96aa2d94
RM
859
860 /* We currently don't have a reliable mechanism for making sure that
861 C++ static destructors are executed in the correct order.
6d52618b 862 So it is possible that other static destructors might want to
96aa2d94
RM
863 write to cout - and they're supposed to be able to do so.
864
adfa2078 865 The following will make the standard streambufs be unbuffered,
96aa2d94 866 which forces any output from late destructors to be written out. */
18d26750 867 _IO_unbuffer_all ();
310b3460
UD
868
869 return result;
96aa2d94
RM
870}
871
f2ea0f5b 872
96aa2d94 873void
9964a145 874_IO_init_marker (struct _IO_marker *marker, FILE *fp)
96aa2d94
RM
875{
876 marker->_sbuf = fp;
40a55d20 877 if (_IO_in_put_mode (fp))
d18ea0c5 878 _IO_switch_to_get_mode (fp);
40a55d20 879 if (_IO_in_backup (fp))
96aa2d94
RM
880 marker->_pos = fp->_IO_read_ptr - fp->_IO_read_end;
881 else
882 marker->_pos = fp->_IO_read_ptr - fp->_IO_read_base;
adfa2078 883
96aa2d94
RM
884 /* Should perhaps sort the chain? */
885 marker->_next = fp->_markers;
886 fp->_markers = marker;
887}
888
889void
9d46370c 890_IO_remove_marker (struct _IO_marker *marker)
96aa2d94
RM
891{
892 /* Unlink from sb's chain. */
40a55d20 893 struct _IO_marker **ptr = &marker->_sbuf->_markers;
96aa2d94
RM
894 for (; ; ptr = &(*ptr)->_next)
895 {
896 if (*ptr == NULL)
897 break;
898 else if (*ptr == marker)
899 {
900 *ptr = marker->_next;
901 return;
902 }
903 }
30bfee26
ZW
904 /* FIXME: if _sbuf has a backup area that is no longer needed,
905 should we delete it now, or wait until the next underflow? */
96aa2d94
RM
906}
907
908#define BAD_DELTA EOF
909
910int
9d46370c 911_IO_marker_difference (struct _IO_marker *mark1, struct _IO_marker *mark2)
96aa2d94
RM
912{
913 return mark1->_pos - mark2->_pos;
914}
915
6d52618b 916/* Return difference between MARK and current position of MARK's stream. */
96aa2d94 917int
9d46370c 918_IO_marker_delta (struct _IO_marker *mark)
96aa2d94
RM
919{
920 int cur_pos;
921 if (mark->_sbuf == NULL)
922 return BAD_DELTA;
40a55d20 923 if (_IO_in_backup (mark->_sbuf))
96aa2d94
RM
924 cur_pos = mark->_sbuf->_IO_read_ptr - mark->_sbuf->_IO_read_end;
925 else
926 cur_pos = mark->_sbuf->_IO_read_ptr - mark->_sbuf->_IO_read_base;
927 return mark->_pos - cur_pos;
928}
929
930int
9964a145 931_IO_seekmark (FILE *fp, struct _IO_marker *mark, int delta)
96aa2d94
RM
932{
933 if (mark->_sbuf != fp)
934 return EOF;
935 if (mark->_pos >= 0)
936 {
40a55d20
UD
937 if (_IO_in_backup (fp))
938 _IO_switch_to_main_get_area (fp);
96aa2d94
RM
939 fp->_IO_read_ptr = fp->_IO_read_base + mark->_pos;
940 }
941 else
942 {
40a55d20 943 if (!_IO_in_backup (fp))
05f732b3 944 _IO_switch_to_backup_area (fp);
96aa2d94
RM
945 fp->_IO_read_ptr = fp->_IO_read_end + mark->_pos;
946 }
947 return 0;
948}
949
950void
9964a145 951_IO_unsave_markers (FILE *fp)
96aa2d94 952{
40a55d20 953 struct _IO_marker *mark = fp->_markers;
96aa2d94
RM
954 if (mark)
955 {
96aa2d94
RM
956 fp->_markers = 0;
957 }
958
40a55d20 959 if (_IO_have_backup (fp))
d18ea0c5 960 _IO_free_backup_area (fp);
96aa2d94 961}
d18ea0c5 962libc_hidden_def (_IO_unsave_markers)
96aa2d94 963
96aa2d94 964int
9964a145 965_IO_default_pbackfail (FILE *fp, int c)
96aa2d94 966{
00bc5db0 967 if (fp->_IO_read_ptr > fp->_IO_read_base && !_IO_in_backup (fp)
c94a8080 968 && (unsigned char) fp->_IO_read_ptr[-1] == c)
00bc5db0
UD
969 --fp->_IO_read_ptr;
970 else
40a55d20
UD
971 {
972 /* Need to handle a filebuf in write mode (switch to read mode). FIXME!*/
05f732b3 973 if (!_IO_in_backup (fp))
40a55d20 974 {
05f732b3
UD
975 /* We need to keep the invariant that the main get area
976 logically follows the backup area. */
977 if (fp->_IO_read_ptr > fp->_IO_read_base && _IO_have_backup (fp))
978 {
979 if (save_for_backup (fp, fp->_IO_read_ptr))
980 return EOF;
981 }
982 else if (!_IO_have_backup (fp))
983 {
984 /* No backup buffer: allocate one. */
985 /* Use nshort buffer, if unused? (probably not) FIXME */
986 int backup_size = 128;
987 char *bbuf = (char *) malloc (backup_size);
988 if (bbuf == NULL)
989 return EOF;
990 fp->_IO_save_base = bbuf;
991 fp->_IO_save_end = fp->_IO_save_base + backup_size;
992 fp->_IO_backup_base = fp->_IO_save_end;
993 }
994 fp->_IO_read_base = fp->_IO_read_ptr;
40a55d20
UD
995 _IO_switch_to_backup_area (fp);
996 }
997 else if (fp->_IO_read_ptr <= fp->_IO_read_base)
998 {
999 /* Increase size of existing backup buffer. */
9964a145
ZW
1000 size_t new_size;
1001 size_t old_size = fp->_IO_read_end - fp->_IO_read_base;
40a55d20
UD
1002 char *new_buf;
1003 new_size = 2 * old_size;
1004 new_buf = (char *) malloc (new_size);
1005 if (new_buf == NULL)
1006 return EOF;
1007 memcpy (new_buf + (new_size - old_size), fp->_IO_read_base,
1008 old_size);
1009 free (fp->_IO_read_base);
1010 _IO_setg (fp, new_buf, new_buf + (new_size - old_size),
1011 new_buf + new_size);
1012 fp->_IO_backup_base = fp->_IO_read_ptr;
1013 }
00bc5db0
UD
1014
1015 *--fp->_IO_read_ptr = c;
40a55d20 1016 }
00bc5db0 1017 return (unsigned char) c;
96aa2d94 1018}
d18ea0c5 1019libc_hidden_def (_IO_default_pbackfail)
96aa2d94 1020
9964a145
ZW
1021off64_t
1022_IO_default_seek (FILE *fp, off64_t offset, int dir)
96aa2d94
RM
1023{
1024 return _IO_pos_BAD;
1025}
1026
1027int
9964a145 1028_IO_default_stat (FILE *fp, void *st)
96aa2d94
RM
1029{
1030 return EOF;
1031}
1032
9964a145
ZW
1033ssize_t
1034_IO_default_read (FILE *fp, void *data, ssize_t n)
96aa2d94
RM
1035{
1036 return -1;
1037}
1038
9964a145
ZW
1039ssize_t
1040_IO_default_write (FILE *fp, const void *data, ssize_t n)
96aa2d94
RM
1041{
1042 return 0;
1043}
1044
319d719d 1045int
9964a145 1046_IO_default_showmanyc (FILE *fp)
dfd2257a
UD
1047{
1048 return -1;
1049}
1050
1051void
9964a145 1052_IO_default_imbue (FILE *fp, void *locale)
dfd2257a
UD
1053{
1054}
1055
3fc9ca4e 1056_IO_ITER
60d2f8f3 1057_IO_iter_begin (void)
3fc9ca4e 1058{
d18ea0c5 1059 return (_IO_ITER) _IO_list_all;
3fc9ca4e 1060}
1d2b6e0c 1061libc_hidden_def (_IO_iter_begin)
3fc9ca4e
UD
1062
1063_IO_ITER
60d2f8f3 1064_IO_iter_end (void)
3fc9ca4e 1065{
2ca8b1ee 1066 return NULL;
3fc9ca4e 1067}
1d2b6e0c 1068libc_hidden_def (_IO_iter_end)
3fc9ca4e
UD
1069
1070_IO_ITER
9d46370c 1071_IO_iter_next (_IO_ITER iter)
3fc9ca4e 1072{
73c115ed 1073 return iter->_chain;
3fc9ca4e 1074}
1d2b6e0c 1075libc_hidden_def (_IO_iter_next)
3fc9ca4e 1076
9964a145 1077FILE *
9d46370c 1078_IO_iter_file (_IO_ITER iter)
3fc9ca4e 1079{
73c115ed 1080 return iter;
3fc9ca4e 1081}
1d2b6e0c 1082libc_hidden_def (_IO_iter_file)
3fc9ca4e
UD
1083
1084void
60d2f8f3 1085_IO_list_lock (void)
3fc9ca4e 1086{
92cfdd8a 1087#ifdef _IO_MTSAFE_IO
3fc9ca4e 1088 _IO_lock_lock (list_all_lock);
92cfdd8a 1089#endif
3fc9ca4e 1090}
245eab02 1091libc_hidden_def (_IO_list_lock)
3fc9ca4e
UD
1092
1093void
60d2f8f3 1094_IO_list_unlock (void)
3fc9ca4e 1095{
92cfdd8a
AJ
1096#ifdef _IO_MTSAFE_IO
1097 _IO_lock_unlock (list_all_lock);
1098#endif
3fc9ca4e 1099}
245eab02 1100libc_hidden_def (_IO_list_unlock)
3fc9ca4e
UD
1101
1102void
60d2f8f3 1103_IO_list_resetlock (void)
3fc9ca4e 1104{
92cfdd8a 1105#ifdef _IO_MTSAFE_IO
3fc9ca4e 1106 _IO_lock_init (list_all_lock);
92cfdd8a 1107#endif
3fc9ca4e 1108}
245eab02 1109libc_hidden_def (_IO_list_resetlock)
3fc9ca4e 1110
f5bf21a7 1111text_set_element(__libc_atexit, _IO_cleanup);