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