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