Back to index

glibc  2.9
oldfileops.c
Go to the documentation of this file.
00001 /* Copyright (C) 1993, 1995, 1997-2004, 2005, 2007
00002    Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004    Written by Per Bothner <bothner@cygnus.com>.
00005 
00006    The GNU C Library is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU Lesser General Public
00008    License as published by the Free Software Foundation; either
00009    version 2.1 of the License, or (at your option) any later version.
00010 
00011    The GNU C Library is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014    Lesser General Public License for more details.
00015 
00016    You should have received a copy of the GNU Lesser General Public
00017    License along with the GNU C Library; if not, write to the Free
00018    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00019    02111-1307 USA.
00020 
00021    As a special exception, if you link the code in this file with
00022    files compiled with a GNU compiler to produce an executable,
00023    that does not cause the resulting executable to be covered by
00024    the GNU Lesser General Public License.  This exception does not
00025    however invalidate any other reasons why the executable file
00026    might be covered by the GNU Lesser General Public License.
00027    This exception applies to code released by its copyright holders
00028    in files containing the exception.  */
00029 
00030 /* This is a compatibility file.  If we don't build the libc with
00031    versioning don't compile this file.  */
00032 #include <shlib-compat.h>
00033 #if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
00034 
00035 #ifndef _POSIX_SOURCE
00036 # define _POSIX_SOURCE
00037 #endif
00038 #define _IO_USE_OLD_IO_FILE
00039 #include "libioP.h"
00040 #include <fcntl.h>
00041 #include <sys/types.h>
00042 #include <sys/stat.h>
00043 #include <string.h>
00044 #include <errno.h>
00045 #ifdef __STDC__
00046 #include <stdlib.h>
00047 #endif
00048 #ifndef errno
00049 extern int errno;
00050 #endif
00051 #ifndef __set_errno
00052 # define __set_errno(Val) errno = (Val)
00053 #endif
00054 
00055 
00056 #ifdef _LIBC
00057 # define open(Name, Flags, Prot) __open (Name, Flags, Prot)
00058 # define close(FD) __close (FD)
00059 # define lseek(FD, Offset, Whence) __lseek (FD, Offset, Whence)
00060 # define read(FD, Buf, NBytes) __read (FD, Buf, NBytes)
00061 # define write(FD, Buf, NBytes) __write (FD, Buf, NBytes)
00062 #endif
00063 
00064 /* An fstream can be in at most one of put mode, get mode, or putback mode.
00065    Putback mode is a variant of get mode.
00066 
00067    In a filebuf, there is only one current position, instead of two
00068    separate get and put pointers.  In get mode, the current position
00069    is that of gptr(); in put mode that of pptr().
00070 
00071    The position in the buffer that corresponds to the position
00072    in external file system is normally _IO_read_end, except in putback
00073    mode, when it is _IO_save_end.
00074    If the field _fb._offset is >= 0, it gives the offset in
00075    the file as a whole corresponding to eGptr(). (?)
00076 
00077    PUT MODE:
00078    If a filebuf is in put mode, then all of _IO_read_ptr, _IO_read_end,
00079    and _IO_read_base are equal to each other.  These are usually equal
00080    to _IO_buf_base, though not necessarily if we have switched from
00081    get mode to put mode.  (The reason is to maintain the invariant
00082    that _IO_read_end corresponds to the external file position.)
00083    _IO_write_base is non-NULL and usually equal to _IO_base_base.
00084    We also have _IO_write_end == _IO_buf_end, but only in fully buffered mode.
00085    The un-flushed character are those between _IO_write_base and _IO_write_ptr.
00086 
00087    GET MODE:
00088    If a filebuf is in get or putback mode, eback() != egptr().
00089    In get mode, the unread characters are between gptr() and egptr().
00090    The OS file position corresponds to that of egptr().
00091 
00092    PUTBACK MODE:
00093    Putback mode is used to remember "excess" characters that have
00094    been sputbackc'd in a separate putback buffer.
00095    In putback mode, the get buffer points to the special putback buffer.
00096    The unread characters are the characters between gptr() and egptr()
00097    in the putback buffer, as well as the area between save_gptr()
00098    and save_egptr(), which point into the original reserve buffer.
00099    (The pointers save_gptr() and save_egptr() are the values
00100    of gptr() and egptr() at the time putback mode was entered.)
00101    The OS position corresponds to that of save_egptr().
00102 
00103    LINE BUFFERED OUTPUT:
00104    During line buffered output, _IO_write_base==base() && epptr()==base().
00105    However, ptr() may be anywhere between base() and ebuf().
00106    This forces a call to filebuf::overflow(int C) on every put.
00107    If there is more space in the buffer, and C is not a '\n',
00108    then C is inserted, and pptr() incremented.
00109 
00110    UNBUFFERED STREAMS:
00111    If a filebuf is unbuffered(), the _shortbuf[1] is used as the buffer.
00112 */
00113 
00114 #define CLOSED_FILEBUF_FLAGS \
00115   (_IO_IS_FILEBUF+_IO_NO_READS+_IO_NO_WRITES+_IO_TIED_PUT_GET)
00116 
00117 
00118 void
00119 attribute_compat_text_section
00120 _IO_old_file_init (fp)
00121      struct _IO_FILE_plus *fp;
00122 {
00123   /* POSIX.1 allows another file handle to be used to change the position
00124      of our file descriptor.  Hence we actually don't know the actual
00125      position before we do the first fseek (and until a following fflush). */
00126   fp->file._old_offset = _IO_pos_BAD;
00127   fp->file._IO_file_flags |= CLOSED_FILEBUF_FLAGS;
00128 
00129   INTUSE(_IO_link_in) (fp);
00130   fp->file._vtable_offset = ((int) sizeof (struct _IO_FILE)
00131                           - (int) sizeof (struct _IO_FILE_complete));
00132   fp->file._fileno = -1;
00133 
00134 #if defined SHARED && defined _LIBC
00135   if (__builtin_expect (&_IO_stdin_used != NULL, 1)
00136       || (fp != (struct _IO_FILE_plus *) _IO_stdin
00137          && fp != (struct _IO_FILE_plus *) _IO_stdout
00138          && fp != (struct _IO_FILE_plus *) _IO_stderr))
00139     /* The object is dynamically allocated and large enough.  Initialize
00140        the _mode element as well.  */
00141     ((struct _IO_FILE_complete *) fp)->_mode = -1;
00142 #endif
00143 }
00144 
00145 int
00146 attribute_compat_text_section
00147 _IO_old_file_close_it (fp)
00148      _IO_FILE *fp;
00149 {
00150   int write_status, close_status;
00151   if (!_IO_file_is_open (fp))
00152     return EOF;
00153 
00154   write_status = _IO_old_do_flush (fp);
00155 
00156   INTUSE(_IO_unsave_markers) (fp);
00157 
00158   close_status = _IO_SYSCLOSE (fp);
00159 
00160   /* Free buffer. */
00161   INTUSE(_IO_setb) (fp, NULL, NULL, 0);
00162   _IO_setg (fp, NULL, NULL, NULL);
00163   _IO_setp (fp, NULL, NULL);
00164 
00165   INTUSE(_IO_un_link) ((struct _IO_FILE_plus *) fp);
00166   fp->_flags = _IO_MAGIC|CLOSED_FILEBUF_FLAGS;
00167   fp->_fileno = -1;
00168   fp->_old_offset = _IO_pos_BAD;
00169 
00170   return close_status ? close_status : write_status;
00171 }
00172 
00173 void
00174 attribute_compat_text_section
00175 _IO_old_file_finish (fp, dummy)
00176      _IO_FILE *fp;
00177      int dummy;
00178 {
00179   if (_IO_file_is_open (fp))
00180     {
00181       _IO_old_do_flush (fp);
00182       if (!(fp->_flags & _IO_DELETE_DONT_CLOSE))
00183        _IO_SYSCLOSE (fp);
00184     }
00185   INTUSE(_IO_default_finish) (fp, 0);
00186 }
00187 
00188 _IO_FILE *
00189 attribute_compat_text_section
00190 _IO_old_file_fopen (fp, filename, mode)
00191      _IO_FILE *fp;
00192      const char *filename;
00193      const char *mode;
00194 {
00195   int oflags = 0, omode;
00196   int read_write, fdesc;
00197   int oprot = 0666;
00198   if (_IO_file_is_open (fp))
00199     return 0;
00200   switch (*mode++)
00201     {
00202     case 'r':
00203       omode = O_RDONLY;
00204       read_write = _IO_NO_WRITES;
00205       break;
00206     case 'w':
00207       omode = O_WRONLY;
00208       oflags = O_CREAT|O_TRUNC;
00209       read_write = _IO_NO_READS;
00210       break;
00211     case 'a':
00212       omode = O_WRONLY;
00213       oflags = O_CREAT|O_APPEND;
00214       read_write = _IO_NO_READS|_IO_IS_APPENDING;
00215       break;
00216     default:
00217       __set_errno (EINVAL);
00218       return NULL;
00219     }
00220   if (mode[0] == '+' || (mode[0] == 'b' && mode[1] == '+'))
00221     {
00222       omode = O_RDWR;
00223       read_write &= _IO_IS_APPENDING;
00224     }
00225   fdesc = open (filename, omode|oflags, oprot);
00226   if (fdesc < 0)
00227     return NULL;
00228   fp->_fileno = fdesc;
00229   _IO_mask_flags (fp, read_write,_IO_NO_READS+_IO_NO_WRITES+_IO_IS_APPENDING);
00230   if (read_write & _IO_IS_APPENDING)
00231     if (_IO_SEEKOFF (fp, (_IO_off_t)0, _IO_seek_end, _IOS_INPUT|_IOS_OUTPUT)
00232        == _IO_pos_BAD && errno != ESPIPE)
00233       return NULL;
00234   INTUSE(_IO_link_in) ((struct _IO_FILE_plus *) fp);
00235   return fp;
00236 }
00237 
00238 _IO_FILE *
00239 attribute_compat_text_section
00240 _IO_old_file_attach (fp, fd)
00241      _IO_FILE *fp;
00242      int fd;
00243 {
00244   if (_IO_file_is_open (fp))
00245     return NULL;
00246   fp->_fileno = fd;
00247   fp->_flags &= ~(_IO_NO_READS+_IO_NO_WRITES);
00248   fp->_flags |= _IO_DELETE_DONT_CLOSE;
00249   /* Get the current position of the file. */
00250   /* We have to do that since that may be junk. */
00251   fp->_old_offset = _IO_pos_BAD;
00252   if (_IO_SEEKOFF (fp, (_IO_off_t)0, _IO_seek_cur, _IOS_INPUT|_IOS_OUTPUT)
00253       == _IO_pos_BAD && errno != ESPIPE)
00254     return NULL;
00255   return fp;
00256 }
00257 
00258 _IO_FILE *
00259 attribute_compat_text_section
00260 _IO_old_file_setbuf (fp, p, len)
00261      _IO_FILE *fp;
00262      char *p;
00263      _IO_ssize_t len;
00264 {
00265     if (_IO_default_setbuf (fp, p, len) == NULL)
00266       return NULL;
00267 
00268     fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end
00269       = fp->_IO_buf_base;
00270     _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
00271 
00272     return fp;
00273 }
00274 
00275 static int old_do_write (_IO_FILE *, const char *, _IO_size_t);
00276 
00277 /* Write TO_DO bytes from DATA to FP.
00278    Then mark FP as having empty buffers. */
00279 
00280 int
00281 attribute_compat_text_section
00282 _IO_old_do_write (fp, data, to_do)
00283      _IO_FILE *fp;
00284      const char *data;
00285      _IO_size_t to_do;
00286 {
00287   return (to_do == 0 || (_IO_size_t) old_do_write (fp, data, to_do) == to_do)
00288         ? 0 : EOF;
00289 }
00290 
00291 static int
00292 attribute_compat_text_section
00293 old_do_write (fp, data, to_do)
00294      _IO_FILE *fp;
00295      const char *data;
00296      _IO_size_t to_do;
00297 {
00298   _IO_size_t count;
00299   if (fp->_flags & _IO_IS_APPENDING)
00300     /* On a system without a proper O_APPEND implementation,
00301        you would need to sys_seek(0, SEEK_END) here, but is
00302        is not needed nor desirable for Unix- or Posix-like systems.
00303        Instead, just indicate that offset (before and after) is
00304        unpredictable. */
00305     fp->_old_offset = _IO_pos_BAD;
00306   else if (fp->_IO_read_end != fp->_IO_write_base)
00307     {
00308       _IO_off_t new_pos
00309        = _IO_SYSSEEK (fp, fp->_IO_write_base - fp->_IO_read_end, 1);
00310       if (new_pos == _IO_pos_BAD)
00311        return 0;
00312       fp->_old_offset = new_pos;
00313     }
00314   count = _IO_SYSWRITE (fp, data, to_do);
00315   if (fp->_cur_column && count)
00316     fp->_cur_column = INTUSE(_IO_adjust_column) (fp->_cur_column - 1, data,
00317                                            count) + 1;
00318   _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
00319   fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_buf_base;
00320   fp->_IO_write_end = ((fp->_flags & (_IO_LINE_BUF+_IO_UNBUFFERED))
00321                      ? fp->_IO_buf_base : fp->_IO_buf_end);
00322   return count;
00323 }
00324 
00325 int
00326 attribute_compat_text_section
00327 _IO_old_file_underflow (fp)
00328      _IO_FILE *fp;
00329 {
00330   _IO_ssize_t count;
00331 #if 0
00332   /* SysV does not make this test; take it out for compatibility */
00333   if (fp->_flags & _IO_EOF_SEEN)
00334     return (EOF);
00335 #endif
00336 
00337   if (fp->_flags & _IO_NO_READS)
00338     {
00339       fp->_flags |= _IO_ERR_SEEN;
00340       __set_errno (EBADF);
00341       return EOF;
00342     }
00343   if (fp->_IO_read_ptr < fp->_IO_read_end)
00344     return *(unsigned char *) fp->_IO_read_ptr;
00345 
00346   if (fp->_IO_buf_base == NULL)
00347     {
00348       /* Maybe we already have a push back pointer.  */
00349       if (fp->_IO_save_base != NULL)
00350        {
00351          free (fp->_IO_save_base);
00352          fp->_flags &= ~_IO_IN_BACKUP;
00353        }
00354       INTUSE(_IO_doallocbuf) (fp);
00355     }
00356 
00357   /* Flush all line buffered files before reading. */
00358   /* FIXME This can/should be moved to genops ?? */
00359   if (fp->_flags & (_IO_LINE_BUF|_IO_UNBUFFERED))
00360     INTUSE(_IO_flush_all_linebuffered) ();
00361 
00362   INTUSE(_IO_switch_to_get_mode) (fp);
00363 
00364   /* This is very tricky. We have to adjust those
00365      pointers before we call _IO_SYSREAD () since
00366      we may longjump () out while waiting for
00367      input. Those pointers may be screwed up. H.J. */
00368   fp->_IO_read_base = fp->_IO_read_ptr = fp->_IO_buf_base;
00369   fp->_IO_read_end = fp->_IO_buf_base;
00370   fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end
00371     = fp->_IO_buf_base;
00372 
00373   count = _IO_SYSREAD (fp, fp->_IO_buf_base,
00374                      fp->_IO_buf_end - fp->_IO_buf_base);
00375   if (count <= 0)
00376     {
00377       if (count == 0)
00378        fp->_flags |= _IO_EOF_SEEN;
00379       else
00380        fp->_flags |= _IO_ERR_SEEN, count = 0;
00381   }
00382   fp->_IO_read_end += count;
00383   if (count == 0)
00384     return EOF;
00385   if (fp->_old_offset != _IO_pos_BAD)
00386     _IO_pos_adjust (fp->_old_offset, count);
00387   return *(unsigned char *) fp->_IO_read_ptr;
00388 }
00389 
00390 int
00391 attribute_compat_text_section
00392 _IO_old_file_overflow (f, ch)
00393       _IO_FILE *f;
00394       int ch;
00395 {
00396   if (f->_flags & _IO_NO_WRITES) /* SET ERROR */
00397     {
00398       f->_flags |= _IO_ERR_SEEN;
00399       __set_errno (EBADF);
00400       return EOF;
00401     }
00402   /* If currently reading or no buffer allocated. */
00403   if ((f->_flags & _IO_CURRENTLY_PUTTING) == 0)
00404     {
00405       /* Allocate a buffer if needed. */
00406       if (f->_IO_write_base == 0)
00407        {
00408          INTUSE(_IO_doallocbuf) (f);
00409          _IO_setg (f, f->_IO_buf_base, f->_IO_buf_base, f->_IO_buf_base);
00410        }
00411       /* Otherwise must be currently reading.
00412         If _IO_read_ptr (and hence also _IO_read_end) is at the buffer end,
00413         logically slide the buffer forwards one block (by setting the
00414         read pointers to all point at the beginning of the block).  This
00415         makes room for subsequent output.
00416         Otherwise, set the read pointers to _IO_read_end (leaving that
00417         alone, so it can continue to correspond to the external position). */
00418       if (f->_IO_read_ptr == f->_IO_buf_end)
00419        f->_IO_read_end = f->_IO_read_ptr = f->_IO_buf_base;
00420       f->_IO_write_ptr = f->_IO_read_ptr;
00421       f->_IO_write_base = f->_IO_write_ptr;
00422       f->_IO_write_end = f->_IO_buf_end;
00423       f->_IO_read_base = f->_IO_read_ptr = f->_IO_read_end;
00424 
00425       if (f->_flags & (_IO_LINE_BUF+_IO_UNBUFFERED))
00426        f->_IO_write_end = f->_IO_write_ptr;
00427       f->_flags |= _IO_CURRENTLY_PUTTING;
00428     }
00429   if (ch == EOF)
00430     return _IO_old_do_flush (f);
00431   if (f->_IO_write_ptr == f->_IO_buf_end ) /* Buffer is really full */
00432     if (_IO_old_do_flush (f) == EOF)
00433       return EOF;
00434   *f->_IO_write_ptr++ = ch;
00435   if ((f->_flags & _IO_UNBUFFERED)
00436       || ((f->_flags & _IO_LINE_BUF) && ch == '\n'))
00437     if (_IO_old_do_flush (f) == EOF)
00438       return EOF;
00439   return (unsigned char) ch;
00440 }
00441 
00442 int
00443 attribute_compat_text_section
00444 _IO_old_file_sync (fp)
00445      _IO_FILE *fp;
00446 {
00447   _IO_ssize_t delta;
00448   int retval = 0;
00449 
00450   /*    char* ptr = cur_ptr(); */
00451   if (fp->_IO_write_ptr > fp->_IO_write_base)
00452     if (_IO_old_do_flush(fp)) return EOF;
00453   delta = fp->_IO_read_ptr - fp->_IO_read_end;
00454   if (delta != 0)
00455     {
00456 #ifdef TODO
00457       if (_IO_in_backup (fp))
00458        delta -= eGptr () - Gbase ();
00459 #endif
00460       _IO_off_t new_pos = _IO_SYSSEEK (fp, delta, 1);
00461       if (new_pos != (_IO_off_t) EOF)
00462        fp->_IO_read_end = fp->_IO_read_ptr;
00463 #ifdef ESPIPE
00464       else if (errno == ESPIPE)
00465        ; /* Ignore error from unseekable devices. */
00466 #endif
00467       else
00468        retval = EOF;
00469     }
00470   if (retval != EOF)
00471     fp->_old_offset = _IO_pos_BAD;
00472   /* FIXME: Cleanup - can this be shared? */
00473   /*    setg(base(), ptr, ptr); */
00474   return retval;
00475 }
00476 
00477 _IO_off64_t
00478 attribute_compat_text_section
00479 _IO_old_file_seekoff (fp, offset, dir, mode)
00480      _IO_FILE *fp;
00481      _IO_off64_t offset;
00482      int dir;
00483      int mode;
00484 {
00485   _IO_off_t result;
00486   _IO_off64_t delta, new_offset;
00487   long count;
00488   /* POSIX.1 8.2.3.7 says that after a call the fflush() the file
00489      offset of the underlying file must be exact.  */
00490   int must_be_exact = (fp->_IO_read_base == fp->_IO_read_end
00491                      && fp->_IO_write_base == fp->_IO_write_ptr);
00492 
00493   if (mode == 0)
00494     dir = _IO_seek_cur, offset = 0; /* Don't move any pointers. */
00495 
00496   /* Flush unwritten characters.
00497      (This may do an unneeded write if we seek within the buffer.
00498      But to be able to switch to reading, we would need to set
00499      egptr to ptr.  That can't be done in the current design,
00500      which assumes file_ptr() is eGptr.  Anyway, since we probably
00501      end up flushing when we close(), it doesn't make much difference.)
00502      FIXME: simulate mem-papped files. */
00503 
00504   if (fp->_IO_write_ptr > fp->_IO_write_base || _IO_in_put_mode (fp))
00505     if (INTUSE(_IO_switch_to_get_mode) (fp))
00506       return EOF;
00507 
00508   if (fp->_IO_buf_base == NULL)
00509     {
00510       /* It could be that we already have a pushback buffer.  */
00511       if (fp->_IO_read_base != NULL)
00512        {
00513          free (fp->_IO_read_base);
00514          fp->_flags &= ~_IO_IN_BACKUP;
00515        }
00516       INTUSE(_IO_doallocbuf) (fp);
00517       _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
00518       _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
00519     }
00520 
00521   switch (dir)
00522     {
00523     case _IO_seek_cur:
00524       /* Adjust for read-ahead (bytes is buffer). */
00525       offset -= fp->_IO_read_end - fp->_IO_read_ptr;
00526       if (fp->_old_offset == _IO_pos_BAD)
00527        goto dumb;
00528       /* Make offset absolute, assuming current pointer is file_ptr(). */
00529       offset += fp->_old_offset;
00530 
00531       dir = _IO_seek_set;
00532       break;
00533     case _IO_seek_set:
00534       break;
00535     case _IO_seek_end:
00536       {
00537        struct _G_stat64 st;
00538        if (_IO_SYSSTAT (fp, &st) == 0 && S_ISREG (st.st_mode))
00539          {
00540            offset += st.st_size;
00541            dir = _IO_seek_set;
00542          }
00543        else
00544          goto dumb;
00545       }
00546     }
00547   /* At this point, dir==_IO_seek_set. */
00548 
00549   /* If we are only interested in the current position we've found it now.  */
00550   if (mode == 0)
00551     return offset;
00552 
00553   /* If destination is within current buffer, optimize: */
00554   if (fp->_old_offset != _IO_pos_BAD && fp->_IO_read_base != NULL
00555       && !_IO_in_backup (fp))
00556     {
00557       /* Offset relative to start of main get area. */
00558       _IO_off_t rel_offset = (offset - fp->_old_offset
00559                            + (fp->_IO_read_end - fp->_IO_read_base));
00560       if (rel_offset >= 0)
00561        {
00562 #if 0
00563          if (_IO_in_backup (fp))
00564            _IO_switch_to_main_get_area (fp);
00565 #endif
00566          if (rel_offset <= fp->_IO_read_end - fp->_IO_read_base)
00567            {
00568              _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base + rel_offset,
00569                      fp->_IO_read_end);
00570              _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
00571              {
00572               _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
00573               goto resync;
00574              }
00575            }
00576 #ifdef TODO
00577            /* If we have streammarkers, seek forward by reading ahead. */
00578            if (_IO_have_markers (fp))
00579              {
00580               int to_skip = rel_offset
00581                 - (fp->_IO_read_ptr - fp->_IO_read_base);
00582               if (ignore (to_skip) != to_skip)
00583                 goto dumb;
00584               _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
00585               goto resync;
00586              }
00587 #endif
00588        }
00589 #ifdef TODO
00590       if (rel_offset < 0 && rel_offset >= Bbase () - Bptr ())
00591        {
00592          if (!_IO_in_backup (fp))
00593            _IO_switch_to_backup_area (fp);
00594          gbump (fp->_IO_read_end + rel_offset - fp->_IO_read_ptr);
00595          _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
00596          goto resync;
00597        }
00598 #endif
00599     }
00600 
00601 #ifdef TODO
00602   INTUSE(_IO_unsave_markers) (fp);
00603 #endif
00604 
00605   if (fp->_flags & _IO_NO_READS)
00606     goto dumb;
00607 
00608   /* Try to seek to a block boundary, to improve kernel page management. */
00609   new_offset = offset & ~(fp->_IO_buf_end - fp->_IO_buf_base - 1);
00610   delta = offset - new_offset;
00611   if (delta > fp->_IO_buf_end - fp->_IO_buf_base)
00612     {
00613       new_offset = offset;
00614       delta = 0;
00615     }
00616   result = _IO_SYSSEEK (fp, new_offset, 0);
00617   if (result < 0)
00618     return EOF;
00619   if (delta == 0)
00620     count = 0;
00621   else
00622     {
00623       count = _IO_SYSREAD (fp, fp->_IO_buf_base,
00624                         (must_be_exact
00625                          ? delta : fp->_IO_buf_end - fp->_IO_buf_base));
00626       if (count < delta)
00627        {
00628          /* We weren't allowed to read, but try to seek the remainder. */
00629          offset = count == EOF ? delta : delta-count;
00630          dir = _IO_seek_cur;
00631          goto dumb;
00632        }
00633     }
00634   _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base + delta,
00635            fp->_IO_buf_base + count);
00636   _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
00637   fp->_old_offset = result + count;
00638   _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
00639   return offset;
00640  dumb:
00641 
00642   INTUSE(_IO_unsave_markers) (fp);
00643   result = _IO_SYSSEEK (fp, offset, dir);
00644   if (result != EOF)
00645     {
00646       _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
00647       fp->_old_offset = result;
00648       _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
00649       _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
00650     }
00651   return result;
00652 
00653 resync:
00654   /* We need to do it since it is possible that the file offset in
00655      the kernel may be changed behind our back. It may happen when
00656      we fopen a file and then do a fork. One process may access the
00657      the file and the kernel file offset will be changed. */
00658   if (fp->_old_offset >= 0)
00659     _IO_SYSSEEK (fp, fp->_old_offset, 0);
00660 
00661   return offset;
00662 }
00663 
00664 _IO_ssize_t
00665 attribute_compat_text_section
00666 _IO_old_file_write (f, data, n)
00667      _IO_FILE *f;
00668      const void *data;
00669      _IO_ssize_t n;
00670 {
00671   _IO_ssize_t to_do = n;
00672   while (to_do > 0)
00673     {
00674       _IO_ssize_t count = write (f->_fileno, data, to_do);
00675       if (count == EOF)
00676        {
00677          f->_flags |= _IO_ERR_SEEN;
00678          break;
00679         }
00680       to_do -= count;
00681       data = (void *) ((char *) data + count);
00682     }
00683   n -= to_do;
00684   if (f->_old_offset >= 0)
00685     f->_old_offset += n;
00686   return n;
00687 }
00688 
00689 _IO_size_t
00690 attribute_compat_text_section
00691 _IO_old_file_xsputn (f, data, n)
00692      _IO_FILE *f;
00693      const void *data;
00694      _IO_size_t n;
00695 {
00696   register const char *s = (char *) data;
00697   _IO_size_t to_do = n;
00698   int must_flush = 0;
00699   _IO_size_t count = 0;
00700 
00701   if (n <= 0)
00702     return 0;
00703   /* This is an optimized implementation.
00704      If the amount to be written straddles a block boundary
00705      (or the filebuf is unbuffered), use sys_write directly. */
00706 
00707   /* First figure out how much space is available in the buffer. */
00708   if ((f->_flags & _IO_LINE_BUF) && (f->_flags & _IO_CURRENTLY_PUTTING))
00709     {
00710       count = f->_IO_buf_end - f->_IO_write_ptr;
00711       if (count >= n)
00712        {
00713          register const char *p;
00714          for (p = s + n; p > s; )
00715            {
00716              if (*--p == '\n')
00717               {
00718                 count = p - s + 1;
00719                 must_flush = 1;
00720                 break;
00721               }
00722            }
00723        }
00724     }
00725   else if (f->_IO_write_end > f->_IO_write_ptr)
00726     count = f->_IO_write_end - f->_IO_write_ptr; /* Space available. */
00727 
00728   /* Then fill the buffer. */
00729   if (count > 0)
00730     {
00731       if (count > to_do)
00732        count = to_do;
00733       if (count > 20)
00734        {
00735 #ifdef _LIBC
00736          f->_IO_write_ptr = __mempcpy (f->_IO_write_ptr, s, count);
00737 #else
00738          memcpy (f->_IO_write_ptr, s, count);
00739          f->_IO_write_ptr += count;
00740 #endif
00741          s += count;
00742        }
00743       else
00744        {
00745          register char *p = f->_IO_write_ptr;
00746          register int i = (int) count;
00747          while (--i >= 0)
00748            *p++ = *s++;
00749          f->_IO_write_ptr = p;
00750        }
00751       to_do -= count;
00752     }
00753   if (to_do + must_flush > 0)
00754     {
00755       _IO_size_t block_size, do_write;
00756       /* Next flush the (full) buffer. */
00757       if (__overflow (f, EOF) == EOF)
00758        return to_do == 0 ? EOF : n - to_do;
00759 
00760       /* Try to maintain alignment: write a whole number of blocks.
00761         dont_write is what gets left over. */
00762       block_size = f->_IO_buf_end - f->_IO_buf_base;
00763       do_write = to_do - (block_size >= 128 ? to_do % block_size : 0);
00764 
00765       if (do_write)
00766         {
00767          count = old_do_write (f, s, do_write);
00768          to_do -= count;
00769          if (count < do_write)
00770            return n - to_do;
00771         }
00772 
00773       /* Now write out the remainder.  Normally, this will fit in the
00774         buffer, but it's somewhat messier for line-buffered files,
00775         so we let _IO_default_xsputn handle the general case. */
00776       if (to_do)
00777        to_do -= INTUSE(_IO_default_xsputn) (f, s+do_write, to_do);
00778     }
00779   return n - to_do;
00780 }
00781 
00782 
00783 const struct _IO_jump_t _IO_old_file_jumps =
00784 {
00785   JUMP_INIT_DUMMY,
00786   JUMP_INIT(finish, _IO_old_file_finish),
00787   JUMP_INIT(overflow, _IO_old_file_overflow),
00788   JUMP_INIT(underflow, _IO_old_file_underflow),
00789   JUMP_INIT(uflow, INTUSE(_IO_default_uflow)),
00790   JUMP_INIT(pbackfail, INTUSE(_IO_default_pbackfail)),
00791   JUMP_INIT(xsputn, _IO_old_file_xsputn),
00792   JUMP_INIT(xsgetn, INTUSE(_IO_default_xsgetn)),
00793   JUMP_INIT(seekoff, _IO_old_file_seekoff),
00794   JUMP_INIT(seekpos, _IO_default_seekpos),
00795   JUMP_INIT(setbuf, _IO_old_file_setbuf),
00796   JUMP_INIT(sync, _IO_old_file_sync),
00797   JUMP_INIT(doallocate, INTUSE(_IO_file_doallocate)),
00798   JUMP_INIT(read, INTUSE(_IO_file_read)),
00799   JUMP_INIT(write, _IO_old_file_write),
00800   JUMP_INIT(seek, INTUSE(_IO_file_seek)),
00801   JUMP_INIT(close, INTUSE(_IO_file_close)),
00802   JUMP_INIT(stat, INTUSE(_IO_file_stat))
00803 };
00804 
00805 compat_symbol (libc, _IO_old_do_write, _IO_do_write, GLIBC_2_0);
00806 compat_symbol (libc, _IO_old_file_attach, _IO_file_attach, GLIBC_2_0);
00807 compat_symbol (libc, _IO_old_file_close_it, _IO_file_close_it, GLIBC_2_0);
00808 compat_symbol (libc, _IO_old_file_finish, _IO_file_finish, GLIBC_2_0);
00809 compat_symbol (libc, _IO_old_file_fopen, _IO_file_fopen, GLIBC_2_0);
00810 compat_symbol (libc, _IO_old_file_init, _IO_file_init, GLIBC_2_0);
00811 compat_symbol (libc, _IO_old_file_setbuf, _IO_file_setbuf, GLIBC_2_0);
00812 compat_symbol (libc, _IO_old_file_sync, _IO_file_sync, GLIBC_2_0);
00813 compat_symbol (libc, _IO_old_file_overflow, _IO_file_overflow, GLIBC_2_0);
00814 compat_symbol (libc, _IO_old_file_seekoff, _IO_file_seekoff, GLIBC_2_0);
00815 compat_symbol (libc, _IO_old_file_underflow, _IO_file_underflow, GLIBC_2_0);
00816 compat_symbol (libc, _IO_old_file_write, _IO_file_write, GLIBC_2_0);
00817 compat_symbol (libc, _IO_old_file_xsputn, _IO_file_xsputn, GLIBC_2_0);
00818 
00819 #endif