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