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