Remove sys/segments.h dependency
[kopensolaris-gnu/glibc.git] / libio / fileops.c
1 /* Copyright (C) 1993, 1995, 1997-2005, 2006, 2007
2    Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4    Written by Per Bothner <bothner@cygnus.com>.
5
6    The GNU C Library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Lesser General Public
8    License as published by the Free Software Foundation; either
9    version 2.1 of the License, or (at your option) any later version.
10
11    The GNU C Library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Lesser General Public License for more details.
15
16    You should have received a copy of the GNU Lesser General Public
17    License along with the GNU C Library; if not, write to the Free
18    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19    02111-1307 USA.
20
21    As a special exception, if you link the code in this file with
22    files compiled with a GNU compiler to produce an executable,
23    that does not cause the resulting executable to be covered by
24    the GNU Lesser General Public License.  This exception does not
25    however invalidate any other reasons why the executable file
26    might be covered by the GNU Lesser General Public License.
27    This exception applies to code released by its copyright holders
28    in files containing the exception.  */
29
30
31 #ifndef _POSIX_SOURCE
32 # define _POSIX_SOURCE
33 #endif
34 #include "libioP.h"
35 #include <assert.h>
36 #include <fcntl.h>
37 #include <sys/param.h>
38 #include <sys/types.h>
39 #include <sys/stat.h>
40 #include <string.h>
41 #include <errno.h>
42 #include <unistd.h>
43 #ifdef __STDC__
44 #include <stdlib.h>
45 #endif
46 #if _LIBC
47 # include "../wcsmbs/wcsmbsload.h"
48 # include "../iconv/gconv_charset.h"
49 # include "../iconv/gconv_int.h"
50 # include <shlib-compat.h>
51 # include <not-cancel.h>
52 #endif
53 #ifndef errno
54 extern int errno;
55 #endif
56 #ifndef __set_errno
57 # define __set_errno(Val) errno = (Val)
58 #endif
59
60
61 #ifdef _LIBC
62 # define open(Name, Flags, Prot) __open (Name, Flags, Prot)
63 # define lseek(FD, Offset, Whence) __lseek (FD, Offset, Whence)
64 # define read(FD, Buf, NBytes) __read (FD, Buf, NBytes)
65 # define write(FD, Buf, NBytes) __write (FD, Buf, NBytes)
66 # define _IO_do_write _IO_new_do_write /* For macro uses.  */
67 # define _IO_file_close_it _IO_new_file_close_it
68 #else
69 # define _IO_new_do_write _IO_do_write
70 # define _IO_new_file_attach _IO_file_attach
71 # define _IO_new_file_close_it _IO_file_close_it
72 # define _IO_new_file_finish _IO_file_finish
73 # define _IO_new_file_fopen _IO_file_fopen
74 # define _IO_new_file_init _IO_file_init
75 # define _IO_new_file_setbuf _IO_file_setbuf
76 # define _IO_new_file_sync _IO_file_sync
77 # define _IO_new_file_overflow _IO_file_overflow
78 # define _IO_new_file_seekoff _IO_file_seekoff
79 # define _IO_new_file_underflow _IO_file_underflow
80 # define _IO_new_file_write _IO_file_write
81 # define _IO_new_file_xsputn _IO_file_xsputn
82 #endif
83
84
85 #ifdef _LIBC
86 extern struct __gconv_trans_data __libio_translit attribute_hidden;
87 #endif
88
89
90 /* An fstream can be in at most one of put mode, get mode, or putback mode.
91    Putback mode is a variant of get mode.
92
93    In a filebuf, there is only one current position, instead of two
94    separate get and put pointers.  In get mode, the current position
95    is that of gptr(); in put mode that of pptr().
96
97    The position in the buffer that corresponds to the position
98    in external file system is normally _IO_read_end, except in putback
99    mode, when it is _IO_save_end.
100    If the field _fb._offset is >= 0, it gives the offset in
101    the file as a whole corresponding to eGptr(). (?)
102
103    PUT MODE:
104    If a filebuf is in put mode, then all of _IO_read_ptr, _IO_read_end,
105    and _IO_read_base are equal to each other.  These are usually equal
106    to _IO_buf_base, though not necessarily if we have switched from
107    get mode to put mode.  (The reason is to maintain the invariant
108    that _IO_read_end corresponds to the external file position.)
109    _IO_write_base is non-NULL and usually equal to _IO_base_base.
110    We also have _IO_write_end == _IO_buf_end, but only in fully buffered mode.
111    The un-flushed character are those between _IO_write_base and _IO_write_ptr.
112
113    GET MODE:
114    If a filebuf is in get or putback mode, eback() != egptr().
115    In get mode, the unread characters are between gptr() and egptr().
116    The OS file position corresponds to that of egptr().
117
118    PUTBACK MODE:
119    Putback mode is used to remember "excess" characters that have
120    been sputbackc'd in a separate putback buffer.
121    In putback mode, the get buffer points to the special putback buffer.
122    The unread characters are the characters between gptr() and egptr()
123    in the putback buffer, as well as the area between save_gptr()
124    and save_egptr(), which point into the original reserve buffer.
125    (The pointers save_gptr() and save_egptr() are the values
126    of gptr() and egptr() at the time putback mode was entered.)
127    The OS position corresponds to that of save_egptr().
128
129    LINE BUFFERED OUTPUT:
130    During line buffered output, _IO_write_base==base() && epptr()==base().
131    However, ptr() may be anywhere between base() and ebuf().
132    This forces a call to filebuf::overflow(int C) on every put.
133    If there is more space in the buffer, and C is not a '\n',
134    then C is inserted, and pptr() incremented.
135
136    UNBUFFERED STREAMS:
137    If a filebuf is unbuffered(), the _shortbuf[1] is used as the buffer.
138 */
139
140 #define CLOSED_FILEBUF_FLAGS \
141   (_IO_IS_FILEBUF+_IO_NO_READS+_IO_NO_WRITES+_IO_TIED_PUT_GET)
142
143
144 void
145 _IO_new_file_init (fp)
146      struct _IO_FILE_plus *fp;
147 {
148   /* POSIX.1 allows another file handle to be used to change the position
149      of our file descriptor.  Hence we actually don't know the actual
150      position before we do the first fseek (and until a following fflush). */
151   fp->file._offset = _IO_pos_BAD;
152   fp->file._IO_file_flags |= CLOSED_FILEBUF_FLAGS;
153
154   INTUSE(_IO_link_in) (fp);
155   fp->file._fileno = -1;
156 }
157 INTDEF2(_IO_new_file_init, _IO_file_init)
158
159 int
160 _IO_new_file_close_it (fp)
161      _IO_FILE *fp;
162 {
163   int write_status, close_status;
164   if (!_IO_file_is_open (fp))
165     return EOF;
166
167   if ((fp->_flags & _IO_NO_WRITES) == 0
168       && (fp->_flags & _IO_CURRENTLY_PUTTING) != 0)
169     write_status = _IO_do_flush (fp);
170   else
171     write_status = 0;
172
173   INTUSE(_IO_unsave_markers) (fp);
174
175   close_status = _IO_SYSCLOSE (fp);
176
177   /* Free buffer. */
178 #if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T
179   if (fp->_mode > 0)
180     {
181       if (_IO_have_wbackup (fp))
182         INTUSE(_IO_free_wbackup_area) (fp);
183       INTUSE(_IO_wsetb) (fp, NULL, NULL, 0);
184       _IO_wsetg (fp, NULL, NULL, NULL);
185       _IO_wsetp (fp, NULL, NULL);
186     }
187 #endif
188   INTUSE(_IO_setb) (fp, NULL, NULL, 0);
189   _IO_setg (fp, NULL, NULL, NULL);
190   _IO_setp (fp, NULL, NULL);
191
192   INTUSE(_IO_un_link) ((struct _IO_FILE_plus *) fp);
193   fp->_flags = _IO_MAGIC|CLOSED_FILEBUF_FLAGS;
194   fp->_fileno = -1;
195   fp->_offset = _IO_pos_BAD;
196
197   return close_status ? close_status : write_status;
198 }
199 INTDEF2(_IO_new_file_close_it, _IO_file_close_it)
200
201 void
202 _IO_new_file_finish (fp, dummy)
203      _IO_FILE *fp;
204      int dummy;
205 {
206   if (_IO_file_is_open (fp))
207     {
208       _IO_do_flush (fp);
209       if (!(fp->_flags & _IO_DELETE_DONT_CLOSE))
210         _IO_SYSCLOSE (fp);
211     }
212   INTUSE(_IO_default_finish) (fp, 0);
213 }
214 INTDEF2(_IO_new_file_finish, _IO_file_finish)
215
216 _IO_FILE *
217 _IO_file_open (fp, filename, posix_mode, prot, read_write, is32not64)
218      _IO_FILE *fp;
219      const char *filename;
220      int posix_mode;
221      int prot;
222      int read_write;
223      int is32not64;
224 {
225   int fdesc;
226 #ifdef _LIBC
227   if (__builtin_expect (fp->_flags2 & _IO_FLAGS2_NOTCANCEL, 0))
228     fdesc = open_not_cancel (filename,
229                              posix_mode | (is32not64 ? 0 : O_LARGEFILE), prot);
230   else
231     fdesc = open (filename, posix_mode | (is32not64 ? 0 : O_LARGEFILE), prot);
232 #else
233   fdesc = open (filename, posix_mode, prot);
234 #endif
235   if (fdesc < 0)
236     return NULL;
237   fp->_fileno = fdesc;
238   _IO_mask_flags (fp, read_write,_IO_NO_READS+_IO_NO_WRITES+_IO_IS_APPENDING);
239   if ((read_write & _IO_IS_APPENDING) && (read_write & _IO_NO_READS))
240     if (_IO_SEEKOFF (fp, (_IO_off64_t)0, _IO_seek_end, _IOS_INPUT|_IOS_OUTPUT)
241         == _IO_pos_BAD && errno != ESPIPE)
242       {
243         close_not_cancel (fdesc);
244         return NULL;
245       }
246   INTUSE(_IO_link_in) ((struct _IO_FILE_plus *) fp);
247   return fp;
248 }
249 libc_hidden_def (_IO_file_open)
250
251 _IO_FILE *
252 _IO_new_file_fopen (fp, filename, mode, is32not64)
253      _IO_FILE *fp;
254      const char *filename;
255      const char *mode;
256      int is32not64;
257 {
258   int oflags = 0, omode;
259   int read_write;
260   int oprot = 0666;
261   int i;
262   _IO_FILE *result;
263 #ifdef _LIBC
264   const char *cs;
265   const char *last_recognized;
266 #endif
267
268   if (_IO_file_is_open (fp))
269     return 0;
270   switch (*mode)
271     {
272     case 'r':
273       omode = O_RDONLY;
274       read_write = _IO_NO_WRITES;
275       break;
276     case 'w':
277       omode = O_WRONLY;
278       oflags = O_CREAT|O_TRUNC;
279       read_write = _IO_NO_READS;
280       break;
281     case 'a':
282       omode = O_WRONLY;
283       oflags = O_CREAT|O_APPEND;
284       read_write = _IO_NO_READS|_IO_IS_APPENDING;
285       break;
286     default:
287       __set_errno (EINVAL);
288       return NULL;
289     }
290 #ifdef _LIBC
291   last_recognized = mode;
292 #endif
293   for (i = 1; i < 6; ++i)
294     {
295       switch (*++mode)
296         {
297         case '\0':
298           break;
299         case '+':
300           omode = O_RDWR;
301           read_write &= _IO_IS_APPENDING;
302 #ifdef _LIBC
303           last_recognized = mode;
304 #endif
305           continue;
306         case 'x':
307           oflags |= O_EXCL;
308 #ifdef _LIBC
309           last_recognized = mode;
310 #endif
311           continue;
312         case 'b':
313 #ifdef _LIBC
314           last_recognized = mode;
315 #endif
316           continue;
317         case 'm':
318           fp->_flags2 |= _IO_FLAGS2_MMAP;
319           continue;
320         case 'c':
321           fp->_flags2 |= _IO_FLAGS2_NOTCANCEL;
322           break;
323 #ifdef O_CLOEXEC
324         case 'e':
325           oflags |= O_CLOEXEC;
326           break;
327 #endif
328         default:
329           /* Ignore.  */
330           continue;
331         }
332       break;
333     }
334
335   result = _IO_file_open (fp, filename, omode|oflags, oprot, read_write,
336                           is32not64);
337
338
339 #ifdef _LIBC
340   if (result != NULL)
341     {
342       /* Test whether the mode string specifies the conversion.  */
343       cs = strstr (last_recognized + 1, ",ccs=");
344       if (cs != NULL)
345         {
346           /* Yep.  Load the appropriate conversions and set the orientation
347              to wide.  */
348           struct gconv_fcts fcts;
349           struct _IO_codecvt *cc;
350           char *endp = __strchrnul (cs + 5, ',');
351           char ccs[endp - (cs + 5) + 3];
352
353           *((char *) __mempcpy (ccs, cs + 5, endp - (cs + 5))) = '\0';
354           strip (ccs, ccs);
355
356           if (__wcsmbs_named_conv (&fcts, ccs[2] == '\0'
357                                    ? upstr (ccs, cs + 5) : ccs) != 0)
358             {
359               /* Something went wrong, we cannot load the conversion modules.
360                  This means we cannot proceed since the user explicitly asked
361                  for these.  */
362               (void) INTUSE(_IO_file_close_it) (fp);
363               __set_errno (EINVAL);
364               return NULL;
365             }
366
367           assert (fcts.towc_nsteps == 1);
368           assert (fcts.tomb_nsteps == 1);
369
370           fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_read_end;
371           fp->_wide_data->_IO_write_ptr = fp->_wide_data->_IO_write_base;
372
373           /* Clear the state.  We start all over again.  */
374           memset (&fp->_wide_data->_IO_state, '\0', sizeof (__mbstate_t));
375           memset (&fp->_wide_data->_IO_last_state, '\0', sizeof (__mbstate_t));
376
377           cc = fp->_codecvt = &fp->_wide_data->_codecvt;
378
379           /* The functions are always the same.  */
380           *cc = __libio_codecvt;
381
382           cc->__cd_in.__cd.__nsteps = fcts.towc_nsteps;
383           cc->__cd_in.__cd.__steps = fcts.towc;
384
385           cc->__cd_in.__cd.__data[0].__invocation_counter = 0;
386           cc->__cd_in.__cd.__data[0].__internal_use = 1;
387           cc->__cd_in.__cd.__data[0].__flags = __GCONV_IS_LAST;
388           cc->__cd_in.__cd.__data[0].__statep = &result->_wide_data->_IO_state;
389
390           /* XXX For now no transliteration.  */
391           cc->__cd_in.__cd.__data[0].__trans = NULL;
392
393           cc->__cd_out.__cd.__nsteps = fcts.tomb_nsteps;
394           cc->__cd_out.__cd.__steps = fcts.tomb;
395
396           cc->__cd_out.__cd.__data[0].__invocation_counter = 0;
397           cc->__cd_out.__cd.__data[0].__internal_use = 1;
398           cc->__cd_out.__cd.__data[0].__flags = __GCONV_IS_LAST;
399           cc->__cd_out.__cd.__data[0].__statep =
400             &result->_wide_data->_IO_state;
401
402           /* And now the transliteration.  */
403           cc->__cd_out.__cd.__data[0].__trans = &__libio_translit;
404
405           /* From now on use the wide character callback functions.  */
406           ((struct _IO_FILE_plus *) fp)->vtable = fp->_wide_data->_wide_vtable;
407
408           /* Set the mode now.  */
409           result->_mode = 1;
410         }
411     }
412 #endif  /* GNU libc */
413
414   return result;
415 }
416 INTDEF2(_IO_new_file_fopen, _IO_file_fopen)
417
418 _IO_FILE *
419 _IO_new_file_attach (fp, fd)
420      _IO_FILE *fp;
421      int fd;
422 {
423   if (_IO_file_is_open (fp))
424     return NULL;
425   fp->_fileno = fd;
426   fp->_flags &= ~(_IO_NO_READS+_IO_NO_WRITES);
427   fp->_flags |= _IO_DELETE_DONT_CLOSE;
428   /* Get the current position of the file. */
429   /* We have to do that since that may be junk. */
430   fp->_offset = _IO_pos_BAD;
431   if (_IO_SEEKOFF (fp, (_IO_off64_t)0, _IO_seek_cur, _IOS_INPUT|_IOS_OUTPUT)
432       == _IO_pos_BAD && errno != ESPIPE)
433     return NULL;
434   return fp;
435 }
436 INTDEF2(_IO_new_file_attach, _IO_file_attach)
437
438 _IO_FILE *
439 _IO_new_file_setbuf (fp, p, len)
440      _IO_FILE *fp;
441      char *p;
442      _IO_ssize_t len;
443 {
444   if (_IO_default_setbuf (fp, p, len) == NULL)
445     return NULL;
446
447   fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end
448     = fp->_IO_buf_base;
449   _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
450
451   return fp;
452 }
453 INTDEF2(_IO_new_file_setbuf, _IO_file_setbuf)
454
455
456 _IO_FILE *
457 _IO_file_setbuf_mmap (fp, p, len)
458      _IO_FILE *fp;
459      char *p;
460      _IO_ssize_t len;
461 {
462   _IO_FILE *result;
463
464   /* Change the function table.  */
465   _IO_JUMPS ((struct _IO_FILE_plus *) fp) = &_IO_file_jumps;
466   fp->_wide_data->_wide_vtable = &_IO_wfile_jumps;
467
468   /* And perform the normal operation.  */
469   result = _IO_new_file_setbuf (fp, p, len);
470
471   /* If the call failed, restore to using mmap.  */
472   if (result == NULL)
473     {
474       _IO_JUMPS ((struct _IO_FILE_plus *) fp) = &_IO_file_jumps_mmap;
475       fp->_wide_data->_wide_vtable = &_IO_wfile_jumps_mmap;
476     }
477
478   return result;
479 }
480
481 static _IO_size_t new_do_write (_IO_FILE *, const char *, _IO_size_t);
482
483 /* Write TO_DO bytes from DATA to FP.
484    Then mark FP as having empty buffers. */
485
486 int
487 _IO_new_do_write (fp, data, to_do)
488      _IO_FILE *fp;
489      const char *data;
490      _IO_size_t to_do;
491 {
492   return (to_do == 0
493           || (_IO_size_t) new_do_write (fp, data, to_do) == to_do) ? 0 : EOF;
494 }
495 INTDEF2(_IO_new_do_write, _IO_do_write)
496
497 static
498 _IO_size_t
499 new_do_write (fp, data, to_do)
500      _IO_FILE *fp;
501      const char *data;
502      _IO_size_t to_do;
503 {
504   _IO_size_t count;
505   if (fp->_flags & _IO_IS_APPENDING)
506     /* On a system without a proper O_APPEND implementation,
507        you would need to sys_seek(0, SEEK_END) here, but is
508        is not needed nor desirable for Unix- or Posix-like systems.
509        Instead, just indicate that offset (before and after) is
510        unpredictable. */
511     fp->_offset = _IO_pos_BAD;
512   else if (fp->_IO_read_end != fp->_IO_write_base)
513     {
514       _IO_off64_t new_pos
515         = _IO_SYSSEEK (fp, fp->_IO_write_base - fp->_IO_read_end, 1);
516       if (new_pos == _IO_pos_BAD)
517         return 0;
518       fp->_offset = new_pos;
519     }
520   count = _IO_SYSWRITE (fp, data, to_do);
521   if (fp->_cur_column && count)
522     fp->_cur_column = INTUSE(_IO_adjust_column) (fp->_cur_column - 1, data,
523                                                  count) + 1;
524   _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
525   fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_buf_base;
526   fp->_IO_write_end = (fp->_mode <= 0
527                        && (fp->_flags & (_IO_LINE_BUF+_IO_UNBUFFERED))
528                        ? fp->_IO_buf_base : fp->_IO_buf_end);
529   return count;
530 }
531
532 int
533 _IO_new_file_underflow (fp)
534      _IO_FILE *fp;
535 {
536   _IO_ssize_t count;
537 #if 0
538   /* SysV does not make this test; take it out for compatibility */
539   if (fp->_flags & _IO_EOF_SEEN)
540     return (EOF);
541 #endif
542
543   if (fp->_flags & _IO_NO_READS)
544     {
545       fp->_flags |= _IO_ERR_SEEN;
546       __set_errno (EBADF);
547       return EOF;
548     }
549   if (fp->_IO_read_ptr < fp->_IO_read_end)
550     return *(unsigned char *) fp->_IO_read_ptr;
551
552   if (fp->_IO_buf_base == NULL)
553     {
554       /* Maybe we already have a push back pointer.  */
555       if (fp->_IO_save_base != NULL)
556         {
557           free (fp->_IO_save_base);
558           fp->_flags &= ~_IO_IN_BACKUP;
559         }
560       INTUSE(_IO_doallocbuf) (fp);
561     }
562
563   /* Flush all line buffered files before reading. */
564   /* FIXME This can/should be moved to genops ?? */
565   if (fp->_flags & (_IO_LINE_BUF|_IO_UNBUFFERED))
566     {
567 #if 0
568       INTUSE(_IO_flush_all_linebuffered) ();
569 #else
570       /* We used to flush all line-buffered stream.  This really isn't
571          required by any standard.  My recollection is that
572          traditional Unix systems did this for stdout.  stderr better
573          not be line buffered.  So we do just that here
574          explicitly.  --drepper */
575       _IO_acquire_lock (_IO_stdout);
576
577       if ((_IO_stdout->_flags & (_IO_LINKED | _IO_NO_WRITES | _IO_LINE_BUF))
578           == (_IO_LINKED | _IO_LINE_BUF))
579         _IO_OVERFLOW (_IO_stdout, EOF);
580
581       _IO_release_lock (_IO_stdout);
582 #endif
583     }
584
585   INTUSE(_IO_switch_to_get_mode) (fp);
586
587   /* This is very tricky. We have to adjust those
588      pointers before we call _IO_SYSREAD () since
589      we may longjump () out while waiting for
590      input. Those pointers may be screwed up. H.J. */
591   fp->_IO_read_base = fp->_IO_read_ptr = fp->_IO_buf_base;
592   fp->_IO_read_end = fp->_IO_buf_base;
593   fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end
594     = fp->_IO_buf_base;
595
596   count = _IO_SYSREAD (fp, fp->_IO_buf_base,
597                        fp->_IO_buf_end - fp->_IO_buf_base);
598   if (count <= 0)
599     {
600       if (count == 0)
601         fp->_flags |= _IO_EOF_SEEN;
602       else
603         fp->_flags |= _IO_ERR_SEEN, count = 0;
604   }
605   fp->_IO_read_end += count;
606   if (count == 0)
607     return EOF;
608   if (fp->_offset != _IO_pos_BAD)
609     _IO_pos_adjust (fp->_offset, count);
610   return *(unsigned char *) fp->_IO_read_ptr;
611 }
612 INTDEF2(_IO_new_file_underflow, _IO_file_underflow)
613
614 /* Guts of underflow callback if we mmap the file.  This stats the file and
615    updates the stream state to match.  In the normal case we return zero.
616    If the file is no longer eligible for mmap, its jump tables are reset to
617    the vanilla ones and we return nonzero.  */
618 static int
619 mmap_remap_check (_IO_FILE *fp)
620 {
621   struct _G_stat64 st;
622
623   if (_IO_SYSSTAT (fp, &st) == 0
624       && S_ISREG (st.st_mode) && st.st_size != 0
625       /* Limit the file size to 1MB for 32-bit machines.  */
626       && (sizeof (ptrdiff_t) > 4 || st.st_size < 1*1024*1024))
627     {
628       const size_t pagesize = __getpagesize ();
629 # define ROUNDED(x)     (((x) + pagesize - 1) & ~(pagesize - 1))
630       if (ROUNDED (st.st_size) < ROUNDED (fp->_IO_buf_end
631                                           - fp->_IO_buf_base))
632         {
633           /* We can trim off some pages past the end of the file.  */
634           (void) __munmap (fp->_IO_buf_base + ROUNDED (st.st_size),
635                            ROUNDED (fp->_IO_buf_end - fp->_IO_buf_base)
636                            - ROUNDED (st.st_size));
637           fp->_IO_buf_end = fp->_IO_buf_base + st.st_size;
638         }
639       else if (ROUNDED (st.st_size) > ROUNDED (fp->_IO_buf_end
640                                                - fp->_IO_buf_base))
641         {
642           /* The file added some pages.  We need to remap it.  */
643           void *p;
644 #ifdef _G_HAVE_MREMAP
645           p = __mremap (fp->_IO_buf_base, ROUNDED (fp->_IO_buf_end
646                                                    - fp->_IO_buf_base),
647                         ROUNDED (st.st_size), MREMAP_MAYMOVE);
648           if (p == MAP_FAILED)
649             {
650               (void) __munmap (fp->_IO_buf_base,
651                                fp->_IO_buf_end - fp->_IO_buf_base);
652               goto punt;
653             }
654 #else
655           (void) __munmap (fp->_IO_buf_base,
656                            fp->_IO_buf_end - fp->_IO_buf_base);
657 # ifdef _G_MMAP64
658           p = _G_MMAP64 (NULL, st.st_size, PROT_READ, MAP_SHARED,
659                          fp->_fileno, 0);
660 # else
661           p = __mmap (NULL, st.st_size, PROT_READ, MAP_SHARED,
662                       fp->_fileno, 0);
663 # endif
664           if (p == MAP_FAILED)
665             goto punt;
666 #endif
667           fp->_IO_buf_base = p;
668           fp->_IO_buf_end = fp->_IO_buf_base + st.st_size;
669         }
670       else
671         {
672           /* The number of pages didn't change.  */
673           fp->_IO_buf_end = fp->_IO_buf_base + st.st_size;
674         }
675 # undef ROUNDED
676
677       fp->_offset -= fp->_IO_read_end - fp->_IO_read_ptr;
678       _IO_setg (fp, fp->_IO_buf_base,
679                 fp->_offset < fp->_IO_buf_end - fp->_IO_buf_base
680                 ? fp->_IO_buf_base + fp->_offset : fp->_IO_buf_end,
681                 fp->_IO_buf_end);
682
683       /* If we are already positioned at or past the end of the file, don't
684          change the current offset.  If not, seek past what we have mapped,
685          mimicking the position left by a normal underflow reading into its
686          buffer until EOF.  */
687
688       if (fp->_offset < fp->_IO_buf_end - fp->_IO_buf_base)
689         {
690           if (
691 # ifdef _G_LSEEK64
692               _G_LSEEK64
693 # else
694               __lseek
695 # endif
696               (fp->_fileno, fp->_IO_buf_end - fp->_IO_buf_base, SEEK_SET)
697               != fp->_IO_buf_end - fp->_IO_buf_base)
698             fp->_flags |= _IO_ERR_SEEN;
699           else
700             fp->_offset = fp->_IO_buf_end - fp->_IO_buf_base;
701         }
702
703       return 0;
704     }
705   else
706     {
707       /* Life is no longer good for mmap.  Punt it.  */
708       (void) __munmap (fp->_IO_buf_base,
709                        fp->_IO_buf_end - fp->_IO_buf_base);
710     punt:
711       fp->_IO_buf_base = fp->_IO_buf_end = NULL;
712       _IO_setg (fp, NULL, NULL, NULL);
713       if (fp->_mode <= 0)
714         _IO_JUMPS ((struct _IO_FILE_plus *) fp) = &_IO_file_jumps;
715       else
716         _IO_JUMPS ((struct _IO_FILE_plus *) fp) = &_IO_wfile_jumps;
717       fp->_wide_data->_wide_vtable = &_IO_wfile_jumps;
718
719       return 1;
720     }
721 }
722
723 /* Special callback replacing the underflow callbacks if we mmap the file.  */
724 int
725 _IO_file_underflow_mmap (_IO_FILE *fp)
726 {
727   if (fp->_IO_read_ptr < fp->_IO_read_end)
728     return *(unsigned char *) fp->_IO_read_ptr;
729
730   if (__builtin_expect (mmap_remap_check (fp), 0))
731     /* We punted to the regular file functions.  */
732     return _IO_UNDERFLOW (fp);
733
734   if (fp->_IO_read_ptr < fp->_IO_read_end)
735     return *(unsigned char *) fp->_IO_read_ptr;
736
737   fp->_flags |= _IO_EOF_SEEN;
738   return EOF;
739 }
740
741 static void
742 decide_maybe_mmap (_IO_FILE *fp)
743 {
744   /* We use the file in read-only mode.  This could mean we can
745      mmap the file and use it without any copying.  But not all
746      file descriptors are for mmap-able objects and on 32-bit
747      machines we don't want to map files which are too large since
748      this would require too much virtual memory.  */
749   struct _G_stat64 st;
750
751   if (_IO_SYSSTAT (fp, &st) == 0
752       && S_ISREG (st.st_mode) && st.st_size != 0
753       /* Limit the file size to 1MB for 32-bit machines.  */
754       && (sizeof (ptrdiff_t) > 4 || st.st_size < 1*1024*1024)
755       /* Sanity check.  */
756       && (fp->_offset == _IO_pos_BAD || fp->_offset <= st.st_size))
757     {
758       /* Try to map the file.  */
759       void *p;
760
761 # ifdef _G_MMAP64
762       p = _G_MMAP64 (NULL, st.st_size, PROT_READ, MAP_SHARED, fp->_fileno, 0);
763 # else
764       p = __mmap (NULL, st.st_size, PROT_READ, MAP_SHARED, fp->_fileno, 0);
765 # endif
766       if (p != MAP_FAILED)
767         {
768           /* OK, we managed to map the file.  Set the buffer up and use a
769              special jump table with simplified underflow functions which
770              never tries to read anything from the file.  */
771
772           if (
773 # ifdef _G_LSEEK64
774               _G_LSEEK64
775 # else
776               __lseek
777 # endif
778               (fp->_fileno, st.st_size, SEEK_SET) != st.st_size)
779             {
780               (void) __munmap (p, st.st_size);
781               fp->_offset = _IO_pos_BAD;
782             }
783           else
784             {
785               INTUSE(_IO_setb) (fp, p, (char *) p + st.st_size, 0);
786
787               if (fp->_offset == _IO_pos_BAD)
788                 fp->_offset = 0;
789
790               _IO_setg (fp, p, p + fp->_offset, p + st.st_size);
791               fp->_offset = st.st_size;
792
793               if (fp->_mode <= 0)
794                 _IO_JUMPS ((struct _IO_FILE_plus *)fp) = &_IO_file_jumps_mmap;
795               else
796                 _IO_JUMPS ((struct _IO_FILE_plus *)fp) = &_IO_wfile_jumps_mmap;
797               fp->_wide_data->_wide_vtable = &_IO_wfile_jumps_mmap;
798
799               return;
800             }
801         }
802     }
803
804   /* We couldn't use mmap, so revert to the vanilla file operations.  */
805
806   if (fp->_mode <= 0)
807     _IO_JUMPS ((struct _IO_FILE_plus *) fp) = &_IO_file_jumps;
808   else
809     _IO_JUMPS ((struct _IO_FILE_plus *) fp) = &_IO_wfile_jumps;
810   fp->_wide_data->_wide_vtable = &_IO_wfile_jumps;
811 }
812
813 int
814 _IO_file_underflow_maybe_mmap (_IO_FILE *fp)
815 {
816   /* This is the first read attempt.  Choose mmap or vanilla operations
817      and then punt to the chosen underflow routine.  */
818   decide_maybe_mmap (fp);
819   return _IO_UNDERFLOW (fp);
820 }
821
822
823 int
824 _IO_new_file_overflow (f, ch)
825       _IO_FILE *f;
826       int ch;
827 {
828   if (f->_flags & _IO_NO_WRITES) /* SET ERROR */
829     {
830       f->_flags |= _IO_ERR_SEEN;
831       __set_errno (EBADF);
832       return EOF;
833     }
834   /* If currently reading or no buffer allocated. */
835   if ((f->_flags & _IO_CURRENTLY_PUTTING) == 0 || f->_IO_write_base == NULL)
836     {
837       /* Allocate a buffer if needed. */
838       if (f->_IO_write_base == NULL)
839         {
840           INTUSE(_IO_doallocbuf) (f);
841           _IO_setg (f, f->_IO_buf_base, f->_IO_buf_base, f->_IO_buf_base);
842         }
843       /* Otherwise must be currently reading.
844          If _IO_read_ptr (and hence also _IO_read_end) is at the buffer end,
845          logically slide the buffer forwards one block (by setting the
846          read pointers to all point at the beginning of the block).  This
847          makes room for subsequent output.
848          Otherwise, set the read pointers to _IO_read_end (leaving that
849          alone, so it can continue to correspond to the external position). */
850       if (__builtin_expect (_IO_in_backup (f), 0))
851         {
852           size_t nbackup = f->_IO_read_end - f->_IO_read_ptr;
853           INTUSE(_IO_free_backup_area) (f);
854           f->_IO_read_base -= MIN (nbackup,
855                                    f->_IO_read_base - f->_IO_buf_base);
856           f->_IO_read_ptr = f->_IO_read_base;
857         }
858
859       if (f->_IO_read_ptr == f->_IO_buf_end)
860         f->_IO_read_end = f->_IO_read_ptr = f->_IO_buf_base;
861       f->_IO_write_ptr = f->_IO_read_ptr;
862       f->_IO_write_base = f->_IO_write_ptr;
863       f->_IO_write_end = f->_IO_buf_end;
864       f->_IO_read_base = f->_IO_read_ptr = f->_IO_read_end;
865
866       f->_flags |= _IO_CURRENTLY_PUTTING;
867       if (f->_mode <= 0 && f->_flags & (_IO_LINE_BUF+_IO_UNBUFFERED))
868         f->_IO_write_end = f->_IO_write_ptr;
869     }
870   if (ch == EOF)
871     return INTUSE(_IO_do_write) (f, f->_IO_write_base,
872                                  f->_IO_write_ptr - f->_IO_write_base);
873   if (f->_IO_write_ptr == f->_IO_buf_end ) /* Buffer is really full */
874     if (_IO_do_flush (f) == EOF)
875       return EOF;
876   *f->_IO_write_ptr++ = ch;
877   if ((f->_flags & _IO_UNBUFFERED)
878       || ((f->_flags & _IO_LINE_BUF) && ch == '\n'))
879     if (INTUSE(_IO_do_write) (f, f->_IO_write_base,
880                               f->_IO_write_ptr - f->_IO_write_base) == EOF)
881       return EOF;
882   return (unsigned char) ch;
883 }
884 INTDEF2(_IO_new_file_overflow, _IO_file_overflow)
885
886 int
887 _IO_new_file_sync (fp)
888      _IO_FILE *fp;
889 {
890   _IO_ssize_t delta;
891   int retval = 0;
892
893   /*    char* ptr = cur_ptr(); */
894   if (fp->_IO_write_ptr > fp->_IO_write_base)
895     if (_IO_do_flush(fp)) return EOF;
896   delta = fp->_IO_read_ptr - fp->_IO_read_end;
897   if (delta != 0)
898     {
899 #ifdef TODO
900       if (_IO_in_backup (fp))
901         delta -= eGptr () - Gbase ();
902 #endif
903       _IO_off64_t new_pos = _IO_SYSSEEK (fp, delta, 1);
904       if (new_pos != (_IO_off64_t) EOF)
905         fp->_IO_read_end = fp->_IO_read_ptr;
906 #ifdef ESPIPE
907       else if (errno == ESPIPE)
908         ; /* Ignore error from unseekable devices. */
909 #endif
910       else
911         retval = EOF;
912     }
913   if (retval != EOF)
914     fp->_offset = _IO_pos_BAD;
915   /* FIXME: Cleanup - can this be shared? */
916   /*    setg(base(), ptr, ptr); */
917   return retval;
918 }
919 INTDEF2(_IO_new_file_sync, _IO_file_sync)
920
921 static int
922 _IO_file_sync_mmap (_IO_FILE *fp)
923 {
924   if (fp->_IO_read_ptr != fp->_IO_read_end)
925     {
926 #ifdef TODO
927       if (_IO_in_backup (fp))
928         delta -= eGptr () - Gbase ();
929 #endif
930       if (
931 # ifdef _G_LSEEK64
932           _G_LSEEK64
933 # else
934           __lseek
935 # endif
936           (fp->_fileno, fp->_IO_read_ptr - fp->_IO_buf_base, SEEK_SET)
937           != fp->_IO_read_ptr - fp->_IO_buf_base)
938         {
939           fp->_flags |= _IO_ERR_SEEN;
940           return EOF;
941         }
942     }
943   fp->_offset = fp->_IO_read_ptr - fp->_IO_buf_base;
944   fp->_IO_read_end = fp->_IO_read_ptr = fp->_IO_read_base;
945   return 0;
946 }
947
948
949 _IO_off64_t
950 _IO_new_file_seekoff (fp, offset, dir, mode)
951      _IO_FILE *fp;
952      _IO_off64_t offset;
953      int dir;
954      int mode;
955 {
956   _IO_off64_t result;
957   _IO_off64_t delta, new_offset;
958   long count;
959   /* POSIX.1 8.2.3.7 says that after a call the fflush() the file
960      offset of the underlying file must be exact.  */
961   int must_be_exact = (fp->_IO_read_base == fp->_IO_read_end
962                        && fp->_IO_write_base == fp->_IO_write_ptr);
963
964   if (mode == 0)
965     dir = _IO_seek_cur, offset = 0; /* Don't move any pointers. */
966
967   /* Flush unwritten characters.
968      (This may do an unneeded write if we seek within the buffer.
969      But to be able to switch to reading, we would need to set
970      egptr to ptr.  That can't be done in the current design,
971      which assumes file_ptr() is eGptr.  Anyway, since we probably
972      end up flushing when we close(), it doesn't make much difference.)
973      FIXME: simulate mem-papped files. */
974
975   if (fp->_IO_write_ptr > fp->_IO_write_base || _IO_in_put_mode (fp))
976     if (INTUSE(_IO_switch_to_get_mode) (fp))
977       return EOF;
978
979   if (fp->_IO_buf_base == NULL)
980     {
981       /* It could be that we already have a pushback buffer.  */
982       if (fp->_IO_read_base != NULL)
983         {
984           free (fp->_IO_read_base);
985           fp->_flags &= ~_IO_IN_BACKUP;
986         }
987       INTUSE(_IO_doallocbuf) (fp);
988       _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
989       _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
990     }
991
992   switch (dir)
993     {
994     case _IO_seek_cur:
995       /* Adjust for read-ahead (bytes is buffer). */
996       offset -= fp->_IO_read_end - fp->_IO_read_ptr;
997       if (fp->_offset == _IO_pos_BAD)
998         {
999           if (mode != 0)
1000             goto dumb;
1001           else
1002             {
1003               result = _IO_SYSSEEK (fp, 0, dir);
1004               if (result == EOF)
1005                 return result;
1006
1007               fp->_offset = result;
1008             }
1009         }
1010       /* Make offset absolute, assuming current pointer is file_ptr(). */
1011       offset += fp->_offset;
1012       if (offset < 0)
1013         {
1014           __set_errno (EINVAL);
1015           return EOF;
1016         }
1017
1018       dir = _IO_seek_set;
1019       break;
1020     case _IO_seek_set:
1021       break;
1022     case _IO_seek_end:
1023       {
1024         struct _G_stat64 st;
1025         if (_IO_SYSSTAT (fp, &st) == 0 && S_ISREG (st.st_mode))
1026           {
1027             offset += st.st_size;
1028             dir = _IO_seek_set;
1029           }
1030         else
1031           goto dumb;
1032       }
1033     }
1034   /* At this point, dir==_IO_seek_set. */
1035
1036   /* If we are only interested in the current position we've found it now.  */
1037   if (mode == 0)
1038     return offset;
1039
1040   /* If destination is within current buffer, optimize: */
1041   if (fp->_offset != _IO_pos_BAD && fp->_IO_read_base != NULL
1042       && !_IO_in_backup (fp))
1043     {
1044       _IO_off64_t start_offset = (fp->_offset
1045                                   - (fp->_IO_read_end - fp->_IO_buf_base));
1046       if (offset >= start_offset && offset < fp->_offset)
1047         {
1048           _IO_setg (fp, fp->_IO_buf_base,
1049                     fp->_IO_buf_base + (offset - start_offset),
1050                     fp->_IO_read_end);
1051           _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
1052
1053           _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
1054           goto resync;
1055         }
1056     }
1057
1058   if (fp->_flags & _IO_NO_READS)
1059     goto dumb;
1060
1061   /* Try to seek to a block boundary, to improve kernel page management. */
1062   new_offset = offset & ~(fp->_IO_buf_end - fp->_IO_buf_base - 1);
1063   delta = offset - new_offset;
1064   if (delta > fp->_IO_buf_end - fp->_IO_buf_base)
1065     {
1066       new_offset = offset;
1067       delta = 0;
1068     }
1069   result = _IO_SYSSEEK (fp, new_offset, 0);
1070   if (result < 0)
1071     return EOF;
1072   if (delta == 0)
1073     count = 0;
1074   else
1075     {
1076       count = _IO_SYSREAD (fp, fp->_IO_buf_base,
1077                            (must_be_exact
1078                             ? delta : fp->_IO_buf_end - fp->_IO_buf_base));
1079       if (count < delta)
1080         {
1081           /* We weren't allowed to read, but try to seek the remainder. */
1082           offset = count == EOF ? delta : delta-count;
1083           dir = _IO_seek_cur;
1084           goto dumb;
1085         }
1086     }
1087   _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base + delta,
1088             fp->_IO_buf_base + count);
1089   _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
1090   fp->_offset = result + count;
1091   _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
1092   return offset;
1093  dumb:
1094
1095   INTUSE(_IO_unsave_markers) (fp);
1096   result = _IO_SYSSEEK (fp, offset, dir);
1097   if (result != EOF)
1098     {
1099       _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
1100       fp->_offset = result;
1101       _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
1102       _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
1103     }
1104   return result;
1105
1106 resync:
1107   /* We need to do it since it is possible that the file offset in
1108      the kernel may be changed behind our back. It may happen when
1109      we fopen a file and then do a fork. One process may access the
1110      the file and the kernel file offset will be changed. */
1111   if (fp->_offset >= 0)
1112     _IO_SYSSEEK (fp, fp->_offset, 0);
1113
1114   return offset;
1115 }
1116 INTDEF2(_IO_new_file_seekoff, _IO_file_seekoff)
1117
1118 _IO_off64_t
1119 _IO_file_seekoff_mmap (fp, offset, dir, mode)
1120      _IO_FILE *fp;
1121      _IO_off64_t offset;
1122      int dir;
1123      int mode;
1124 {
1125   _IO_off64_t result;
1126
1127   /* If we are only interested in the current position, calculate it and
1128      return right now.  This calculation does the right thing when we are
1129      using a pushback buffer, but in the usual case has the same value as
1130      (fp->_IO_read_ptr - fp->_IO_buf_base).  */
1131   if (mode == 0)
1132     return fp->_offset - (fp->_IO_read_end - fp->_IO_read_ptr);
1133
1134   switch (dir)
1135     {
1136     case _IO_seek_cur:
1137       /* Adjust for read-ahead (bytes is buffer). */
1138       offset += fp->_IO_read_ptr - fp->_IO_read_base;
1139       break;
1140     case _IO_seek_set:
1141       break;
1142     case _IO_seek_end:
1143       offset += fp->_IO_buf_end - fp->_IO_buf_base;
1144       break;
1145     }
1146   /* At this point, dir==_IO_seek_set. */
1147
1148   if (offset < 0)
1149     {
1150       /* No negative offsets are valid.  */
1151       __set_errno (EINVAL);
1152       return EOF;
1153     }
1154
1155   result = _IO_SYSSEEK (fp, offset, 0);
1156   if (result < 0)
1157     return EOF;
1158
1159   if (offset > fp->_IO_buf_end - fp->_IO_buf_base)
1160     /* One can fseek arbitrarily past the end of the file
1161        and it is meaningless until one attempts to read.
1162        Leave the buffer pointers in EOF state until underflow.  */
1163     _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_end, fp->_IO_buf_end);
1164   else
1165     /* Adjust the read pointers to match the file position,
1166        but so the next read attempt will call underflow.  */
1167     _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base + offset,
1168               fp->_IO_buf_base + offset);
1169
1170   fp->_offset = result;
1171
1172   _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
1173
1174   return offset;
1175 }
1176
1177 static _IO_off64_t
1178 _IO_file_seekoff_maybe_mmap (_IO_FILE *fp, _IO_off64_t offset, int dir,
1179                              int mode)
1180 {
1181   /* We only get here when we haven't tried to read anything yet.
1182      So there is nothing more useful for us to do here than just
1183      the underlying lseek call.  */
1184
1185   _IO_off64_t result = _IO_SYSSEEK (fp, offset, dir);
1186   if (result < 0)
1187     return EOF;
1188
1189   fp->_offset = result;
1190   return result;
1191 }
1192
1193 _IO_ssize_t
1194 _IO_file_read (fp, buf, size)
1195      _IO_FILE *fp;
1196      void *buf;
1197      _IO_ssize_t size;
1198 {
1199   return (__builtin_expect (fp->_flags2 & _IO_FLAGS2_NOTCANCEL, 0)
1200           ? read_not_cancel (fp->_fileno, buf, size)
1201           : read (fp->_fileno, buf, size));
1202 }
1203 INTDEF(_IO_file_read)
1204
1205 _IO_off64_t
1206 _IO_file_seek (fp, offset, dir)
1207      _IO_FILE *fp;
1208      _IO_off64_t offset;
1209      int dir;
1210 {
1211 #ifdef _G_LSEEK64
1212   return _G_LSEEK64 (fp->_fileno, offset, dir);
1213 #else
1214   return lseek (fp->_fileno, offset, dir);
1215 #endif
1216 }
1217 INTDEF(_IO_file_seek)
1218
1219 int
1220 _IO_file_stat (fp, st)
1221      _IO_FILE *fp;
1222      void *st;
1223 {
1224 #ifdef _G_FSTAT64
1225   return _G_FSTAT64 (fp->_fileno, (struct _G_stat64 *) st);
1226 #else
1227   return fstat (fp->_fileno, (struct stat *) st);
1228 #endif
1229 }
1230 INTDEF(_IO_file_stat)
1231
1232 int
1233 _IO_file_close_mmap (fp)
1234      _IO_FILE *fp;
1235 {
1236   /* In addition to closing the file descriptor we have to unmap the file.  */
1237   (void) __munmap (fp->_IO_buf_base, fp->_IO_buf_end - fp->_IO_buf_base);
1238   fp->_IO_buf_base = fp->_IO_buf_end = NULL;
1239   /* Cancelling close should be avoided if possible since it leaves an
1240      unrecoverable state behind.  */
1241   return close_not_cancel (fp->_fileno);
1242 }
1243
1244 int
1245 _IO_file_close (fp)
1246      _IO_FILE *fp;
1247 {
1248   /* Cancelling close should be avoided if possible since it leaves an
1249      unrecoverable state behind.  */
1250   return close_not_cancel (fp->_fileno);
1251 }
1252 INTDEF(_IO_file_close)
1253
1254 _IO_ssize_t
1255 _IO_new_file_write (f, data, n)
1256      _IO_FILE *f;
1257      const void *data;
1258      _IO_ssize_t n;
1259 {
1260   _IO_ssize_t to_do = n;
1261   while (to_do > 0)
1262     {
1263       _IO_ssize_t count = (__builtin_expect (f->_flags2
1264                                              & _IO_FLAGS2_NOTCANCEL, 0)
1265                            ? write_not_cancel (f->_fileno, data, to_do)
1266                            : write (f->_fileno, data, to_do));
1267       if (count < 0)
1268         {
1269           f->_flags |= _IO_ERR_SEEN;
1270           break;
1271         }
1272       to_do -= count;
1273       data = (void *) ((char *) data + count);
1274     }
1275   n -= to_do;
1276   if (f->_offset >= 0)
1277     f->_offset += n;
1278   return n;
1279 }
1280
1281 _IO_size_t
1282 _IO_new_file_xsputn (f, data, n)
1283      _IO_FILE *f;
1284      const void *data;
1285      _IO_size_t n;
1286 {
1287   register const char *s = (const char *) data;
1288   _IO_size_t to_do = n;
1289   int must_flush = 0;
1290   _IO_size_t count = 0;
1291
1292   if (n <= 0)
1293     return 0;
1294   /* This is an optimized implementation.
1295      If the amount to be written straddles a block boundary
1296      (or the filebuf is unbuffered), use sys_write directly. */
1297
1298   /* First figure out how much space is available in the buffer. */
1299   if ((f->_flags & _IO_LINE_BUF) && (f->_flags & _IO_CURRENTLY_PUTTING))
1300     {
1301       count = f->_IO_buf_end - f->_IO_write_ptr;
1302       if (count >= n)
1303         {
1304           register const char *p;
1305           for (p = s + n; p > s; )
1306             {
1307               if (*--p == '\n')
1308                 {
1309                   count = p - s + 1;
1310                   must_flush = 1;
1311                   break;
1312                 }
1313             }
1314         }
1315     }
1316   else if (f->_IO_write_end > f->_IO_write_ptr)
1317     count = f->_IO_write_end - f->_IO_write_ptr; /* Space available. */
1318
1319   /* Then fill the buffer. */
1320   if (count > 0)
1321     {
1322       if (count > to_do)
1323         count = to_do;
1324       if (count > 20)
1325         {
1326 #ifdef _LIBC
1327           f->_IO_write_ptr = __mempcpy (f->_IO_write_ptr, s, count);
1328 #else
1329           memcpy (f->_IO_write_ptr, s, count);
1330           f->_IO_write_ptr += count;
1331 #endif
1332           s += count;
1333         }
1334       else
1335         {
1336           register char *p = f->_IO_write_ptr;
1337           register int i = (int) count;
1338           while (--i >= 0)
1339             *p++ = *s++;
1340           f->_IO_write_ptr = p;
1341         }
1342       to_do -= count;
1343     }
1344   if (to_do + must_flush > 0)
1345     {
1346       _IO_size_t block_size, do_write;
1347       /* Next flush the (full) buffer. */
1348       if (_IO_OVERFLOW (f, EOF) == EOF)
1349         /* If nothing else has to be written we must not signal the
1350            caller that everything has been written.  */
1351         return to_do == 0 ? EOF : n - to_do;
1352
1353       /* Try to maintain alignment: write a whole number of blocks.
1354          dont_write is what gets left over. */
1355       block_size = f->_IO_buf_end - f->_IO_buf_base;
1356       do_write = to_do - (block_size >= 128 ? to_do % block_size : 0);
1357
1358       if (do_write)
1359         {
1360           count = new_do_write (f, s, do_write);
1361           to_do -= count;
1362           if (count < do_write)
1363             return n - to_do;
1364         }
1365
1366       /* Now write out the remainder.  Normally, this will fit in the
1367          buffer, but it's somewhat messier for line-buffered files,
1368          so we let _IO_default_xsputn handle the general case. */
1369       if (to_do)
1370         to_do -= INTUSE(_IO_default_xsputn) (f, s+do_write, to_do);
1371     }
1372   return n - to_do;
1373 }
1374 INTDEF2(_IO_new_file_xsputn, _IO_file_xsputn)
1375
1376 _IO_size_t
1377 _IO_file_xsgetn (fp, data, n)
1378      _IO_FILE *fp;
1379      void *data;
1380      _IO_size_t n;
1381 {
1382   register _IO_size_t want, have;
1383   register _IO_ssize_t count;
1384   register char *s = data;
1385
1386   want = n;
1387
1388   if (fp->_IO_buf_base == NULL)
1389     {
1390       /* Maybe we already have a push back pointer.  */
1391       if (fp->_IO_save_base != NULL)
1392         {
1393           free (fp->_IO_save_base);
1394           fp->_flags &= ~_IO_IN_BACKUP;
1395         }
1396       INTUSE(_IO_doallocbuf) (fp);
1397     }
1398
1399   while (want > 0)
1400     {
1401       have = fp->_IO_read_end - fp->_IO_read_ptr;
1402       if (want <= have)
1403         {
1404           memcpy (s, fp->_IO_read_ptr, want);
1405           fp->_IO_read_ptr += want;
1406           want = 0;
1407         }
1408       else
1409         {
1410           if (have > 0)
1411             {
1412 #ifdef _LIBC
1413               s = __mempcpy (s, fp->_IO_read_ptr, have);
1414 #else
1415               memcpy (s, fp->_IO_read_ptr, have);
1416               s += have;
1417 #endif
1418               want -= have;
1419               fp->_IO_read_ptr += have;
1420             }
1421
1422           /* Check for backup and repeat */
1423           if (_IO_in_backup (fp))
1424             {
1425               _IO_switch_to_main_get_area (fp);
1426               continue;
1427             }
1428
1429           /* If we now want less than a buffer, underflow and repeat
1430              the copy.  Otherwise, _IO_SYSREAD directly to
1431              the user buffer. */
1432           if (fp->_IO_buf_base
1433               && want < (size_t) (fp->_IO_buf_end - fp->_IO_buf_base))
1434             {
1435               if (__underflow (fp) == EOF)
1436                 break;
1437
1438               continue;
1439             }
1440
1441           /* These must be set before the sysread as we might longjmp out
1442              waiting for input. */
1443           _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
1444           _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
1445
1446           /* Try to maintain alignment: read a whole number of blocks.  */
1447           count = want;
1448           if (fp->_IO_buf_base)
1449             {
1450               _IO_size_t block_size = fp->_IO_buf_end - fp->_IO_buf_base;
1451               if (block_size >= 128)
1452                 count -= want % block_size;
1453             }
1454
1455           count = _IO_SYSREAD (fp, s, count);
1456           if (count <= 0)
1457             {
1458               if (count == 0)
1459                 fp->_flags |= _IO_EOF_SEEN;
1460               else
1461                 fp->_flags |= _IO_ERR_SEEN;
1462
1463               break;
1464             }
1465
1466           s += count;
1467           want -= count;
1468           if (fp->_offset != _IO_pos_BAD)
1469             _IO_pos_adjust (fp->_offset, count);
1470         }
1471     }
1472
1473   return n - want;
1474 }
1475 INTDEF(_IO_file_xsgetn)
1476
1477 static _IO_size_t _IO_file_xsgetn_mmap (_IO_FILE *, void *, _IO_size_t);
1478 static _IO_size_t
1479 _IO_file_xsgetn_mmap (fp, data, n)
1480      _IO_FILE *fp;
1481      void *data;
1482      _IO_size_t n;
1483 {
1484   register _IO_size_t have;
1485   char *read_ptr = fp->_IO_read_ptr;
1486   register char *s = (char *) data;
1487
1488   have = fp->_IO_read_end - fp->_IO_read_ptr;
1489
1490   if (have < n)
1491     {
1492       if (__builtin_expect (_IO_in_backup (fp), 0))
1493         {
1494 #ifdef _LIBC
1495           s = __mempcpy (s, read_ptr, have);
1496 #else
1497           memcpy (s, read_ptr, have);
1498           s += have;
1499 #endif
1500           n -= have;
1501           _IO_switch_to_main_get_area (fp);
1502           read_ptr = fp->_IO_read_ptr;
1503           have = fp->_IO_read_end - fp->_IO_read_ptr;
1504         }
1505
1506       if (have < n)
1507         {
1508           /* Check that we are mapping all of the file, in case it grew.  */
1509           if (__builtin_expect (mmap_remap_check (fp), 0))
1510             /* We punted mmap, so complete with the vanilla code.  */
1511             return s - (char *) data + _IO_XSGETN (fp, data, n);
1512
1513           read_ptr = fp->_IO_read_ptr;
1514           have = fp->_IO_read_end - read_ptr;
1515         }
1516     }
1517
1518   if (have < n)
1519     fp->_flags |= _IO_EOF_SEEN;
1520
1521   if (have != 0)
1522     {
1523       have = MIN (have, n);
1524 #ifdef _LIBC
1525       s = __mempcpy (s, read_ptr, have);
1526 #else
1527       memcpy (s, read_ptr, have);
1528       s += have;
1529 #endif
1530       fp->_IO_read_ptr = read_ptr + have;
1531     }
1532
1533   return s - (char *) data;
1534 }
1535
1536 static _IO_size_t _IO_file_xsgetn_maybe_mmap (_IO_FILE *, void *, _IO_size_t);
1537 static _IO_size_t
1538 _IO_file_xsgetn_maybe_mmap (fp, data, n)
1539      _IO_FILE *fp;
1540      void *data;
1541      _IO_size_t n;
1542 {
1543   /* We only get here if this is the first attempt to read something.
1544      Decide which operations to use and then punt to the chosen one.  */
1545
1546   decide_maybe_mmap (fp);
1547   return _IO_XSGETN (fp, data, n);
1548 }
1549
1550 #ifdef _LIBC
1551 # undef _IO_do_write
1552 # undef _IO_file_close_it
1553 versioned_symbol (libc, _IO_new_do_write, _IO_do_write, GLIBC_2_1);
1554 versioned_symbol (libc, _IO_new_file_attach, _IO_file_attach, GLIBC_2_1);
1555 versioned_symbol (libc, _IO_new_file_close_it, _IO_file_close_it, GLIBC_2_1);
1556 versioned_symbol (libc, _IO_new_file_finish, _IO_file_finish, GLIBC_2_1);
1557 versioned_symbol (libc, _IO_new_file_fopen, _IO_file_fopen, GLIBC_2_1);
1558 versioned_symbol (libc, _IO_new_file_init, _IO_file_init, GLIBC_2_1);
1559 versioned_symbol (libc, _IO_new_file_setbuf, _IO_file_setbuf, GLIBC_2_1);
1560 versioned_symbol (libc, _IO_new_file_sync, _IO_file_sync, GLIBC_2_1);
1561 versioned_symbol (libc, _IO_new_file_overflow, _IO_file_overflow, GLIBC_2_1);
1562 versioned_symbol (libc, _IO_new_file_seekoff, _IO_file_seekoff, GLIBC_2_1);
1563 versioned_symbol (libc, _IO_new_file_underflow, _IO_file_underflow, GLIBC_2_1);
1564 versioned_symbol (libc, _IO_new_file_write, _IO_file_write, GLIBC_2_1);
1565 versioned_symbol (libc, _IO_new_file_xsputn, _IO_file_xsputn, GLIBC_2_1);
1566 #endif
1567
1568 const struct _IO_jump_t _IO_file_jumps =
1569 {
1570   JUMP_INIT_DUMMY,
1571   JUMP_INIT(finish, INTUSE(_IO_file_finish)),
1572   JUMP_INIT(overflow, INTUSE(_IO_file_overflow)),
1573   JUMP_INIT(underflow, INTUSE(_IO_file_underflow)),
1574   JUMP_INIT(uflow, INTUSE(_IO_default_uflow)),
1575   JUMP_INIT(pbackfail, INTUSE(_IO_default_pbackfail)),
1576   JUMP_INIT(xsputn, INTUSE(_IO_file_xsputn)),
1577   JUMP_INIT(xsgetn, INTUSE(_IO_file_xsgetn)),
1578   JUMP_INIT(seekoff, _IO_new_file_seekoff),
1579   JUMP_INIT(seekpos, _IO_default_seekpos),
1580   JUMP_INIT(setbuf, _IO_new_file_setbuf),
1581   JUMP_INIT(sync, _IO_new_file_sync),
1582   JUMP_INIT(doallocate, INTUSE(_IO_file_doallocate)),
1583   JUMP_INIT(read, INTUSE(_IO_file_read)),
1584   JUMP_INIT(write, _IO_new_file_write),
1585   JUMP_INIT(seek, INTUSE(_IO_file_seek)),
1586   JUMP_INIT(close, INTUSE(_IO_file_close)),
1587   JUMP_INIT(stat, INTUSE(_IO_file_stat)),
1588   JUMP_INIT(showmanyc, _IO_default_showmanyc),
1589   JUMP_INIT(imbue, _IO_default_imbue)
1590 };
1591 libc_hidden_data_def (_IO_file_jumps)
1592
1593 const struct _IO_jump_t _IO_file_jumps_mmap =
1594 {
1595   JUMP_INIT_DUMMY,
1596   JUMP_INIT(finish, INTUSE(_IO_file_finish)),
1597   JUMP_INIT(overflow, INTUSE(_IO_file_overflow)),
1598   JUMP_INIT(underflow, _IO_file_underflow_mmap),
1599   JUMP_INIT(uflow, INTUSE(_IO_default_uflow)),
1600   JUMP_INIT(pbackfail, INTUSE(_IO_default_pbackfail)),
1601   JUMP_INIT(xsputn, _IO_new_file_xsputn),
1602   JUMP_INIT(xsgetn, _IO_file_xsgetn_mmap),
1603   JUMP_INIT(seekoff, _IO_file_seekoff_mmap),
1604   JUMP_INIT(seekpos, _IO_default_seekpos),
1605   JUMP_INIT(setbuf, (_IO_setbuf_t) _IO_file_setbuf_mmap),
1606   JUMP_INIT(sync, _IO_file_sync_mmap),
1607   JUMP_INIT(doallocate, INTUSE(_IO_file_doallocate)),
1608   JUMP_INIT(read, INTUSE(_IO_file_read)),
1609   JUMP_INIT(write, _IO_new_file_write),
1610   JUMP_INIT(seek, INTUSE(_IO_file_seek)),
1611   JUMP_INIT(close, _IO_file_close_mmap),
1612   JUMP_INIT(stat, INTUSE(_IO_file_stat)),
1613   JUMP_INIT(showmanyc, _IO_default_showmanyc),
1614   JUMP_INIT(imbue, _IO_default_imbue)
1615 };
1616
1617 const struct _IO_jump_t _IO_file_jumps_maybe_mmap =
1618 {
1619   JUMP_INIT_DUMMY,
1620   JUMP_INIT(finish, INTUSE(_IO_file_finish)),
1621   JUMP_INIT(overflow, INTUSE(_IO_file_overflow)),
1622   JUMP_INIT(underflow, _IO_file_underflow_maybe_mmap),
1623   JUMP_INIT(uflow, INTUSE(_IO_default_uflow)),
1624   JUMP_INIT(pbackfail, INTUSE(_IO_default_pbackfail)),
1625   JUMP_INIT(xsputn, _IO_new_file_xsputn),
1626   JUMP_INIT(xsgetn, _IO_file_xsgetn_maybe_mmap),
1627   JUMP_INIT(seekoff, _IO_file_seekoff_maybe_mmap),
1628   JUMP_INIT(seekpos, _IO_default_seekpos),
1629   JUMP_INIT(setbuf, (_IO_setbuf_t) _IO_file_setbuf_mmap),
1630   JUMP_INIT(sync, _IO_new_file_sync),
1631   JUMP_INIT(doallocate, INTUSE(_IO_file_doallocate)),
1632   JUMP_INIT(read, INTUSE(_IO_file_read)),
1633   JUMP_INIT(write, _IO_new_file_write),
1634   JUMP_INIT(seek, INTUSE(_IO_file_seek)),
1635   JUMP_INIT(close, _IO_file_close),
1636   JUMP_INIT(stat, INTUSE(_IO_file_stat)),
1637   JUMP_INIT(showmanyc, _IO_default_showmanyc),
1638   JUMP_INIT(imbue, _IO_default_imbue)
1639 };