1 /* Copyright (C) 1993-2013 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Written by Per Bothner <bothner@cygnus.com>.
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.
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.
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/>.
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. */
28 /* This is a compatibility file. If we don't build the libc with
29 versioning don't compile this file. */
30 #include <shlib-compat.h>
31 #if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
34 # define _POSIX_SOURCE
36 #define _IO_USE_OLD_IO_FILE
39 #include <sys/types.h>
48 # define __set_errno(Val) errno = (Val)
53 # define open(Name, Flags, Prot) __open (Name, Flags, Prot)
54 # define close(FD) __close (FD)
55 # define lseek(FD, Offset, Whence) __lseek (FD, Offset, Whence)
56 # define read(FD, Buf, NBytes) __read (FD, Buf, NBytes)
57 # define write(FD, Buf, NBytes) __write (FD, Buf, NBytes)
60 /* An fstream can be in at most one of put mode, get mode, or putback mode.
61 Putback mode is a variant of get mode.
63 In a filebuf, there is only one current position, instead of two
64 separate get and put pointers. In get mode, the current position
65 is that of gptr(); in put mode that of pptr().
67 The position in the buffer that corresponds to the position
68 in external file system is normally _IO_read_end, except in putback
69 mode, when it is _IO_save_end.
70 If the field _fb._offset is >= 0, it gives the offset in
71 the file as a whole corresponding to eGptr(). (?)
74 If a filebuf is in put mode, then all of _IO_read_ptr, _IO_read_end,
75 and _IO_read_base are equal to each other. These are usually equal
76 to _IO_buf_base, though not necessarily if we have switched from
77 get mode to put mode. (The reason is to maintain the invariant
78 that _IO_read_end corresponds to the external file position.)
79 _IO_write_base is non-NULL and usually equal to _IO_buf_base.
80 We also have _IO_write_end == _IO_buf_end, but only in fully buffered mode.
81 The un-flushed character are those between _IO_write_base and _IO_write_ptr.
84 If a filebuf is in get or putback mode, eback() != egptr().
85 In get mode, the unread characters are between gptr() and egptr().
86 The OS file position corresponds to that of egptr().
89 Putback mode is used to remember "excess" characters that have
90 been sputbackc'd in a separate putback buffer.
91 In putback mode, the get buffer points to the special putback buffer.
92 The unread characters are the characters between gptr() and egptr()
93 in the putback buffer, as well as the area between save_gptr()
94 and save_egptr(), which point into the original reserve buffer.
95 (The pointers save_gptr() and save_egptr() are the values
96 of gptr() and egptr() at the time putback mode was entered.)
97 The OS position corresponds to that of save_egptr().
100 During line buffered output, _IO_write_base==base() && epptr()==base().
101 However, ptr() may be anywhere between base() and ebuf().
102 This forces a call to filebuf::overflow(int C) on every put.
103 If there is more space in the buffer, and C is not a '\n',
104 then C is inserted, and pptr() incremented.
107 If a filebuf is unbuffered(), the _shortbuf[1] is used as the buffer.
110 #define CLOSED_FILEBUF_FLAGS \
111 (_IO_IS_FILEBUF+_IO_NO_READS+_IO_NO_WRITES+_IO_TIED_PUT_GET)
115 attribute_compat_text_section
116 _IO_old_file_init (fp)
117 struct _IO_FILE_plus *fp;
119 /* POSIX.1 allows another file handle to be used to change the position
120 of our file descriptor. Hence we actually don't know the actual
121 position before we do the first fseek (and until a following fflush). */
122 fp->file._old_offset = _IO_pos_BAD;
123 fp->file._IO_file_flags |= CLOSED_FILEBUF_FLAGS;
126 fp->file._vtable_offset = ((int) sizeof (struct _IO_FILE)
127 - (int) sizeof (struct _IO_FILE_complete));
128 fp->file._fileno = -1;
130 #if defined SHARED && defined _LIBC
131 if (__builtin_expect (&_IO_stdin_used != NULL, 1)
132 || (fp != (struct _IO_FILE_plus *) _IO_stdin
133 && fp != (struct _IO_FILE_plus *) _IO_stdout
134 && fp != (struct _IO_FILE_plus *) _IO_stderr))
135 /* The object is dynamically allocated and large enough. Initialize
136 the _mode element as well. */
137 ((struct _IO_FILE_complete *) fp)->_mode = -1;
142 attribute_compat_text_section
143 _IO_old_file_close_it (fp)
146 int write_status, close_status;
147 if (!_IO_file_is_open (fp))
150 write_status = _IO_old_do_flush (fp);
152 _IO_unsave_markers (fp);
154 close_status = ((fp->_flags2 & _IO_FLAGS2_NOCLOSE) == 0
155 ? _IO_SYSCLOSE (fp) : 0);
158 _IO_setb (fp, NULL, NULL, 0);
159 _IO_setg (fp, NULL, NULL, NULL);
160 _IO_setp (fp, NULL, NULL);
162 _IO_un_link ((struct _IO_FILE_plus *) fp);
163 fp->_flags = _IO_MAGIC|CLOSED_FILEBUF_FLAGS;
165 fp->_old_offset = _IO_pos_BAD;
167 return close_status ? close_status : write_status;
171 attribute_compat_text_section
172 _IO_old_file_finish (fp, dummy)
176 if (_IO_file_is_open (fp))
178 _IO_old_do_flush (fp);
179 if (!(fp->_flags & _IO_DELETE_DONT_CLOSE))
182 _IO_default_finish (fp, 0);
186 attribute_compat_text_section
187 _IO_old_file_fopen (fp, filename, mode)
189 const char *filename;
192 int oflags = 0, omode;
193 int read_write, fdesc;
195 if (_IO_file_is_open (fp))
201 read_write = _IO_NO_WRITES;
205 oflags = O_CREAT|O_TRUNC;
206 read_write = _IO_NO_READS;
210 oflags = O_CREAT|O_APPEND;
211 read_write = _IO_NO_READS|_IO_IS_APPENDING;
214 __set_errno (EINVAL);
217 if (mode[0] == '+' || (mode[0] == 'b' && mode[1] == '+'))
220 read_write &= _IO_IS_APPENDING;
222 fdesc = open (filename, omode|oflags, oprot);
226 _IO_mask_flags (fp, read_write,_IO_NO_READS+_IO_NO_WRITES+_IO_IS_APPENDING);
227 if (read_write & _IO_IS_APPENDING)
228 if (_IO_SEEKOFF (fp, (_IO_off_t)0, _IO_seek_end, _IOS_INPUT|_IOS_OUTPUT)
229 == _IO_pos_BAD && errno != ESPIPE)
231 _IO_link_in ((struct _IO_FILE_plus *) fp);
236 attribute_compat_text_section
237 _IO_old_file_attach (fp, fd)
241 if (_IO_file_is_open (fp))
244 fp->_flags &= ~(_IO_NO_READS+_IO_NO_WRITES);
245 fp->_flags |= _IO_DELETE_DONT_CLOSE;
246 /* Get the current position of the file. */
247 /* We have to do that since that may be junk. */
248 fp->_old_offset = _IO_pos_BAD;
249 if (_IO_SEEKOFF (fp, (_IO_off_t)0, _IO_seek_cur, _IOS_INPUT|_IOS_OUTPUT)
250 == _IO_pos_BAD && errno != ESPIPE)
256 attribute_compat_text_section
257 _IO_old_file_setbuf (fp, p, len)
262 if (_IO_default_setbuf (fp, p, len) == NULL)
265 fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end
267 _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
272 static int old_do_write (_IO_FILE *, const char *, _IO_size_t);
274 /* Write TO_DO bytes from DATA to FP.
275 Then mark FP as having empty buffers. */
278 attribute_compat_text_section
279 _IO_old_do_write (fp, data, to_do)
284 return (to_do == 0 || (_IO_size_t) old_do_write (fp, data, to_do) == to_do)
289 attribute_compat_text_section
290 old_do_write (fp, data, to_do)
296 if (fp->_flags & _IO_IS_APPENDING)
297 /* On a system without a proper O_APPEND implementation,
298 you would need to sys_seek(0, SEEK_END) here, but is
299 not needed nor desirable for Unix- or Posix-like systems.
300 Instead, just indicate that offset (before and after) is
302 fp->_old_offset = _IO_pos_BAD;
303 else if (fp->_IO_read_end != fp->_IO_write_base)
306 = _IO_SYSSEEK (fp, fp->_IO_write_base - fp->_IO_read_end, 1);
307 if (new_pos == _IO_pos_BAD)
309 fp->_old_offset = new_pos;
311 count = _IO_SYSWRITE (fp, data, to_do);
312 if (fp->_cur_column && count)
313 fp->_cur_column = _IO_adjust_column (fp->_cur_column - 1, data, count) + 1;
314 _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
315 fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_buf_base;
316 fp->_IO_write_end = ((fp->_flags & (_IO_LINE_BUF+_IO_UNBUFFERED))
317 ? fp->_IO_buf_base : fp->_IO_buf_end);
322 attribute_compat_text_section
323 _IO_old_file_underflow (fp)
328 /* SysV does not make this test; take it out for compatibility */
329 if (fp->_flags & _IO_EOF_SEEN)
333 if (fp->_flags & _IO_NO_READS)
335 fp->_flags |= _IO_ERR_SEEN;
339 if (fp->_IO_read_ptr < fp->_IO_read_end)
340 return *(unsigned char *) fp->_IO_read_ptr;
342 if (fp->_IO_buf_base == NULL)
344 /* Maybe we already have a push back pointer. */
345 if (fp->_IO_save_base != NULL)
347 free (fp->_IO_save_base);
348 fp->_flags &= ~_IO_IN_BACKUP;
353 /* Flush all line buffered files before reading. */
354 /* FIXME This can/should be moved to genops ?? */
355 if (fp->_flags & (_IO_LINE_BUF|_IO_UNBUFFERED))
356 _IO_flush_all_linebuffered ();
358 _IO_switch_to_get_mode (fp);
360 /* This is very tricky. We have to adjust those
361 pointers before we call _IO_SYSREAD () since
362 we may longjump () out while waiting for
363 input. Those pointers may be screwed up. H.J. */
364 fp->_IO_read_base = fp->_IO_read_ptr = fp->_IO_buf_base;
365 fp->_IO_read_end = fp->_IO_buf_base;
366 fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end
369 count = _IO_SYSREAD (fp, fp->_IO_buf_base,
370 fp->_IO_buf_end - fp->_IO_buf_base);
374 fp->_flags |= _IO_EOF_SEEN;
376 fp->_flags |= _IO_ERR_SEEN, count = 0;
378 fp->_IO_read_end += count;
381 if (fp->_old_offset != _IO_pos_BAD)
382 _IO_pos_adjust (fp->_old_offset, count);
383 return *(unsigned char *) fp->_IO_read_ptr;
387 attribute_compat_text_section
388 _IO_old_file_overflow (f, ch)
392 if (f->_flags & _IO_NO_WRITES) /* SET ERROR */
394 f->_flags |= _IO_ERR_SEEN;
398 /* If currently reading or no buffer allocated. */
399 if ((f->_flags & _IO_CURRENTLY_PUTTING) == 0)
401 /* Allocate a buffer if needed. */
402 if (f->_IO_write_base == 0)
405 _IO_setg (f, f->_IO_buf_base, f->_IO_buf_base, f->_IO_buf_base);
407 /* Otherwise must be currently reading.
408 If _IO_read_ptr (and hence also _IO_read_end) is at the buffer end,
409 logically slide the buffer forwards one block (by setting the
410 read pointers to all point at the beginning of the block). This
411 makes room for subsequent output.
412 Otherwise, set the read pointers to _IO_read_end (leaving that
413 alone, so it can continue to correspond to the external position). */
414 if (f->_IO_read_ptr == f->_IO_buf_end)
415 f->_IO_read_end = f->_IO_read_ptr = f->_IO_buf_base;
416 f->_IO_write_ptr = f->_IO_read_ptr;
417 f->_IO_write_base = f->_IO_write_ptr;
418 f->_IO_write_end = f->_IO_buf_end;
419 f->_IO_read_base = f->_IO_read_ptr = f->_IO_read_end;
421 if (f->_flags & (_IO_LINE_BUF+_IO_UNBUFFERED))
422 f->_IO_write_end = f->_IO_write_ptr;
423 f->_flags |= _IO_CURRENTLY_PUTTING;
426 return _IO_old_do_flush (f);
427 if (f->_IO_write_ptr == f->_IO_buf_end ) /* Buffer is really full */
428 if (_IO_old_do_flush (f) == EOF)
430 *f->_IO_write_ptr++ = ch;
431 if ((f->_flags & _IO_UNBUFFERED)
432 || ((f->_flags & _IO_LINE_BUF) && ch == '\n'))
433 if (_IO_old_do_flush (f) == EOF)
435 return (unsigned char) ch;
439 attribute_compat_text_section
440 _IO_old_file_sync (fp)
446 /* char* ptr = cur_ptr(); */
447 if (fp->_IO_write_ptr > fp->_IO_write_base)
448 if (_IO_old_do_flush(fp)) return EOF;
449 delta = fp->_IO_read_ptr - fp->_IO_read_end;
453 if (_IO_in_backup (fp))
454 delta -= eGptr () - Gbase ();
456 _IO_off_t new_pos = _IO_SYSSEEK (fp, delta, 1);
457 if (new_pos != (_IO_off_t) EOF)
458 fp->_IO_read_end = fp->_IO_read_ptr;
460 else if (errno == ESPIPE)
461 ; /* Ignore error from unseekable devices. */
467 fp->_old_offset = _IO_pos_BAD;
468 /* FIXME: Cleanup - can this be shared? */
469 /* setg(base(), ptr, ptr); */
474 attribute_compat_text_section
475 _IO_old_file_seekoff (fp, offset, dir, mode)
482 _IO_off64_t delta, new_offset;
484 /* POSIX.1 8.2.3.7 says that after a call the fflush() the file
485 offset of the underlying file must be exact. */
486 int must_be_exact = (fp->_IO_read_base == fp->_IO_read_end
487 && fp->_IO_write_base == fp->_IO_write_ptr);
490 dir = _IO_seek_cur, offset = 0; /* Don't move any pointers. */
492 /* Flush unwritten characters.
493 (This may do an unneeded write if we seek within the buffer.
494 But to be able to switch to reading, we would need to set
495 egptr to pptr. That can't be done in the current design,
496 which assumes file_ptr() is eGptr. Anyway, since we probably
497 end up flushing when we close(), it doesn't make much difference.)
498 FIXME: simulate mem-mapped files. */
500 if (fp->_IO_write_ptr > fp->_IO_write_base || _IO_in_put_mode (fp))
501 if (_IO_switch_to_get_mode (fp))
504 if (fp->_IO_buf_base == NULL)
506 /* It could be that we already have a pushback buffer. */
507 if (fp->_IO_read_base != NULL)
509 free (fp->_IO_read_base);
510 fp->_flags &= ~_IO_IN_BACKUP;
513 _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
514 _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
520 /* Adjust for read-ahead (bytes is buffer). */
521 offset -= fp->_IO_read_end - fp->_IO_read_ptr;
522 if (fp->_old_offset == _IO_pos_BAD)
524 /* Make offset absolute, assuming current pointer is file_ptr(). */
525 offset += fp->_old_offset;
534 if (_IO_SYSSTAT (fp, &st) == 0 && S_ISREG (st.st_mode))
536 offset += st.st_size;
543 /* At this point, dir==_IO_seek_set. */
545 /* If we are only interested in the current position we've found it now. */
549 /* If destination is within current buffer, optimize: */
550 if (fp->_old_offset != _IO_pos_BAD && fp->_IO_read_base != NULL
551 && !_IO_in_backup (fp))
553 /* Offset relative to start of main get area. */
554 _IO_off_t rel_offset = (offset - fp->_old_offset
555 + (fp->_IO_read_end - fp->_IO_read_base));
559 if (_IO_in_backup (fp))
560 _IO_switch_to_main_get_area (fp);
562 if (rel_offset <= fp->_IO_read_end - fp->_IO_read_base)
564 _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base + rel_offset,
566 _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
568 _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
573 /* If we have streammarkers, seek forward by reading ahead. */
574 if (_IO_have_markers (fp))
576 int to_skip = rel_offset
577 - (fp->_IO_read_ptr - fp->_IO_read_base);
578 if (ignore (to_skip) != to_skip)
580 _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
586 if (rel_offset < 0 && rel_offset >= Bbase () - Bptr ())
588 if (!_IO_in_backup (fp))
589 _IO_switch_to_backup_area (fp);
590 gbump (fp->_IO_read_end + rel_offset - fp->_IO_read_ptr);
591 _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
598 _IO_unsave_markers (fp);
601 if (fp->_flags & _IO_NO_READS)
604 /* Try to seek to a block boundary, to improve kernel page management. */
605 new_offset = offset & ~(fp->_IO_buf_end - fp->_IO_buf_base - 1);
606 delta = offset - new_offset;
607 if (delta > fp->_IO_buf_end - fp->_IO_buf_base)
612 result = _IO_SYSSEEK (fp, new_offset, 0);
619 count = _IO_SYSREAD (fp, fp->_IO_buf_base,
621 ? delta : fp->_IO_buf_end - fp->_IO_buf_base));
624 /* We weren't allowed to read, but try to seek the remainder. */
625 offset = count == EOF ? delta : delta-count;
630 _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base + delta,
631 fp->_IO_buf_base + count);
632 _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
633 fp->_old_offset = result + count;
634 _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
638 _IO_unsave_markers (fp);
639 result = _IO_SYSSEEK (fp, offset, dir);
642 _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
643 fp->_old_offset = result;
644 _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
645 _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
650 /* We need to do it since it is possible that the file offset in
651 the kernel may be changed behind our back. It may happen when
652 we fopen a file and then do a fork. One process may access the
653 file and the kernel file offset will be changed. */
654 if (fp->_old_offset >= 0)
655 _IO_SYSSEEK (fp, fp->_old_offset, 0);
661 attribute_compat_text_section
662 _IO_old_file_write (f, data, n)
667 _IO_ssize_t to_do = n;
670 _IO_ssize_t count = write (f->_fileno, data, to_do);
673 f->_flags |= _IO_ERR_SEEN;
677 data = (void *) ((char *) data + count);
680 if (f->_old_offset >= 0)
686 attribute_compat_text_section
687 _IO_old_file_xsputn (f, data, n)
692 const char *s = (char *) data;
693 _IO_size_t to_do = n;
695 _IO_size_t count = 0;
699 /* This is an optimized implementation.
700 If the amount to be written straddles a block boundary
701 (or the filebuf is unbuffered), use sys_write directly. */
703 /* First figure out how much space is available in the buffer. */
704 if ((f->_flags & _IO_LINE_BUF) && (f->_flags & _IO_CURRENTLY_PUTTING))
706 count = f->_IO_buf_end - f->_IO_write_ptr;
710 for (p = s + n; p > s; )
721 else if (f->_IO_write_end > f->_IO_write_ptr)
722 count = f->_IO_write_end - f->_IO_write_ptr; /* Space available. */
724 /* Then fill the buffer. */
732 f->_IO_write_ptr = __mempcpy (f->_IO_write_ptr, s, count);
734 memcpy (f->_IO_write_ptr, s, count);
735 f->_IO_write_ptr += count;
741 char *p = f->_IO_write_ptr;
745 f->_IO_write_ptr = p;
749 if (to_do + must_flush > 0)
751 _IO_size_t block_size, do_write;
752 /* Next flush the (full) buffer. */
753 if (__overflow (f, EOF) == EOF)
754 return to_do == 0 ? EOF : n - to_do;
756 /* Try to maintain alignment: write a whole number of blocks.
757 dont_write is what gets left over. */
758 block_size = f->_IO_buf_end - f->_IO_buf_base;
759 do_write = to_do - (block_size >= 128 ? to_do % block_size : 0);
763 count = old_do_write (f, s, do_write);
765 if (count < do_write)
769 /* Now write out the remainder. Normally, this will fit in the
770 buffer, but it's somewhat messier for line-buffered files,
771 so we let _IO_default_xsputn handle the general case. */
773 to_do -= _IO_default_xsputn (f, s+do_write, to_do);
779 const struct _IO_jump_t _IO_old_file_jumps =
782 JUMP_INIT(finish, _IO_old_file_finish),
783 JUMP_INIT(overflow, _IO_old_file_overflow),
784 JUMP_INIT(underflow, _IO_old_file_underflow),
785 JUMP_INIT(uflow, _IO_default_uflow),
786 JUMP_INIT(pbackfail, _IO_default_pbackfail),
787 JUMP_INIT(xsputn, _IO_old_file_xsputn),
788 JUMP_INIT(xsgetn, _IO_default_xsgetn),
789 JUMP_INIT(seekoff, _IO_old_file_seekoff),
790 JUMP_INIT(seekpos, _IO_default_seekpos),
791 JUMP_INIT(setbuf, _IO_old_file_setbuf),
792 JUMP_INIT(sync, _IO_old_file_sync),
793 JUMP_INIT(doallocate, _IO_file_doallocate),
794 JUMP_INIT(read, _IO_file_read),
795 JUMP_INIT(write, _IO_old_file_write),
796 JUMP_INIT(seek, _IO_file_seek),
797 JUMP_INIT(close, _IO_file_close),
798 JUMP_INIT(stat, _IO_file_stat)
801 compat_symbol (libc, _IO_old_do_write, _IO_do_write, GLIBC_2_0);
802 compat_symbol (libc, _IO_old_file_attach, _IO_file_attach, GLIBC_2_0);
803 compat_symbol (libc, _IO_old_file_close_it, _IO_file_close_it, GLIBC_2_0);
804 compat_symbol (libc, _IO_old_file_finish, _IO_file_finish, GLIBC_2_0);
805 compat_symbol (libc, _IO_old_file_fopen, _IO_file_fopen, GLIBC_2_0);
806 compat_symbol (libc, _IO_old_file_init, _IO_file_init, GLIBC_2_0);
807 compat_symbol (libc, _IO_old_file_setbuf, _IO_file_setbuf, GLIBC_2_0);
808 compat_symbol (libc, _IO_old_file_sync, _IO_file_sync, GLIBC_2_0);
809 compat_symbol (libc, _IO_old_file_overflow, _IO_file_overflow, GLIBC_2_0);
810 compat_symbol (libc, _IO_old_file_seekoff, _IO_file_seekoff, GLIBC_2_0);
811 compat_symbol (libc, _IO_old_file_underflow, _IO_file_underflow, GLIBC_2_0);
812 compat_symbol (libc, _IO_old_file_write, _IO_file_write, GLIBC_2_0);
813 compat_symbol (libc, _IO_old_file_xsputn, _IO_file_xsputn, GLIBC_2_0);