Back to index

glibc  2.9
fileops.c
Go to the documentation of this file.
00001 /* Copyright (C) 1993, 1995, 1997-2005, 2006, 2007, 2008
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 
00031 #ifndef _POSIX_SOURCE
00032 # define _POSIX_SOURCE
00033 #endif
00034 #include "libioP.h"
00035 #include <assert.h>
00036 #include <fcntl.h>
00037 #include <sys/param.h>
00038 #include <sys/types.h>
00039 #include <sys/stat.h>
00040 #include <string.h>
00041 #include <errno.h>
00042 #include <unistd.h>
00043 #ifdef __STDC__
00044 #include <stdlib.h>
00045 #endif
00046 #if _LIBC
00047 # include "../wcsmbs/wcsmbsload.h"
00048 # include "../iconv/gconv_charset.h"
00049 # include "../iconv/gconv_int.h"
00050 # include <shlib-compat.h>
00051 # include <not-cancel.h>
00052 #endif
00053 #ifndef errno
00054 extern int errno;
00055 #endif
00056 #ifndef __set_errno
00057 # define __set_errno(Val) errno = (Val)
00058 #endif
00059 
00060 
00061 #ifdef _LIBC
00062 # define open(Name, Flags, Prot) __open (Name, Flags, Prot)
00063 # define lseek(FD, Offset, Whence) __lseek (FD, Offset, Whence)
00064 # define read(FD, Buf, NBytes) __read (FD, Buf, NBytes)
00065 # define write(FD, Buf, NBytes) __write (FD, Buf, NBytes)
00066 # define _IO_do_write _IO_new_do_write /* For macro uses.  */
00067 # define _IO_file_close_it _IO_new_file_close_it
00068 #else
00069 # define _IO_new_do_write _IO_do_write
00070 # define _IO_new_file_attach _IO_file_attach
00071 # define _IO_new_file_close_it _IO_file_close_it
00072 # define _IO_new_file_finish _IO_file_finish
00073 # define _IO_new_file_fopen _IO_file_fopen
00074 # define _IO_new_file_init _IO_file_init
00075 # define _IO_new_file_setbuf _IO_file_setbuf
00076 # define _IO_new_file_sync _IO_file_sync
00077 # define _IO_new_file_overflow _IO_file_overflow
00078 # define _IO_new_file_seekoff _IO_file_seekoff
00079 # define _IO_new_file_underflow _IO_file_underflow
00080 # define _IO_new_file_write _IO_file_write
00081 # define _IO_new_file_xsputn _IO_file_xsputn
00082 #endif
00083 
00084 
00085 #ifdef _LIBC
00086 extern struct __gconv_trans_data __libio_translit attribute_hidden;
00087 #endif
00088 
00089 
00090 /* An fstream can be in at most one of put mode, get mode, or putback mode.
00091    Putback mode is a variant of get mode.
00092 
00093    In a filebuf, there is only one current position, instead of two
00094    separate get and put pointers.  In get mode, the current position
00095    is that of gptr(); in put mode that of pptr().
00096 
00097    The position in the buffer that corresponds to the position
00098    in external file system is normally _IO_read_end, except in putback
00099    mode, when it is _IO_save_end.
00100    If the field _fb._offset is >= 0, it gives the offset in
00101    the file as a whole corresponding to eGptr(). (?)
00102 
00103    PUT MODE:
00104    If a filebuf is in put mode, then all of _IO_read_ptr, _IO_read_end,
00105    and _IO_read_base are equal to each other.  These are usually equal
00106    to _IO_buf_base, though not necessarily if we have switched from
00107    get mode to put mode.  (The reason is to maintain the invariant
00108    that _IO_read_end corresponds to the external file position.)
00109    _IO_write_base is non-NULL and usually equal to _IO_base_base.
00110    We also have _IO_write_end == _IO_buf_end, but only in fully buffered mode.
00111    The un-flushed character are those between _IO_write_base and _IO_write_ptr.
00112 
00113    GET MODE:
00114    If a filebuf is in get or putback mode, eback() != egptr().
00115    In get mode, the unread characters are between gptr() and egptr().
00116    The OS file position corresponds to that of egptr().
00117 
00118    PUTBACK MODE:
00119    Putback mode is used to remember "excess" characters that have
00120    been sputbackc'd in a separate putback buffer.
00121    In putback mode, the get buffer points to the special putback buffer.
00122    The unread characters are the characters between gptr() and egptr()
00123    in the putback buffer, as well as the area between save_gptr()
00124    and save_egptr(), which point into the original reserve buffer.
00125    (The pointers save_gptr() and save_egptr() are the values
00126    of gptr() and egptr() at the time putback mode was entered.)
00127    The OS position corresponds to that of save_egptr().
00128 
00129    LINE BUFFERED OUTPUT:
00130    During line buffered output, _IO_write_base==base() && epptr()==base().
00131    However, ptr() may be anywhere between base() and ebuf().
00132    This forces a call to filebuf::overflow(int C) on every put.
00133    If there is more space in the buffer, and C is not a '\n',
00134    then C is inserted, and pptr() incremented.
00135 
00136    UNBUFFERED STREAMS:
00137    If a filebuf is unbuffered(), the _shortbuf[1] is used as the buffer.
00138 */
00139 
00140 #define CLOSED_FILEBUF_FLAGS \
00141   (_IO_IS_FILEBUF+_IO_NO_READS+_IO_NO_WRITES+_IO_TIED_PUT_GET)
00142 
00143 
00144 void
00145 _IO_new_file_init (fp)
00146      struct _IO_FILE_plus *fp;
00147 {
00148   /* POSIX.1 allows another file handle to be used to change the position
00149      of our file descriptor.  Hence we actually don't know the actual
00150      position before we do the first fseek (and until a following fflush). */
00151   fp->file._offset = _IO_pos_BAD;
00152   fp->file._IO_file_flags |= CLOSED_FILEBUF_FLAGS;
00153 
00154   INTUSE(_IO_link_in) (fp);
00155   fp->file._fileno = -1;
00156 }
00157 INTDEF2(_IO_new_file_init, _IO_file_init)
00158 
00159 int
00160 _IO_new_file_close_it (fp)
00161      _IO_FILE *fp;
00162 {
00163   int write_status, close_status;
00164   if (!_IO_file_is_open (fp))
00165     return EOF;
00166 
00167   if ((fp->_flags & _IO_NO_WRITES) == 0
00168       && (fp->_flags & _IO_CURRENTLY_PUTTING) != 0)
00169     write_status = _IO_do_flush (fp);
00170   else
00171     write_status = 0;
00172 
00173   INTUSE(_IO_unsave_markers) (fp);
00174 
00175   close_status = _IO_SYSCLOSE (fp);
00176 
00177   /* Free buffer. */
00178 #if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T
00179   if (fp->_mode > 0)
00180     {
00181       if (_IO_have_wbackup (fp))
00182        INTUSE(_IO_free_wbackup_area) (fp);
00183       INTUSE(_IO_wsetb) (fp, NULL, NULL, 0);
00184       _IO_wsetg (fp, NULL, NULL, NULL);
00185       _IO_wsetp (fp, NULL, NULL);
00186     }
00187 #endif
00188   INTUSE(_IO_setb) (fp, NULL, NULL, 0);
00189   _IO_setg (fp, NULL, NULL, NULL);
00190   _IO_setp (fp, NULL, NULL);
00191 
00192   INTUSE(_IO_un_link) ((struct _IO_FILE_plus *) fp);
00193   fp->_flags = _IO_MAGIC|CLOSED_FILEBUF_FLAGS;
00194   fp->_fileno = -1;
00195   fp->_offset = _IO_pos_BAD;
00196 
00197   return close_status ? close_status : write_status;
00198 }
00199 INTDEF2(_IO_new_file_close_it, _IO_file_close_it)
00200 
00201 void
00202 _IO_new_file_finish (fp, dummy)
00203      _IO_FILE *fp;
00204      int dummy;
00205 {
00206   if (_IO_file_is_open (fp))
00207     {
00208       _IO_do_flush (fp);
00209       if (!(fp->_flags & _IO_DELETE_DONT_CLOSE))
00210        _IO_SYSCLOSE (fp);
00211     }
00212   INTUSE(_IO_default_finish) (fp, 0);
00213 }
00214 INTDEF2(_IO_new_file_finish, _IO_file_finish)
00215 
00216 _IO_FILE *
00217 _IO_file_open (fp, filename, posix_mode, prot, read_write, is32not64)
00218      _IO_FILE *fp;
00219      const char *filename;
00220      int posix_mode;
00221      int prot;
00222      int read_write;
00223      int is32not64;
00224 {
00225   int fdesc;
00226 #ifdef _LIBC
00227   if (__builtin_expect (fp->_flags2 & _IO_FLAGS2_NOTCANCEL, 0))
00228     fdesc = open_not_cancel (filename,
00229                           posix_mode | (is32not64 ? 0 : O_LARGEFILE), prot);
00230   else
00231     fdesc = open (filename, posix_mode | (is32not64 ? 0 : O_LARGEFILE), prot);
00232 #else
00233   fdesc = open (filename, posix_mode, prot);
00234 #endif
00235   if (fdesc < 0)
00236     return NULL;
00237   fp->_fileno = fdesc;
00238   _IO_mask_flags (fp, read_write,_IO_NO_READS+_IO_NO_WRITES+_IO_IS_APPENDING);
00239   if ((read_write & _IO_IS_APPENDING) && (read_write & _IO_NO_READS))
00240     if (_IO_SEEKOFF (fp, (_IO_off64_t)0, _IO_seek_end, _IOS_INPUT|_IOS_OUTPUT)
00241        == _IO_pos_BAD && errno != ESPIPE)
00242       {
00243        close_not_cancel (fdesc);
00244        return NULL;
00245       }
00246   INTUSE(_IO_link_in) ((struct _IO_FILE_plus *) fp);
00247   return fp;
00248 }
00249 libc_hidden_def (_IO_file_open)
00250 
00251 _IO_FILE *
00252 _IO_new_file_fopen (fp, filename, mode, is32not64)
00253      _IO_FILE *fp;
00254      const char *filename;
00255      const char *mode;
00256      int is32not64;
00257 {
00258   int oflags = 0, omode;
00259   int read_write;
00260   int oprot = 0666;
00261   int i;
00262   _IO_FILE *result;
00263 #ifdef _LIBC
00264   const char *cs;
00265   const char *last_recognized;
00266 #endif
00267 
00268   if (_IO_file_is_open (fp))
00269     return 0;
00270   switch (*mode)
00271     {
00272     case 'r':
00273       omode = O_RDONLY;
00274       read_write = _IO_NO_WRITES;
00275       break;
00276     case 'w':
00277       omode = O_WRONLY;
00278       oflags = O_CREAT|O_TRUNC;
00279       read_write = _IO_NO_READS;
00280       break;
00281     case 'a':
00282       omode = O_WRONLY;
00283       oflags = O_CREAT|O_APPEND;
00284       read_write = _IO_NO_READS|_IO_IS_APPENDING;
00285       break;
00286     default:
00287       __set_errno (EINVAL);
00288       return NULL;
00289     }
00290 #ifdef _LIBC
00291   last_recognized = mode;
00292 #endif
00293   for (i = 1; i < 6; ++i)
00294     {
00295       switch (*++mode)
00296        {
00297        case '\0':
00298          break;
00299        case '+':
00300          omode = O_RDWR;
00301          read_write &= _IO_IS_APPENDING;
00302 #ifdef _LIBC
00303          last_recognized = mode;
00304 #endif
00305          continue;
00306        case 'x':
00307          oflags |= O_EXCL;
00308 #ifdef _LIBC
00309          last_recognized = mode;
00310 #endif
00311          continue;
00312        case 'b':
00313 #ifdef _LIBC
00314          last_recognized = mode;
00315 #endif
00316          continue;
00317        case 'm':
00318          fp->_flags2 |= _IO_FLAGS2_MMAP;
00319          continue;
00320        case 'c':
00321          fp->_flags2 |= _IO_FLAGS2_NOTCANCEL;
00322          break;
00323 #ifdef O_CLOEXEC
00324        case 'e':
00325          oflags |= O_CLOEXEC;
00326          break;
00327 #endif
00328        default:
00329          /* Ignore.  */
00330          continue;
00331        }
00332       break;
00333     }
00334 
00335   result = _IO_file_open (fp, filename, omode|oflags, oprot, read_write,
00336                        is32not64);
00337 
00338 
00339 #ifdef _LIBC
00340   if (result != NULL)
00341     {
00342       /* Test whether the mode string specifies the conversion.  */
00343       cs = strstr (last_recognized + 1, ",ccs=");
00344       if (cs != NULL)
00345        {
00346          /* Yep.  Load the appropriate conversions and set the orientation
00347             to wide.  */
00348          struct gconv_fcts fcts;
00349          struct _IO_codecvt *cc;
00350          char *endp = __strchrnul (cs + 5, ',');
00351          char ccs[endp - (cs + 5) + 3];
00352 
00353          *((char *) __mempcpy (ccs, cs + 5, endp - (cs + 5))) = '\0';
00354          strip (ccs, ccs);
00355 
00356          if (__wcsmbs_named_conv (&fcts, ccs[2] == '\0'
00357                                ? upstr (ccs, cs + 5) : ccs) != 0)
00358            {
00359              /* Something went wrong, we cannot load the conversion modules.
00360                This means we cannot proceed since the user explicitly asked
00361                for these.  */
00362              (void) INTUSE(_IO_file_close_it) (fp);
00363              __set_errno (EINVAL);
00364              return NULL;
00365            }
00366 
00367          assert (fcts.towc_nsteps == 1);
00368          assert (fcts.tomb_nsteps == 1);
00369 
00370          fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_read_end;
00371          fp->_wide_data->_IO_write_ptr = fp->_wide_data->_IO_write_base;
00372 
00373          /* Clear the state.  We start all over again.  */
00374          memset (&fp->_wide_data->_IO_state, '\0', sizeof (__mbstate_t));
00375          memset (&fp->_wide_data->_IO_last_state, '\0', sizeof (__mbstate_t));
00376 
00377          cc = fp->_codecvt = &fp->_wide_data->_codecvt;
00378 
00379          /* The functions are always the same.  */
00380          *cc = __libio_codecvt;
00381 
00382          cc->__cd_in.__cd.__nsteps = fcts.towc_nsteps;
00383          cc->__cd_in.__cd.__steps = fcts.towc;
00384 
00385          cc->__cd_in.__cd.__data[0].__invocation_counter = 0;
00386          cc->__cd_in.__cd.__data[0].__internal_use = 1;
00387          cc->__cd_in.__cd.__data[0].__flags = __GCONV_IS_LAST;
00388          cc->__cd_in.__cd.__data[0].__statep = &result->_wide_data->_IO_state;
00389 
00390          /* XXX For now no transliteration.  */
00391          cc->__cd_in.__cd.__data[0].__trans = NULL;
00392 
00393          cc->__cd_out.__cd.__nsteps = fcts.tomb_nsteps;
00394          cc->__cd_out.__cd.__steps = fcts.tomb;
00395 
00396          cc->__cd_out.__cd.__data[0].__invocation_counter = 0;
00397          cc->__cd_out.__cd.__data[0].__internal_use = 1;
00398          cc->__cd_out.__cd.__data[0].__flags = __GCONV_IS_LAST;
00399          cc->__cd_out.__cd.__data[0].__statep =
00400            &result->_wide_data->_IO_state;
00401 
00402          /* And now the transliteration.  */
00403          cc->__cd_out.__cd.__data[0].__trans = &__libio_translit;
00404 
00405          /* From now on use the wide character callback functions.  */
00406          ((struct _IO_FILE_plus *) fp)->vtable = fp->_wide_data->_wide_vtable;
00407 
00408          /* Set the mode now.  */
00409          result->_mode = 1;
00410        }
00411     }
00412 #endif /* GNU libc */
00413 
00414   return result;
00415 }
00416 INTDEF2(_IO_new_file_fopen, _IO_file_fopen)
00417 
00418 _IO_FILE *
00419 _IO_new_file_attach (fp, fd)
00420      _IO_FILE *fp;
00421      int fd;
00422 {
00423   if (_IO_file_is_open (fp))
00424     return NULL;
00425   fp->_fileno = fd;
00426   fp->_flags &= ~(_IO_NO_READS+_IO_NO_WRITES);
00427   fp->_flags |= _IO_DELETE_DONT_CLOSE;
00428   /* Get the current position of the file. */
00429   /* We have to do that since that may be junk. */
00430   fp->_offset = _IO_pos_BAD;
00431   int save_errno = errno;
00432   if (_IO_SEEKOFF (fp, (_IO_off64_t)0, _IO_seek_cur, _IOS_INPUT|_IOS_OUTPUT)
00433       == _IO_pos_BAD && errno != ESPIPE)
00434     return NULL;
00435   __set_errno (save_errno);
00436   return fp;
00437 }
00438 INTDEF2(_IO_new_file_attach, _IO_file_attach)
00439 
00440 _IO_FILE *
00441 _IO_new_file_setbuf (fp, p, len)
00442      _IO_FILE *fp;
00443      char *p;
00444      _IO_ssize_t len;
00445 {
00446   if (_IO_default_setbuf (fp, p, len) == NULL)
00447     return NULL;
00448 
00449   fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end
00450     = fp->_IO_buf_base;
00451   _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
00452 
00453   return fp;
00454 }
00455 INTDEF2(_IO_new_file_setbuf, _IO_file_setbuf)
00456 
00457 
00458 _IO_FILE *
00459 _IO_file_setbuf_mmap (fp, p, len)
00460      _IO_FILE *fp;
00461      char *p;
00462      _IO_ssize_t len;
00463 {
00464   _IO_FILE *result;
00465 
00466   /* Change the function table.  */
00467   _IO_JUMPS ((struct _IO_FILE_plus *) fp) = &_IO_file_jumps;
00468   fp->_wide_data->_wide_vtable = &_IO_wfile_jumps;
00469 
00470   /* And perform the normal operation.  */
00471   result = _IO_new_file_setbuf (fp, p, len);
00472 
00473   /* If the call failed, restore to using mmap.  */
00474   if (result == NULL)
00475     {
00476       _IO_JUMPS ((struct _IO_FILE_plus *) fp) = &_IO_file_jumps_mmap;
00477       fp->_wide_data->_wide_vtable = &_IO_wfile_jumps_mmap;
00478     }
00479 
00480   return result;
00481 }
00482 
00483 static _IO_size_t new_do_write (_IO_FILE *, const char *, _IO_size_t);
00484 
00485 /* Write TO_DO bytes from DATA to FP.
00486    Then mark FP as having empty buffers. */
00487 
00488 int
00489 _IO_new_do_write (fp, data, to_do)
00490      _IO_FILE *fp;
00491      const char *data;
00492      _IO_size_t to_do;
00493 {
00494   return (to_do == 0
00495          || (_IO_size_t) new_do_write (fp, data, to_do) == to_do) ? 0 : EOF;
00496 }
00497 INTDEF2(_IO_new_do_write, _IO_do_write)
00498 
00499 static
00500 _IO_size_t
00501 new_do_write (fp, data, to_do)
00502      _IO_FILE *fp;
00503      const char *data;
00504      _IO_size_t to_do;
00505 {
00506   _IO_size_t count;
00507   if (fp->_flags & _IO_IS_APPENDING)
00508     /* On a system without a proper O_APPEND implementation,
00509        you would need to sys_seek(0, SEEK_END) here, but is
00510        is not needed nor desirable for Unix- or Posix-like systems.
00511        Instead, just indicate that offset (before and after) is
00512        unpredictable. */
00513     fp->_offset = _IO_pos_BAD;
00514   else if (fp->_IO_read_end != fp->_IO_write_base)
00515     {
00516       _IO_off64_t new_pos
00517        = _IO_SYSSEEK (fp, fp->_IO_write_base - fp->_IO_read_end, 1);
00518       if (new_pos == _IO_pos_BAD)
00519        return 0;
00520       fp->_offset = new_pos;
00521     }
00522   count = _IO_SYSWRITE (fp, data, to_do);
00523   if (fp->_cur_column && count)
00524     fp->_cur_column = INTUSE(_IO_adjust_column) (fp->_cur_column - 1, data,
00525                                            count) + 1;
00526   _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
00527   fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_buf_base;
00528   fp->_IO_write_end = (fp->_mode <= 0
00529                      && (fp->_flags & (_IO_LINE_BUF+_IO_UNBUFFERED))
00530                      ? fp->_IO_buf_base : fp->_IO_buf_end);
00531   return count;
00532 }
00533 
00534 int
00535 _IO_new_file_underflow (fp)
00536      _IO_FILE *fp;
00537 {
00538   _IO_ssize_t count;
00539 #if 0
00540   /* SysV does not make this test; take it out for compatibility */
00541   if (fp->_flags & _IO_EOF_SEEN)
00542     return (EOF);
00543 #endif
00544 
00545   if (fp->_flags & _IO_NO_READS)
00546     {
00547       fp->_flags |= _IO_ERR_SEEN;
00548       __set_errno (EBADF);
00549       return EOF;
00550     }
00551   if (fp->_IO_read_ptr < fp->_IO_read_end)
00552     return *(unsigned char *) fp->_IO_read_ptr;
00553 
00554   if (fp->_IO_buf_base == NULL)
00555     {
00556       /* Maybe we already have a push back pointer.  */
00557       if (fp->_IO_save_base != NULL)
00558        {
00559          free (fp->_IO_save_base);
00560          fp->_flags &= ~_IO_IN_BACKUP;
00561        }
00562       INTUSE(_IO_doallocbuf) (fp);
00563     }
00564 
00565   /* Flush all line buffered files before reading. */
00566   /* FIXME This can/should be moved to genops ?? */
00567   if (fp->_flags & (_IO_LINE_BUF|_IO_UNBUFFERED))
00568     {
00569 #if 0
00570       INTUSE(_IO_flush_all_linebuffered) ();
00571 #else
00572       /* We used to flush all line-buffered stream.  This really isn't
00573         required by any standard.  My recollection is that
00574         traditional Unix systems did this for stdout.  stderr better
00575         not be line buffered.  So we do just that here
00576         explicitly.  --drepper */
00577       _IO_acquire_lock (_IO_stdout);
00578 
00579       if ((_IO_stdout->_flags & (_IO_LINKED | _IO_NO_WRITES | _IO_LINE_BUF))
00580          == (_IO_LINKED | _IO_LINE_BUF))
00581        _IO_OVERFLOW (_IO_stdout, EOF);
00582 
00583       _IO_release_lock (_IO_stdout);
00584 #endif
00585     }
00586 
00587   INTUSE(_IO_switch_to_get_mode) (fp);
00588 
00589   /* This is very tricky. We have to adjust those
00590      pointers before we call _IO_SYSREAD () since
00591      we may longjump () out while waiting for
00592      input. Those pointers may be screwed up. H.J. */
00593   fp->_IO_read_base = fp->_IO_read_ptr = fp->_IO_buf_base;
00594   fp->_IO_read_end = fp->_IO_buf_base;
00595   fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end
00596     = fp->_IO_buf_base;
00597 
00598   count = _IO_SYSREAD (fp, fp->_IO_buf_base,
00599                      fp->_IO_buf_end - fp->_IO_buf_base);
00600   if (count <= 0)
00601     {
00602       if (count == 0)
00603        fp->_flags |= _IO_EOF_SEEN;
00604       else
00605        fp->_flags |= _IO_ERR_SEEN, count = 0;
00606   }
00607   fp->_IO_read_end += count;
00608   if (count == 0)
00609     return EOF;
00610   if (fp->_offset != _IO_pos_BAD)
00611     _IO_pos_adjust (fp->_offset, count);
00612   return *(unsigned char *) fp->_IO_read_ptr;
00613 }
00614 INTDEF2(_IO_new_file_underflow, _IO_file_underflow)
00615 
00616 /* Guts of underflow callback if we mmap the file.  This stats the file and
00617    updates the stream state to match.  In the normal case we return zero.
00618    If the file is no longer eligible for mmap, its jump tables are reset to
00619    the vanilla ones and we return nonzero.  */
00620 static int
00621 mmap_remap_check (_IO_FILE *fp)
00622 {
00623   struct _G_stat64 st;
00624 
00625   if (_IO_SYSSTAT (fp, &st) == 0
00626       && S_ISREG (st.st_mode) && st.st_size != 0
00627       /* Limit the file size to 1MB for 32-bit machines.  */
00628       && (sizeof (ptrdiff_t) > 4 || st.st_size < 1*1024*1024))
00629     {
00630       const size_t pagesize = __getpagesize ();
00631 # define ROUNDED(x)  (((x) + pagesize - 1) & ~(pagesize - 1))
00632       if (ROUNDED (st.st_size) < ROUNDED (fp->_IO_buf_end
00633                                      - fp->_IO_buf_base))
00634        {
00635          /* We can trim off some pages past the end of the file.  */
00636          (void) __munmap (fp->_IO_buf_base + ROUNDED (st.st_size),
00637                         ROUNDED (fp->_IO_buf_end - fp->_IO_buf_base)
00638                         - ROUNDED (st.st_size));
00639          fp->_IO_buf_end = fp->_IO_buf_base + st.st_size;
00640        }
00641       else if (ROUNDED (st.st_size) > ROUNDED (fp->_IO_buf_end
00642                                           - fp->_IO_buf_base))
00643        {
00644          /* The file added some pages.  We need to remap it.  */
00645          void *p;
00646 #ifdef _G_HAVE_MREMAP
00647          p = __mremap (fp->_IO_buf_base, ROUNDED (fp->_IO_buf_end
00648                                              - fp->_IO_buf_base),
00649                      ROUNDED (st.st_size), MREMAP_MAYMOVE);
00650          if (p == MAP_FAILED)
00651            {
00652              (void) __munmap (fp->_IO_buf_base,
00653                             fp->_IO_buf_end - fp->_IO_buf_base);
00654              goto punt;
00655            }
00656 #else
00657          (void) __munmap (fp->_IO_buf_base,
00658                         fp->_IO_buf_end - fp->_IO_buf_base);
00659 # ifdef _G_MMAP64
00660          p = _G_MMAP64 (NULL, st.st_size, PROT_READ, MAP_SHARED,
00661                       fp->_fileno, 0);
00662 # else
00663          p = __mmap (NULL, st.st_size, PROT_READ, MAP_SHARED,
00664                     fp->_fileno, 0);
00665 # endif
00666          if (p == MAP_FAILED)
00667            goto punt;
00668 #endif
00669          fp->_IO_buf_base = p;
00670          fp->_IO_buf_end = fp->_IO_buf_base + st.st_size;
00671        }
00672       else
00673        {
00674          /* The number of pages didn't change.  */
00675          fp->_IO_buf_end = fp->_IO_buf_base + st.st_size;
00676        }
00677 # undef ROUNDED
00678 
00679       fp->_offset -= fp->_IO_read_end - fp->_IO_read_ptr;
00680       _IO_setg (fp, fp->_IO_buf_base,
00681               fp->_offset < fp->_IO_buf_end - fp->_IO_buf_base
00682               ? fp->_IO_buf_base + fp->_offset : fp->_IO_buf_end,
00683               fp->_IO_buf_end);
00684 
00685       /* If we are already positioned at or past the end of the file, don't
00686         change the current offset.  If not, seek past what we have mapped,
00687         mimicking the position left by a normal underflow reading into its
00688         buffer until EOF.  */
00689 
00690       if (fp->_offset < fp->_IO_buf_end - fp->_IO_buf_base)
00691        {
00692          if (
00693 # ifdef _G_LSEEK64
00694              _G_LSEEK64
00695 # else
00696              __lseek
00697 # endif
00698              (fp->_fileno, fp->_IO_buf_end - fp->_IO_buf_base, SEEK_SET)
00699              != fp->_IO_buf_end - fp->_IO_buf_base)
00700            fp->_flags |= _IO_ERR_SEEN;
00701          else
00702            fp->_offset = fp->_IO_buf_end - fp->_IO_buf_base;
00703        }
00704 
00705       return 0;
00706     }
00707   else
00708     {
00709       /* Life is no longer good for mmap.  Punt it.  */
00710       (void) __munmap (fp->_IO_buf_base,
00711                      fp->_IO_buf_end - fp->_IO_buf_base);
00712     punt:
00713       fp->_IO_buf_base = fp->_IO_buf_end = NULL;
00714       _IO_setg (fp, NULL, NULL, NULL);
00715       if (fp->_mode <= 0)
00716        _IO_JUMPS ((struct _IO_FILE_plus *) fp) = &_IO_file_jumps;
00717       else
00718        _IO_JUMPS ((struct _IO_FILE_plus *) fp) = &_IO_wfile_jumps;
00719       fp->_wide_data->_wide_vtable = &_IO_wfile_jumps;
00720 
00721       return 1;
00722     }
00723 }
00724 
00725 /* Special callback replacing the underflow callbacks if we mmap the file.  */
00726 int
00727 _IO_file_underflow_mmap (_IO_FILE *fp)
00728 {
00729   if (fp->_IO_read_ptr < fp->_IO_read_end)
00730     return *(unsigned char *) fp->_IO_read_ptr;
00731 
00732   if (__builtin_expect (mmap_remap_check (fp), 0))
00733     /* We punted to the regular file functions.  */
00734     return _IO_UNDERFLOW (fp);
00735 
00736   if (fp->_IO_read_ptr < fp->_IO_read_end)
00737     return *(unsigned char *) fp->_IO_read_ptr;
00738 
00739   fp->_flags |= _IO_EOF_SEEN;
00740   return EOF;
00741 }
00742 
00743 static void
00744 decide_maybe_mmap (_IO_FILE *fp)
00745 {
00746   /* We use the file in read-only mode.  This could mean we can
00747      mmap the file and use it without any copying.  But not all
00748      file descriptors are for mmap-able objects and on 32-bit
00749      machines we don't want to map files which are too large since
00750      this would require too much virtual memory.  */
00751   struct _G_stat64 st;
00752 
00753   if (_IO_SYSSTAT (fp, &st) == 0
00754       && S_ISREG (st.st_mode) && st.st_size != 0
00755       /* Limit the file size to 1MB for 32-bit machines.  */
00756       && (sizeof (ptrdiff_t) > 4 || st.st_size < 1*1024*1024)
00757       /* Sanity check.  */
00758       && (fp->_offset == _IO_pos_BAD || fp->_offset <= st.st_size))
00759     {
00760       /* Try to map the file.  */
00761       void *p;
00762 
00763 # ifdef _G_MMAP64
00764       p = _G_MMAP64 (NULL, st.st_size, PROT_READ, MAP_SHARED, fp->_fileno, 0);
00765 # else
00766       p = __mmap (NULL, st.st_size, PROT_READ, MAP_SHARED, fp->_fileno, 0);
00767 # endif
00768       if (p != MAP_FAILED)
00769        {
00770          /* OK, we managed to map the file.  Set the buffer up and use a
00771             special jump table with simplified underflow functions which
00772             never tries to read anything from the file.  */
00773 
00774          if (
00775 # ifdef _G_LSEEK64
00776              _G_LSEEK64
00777 # else
00778              __lseek
00779 # endif
00780              (fp->_fileno, st.st_size, SEEK_SET) != st.st_size)
00781            {
00782              (void) __munmap (p, st.st_size);
00783              fp->_offset = _IO_pos_BAD;
00784            }
00785          else
00786            {
00787              INTUSE(_IO_setb) (fp, p, (char *) p + st.st_size, 0);
00788 
00789              if (fp->_offset == _IO_pos_BAD)
00790               fp->_offset = 0;
00791 
00792              _IO_setg (fp, p, p + fp->_offset, p + st.st_size);
00793              fp->_offset = st.st_size;
00794 
00795              if (fp->_mode <= 0)
00796               _IO_JUMPS ((struct _IO_FILE_plus *)fp) = &_IO_file_jumps_mmap;
00797              else
00798               _IO_JUMPS ((struct _IO_FILE_plus *)fp) = &_IO_wfile_jumps_mmap;
00799              fp->_wide_data->_wide_vtable = &_IO_wfile_jumps_mmap;
00800 
00801              return;
00802            }
00803        }
00804     }
00805 
00806   /* We couldn't use mmap, so revert to the vanilla file operations.  */
00807 
00808   if (fp->_mode <= 0)
00809     _IO_JUMPS ((struct _IO_FILE_plus *) fp) = &_IO_file_jumps;
00810   else
00811     _IO_JUMPS ((struct _IO_FILE_plus *) fp) = &_IO_wfile_jumps;
00812   fp->_wide_data->_wide_vtable = &_IO_wfile_jumps;
00813 }
00814 
00815 int
00816 _IO_file_underflow_maybe_mmap (_IO_FILE *fp)
00817 {
00818   /* This is the first read attempt.  Choose mmap or vanilla operations
00819      and then punt to the chosen underflow routine.  */
00820   decide_maybe_mmap (fp);
00821   return _IO_UNDERFLOW (fp);
00822 }
00823 
00824 
00825 int
00826 _IO_new_file_overflow (f, ch)
00827       _IO_FILE *f;
00828       int ch;
00829 {
00830   if (f->_flags & _IO_NO_WRITES) /* SET ERROR */
00831     {
00832       f->_flags |= _IO_ERR_SEEN;
00833       __set_errno (EBADF);
00834       return EOF;
00835     }
00836   /* If currently reading or no buffer allocated. */
00837   if ((f->_flags & _IO_CURRENTLY_PUTTING) == 0 || f->_IO_write_base == NULL)
00838     {
00839       /* Allocate a buffer if needed. */
00840       if (f->_IO_write_base == NULL)
00841        {
00842          INTUSE(_IO_doallocbuf) (f);
00843          _IO_setg (f, f->_IO_buf_base, f->_IO_buf_base, f->_IO_buf_base);
00844        }
00845       /* Otherwise must be currently reading.
00846         If _IO_read_ptr (and hence also _IO_read_end) is at the buffer end,
00847         logically slide the buffer forwards one block (by setting the
00848         read pointers to all point at the beginning of the block).  This
00849         makes room for subsequent output.
00850         Otherwise, set the read pointers to _IO_read_end (leaving that
00851         alone, so it can continue to correspond to the external position). */
00852       if (__builtin_expect (_IO_in_backup (f), 0))
00853        {
00854          size_t nbackup = f->_IO_read_end - f->_IO_read_ptr;
00855          INTUSE(_IO_free_backup_area) (f);
00856          f->_IO_read_base -= MIN (nbackup,
00857                                f->_IO_read_base - f->_IO_buf_base);
00858          f->_IO_read_ptr = f->_IO_read_base;
00859        }
00860 
00861       if (f->_IO_read_ptr == f->_IO_buf_end)
00862        f->_IO_read_end = f->_IO_read_ptr = f->_IO_buf_base;
00863       f->_IO_write_ptr = f->_IO_read_ptr;
00864       f->_IO_write_base = f->_IO_write_ptr;
00865       f->_IO_write_end = f->_IO_buf_end;
00866       f->_IO_read_base = f->_IO_read_ptr = f->_IO_read_end;
00867 
00868       f->_flags |= _IO_CURRENTLY_PUTTING;
00869       if (f->_mode <= 0 && f->_flags & (_IO_LINE_BUF+_IO_UNBUFFERED))
00870        f->_IO_write_end = f->_IO_write_ptr;
00871     }
00872   if (ch == EOF)
00873     return INTUSE(_IO_do_write) (f, f->_IO_write_base,
00874                              f->_IO_write_ptr - f->_IO_write_base);
00875   if (f->_IO_write_ptr == f->_IO_buf_end ) /* Buffer is really full */
00876     if (_IO_do_flush (f) == EOF)
00877       return EOF;
00878   *f->_IO_write_ptr++ = ch;
00879   if ((f->_flags & _IO_UNBUFFERED)
00880       || ((f->_flags & _IO_LINE_BUF) && ch == '\n'))
00881     if (INTUSE(_IO_do_write) (f, f->_IO_write_base,
00882                            f->_IO_write_ptr - f->_IO_write_base) == EOF)
00883       return EOF;
00884   return (unsigned char) ch;
00885 }
00886 INTDEF2(_IO_new_file_overflow, _IO_file_overflow)
00887 
00888 int
00889 _IO_new_file_sync (fp)
00890      _IO_FILE *fp;
00891 {
00892   _IO_ssize_t delta;
00893   int retval = 0;
00894 
00895   /*    char* ptr = cur_ptr(); */
00896   if (fp->_IO_write_ptr > fp->_IO_write_base)
00897     if (_IO_do_flush(fp)) return EOF;
00898   delta = fp->_IO_read_ptr - fp->_IO_read_end;
00899   if (delta != 0)
00900     {
00901 #ifdef TODO
00902       if (_IO_in_backup (fp))
00903        delta -= eGptr () - Gbase ();
00904 #endif
00905       _IO_off64_t new_pos = _IO_SYSSEEK (fp, delta, 1);
00906       if (new_pos != (_IO_off64_t) EOF)
00907        fp->_IO_read_end = fp->_IO_read_ptr;
00908 #ifdef ESPIPE
00909       else if (errno == ESPIPE)
00910        ; /* Ignore error from unseekable devices. */
00911 #endif
00912       else
00913        retval = EOF;
00914     }
00915   if (retval != EOF)
00916     fp->_offset = _IO_pos_BAD;
00917   /* FIXME: Cleanup - can this be shared? */
00918   /*    setg(base(), ptr, ptr); */
00919   return retval;
00920 }
00921 INTDEF2(_IO_new_file_sync, _IO_file_sync)
00922 
00923 static int
00924 _IO_file_sync_mmap (_IO_FILE *fp)
00925 {
00926   if (fp->_IO_read_ptr != fp->_IO_read_end)
00927     {
00928 #ifdef TODO
00929       if (_IO_in_backup (fp))
00930        delta -= eGptr () - Gbase ();
00931 #endif
00932       if (
00933 # ifdef _G_LSEEK64
00934          _G_LSEEK64
00935 # else
00936          __lseek
00937 # endif
00938          (fp->_fileno, fp->_IO_read_ptr - fp->_IO_buf_base, SEEK_SET)
00939          != fp->_IO_read_ptr - fp->_IO_buf_base)
00940        {
00941          fp->_flags |= _IO_ERR_SEEN;
00942          return EOF;
00943        }
00944     }
00945   fp->_offset = fp->_IO_read_ptr - fp->_IO_buf_base;
00946   fp->_IO_read_end = fp->_IO_read_ptr = fp->_IO_read_base;
00947   return 0;
00948 }
00949 
00950 
00951 _IO_off64_t
00952 _IO_new_file_seekoff (fp, offset, dir, mode)
00953      _IO_FILE *fp;
00954      _IO_off64_t offset;
00955      int dir;
00956      int mode;
00957 {
00958   _IO_off64_t result;
00959   _IO_off64_t delta, new_offset;
00960   long count;
00961   /* POSIX.1 8.2.3.7 says that after a call the fflush() the file
00962      offset of the underlying file must be exact.  */
00963   int must_be_exact = (fp->_IO_read_base == fp->_IO_read_end
00964                      && fp->_IO_write_base == fp->_IO_write_ptr);
00965 
00966   if (mode == 0)
00967     dir = _IO_seek_cur, offset = 0; /* Don't move any pointers. */
00968 
00969   /* Flush unwritten characters.
00970      (This may do an unneeded write if we seek within the buffer.
00971      But to be able to switch to reading, we would need to set
00972      egptr to ptr.  That can't be done in the current design,
00973      which assumes file_ptr() is eGptr.  Anyway, since we probably
00974      end up flushing when we close(), it doesn't make much difference.)
00975      FIXME: simulate mem-papped files. */
00976 
00977   if (fp->_IO_write_ptr > fp->_IO_write_base || _IO_in_put_mode (fp))
00978     if (INTUSE(_IO_switch_to_get_mode) (fp))
00979       return EOF;
00980 
00981   if (fp->_IO_buf_base == NULL)
00982     {
00983       /* It could be that we already have a pushback buffer.  */
00984       if (fp->_IO_read_base != NULL)
00985        {
00986          free (fp->_IO_read_base);
00987          fp->_flags &= ~_IO_IN_BACKUP;
00988        }
00989       INTUSE(_IO_doallocbuf) (fp);
00990       _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
00991       _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
00992     }
00993 
00994   switch (dir)
00995     {
00996     case _IO_seek_cur:
00997       /* Adjust for read-ahead (bytes is buffer). */
00998       offset -= fp->_IO_read_end - fp->_IO_read_ptr;
00999       if (fp->_offset == _IO_pos_BAD)
01000         {
01001           if (mode != 0)
01002             goto dumb;
01003           else
01004             {
01005               result = _IO_SYSSEEK (fp, 0, dir);
01006               if (result == EOF)
01007                 return result;
01008 
01009               fp->_offset = result;
01010             }
01011         }
01012       /* Make offset absolute, assuming current pointer is file_ptr(). */
01013       offset += fp->_offset;
01014       if (offset < 0)
01015        {
01016          __set_errno (EINVAL);
01017          return EOF;
01018        }
01019 
01020       dir = _IO_seek_set;
01021       break;
01022     case _IO_seek_set:
01023       break;
01024     case _IO_seek_end:
01025       {
01026        struct _G_stat64 st;
01027        if (_IO_SYSSTAT (fp, &st) == 0 && S_ISREG (st.st_mode))
01028          {
01029            offset += st.st_size;
01030            dir = _IO_seek_set;
01031          }
01032        else
01033          goto dumb;
01034       }
01035     }
01036   /* At this point, dir==_IO_seek_set. */
01037 
01038   /* If we are only interested in the current position we've found it now.  */
01039   if (mode == 0)
01040     return offset;
01041 
01042   /* If destination is within current buffer, optimize: */
01043   if (fp->_offset != _IO_pos_BAD && fp->_IO_read_base != NULL
01044       && !_IO_in_backup (fp))
01045     {
01046       _IO_off64_t start_offset = (fp->_offset
01047                               - (fp->_IO_read_end - fp->_IO_buf_base));
01048       if (offset >= start_offset && offset < fp->_offset)
01049        {
01050          _IO_setg (fp, fp->_IO_buf_base,
01051                   fp->_IO_buf_base + (offset - start_offset),
01052                   fp->_IO_read_end);
01053          _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
01054 
01055          _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
01056          goto resync;
01057        }
01058     }
01059 
01060   if (fp->_flags & _IO_NO_READS)
01061     goto dumb;
01062 
01063   /* Try to seek to a block boundary, to improve kernel page management. */
01064   new_offset = offset & ~(fp->_IO_buf_end - fp->_IO_buf_base - 1);
01065   delta = offset - new_offset;
01066   if (delta > fp->_IO_buf_end - fp->_IO_buf_base)
01067     {
01068       new_offset = offset;
01069       delta = 0;
01070     }
01071   result = _IO_SYSSEEK (fp, new_offset, 0);
01072   if (result < 0)
01073     return EOF;
01074   if (delta == 0)
01075     count = 0;
01076   else
01077     {
01078       count = _IO_SYSREAD (fp, fp->_IO_buf_base,
01079                         (must_be_exact
01080                          ? delta : fp->_IO_buf_end - fp->_IO_buf_base));
01081       if (count < delta)
01082        {
01083          /* We weren't allowed to read, but try to seek the remainder. */
01084          offset = count == EOF ? delta : delta-count;
01085          dir = _IO_seek_cur;
01086          goto dumb;
01087        }
01088     }
01089   _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base + delta,
01090            fp->_IO_buf_base + count);
01091   _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
01092   fp->_offset = result + count;
01093   _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
01094   return offset;
01095  dumb:
01096 
01097   INTUSE(_IO_unsave_markers) (fp);
01098   result = _IO_SYSSEEK (fp, offset, dir);
01099   if (result != EOF)
01100     {
01101       _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
01102       fp->_offset = result;
01103       _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
01104       _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
01105     }
01106   return result;
01107 
01108 resync:
01109   /* We need to do it since it is possible that the file offset in
01110      the kernel may be changed behind our back. It may happen when
01111      we fopen a file and then do a fork. One process may access the
01112      the file and the kernel file offset will be changed. */
01113   if (fp->_offset >= 0)
01114     _IO_SYSSEEK (fp, fp->_offset, 0);
01115 
01116   return offset;
01117 }
01118 INTDEF2(_IO_new_file_seekoff, _IO_file_seekoff)
01119 
01120 _IO_off64_t
01121 _IO_file_seekoff_mmap (fp, offset, dir, mode)
01122      _IO_FILE *fp;
01123      _IO_off64_t offset;
01124      int dir;
01125      int mode;
01126 {
01127   _IO_off64_t result;
01128 
01129   /* If we are only interested in the current position, calculate it and
01130      return right now.  This calculation does the right thing when we are
01131      using a pushback buffer, but in the usual case has the same value as
01132      (fp->_IO_read_ptr - fp->_IO_buf_base).  */
01133   if (mode == 0)
01134     return fp->_offset - (fp->_IO_read_end - fp->_IO_read_ptr);
01135 
01136   switch (dir)
01137     {
01138     case _IO_seek_cur:
01139       /* Adjust for read-ahead (bytes is buffer). */
01140       offset += fp->_IO_read_ptr - fp->_IO_read_base;
01141       break;
01142     case _IO_seek_set:
01143       break;
01144     case _IO_seek_end:
01145       offset += fp->_IO_buf_end - fp->_IO_buf_base;
01146       break;
01147     }
01148   /* At this point, dir==_IO_seek_set. */
01149 
01150   if (offset < 0)
01151     {
01152       /* No negative offsets are valid.  */
01153       __set_errno (EINVAL);
01154       return EOF;
01155     }
01156 
01157   result = _IO_SYSSEEK (fp, offset, 0);
01158   if (result < 0)
01159     return EOF;
01160 
01161   if (offset > fp->_IO_buf_end - fp->_IO_buf_base)
01162     /* One can fseek arbitrarily past the end of the file
01163        and it is meaningless until one attempts to read.
01164        Leave the buffer pointers in EOF state until underflow.  */
01165     _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_end, fp->_IO_buf_end);
01166   else
01167     /* Adjust the read pointers to match the file position,
01168        but so the next read attempt will call underflow.  */
01169     _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base + offset,
01170              fp->_IO_buf_base + offset);
01171 
01172   fp->_offset = result;
01173 
01174   _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
01175 
01176   return offset;
01177 }
01178 
01179 static _IO_off64_t
01180 _IO_file_seekoff_maybe_mmap (_IO_FILE *fp, _IO_off64_t offset, int dir,
01181                           int mode)
01182 {
01183   /* We only get here when we haven't tried to read anything yet.
01184      So there is nothing more useful for us to do here than just
01185      the underlying lseek call.  */
01186 
01187   _IO_off64_t result = _IO_SYSSEEK (fp, offset, dir);
01188   if (result < 0)
01189     return EOF;
01190 
01191   fp->_offset = result;
01192   return result;
01193 }
01194 
01195 _IO_ssize_t
01196 _IO_file_read (fp, buf, size)
01197      _IO_FILE *fp;
01198      void *buf;
01199      _IO_ssize_t size;
01200 {
01201   return (__builtin_expect (fp->_flags2 & _IO_FLAGS2_NOTCANCEL, 0)
01202          ? read_not_cancel (fp->_fileno, buf, size)
01203          : read (fp->_fileno, buf, size));
01204 }
01205 INTDEF(_IO_file_read)
01206 
01207 _IO_off64_t
01208 _IO_file_seek (fp, offset, dir)
01209      _IO_FILE *fp;
01210      _IO_off64_t offset;
01211      int dir;
01212 {
01213 #ifdef _G_LSEEK64
01214   return _G_LSEEK64 (fp->_fileno, offset, dir);
01215 #else
01216   return lseek (fp->_fileno, offset, dir);
01217 #endif
01218 }
01219 INTDEF(_IO_file_seek)
01220 
01221 int
01222 _IO_file_stat (fp, st)
01223      _IO_FILE *fp;
01224      void *st;
01225 {
01226 #ifdef _G_FSTAT64
01227   return _G_FSTAT64 (fp->_fileno, (struct _G_stat64 *) st);
01228 #else
01229   return fstat (fp->_fileno, (struct stat *) st);
01230 #endif
01231 }
01232 INTDEF(_IO_file_stat)
01233 
01234 int
01235 _IO_file_close_mmap (fp)
01236      _IO_FILE *fp;
01237 {
01238   /* In addition to closing the file descriptor we have to unmap the file.  */
01239   (void) __munmap (fp->_IO_buf_base, fp->_IO_buf_end - fp->_IO_buf_base);
01240   fp->_IO_buf_base = fp->_IO_buf_end = NULL;
01241   /* Cancelling close should be avoided if possible since it leaves an
01242      unrecoverable state behind.  */
01243   return close_not_cancel (fp->_fileno);
01244 }
01245 
01246 int
01247 _IO_file_close (fp)
01248      _IO_FILE *fp;
01249 {
01250   /* Cancelling close should be avoided if possible since it leaves an
01251      unrecoverable state behind.  */
01252   return close_not_cancel (fp->_fileno);
01253 }
01254 INTDEF(_IO_file_close)
01255 
01256 _IO_ssize_t
01257 _IO_new_file_write (f, data, n)
01258      _IO_FILE *f;
01259      const void *data;
01260      _IO_ssize_t n;
01261 {
01262   _IO_ssize_t to_do = n;
01263   while (to_do > 0)
01264     {
01265       _IO_ssize_t count = (__builtin_expect (f->_flags2
01266                                         & _IO_FLAGS2_NOTCANCEL, 0)
01267                         ? write_not_cancel (f->_fileno, data, to_do)
01268                         : write (f->_fileno, data, to_do));
01269       if (count < 0)
01270        {
01271          f->_flags |= _IO_ERR_SEEN;
01272          break;
01273         }
01274       to_do -= count;
01275       data = (void *) ((char *) data + count);
01276     }
01277   n -= to_do;
01278   if (f->_offset >= 0)
01279     f->_offset += n;
01280   return n;
01281 }
01282 
01283 _IO_size_t
01284 _IO_new_file_xsputn (f, data, n)
01285      _IO_FILE *f;
01286      const void *data;
01287      _IO_size_t n;
01288 {
01289   register const char *s = (const char *) data;
01290   _IO_size_t to_do = n;
01291   int must_flush = 0;
01292   _IO_size_t count = 0;
01293 
01294   if (n <= 0)
01295     return 0;
01296   /* This is an optimized implementation.
01297      If the amount to be written straddles a block boundary
01298      (or the filebuf is unbuffered), use sys_write directly. */
01299 
01300   /* First figure out how much space is available in the buffer. */
01301   if ((f->_flags & _IO_LINE_BUF) && (f->_flags & _IO_CURRENTLY_PUTTING))
01302     {
01303       count = f->_IO_buf_end - f->_IO_write_ptr;
01304       if (count >= n)
01305        {
01306          register const char *p;
01307          for (p = s + n; p > s; )
01308            {
01309              if (*--p == '\n')
01310               {
01311                 count = p - s + 1;
01312                 must_flush = 1;
01313                 break;
01314               }
01315            }
01316        }
01317     }
01318   else if (f->_IO_write_end > f->_IO_write_ptr)
01319     count = f->_IO_write_end - f->_IO_write_ptr; /* Space available. */
01320 
01321   /* Then fill the buffer. */
01322   if (count > 0)
01323     {
01324       if (count > to_do)
01325        count = to_do;
01326       if (count > 20)
01327        {
01328 #ifdef _LIBC
01329          f->_IO_write_ptr = __mempcpy (f->_IO_write_ptr, s, count);
01330 #else
01331          memcpy (f->_IO_write_ptr, s, count);
01332          f->_IO_write_ptr += count;
01333 #endif
01334          s += count;
01335        }
01336       else
01337        {
01338          register char *p = f->_IO_write_ptr;
01339          register int i = (int) count;
01340          while (--i >= 0)
01341            *p++ = *s++;
01342          f->_IO_write_ptr = p;
01343        }
01344       to_do -= count;
01345     }
01346   if (to_do + must_flush > 0)
01347     {
01348       _IO_size_t block_size, do_write;
01349       /* Next flush the (full) buffer. */
01350       if (_IO_OVERFLOW (f, EOF) == EOF)
01351        /* If nothing else has to be written we must not signal the
01352           caller that everything has been written.  */
01353        return to_do == 0 ? EOF : n - to_do;
01354 
01355       /* Try to maintain alignment: write a whole number of blocks.
01356         dont_write is what gets left over. */
01357       block_size = f->_IO_buf_end - f->_IO_buf_base;
01358       do_write = to_do - (block_size >= 128 ? to_do % block_size : 0);
01359 
01360       if (do_write)
01361         {
01362          count = new_do_write (f, s, do_write);
01363          to_do -= count;
01364          if (count < do_write)
01365            return n - to_do;
01366         }
01367 
01368       /* Now write out the remainder.  Normally, this will fit in the
01369         buffer, but it's somewhat messier for line-buffered files,
01370         so we let _IO_default_xsputn handle the general case. */
01371       if (to_do)
01372        to_do -= INTUSE(_IO_default_xsputn) (f, s+do_write, to_do);
01373     }
01374   return n - to_do;
01375 }
01376 INTDEF2(_IO_new_file_xsputn, _IO_file_xsputn)
01377 
01378 _IO_size_t
01379 _IO_file_xsgetn (fp, data, n)
01380      _IO_FILE *fp;
01381      void *data;
01382      _IO_size_t n;
01383 {
01384   register _IO_size_t want, have;
01385   register _IO_ssize_t count;
01386   register char *s = data;
01387 
01388   want = n;
01389 
01390   if (fp->_IO_buf_base == NULL)
01391     {
01392       /* Maybe we already have a push back pointer.  */
01393       if (fp->_IO_save_base != NULL)
01394        {
01395          free (fp->_IO_save_base);
01396          fp->_flags &= ~_IO_IN_BACKUP;
01397        }
01398       INTUSE(_IO_doallocbuf) (fp);
01399     }
01400 
01401   while (want > 0)
01402     {
01403       have = fp->_IO_read_end - fp->_IO_read_ptr;
01404       if (want <= have)
01405        {
01406          memcpy (s, fp->_IO_read_ptr, want);
01407          fp->_IO_read_ptr += want;
01408          want = 0;
01409        }
01410       else
01411        {
01412          if (have > 0)
01413            {
01414 #ifdef _LIBC
01415              s = __mempcpy (s, fp->_IO_read_ptr, have);
01416 #else
01417              memcpy (s, fp->_IO_read_ptr, have);
01418              s += have;
01419 #endif
01420              want -= have;
01421              fp->_IO_read_ptr += have;
01422            }
01423 
01424          /* Check for backup and repeat */
01425          if (_IO_in_backup (fp))
01426            {
01427              _IO_switch_to_main_get_area (fp);
01428              continue;
01429            }
01430 
01431          /* If we now want less than a buffer, underflow and repeat
01432             the copy.  Otherwise, _IO_SYSREAD directly to
01433             the user buffer. */
01434          if (fp->_IO_buf_base
01435              && want < (size_t) (fp->_IO_buf_end - fp->_IO_buf_base))
01436            {
01437              if (__underflow (fp) == EOF)
01438               break;
01439 
01440              continue;
01441            }
01442 
01443          /* These must be set before the sysread as we might longjmp out
01444             waiting for input. */
01445          _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
01446          _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
01447 
01448          /* Try to maintain alignment: read a whole number of blocks.  */
01449          count = want;
01450          if (fp->_IO_buf_base)
01451            {
01452              _IO_size_t block_size = fp->_IO_buf_end - fp->_IO_buf_base;
01453              if (block_size >= 128)
01454               count -= want % block_size;
01455            }
01456 
01457          count = _IO_SYSREAD (fp, s, count);
01458          if (count <= 0)
01459            {
01460              if (count == 0)
01461               fp->_flags |= _IO_EOF_SEEN;
01462              else
01463               fp->_flags |= _IO_ERR_SEEN;
01464 
01465              break;
01466            }
01467 
01468          s += count;
01469          want -= count;
01470          if (fp->_offset != _IO_pos_BAD)
01471            _IO_pos_adjust (fp->_offset, count);
01472        }
01473     }
01474 
01475   return n - want;
01476 }
01477 INTDEF(_IO_file_xsgetn)
01478 
01479 static _IO_size_t _IO_file_xsgetn_mmap (_IO_FILE *, void *, _IO_size_t);
01480 static _IO_size_t
01481 _IO_file_xsgetn_mmap (fp, data, n)
01482      _IO_FILE *fp;
01483      void *data;
01484      _IO_size_t n;
01485 {
01486   register _IO_size_t have;
01487   char *read_ptr = fp->_IO_read_ptr;
01488   register char *s = (char *) data;
01489 
01490   have = fp->_IO_read_end - fp->_IO_read_ptr;
01491 
01492   if (have < n)
01493     {
01494       if (__builtin_expect (_IO_in_backup (fp), 0))
01495        {
01496 #ifdef _LIBC
01497          s = __mempcpy (s, read_ptr, have);
01498 #else
01499          memcpy (s, read_ptr, have);
01500          s += have;
01501 #endif
01502          n -= have;
01503          _IO_switch_to_main_get_area (fp);
01504          read_ptr = fp->_IO_read_ptr;
01505          have = fp->_IO_read_end - fp->_IO_read_ptr;
01506        }
01507 
01508       if (have < n)
01509        {
01510          /* Check that we are mapping all of the file, in case it grew.  */
01511          if (__builtin_expect (mmap_remap_check (fp), 0))
01512            /* We punted mmap, so complete with the vanilla code.  */
01513            return s - (char *) data + _IO_XSGETN (fp, data, n);
01514 
01515          read_ptr = fp->_IO_read_ptr;
01516          have = fp->_IO_read_end - read_ptr;
01517        }
01518     }
01519 
01520   if (have < n)
01521     fp->_flags |= _IO_EOF_SEEN;
01522 
01523   if (have != 0)
01524     {
01525       have = MIN (have, n);
01526 #ifdef _LIBC
01527       s = __mempcpy (s, read_ptr, have);
01528 #else
01529       memcpy (s, read_ptr, have);
01530       s += have;
01531 #endif
01532       fp->_IO_read_ptr = read_ptr + have;
01533     }
01534 
01535   return s - (char *) data;
01536 }
01537 
01538 static _IO_size_t _IO_file_xsgetn_maybe_mmap (_IO_FILE *, void *, _IO_size_t);
01539 static _IO_size_t
01540 _IO_file_xsgetn_maybe_mmap (fp, data, n)
01541      _IO_FILE *fp;
01542      void *data;
01543      _IO_size_t n;
01544 {
01545   /* We only get here if this is the first attempt to read something.
01546      Decide which operations to use and then punt to the chosen one.  */
01547 
01548   decide_maybe_mmap (fp);
01549   return _IO_XSGETN (fp, data, n);
01550 }
01551 
01552 #ifdef _LIBC
01553 # undef _IO_do_write
01554 # undef _IO_file_close_it
01555 versioned_symbol (libc, _IO_new_do_write, _IO_do_write, GLIBC_2_1);
01556 versioned_symbol (libc, _IO_new_file_attach, _IO_file_attach, GLIBC_2_1);
01557 versioned_symbol (libc, _IO_new_file_close_it, _IO_file_close_it, GLIBC_2_1);
01558 versioned_symbol (libc, _IO_new_file_finish, _IO_file_finish, GLIBC_2_1);
01559 versioned_symbol (libc, _IO_new_file_fopen, _IO_file_fopen, GLIBC_2_1);
01560 versioned_symbol (libc, _IO_new_file_init, _IO_file_init, GLIBC_2_1);
01561 versioned_symbol (libc, _IO_new_file_setbuf, _IO_file_setbuf, GLIBC_2_1);
01562 versioned_symbol (libc, _IO_new_file_sync, _IO_file_sync, GLIBC_2_1);
01563 versioned_symbol (libc, _IO_new_file_overflow, _IO_file_overflow, GLIBC_2_1);
01564 versioned_symbol (libc, _IO_new_file_seekoff, _IO_file_seekoff, GLIBC_2_1);
01565 versioned_symbol (libc, _IO_new_file_underflow, _IO_file_underflow, GLIBC_2_1);
01566 versioned_symbol (libc, _IO_new_file_write, _IO_file_write, GLIBC_2_1);
01567 versioned_symbol (libc, _IO_new_file_xsputn, _IO_file_xsputn, GLIBC_2_1);
01568 #endif
01569 
01570 const struct _IO_jump_t _IO_file_jumps =
01571 {
01572   JUMP_INIT_DUMMY,
01573   JUMP_INIT(finish, INTUSE(_IO_file_finish)),
01574   JUMP_INIT(overflow, INTUSE(_IO_file_overflow)),
01575   JUMP_INIT(underflow, INTUSE(_IO_file_underflow)),
01576   JUMP_INIT(uflow, INTUSE(_IO_default_uflow)),
01577   JUMP_INIT(pbackfail, INTUSE(_IO_default_pbackfail)),
01578   JUMP_INIT(xsputn, INTUSE(_IO_file_xsputn)),
01579   JUMP_INIT(xsgetn, INTUSE(_IO_file_xsgetn)),
01580   JUMP_INIT(seekoff, _IO_new_file_seekoff),
01581   JUMP_INIT(seekpos, _IO_default_seekpos),
01582   JUMP_INIT(setbuf, _IO_new_file_setbuf),
01583   JUMP_INIT(sync, _IO_new_file_sync),
01584   JUMP_INIT(doallocate, INTUSE(_IO_file_doallocate)),
01585   JUMP_INIT(read, INTUSE(_IO_file_read)),
01586   JUMP_INIT(write, _IO_new_file_write),
01587   JUMP_INIT(seek, INTUSE(_IO_file_seek)),
01588   JUMP_INIT(close, INTUSE(_IO_file_close)),
01589   JUMP_INIT(stat, INTUSE(_IO_file_stat)),
01590   JUMP_INIT(showmanyc, _IO_default_showmanyc),
01591   JUMP_INIT(imbue, _IO_default_imbue)
01592 };
01593 libc_hidden_data_def (_IO_file_jumps)
01594 
01595 const struct _IO_jump_t _IO_file_jumps_mmap =
01596 {
01597   JUMP_INIT_DUMMY,
01598   JUMP_INIT(finish, INTUSE(_IO_file_finish)),
01599   JUMP_INIT(overflow, INTUSE(_IO_file_overflow)),
01600   JUMP_INIT(underflow, _IO_file_underflow_mmap),
01601   JUMP_INIT(uflow, INTUSE(_IO_default_uflow)),
01602   JUMP_INIT(pbackfail, INTUSE(_IO_default_pbackfail)),
01603   JUMP_INIT(xsputn, _IO_new_file_xsputn),
01604   JUMP_INIT(xsgetn, _IO_file_xsgetn_mmap),
01605   JUMP_INIT(seekoff, _IO_file_seekoff_mmap),
01606   JUMP_INIT(seekpos, _IO_default_seekpos),
01607   JUMP_INIT(setbuf, (_IO_setbuf_t) _IO_file_setbuf_mmap),
01608   JUMP_INIT(sync, _IO_file_sync_mmap),
01609   JUMP_INIT(doallocate, INTUSE(_IO_file_doallocate)),
01610   JUMP_INIT(read, INTUSE(_IO_file_read)),
01611   JUMP_INIT(write, _IO_new_file_write),
01612   JUMP_INIT(seek, INTUSE(_IO_file_seek)),
01613   JUMP_INIT(close, _IO_file_close_mmap),
01614   JUMP_INIT(stat, INTUSE(_IO_file_stat)),
01615   JUMP_INIT(showmanyc, _IO_default_showmanyc),
01616   JUMP_INIT(imbue, _IO_default_imbue)
01617 };
01618 
01619 const struct _IO_jump_t _IO_file_jumps_maybe_mmap =
01620 {
01621   JUMP_INIT_DUMMY,
01622   JUMP_INIT(finish, INTUSE(_IO_file_finish)),
01623   JUMP_INIT(overflow, INTUSE(_IO_file_overflow)),
01624   JUMP_INIT(underflow, _IO_file_underflow_maybe_mmap),
01625   JUMP_INIT(uflow, INTUSE(_IO_default_uflow)),
01626   JUMP_INIT(pbackfail, INTUSE(_IO_default_pbackfail)),
01627   JUMP_INIT(xsputn, _IO_new_file_xsputn),
01628   JUMP_INIT(xsgetn, _IO_file_xsgetn_maybe_mmap),
01629   JUMP_INIT(seekoff, _IO_file_seekoff_maybe_mmap),
01630   JUMP_INIT(seekpos, _IO_default_seekpos),
01631   JUMP_INIT(setbuf, (_IO_setbuf_t) _IO_file_setbuf_mmap),
01632   JUMP_INIT(sync, _IO_new_file_sync),
01633   JUMP_INIT(doallocate, INTUSE(_IO_file_doallocate)),
01634   JUMP_INIT(read, INTUSE(_IO_file_read)),
01635   JUMP_INIT(write, _IO_new_file_write),
01636   JUMP_INIT(seek, INTUSE(_IO_file_seek)),
01637   JUMP_INIT(close, _IO_file_close),
01638   JUMP_INIT(stat, INTUSE(_IO_file_stat)),
01639   JUMP_INIT(showmanyc, _IO_default_showmanyc),
01640   JUMP_INIT(imbue, _IO_default_imbue)
01641 };