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