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