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