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