The base/count bounds checking was insufficient, leading to a kernel memory
[dragonfly.git] / contrib / libio / genops.c
1 /* Copyright (C) 1993, 1995, 1997, 1998 Free Software Foundation, Inc.
2    This file is part of the GNU IO Library.
3
4    This library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU General Public License as
6    published by the Free Software Foundation; either version 2, or (at
7    your option) any later version.
8
9    This library is distributed in the hope that it will be useful, but
10    WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this library; see the file COPYING.  If not, write to
16    the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
17    MA 02111-1307, USA.
18
19    As a special exception, if you link this library with files
20    compiled with a GNU compiler to produce an executable, this does
21    not cause the resulting executable to be covered by the GNU General
22    Public License.  This exception does not however invalidate any
23    other reasons why the executable file might be covered by the GNU
24    General Public License.  */
25
26 /* Generic or default I/O operations. */
27
28 #include "libioP.h"
29 #ifdef __STDC__
30 #include <stdlib.h>
31 #endif
32 #include <string.h>
33
34 void
35 _IO_un_link (fp)
36      _IO_FILE *fp;
37 {
38   if (fp->_flags & _IO_LINKED)
39     {
40       _IO_FILE **f;
41       for (f = &_IO_list_all; *f != NULL; f = &(*f)->_chain)
42         {
43           if (*f == fp)
44             {
45               *f = fp->_chain;
46               break;
47             }
48         }
49       fp->_flags &= ~_IO_LINKED;
50     }
51 }
52
53 void
54 _IO_link_in (fp)
55      _IO_FILE *fp;
56 {
57     if ((fp->_flags & _IO_LINKED) == 0)
58       {
59         fp->_flags |= _IO_LINKED;
60         fp->_chain = _IO_list_all;
61         _IO_list_all = fp;
62       }
63 }
64
65 /* Return minimum _pos markers
66    Assumes the current get area is the main get area. */
67 static _IO_size_t _IO_least_marker __P ((_IO_FILE *fp));
68
69 static _IO_size_t
70 _IO_least_marker (fp)
71      _IO_FILE *fp;
72 {
73   _IO_ssize_t least_so_far = fp->_IO_read_end - fp->_IO_read_base;
74   struct _IO_marker *mark;
75   for (mark = fp->_markers; mark != NULL; mark = mark->_next)
76     if (mark->_pos < least_so_far)
77       least_so_far = mark->_pos;
78   return least_so_far;
79 }
80
81 /* Switch current get area from backup buffer to (start of) main get area. */
82
83 void
84 _IO_switch_to_main_get_area (fp)
85      _IO_FILE *fp;
86 {
87   char *tmp;
88   fp->_flags &= ~_IO_IN_BACKUP;
89   /* Swap _IO_read_end and _IO_save_end. */
90   tmp = fp->_IO_read_end;
91   fp->_IO_read_end = fp->_IO_save_end;
92   fp->_IO_save_end= tmp;
93   /* Swap _IO_read_base and _IO_save_base. */
94   tmp = fp->_IO_read_base;
95   fp->_IO_read_base = fp->_IO_save_base;
96   fp->_IO_save_base = tmp;
97
98   fp->_IO_read_ptr = fp->_IO_read_base;
99 }
100
101 /* Switch current get area from main get area to (end of) backup area. */
102
103 void
104 _IO_switch_to_backup_area (fp)
105      _IO_FILE *fp;
106 {
107   char *tmp;
108   fp->_flags |= _IO_IN_BACKUP;
109   /* Swap _IO_read_end and _IO_save_end. */
110   tmp = fp->_IO_read_end;
111   fp->_IO_read_end = fp->_IO_save_end;
112   fp->_IO_save_end = tmp;
113   /* Swap _gbase and _IO_save_base. */
114   tmp = fp->_IO_read_base;
115   fp->_IO_read_base = fp->_IO_save_base;
116   fp->_IO_save_base = tmp;
117
118   fp->_IO_read_ptr = fp->_IO_read_end;
119 }
120
121 int
122 _IO_switch_to_get_mode (fp)
123      _IO_FILE *fp;
124 {
125   if (fp->_IO_write_ptr > fp->_IO_write_base)
126     if (_IO_OVERFLOW (fp, EOF) == EOF)
127       return EOF;
128   if (_IO_in_backup (fp))
129     fp->_IO_read_base = fp->_IO_backup_base;
130   else
131     {
132       fp->_IO_read_base = fp->_IO_buf_base;
133       if (fp->_IO_write_ptr > fp->_IO_read_end)
134         fp->_IO_read_end = fp->_IO_write_ptr;
135     }
136   fp->_IO_read_ptr = fp->_IO_write_ptr;
137
138   fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end = fp->_IO_read_ptr;
139
140   fp->_flags &= ~_IO_CURRENTLY_PUTTING;
141   return 0;
142 }
143
144 void
145 _IO_free_backup_area (fp)
146      _IO_FILE *fp;
147 {
148   if (_IO_in_backup (fp))
149     _IO_switch_to_main_get_area (fp);  /* Just in case. */
150   free (fp->_IO_save_base);
151   fp->_IO_save_base = NULL;
152   fp->_IO_save_end = NULL;
153   fp->_IO_backup_base = NULL;
154 }
155
156 #if 0
157 int
158 _IO_switch_to_put_mode (fp)
159      _IO_FILE *fp;
160 {
161   fp->_IO_write_base = fp->_IO_read_ptr;
162   fp->_IO_write_ptr = fp->_IO_read_ptr;
163   /* Following is wrong if line- or un-buffered? */
164   fp->_IO_write_end = (fp->_flags & _IO_IN_BACKUP
165                        ? fp->_IO_read_end : fp->_IO_buf_end);
166
167   fp->_IO_read_ptr = fp->_IO_read_end;
168   fp->_IO_read_base = fp->_IO_read_end;
169
170   fp->_flags |= _IO_CURRENTLY_PUTTING;
171   return 0;
172 }
173 #endif
174
175 int
176 __overflow (f, ch)
177      _IO_FILE *f;
178      int ch;
179 {
180   return _IO_OVERFLOW (f, ch);
181 }
182
183 static int save_for_backup __P ((_IO_FILE *fp));
184
185      static int
186 save_for_backup (fp)
187      _IO_FILE *fp;
188 {
189   /* Append [_IO_read_base.._IO_read_end] to backup area. */
190   int least_mark = _IO_least_marker (fp);
191   /* needed_size is how much space we need in the backup area. */
192   int needed_size = (fp->_IO_read_end - fp->_IO_read_base) - least_mark;
193   int current_Bsize = fp->_IO_save_end - fp->_IO_save_base;
194   int avail; /* Extra space available for future expansion. */
195   int delta;
196   struct _IO_marker *mark;
197   if (needed_size > current_Bsize)
198     {
199       char *new_buffer;
200       avail = 100;
201       new_buffer = (char *) malloc (avail + needed_size);
202       if (new_buffer == NULL)
203         return EOF;             /* FIXME */
204       if (least_mark < 0)
205         {
206           memcpy (new_buffer + avail,
207                   fp->_IO_save_end + least_mark,
208                   -least_mark);
209           memcpy (new_buffer + avail - least_mark,
210                   fp->_IO_read_base,
211                   fp->_IO_read_end - fp->_IO_read_base);
212         }
213       else
214         memcpy (new_buffer + avail,
215                 fp->_IO_read_base + least_mark,
216                 needed_size);
217       if (fp->_IO_save_base)
218         free (fp->_IO_save_base);
219       fp->_IO_save_base = new_buffer;
220       fp->_IO_save_end = new_buffer + avail + needed_size;
221     }
222   else
223     {
224       avail = current_Bsize - needed_size;
225       if (least_mark < 0)
226         {
227           memmove (fp->_IO_save_base + avail,
228                    fp->_IO_save_end + least_mark,
229                    -least_mark);
230           memcpy (fp->_IO_save_base + avail - least_mark,
231                   fp->_IO_read_base,
232                   fp->_IO_read_end - fp->_IO_read_base);
233         }
234       else if (needed_size > 0)
235         memcpy (fp->_IO_save_base + avail,
236                 fp->_IO_read_base + least_mark,
237                 needed_size);
238     }
239   /* FIXME: Dubious arithmetic if pointers are NULL */
240   fp->_IO_backup_base = fp->_IO_save_base + avail;
241   /* Adjust all the streammarkers. */
242   delta = fp->_IO_read_end - fp->_IO_read_base;
243   for (mark = fp->_markers; mark != NULL; mark = mark->_next)
244     mark->_pos -= delta;
245   return 0;
246 }
247
248 int
249 __underflow (fp)
250      _IO_FILE *fp;
251 {
252   if (_IO_in_put_mode (fp))
253     if (_IO_switch_to_get_mode (fp) == EOF)
254       return EOF;
255   if (fp->_IO_read_ptr < fp->_IO_read_end)
256     return *(unsigned char *) fp->_IO_read_ptr;
257   if (_IO_in_backup (fp))
258     {
259       _IO_switch_to_main_get_area (fp);
260       if (fp->_IO_read_ptr < fp->_IO_read_end)
261         return *(unsigned char *) fp->_IO_read_ptr;
262     }
263   if (_IO_have_markers (fp))
264     {
265       if (save_for_backup (fp))
266         return EOF;
267     }
268   else if (_IO_have_backup (fp))
269     _IO_free_backup_area (fp);
270   return _IO_UNDERFLOW (fp);
271 }
272
273 int
274 __uflow (fp)
275      _IO_FILE *fp;
276 {
277   if (_IO_in_put_mode (fp))
278     if (_IO_switch_to_get_mode (fp) == EOF)
279       return EOF;
280   if (fp->_IO_read_ptr < fp->_IO_read_end)
281     return *(unsigned char *) fp->_IO_read_ptr++;
282   if (_IO_in_backup (fp))
283     {
284       _IO_switch_to_main_get_area (fp);
285       if (fp->_IO_read_ptr < fp->_IO_read_end)
286         return *(unsigned char *) fp->_IO_read_ptr++;
287     }
288   if (_IO_have_markers (fp))
289     {
290       if (save_for_backup (fp))
291         return EOF;
292     }
293   else if (_IO_have_backup (fp))
294     _IO_free_backup_area (fp);
295   return _IO_UFLOW (fp);
296 }
297
298 void
299 _IO_setb (f, b, eb, a)
300      _IO_FILE *f;
301       char *b;
302      char *eb;
303      int a;
304 {
305   if (f->_IO_buf_base && !(f->_flags & _IO_USER_BUF))
306     FREE_BUF (f->_IO_buf_base, _IO_blen (f));
307   f->_IO_buf_base = b;
308   f->_IO_buf_end = eb;
309   if (a)
310     f->_flags &= ~_IO_USER_BUF;
311   else
312     f->_flags |= _IO_USER_BUF;
313 }
314
315 void
316 _IO_doallocbuf (fp)
317      _IO_FILE *fp;
318 {
319   if (fp->_IO_buf_base)
320     return;
321   if (!(fp->_flags & _IO_UNBUFFERED))
322     if (_IO_DOALLOCATE (fp) != EOF)
323       return;
324   _IO_setb (fp, fp->_shortbuf, fp->_shortbuf+1, 0);
325 }
326
327 int
328 _IO_default_underflow (fp)
329      _IO_FILE *fp;
330 {
331   return EOF;
332 }
333
334 int
335 _IO_default_uflow (fp)
336      _IO_FILE *fp;
337 {
338   int ch = _IO_UNDERFLOW (fp);
339   if (ch == EOF)
340     return EOF;
341   return *(unsigned char *) fp->_IO_read_ptr++;
342 }
343
344 _IO_size_t
345 _IO_default_xsputn (f, data, n)
346      _IO_FILE *f;
347      const void *data;
348      _IO_size_t n;
349 {
350   const char *s = (char *) data;
351   _IO_size_t more = n;
352   if (more <= 0)
353     return 0;
354   for (;;)
355     {
356       /* Space available. */
357       _IO_ssize_t count = f->_IO_write_end - f->_IO_write_ptr;
358       if (count > 0)
359         {
360           if ((_IO_size_t) count > more)
361             count = more;
362           if (count > 20)
363             {
364               memcpy (f->_IO_write_ptr, s, count);
365               s += count;
366               f->_IO_write_ptr += count;
367             }
368           else if (count <= 0)
369             count = 0;
370           else
371             {
372               char *p = f->_IO_write_ptr;
373               _IO_ssize_t i;
374               for (i = count; --i >= 0; )
375                 *p++ = *s++;
376               f->_IO_write_ptr = p;
377             }
378           more -= count;
379         }
380       if (more == 0 || __overflow (f, (unsigned char) *s++) == EOF)
381         break;
382       more--;
383     }
384   return n - more;
385 }
386
387 _IO_size_t
388 _IO_sgetn (fp, data, n)
389      _IO_FILE *fp;
390      void *data;
391      _IO_size_t n;
392 {
393   /* FIXME handle putback buffer here! */
394   return _IO_XSGETN (fp, data, n);
395 }
396
397 _IO_size_t
398 _IO_default_xsgetn (fp, data, n)
399      _IO_FILE *fp;
400      void *data;
401      _IO_size_t n;
402 {
403   _IO_size_t more = n;
404   char *s = (char*) data;
405   for (;;)
406     {
407       /* Data available. */
408       _IO_ssize_t count = fp->_IO_read_end - fp->_IO_read_ptr;
409       if (count > 0)
410         {
411           if ((_IO_size_t) count > more)
412             count = more;
413           if (count > 20)
414             {
415               memcpy (s, fp->_IO_read_ptr, count);
416               s += count;
417               fp->_IO_read_ptr += count;
418             }
419           else if (count <= 0)
420             count = 0;
421           else
422             {
423               char *p = fp->_IO_read_ptr;
424               int i = (int) count;
425               while (--i >= 0)
426                 *s++ = *p++;
427               fp->_IO_read_ptr = p;
428             }
429             more -= count;
430         }
431       if (more == 0 || __underflow (fp) == EOF)
432         break;
433     }
434   return n - more;
435 }
436
437 #if 0
438 /* Seems not to be needed. --drepper */
439 int
440 _IO_sync (fp)
441      _IO_FILE *fp;
442 {
443   return 0;
444 }
445 #endif
446
447 _IO_FILE *
448 _IO_default_setbuf (fp, p, len)
449      _IO_FILE *fp;
450      char *p;
451      _IO_ssize_t len;
452 {
453     if (_IO_SYNC (fp) == EOF)
454         return NULL;
455     if (p == NULL || len == 0)
456       {
457         fp->_flags |= _IO_UNBUFFERED;
458         _IO_setb (fp, fp->_shortbuf, fp->_shortbuf+1, 0);
459       }
460     else
461       {
462         fp->_flags &= ~_IO_UNBUFFERED;
463         _IO_setb (fp, p, p+len, 0);
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
470 _IO_pos_t
471 _IO_default_seekpos (fp, pos, mode)
472      _IO_FILE *fp;
473      _IO_pos_t pos;
474      int mode;
475 {
476   return _IO_SEEKOFF (fp, _IO_pos_as_off (pos), 0, mode);
477 }
478
479 int
480 _IO_default_doallocate (fp)
481      _IO_FILE *fp;
482 {
483   char *buf;
484
485   ALLOC_BUF (buf, _IO_BUFSIZ, EOF);
486   _IO_setb (fp, buf, buf+_IO_BUFSIZ, 1);
487   return 1;
488 }
489
490 void
491 _IO_init (fp, flags)
492      _IO_FILE *fp;
493      int flags;
494 {
495   fp->_flags = _IO_MAGIC|flags;
496   fp->_IO_buf_base = NULL;
497   fp->_IO_buf_end = NULL;
498   fp->_IO_read_base = NULL;
499   fp->_IO_read_ptr = NULL;
500   fp->_IO_read_end = NULL;
501   fp->_IO_write_base = NULL;
502   fp->_IO_write_ptr = NULL;
503   fp->_IO_write_end = NULL;
504   fp->_chain = NULL; /* Not necessary. */
505
506   fp->_IO_save_base = NULL;
507   fp->_IO_backup_base = NULL;
508   fp->_IO_save_end = NULL;
509   fp->_markers = NULL;
510   fp->_cur_column = 0;
511 #ifdef _IO_MTSAFE_IO
512   _IO_lock_init (*fp->_lock);
513 #endif
514 }
515
516 int
517 _IO_default_sync (fp)
518      _IO_FILE *fp;
519 {
520   return 0;
521 }
522
523 /* The way the C++ classes are mapped into the C functions in the
524    current implementation, this function can get called twice! */
525
526 void
527 _IO_default_finish (fp, dummy)
528      _IO_FILE *fp;
529      int dummy;
530 {
531   struct _IO_marker *mark;
532   if (fp->_IO_buf_base && !(fp->_flags & _IO_USER_BUF))
533     {
534       FREE_BUF (fp->_IO_buf_base, _IO_blen (fp));
535       fp->_IO_buf_base = fp->_IO_buf_end = NULL;
536     }
537
538   for (mark = fp->_markers; mark != NULL; mark = mark->_next)
539     mark->_sbuf = NULL;
540
541   if (fp->_IO_save_base)
542     {
543       free (fp->_IO_save_base);
544       fp->_IO_save_base = NULL;
545     }
546
547 #ifdef _IO_MTSAFE_IO
548   _IO_lock_fini (*fp->_lock);
549 #endif
550
551   _IO_un_link (fp);
552 }
553
554 _IO_pos_t
555 _IO_default_seekoff (fp, offset, dir, mode)
556      _IO_FILE *fp;
557      _IO_off_t offset;
558      int dir;
559      int mode;
560 {
561     return _IO_pos_BAD;
562 }
563
564 int
565 _IO_sputbackc (fp, c)
566      _IO_FILE *fp;
567      int c;
568 {
569   int result;
570
571   if (fp->_IO_read_ptr > fp->_IO_read_base
572       && (unsigned char)fp->_IO_read_ptr[-1] == (unsigned char)c)
573     {
574       fp->_IO_read_ptr--;
575       result = (unsigned char) c;
576     }
577   else
578     result = _IO_PBACKFAIL (fp, c);
579
580   if (result != EOF)
581     fp->_flags &= ~_IO_EOF_SEEN;
582
583   return result;
584 }
585
586 int
587 _IO_sungetc (fp)
588      _IO_FILE *fp;
589 {
590   int result;
591
592   if (fp->_IO_read_ptr > fp->_IO_read_base)
593     {
594       fp->_IO_read_ptr--;
595       result = (unsigned char) *fp->_IO_read_ptr;
596     }
597   else
598     result = _IO_PBACKFAIL (fp, EOF);
599
600   if (result != EOF)
601     fp->_flags &= ~_IO_EOF_SEEN;
602
603   return result;
604 }
605
606 #if 0 /* Work in progress */
607 /* Seems not to be needed.  */
608 #if 0
609 void
610 _IO_set_column (fp, c)
611      _IO_FILE *fp;
612      int c;
613 {
614   if (c == -1)
615     fp->_column = -1;
616   else
617     fp->_column = c - (fp->_IO_write_ptr - fp->_IO_write_base);
618 }
619 #else
620 int
621 _IO_set_column (fp, i)
622      _IO_FILE *fp;
623      int i;
624 {
625   fp->_cur_column = i + 1;
626   return 0;
627 }
628 #endif
629 #endif
630
631
632 unsigned
633 _IO_adjust_column (start, line, count)
634      unsigned start;
635      const char *line;
636      int count;
637 {
638   const char *ptr = line + count;
639   while (ptr > line)
640     if (*--ptr == '\n')
641       return line + count - ptr - 1;
642   return start + count;
643 }
644
645 #if 0
646 /* Seems not to be needed. --drepper */
647 int
648 _IO_get_column (fp)
649      _IO_FILE *fp;
650 {
651   if (fp->_cur_column)
652     return _IO_adjust_column (fp->_cur_column - 1,
653                               fp->_IO_write_base,
654                               fp->_IO_write_ptr - fp->_IO_write_base);
655   return -1;
656 }
657 #endif
658
659 int
660 _IO_flush_all ()
661 {
662   int result = 0;
663   _IO_FILE *fp;
664   for (fp = _IO_list_all; fp != NULL; fp = fp->_chain)
665     if (fp->_IO_write_ptr > fp->_IO_write_base
666         && _IO_OVERFLOW (fp, EOF) == EOF)
667       result = EOF;
668   return result;
669 }
670
671 void
672 _IO_flush_all_linebuffered ()
673 {
674   _IO_FILE *fp;
675   for (fp = _IO_list_all; fp != NULL; fp = fp->_chain)
676     if ((fp->_flags & _IO_NO_WRITES) == 0 && fp->_flags & _IO_LINE_BUF)
677       _IO_OVERFLOW (fp, EOF);
678 }
679
680 static void _IO_unbuffer_all __P ((void));
681
682 static void
683 _IO_unbuffer_all ()
684 {
685   _IO_FILE *fp;
686   for (fp = _IO_list_all; fp != NULL; fp = fp->_chain)
687     if (! (fp->_flags & _IO_UNBUFFERED))
688       _IO_SETBUF (fp, NULL, 0);
689 }
690
691 void
692 _IO_cleanup ()
693 {
694   _IO_flush_all ();
695
696   /* We currently don't have a reliable mechanism for making sure that
697      C++ static destructors are executed in the correct order.
698      So it is possible that other static destructors might want to
699      write to cout - and they're supposed to be able to do so.
700
701      The following will make the standard streambufs be unbuffered,
702      which forces any output from late destructors to be written out. */
703   _IO_unbuffer_all ();
704 }
705
706 void
707 _IO_init_marker (marker, fp)
708      struct _IO_marker *marker;
709      _IO_FILE *fp;
710 {
711   marker->_sbuf = fp;
712   if (_IO_in_put_mode (fp))
713     _IO_switch_to_get_mode (fp);
714   if (_IO_in_backup (fp))
715     marker->_pos = fp->_IO_read_ptr - fp->_IO_read_end;
716   else
717     marker->_pos = fp->_IO_read_ptr - fp->_IO_read_base;
718
719   /* Should perhaps sort the chain? */
720   marker->_next = fp->_markers;
721   fp->_markers = marker;
722 }
723
724 void
725 _IO_remove_marker (marker)
726      struct _IO_marker *marker;
727 {
728   /* Unlink from sb's chain. */
729   struct _IO_marker **ptr = &marker->_sbuf->_markers;
730   for (; ; ptr = &(*ptr)->_next)
731     {
732       if (*ptr == NULL)
733         break;
734       else if (*ptr == marker)
735         {
736           *ptr = marker->_next;
737           return;
738         }
739     }
740 #if 0
741     if _sbuf has a backup area that is no longer needed, should we delete
742     it now, or wait until the next underflow?
743 #endif
744 }
745
746 #define BAD_DELTA EOF
747
748 int
749 _IO_marker_difference (mark1, mark2)
750      struct _IO_marker *mark1;
751      struct _IO_marker *mark2;
752 {
753   return mark1->_pos - mark2->_pos;
754 }
755
756 /* Return difference between MARK and current position of MARK's stream. */
757 int
758 _IO_marker_delta (mark)
759      struct _IO_marker *mark;
760 {
761   int cur_pos;
762   if (mark->_sbuf == NULL)
763     return BAD_DELTA;
764   if (_IO_in_backup (mark->_sbuf))
765     cur_pos = mark->_sbuf->_IO_read_ptr - mark->_sbuf->_IO_read_end;
766   else
767     cur_pos = mark->_sbuf->_IO_read_ptr - mark->_sbuf->_IO_read_base;
768   return mark->_pos - cur_pos;
769 }
770
771 int
772 _IO_seekmark (fp, mark, delta)
773      _IO_FILE *fp;
774      struct _IO_marker *mark;
775      int delta;
776 {
777   if (mark->_sbuf != fp)
778     return EOF;
779  if (mark->_pos >= 0)
780     {
781       if (_IO_in_backup (fp))
782         _IO_switch_to_main_get_area (fp);
783       fp->_IO_read_ptr = fp->_IO_read_base + mark->_pos;
784     }
785   else
786     {
787       if (!_IO_in_backup (fp))
788         _IO_switch_to_backup_area (fp);
789       fp->_IO_read_ptr = fp->_IO_read_end + mark->_pos;
790     }
791   return 0;
792 }
793
794 void
795 _IO_unsave_markers (fp)
796      _IO_FILE *fp;
797 {
798   struct _IO_marker *mark = fp->_markers;
799   if (mark)
800     {
801 #ifdef TODO
802       streampos offset = seekoff (0, ios::cur, ios::in);
803       if (offset != EOF)
804         {
805           offset += eGptr () - Gbase ();
806           for ( ; mark != NULL; mark = mark->_next)
807             mark->set_streampos (mark->_pos + offset);
808         }
809     else
810       {
811         for ( ; mark != NULL; mark = mark->_next)
812           mark->set_streampos (EOF);
813       }
814 #endif
815       fp->_markers = 0;
816     }
817
818   if (_IO_have_backup (fp))
819     _IO_free_backup_area (fp);
820 }
821
822 #if 0
823 /* Seems not to be needed. --drepper */
824 int
825 _IO_nobackup_pbackfail (fp, c)
826      _IO_FILE *fp;
827      int c;
828 {
829   if (fp->_IO_read_ptr > fp->_IO_read_base)
830         fp->_IO_read_ptr--;
831   if (c != EOF && *fp->_IO_read_ptr != c)
832       *fp->_IO_read_ptr = c;
833   return (unsigned char) c;
834 }
835 #endif
836
837 int
838 _IO_default_pbackfail (fp, c)
839      _IO_FILE *fp;
840      int c;
841 {
842   if (fp->_IO_read_ptr <= fp->_IO_read_base)
843     {
844       /* Need to handle a filebuf in write mode (switch to read mode). FIXME!*/
845       if (_IO_have_backup (fp) && !_IO_in_backup (fp))
846         _IO_switch_to_backup_area (fp);
847
848       if (!_IO_have_backup (fp))
849         {
850           /* No backup buffer: allocate one. */
851           /* Use nshort buffer, if unused? (probably not)  FIXME */
852           int backup_size = 128;
853           char *bbuf = (char *) malloc (backup_size);
854           if (bbuf == NULL)
855             return EOF;
856           fp->_IO_save_base = bbuf;
857           fp->_IO_save_end = fp->_IO_save_base + backup_size;
858           fp->_IO_backup_base = fp->_IO_save_end;
859           _IO_switch_to_backup_area (fp);
860         }
861       else if (fp->_IO_read_ptr <= fp->_IO_read_base)
862         {
863           /* Increase size of existing backup buffer. */
864           _IO_size_t new_size;
865           _IO_size_t old_size = fp->_IO_read_end - fp->_IO_read_base;
866           char *new_buf;
867           new_size = 2 * old_size;
868           new_buf = (char *) malloc (new_size);
869           if (new_buf == NULL)
870             return EOF;
871           memcpy (new_buf + (new_size - old_size), fp->_IO_read_base,
872                   old_size);
873           free (fp->_IO_read_base);
874           _IO_setg (fp, new_buf, new_buf + (new_size - old_size),
875                     new_buf + new_size);
876           fp->_IO_backup_base = fp->_IO_read_ptr;
877         }
878     }
879   --fp->_IO_read_ptr;
880   if (c != EOF && *fp->_IO_read_ptr != c)
881     *fp->_IO_read_ptr = c;
882   return (unsigned char) *fp->_IO_read_ptr;
883 }
884
885 _IO_pos_t
886 _IO_default_seek (fp, offset, dir)
887      _IO_FILE *fp;
888      _IO_off_t offset;
889      int dir;
890 {
891   return _IO_pos_BAD;
892 }
893
894 int
895 _IO_default_stat (fp, st)
896      _IO_FILE *fp;
897      void* st;
898 {
899   return EOF;
900 }
901
902 _IO_ssize_t
903 _IO_default_read (fp, data, n)
904      _IO_FILE* fp;
905      void *data;
906      _IO_ssize_t n;
907 {
908   return -1;
909 }
910
911 _IO_ssize_t
912 _IO_default_write (fp, data, n)
913      _IO_FILE *fp;
914      const void *data;
915      _IO_ssize_t n;
916 {
917   return 0;
918 }
919
920
921 #ifdef TODO
922 #if defined(linux)
923 #define IO_CLEANUP ;
924 #endif
925
926 #ifdef IO_CLEANUP
927   IO_CLEANUP
928 #else
929 struct __io_defs {
930     __io_defs() { }
931     ~__io_defs() { _IO_cleanup (); }
932 };
933 __io_defs io_defs__;
934 #endif
935
936 #endif /* TODO */
937
938 #ifdef weak_alias
939 weak_alias (_IO_cleanup, _cleanup)
940 #elif defined(_G_STDIO_USES_LIBIO) && defined(_G_HAVE_WEAK_SYMBOL)
941 void _cleanup () __attribute__ ((weak, alias ("_IO_cleanup")));
942 #endif
943
944 #ifdef text_set_element
945 text_set_element(__libc_atexit, _cleanup);
946 #endif