xref: /haiku/src/system/libroot/posix/glibc/libio/fileops.c (revision a06fca85da281c34b4ba6185d04c8b8ec16f1390)
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
_IO_new_file_init(fp)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 }
libc_hidden_def(_IO_file_open)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 #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 }
401 INTDEF2(_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 }
421 INTDEF2(_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 }
INTDEF2(_IO_new_file_setbuf,_IO_file_setbuf)438 INTDEF2(_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 
464 static 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 
469 int
_IO_new_do_write(fp,data,to_do)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 }
478 INTDEF2(_IO_new_do_write, _IO_do_write)
479 
480 static
481 int
482 new_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 
515 int
_IO_new_file_underflow(fp)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 }
INTDEF2(_IO_new_file_underflow,_IO_file_underflow)598 INTDEF2(_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.  */
605 static int
606 mmap_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 
697 punt:
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.  */
714 int
_IO_file_underflow_mmap(_IO_FILE * fp)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 
732 static void
decide_maybe_mmap(_IO_FILE * fp)733 decide_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 
806 int
_IO_file_underflow_maybe_mmap(_IO_FILE * fp)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 
817 int
_IO_new_file_overflow(f,ch)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 }
869 INTDEF2(_IO_new_file_overflow, _IO_file_overflow)
870 
871 int
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 }
INTDEF2(_IO_new_file_sync,_IO_file_sync)904 INTDEF2(_IO_new_file_sync, _IO_file_sync)
905 
906 #ifdef HAVE_MMAP
907 static int
908 _IO_file_sync_mmap (_IO_FILE *fp)
909 {
910   if (fp->_IO_read_ptr != fp->_IO_read_end)
911     {
912 #ifdef TODO
913       if (_IO_in_backup (fp))
914 	delta -= eGptr () - Gbase ();
915 #endif
916       if (
917 # ifdef _G_LSEEK64
918 	  _G_LSEEK64
919 # else
920 	  __lseek
921 # endif
922 	  (fp->_fileno, fp->_IO_read_ptr - fp->_IO_buf_base, SEEK_SET)
923 	  != fp->_IO_read_ptr - fp->_IO_buf_base)
924 	{
925 	  fp->_flags |= _IO_ERR_SEEN;
926 	  return EOF;
927 	}
928     }
929   fp->_offset = fp->_IO_read_ptr - fp->_IO_buf_base;
930   fp->_IO_read_end = fp->_IO_read_ptr = fp->_IO_read_base;
931   return 0;
932 }
933 #endif	/* HAVE_MMAP */
934 
935 
936 _IO_off64_t
_IO_new_file_seekoff(fp,offset,dir,mode)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 
1116 resync:
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 }
1126 INTDEF2(_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
1188 static _IO_off64_t
_IO_file_seekoff_maybe_mmap(_IO_FILE * fp,_IO_off64_t offset,int dir,int mode)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
_IO_file_read(fp,buf,size)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 }
1213 INTDEF(_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 }
1227 INTDEF(_IO_file_seek)
1228 
1229 int
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 }
1240 INTDEF(_IO_file_stat)
1241 
1242 #ifdef HAVE_MMAP
1243 int
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 
1254 int
_IO_file_close(fp)1255 _IO_file_close (fp)
1256      _IO_FILE *fp;
1257 {
1258   return close (fp->_fileno);
1259 }
1260 INTDEF(_IO_file_close)
1261 
1262 _IO_ssize_t
1263 _IO_new_file_write (f, data, n)
1264      _IO_FILE *f;
1265      const void *data;
1266      _IO_ssize_t n;
1267 {
1268   _IO_ssize_t to_do = n;
1269   while (to_do > 0)
1270     {
1271       _IO_ssize_t count = write (f->_fileno, data, to_do);
1272       if (count < 0)
1273 	{
1274 	  f->_flags |= _IO_ERR_SEEN;
1275 	  break;
1276         }
1277       to_do -= count;
1278       data = (void *) ((char *) data + count);
1279     }
1280   n -= to_do;
1281   if (f->_offset >= 0)
1282     f->_offset += n;
1283   return n;
1284 }
1285 
1286 _IO_size_t
_IO_new_file_xsputn(f,data,n)1287 _IO_new_file_xsputn (f, data, n)
1288      _IO_FILE *f;
1289      const void *data;
1290      _IO_size_t n;
1291 {
1292   register const char *s = (const char *) data;
1293   _IO_size_t to_do = n;
1294   int must_flush = 0;
1295   _IO_size_t count;
1296 
1297   if (n <= 0)
1298     return 0;
1299   /* This is an optimized implementation.
1300      If the amount to be written straddles a block boundary
1301      (or the filebuf is unbuffered), use sys_write directly. */
1302 
1303   /* First figure out how much space is available in the buffer. */
1304   count = f->_IO_write_end - f->_IO_write_ptr; /* Space available. */
1305   if ((f->_flags & _IO_LINE_BUF) && (f->_flags & _IO_CURRENTLY_PUTTING))
1306     {
1307       count = f->_IO_buf_end - f->_IO_write_ptr;
1308       if (count >= n)
1309 	{
1310 	  register const char *p;
1311 	  for (p = s + n; p > s; )
1312 	    {
1313 	      if (*--p == '\n')
1314 		{
1315 		  count = p - s + 1;
1316 		  must_flush = 1;
1317 		  break;
1318 		}
1319 	    }
1320 	}
1321     }
1322   /* Then fill the buffer. */
1323   if (count > 0)
1324     {
1325       if (count > to_do)
1326 	count = to_do;
1327       if (count > 20)
1328 	{
1329 #ifdef _LIBC
1330 	  f->_IO_write_ptr = __mempcpy (f->_IO_write_ptr, s, count);
1331 #else
1332 	  memcpy (f->_IO_write_ptr, s, count);
1333 	  f->_IO_write_ptr += count;
1334 #endif
1335 	  s += count;
1336 	}
1337       else
1338 	{
1339 	  register char *p = f->_IO_write_ptr;
1340 	  register int i = (int) count;
1341 	  while (--i >= 0)
1342 	    *p++ = *s++;
1343 	  f->_IO_write_ptr = p;
1344 	}
1345       to_do -= count;
1346     }
1347   if (to_do + must_flush > 0)
1348     {
1349       _IO_size_t block_size, do_write;
1350       /* Next flush the (full) buffer. */
1351       if (_IO_OVERFLOW (f, EOF) == EOF)
1352 	return n - to_do;
1353 
1354       /* Try to maintain alignment: write a whole number of blocks.
1355 	 dont_write is what gets left over. */
1356       block_size = f->_IO_buf_end - f->_IO_buf_base;
1357       do_write = to_do - (block_size >= 128 ? to_do % block_size : 0);
1358 
1359       if (do_write)
1360         {
1361 	  count = new_do_write (f, s, do_write);
1362 	  to_do -= count;
1363 	  if (count < do_write)
1364 	    return n - to_do;
1365         }
1366 
1367       /* Now write out the remainder.  Normally, this will fit in the
1368 	 buffer, but it's somewhat messier for line-buffered files,
1369 	 so we let _IO_default_xsputn handle the general case. */
1370       if (to_do)
1371 	to_do -= INTUSE(_IO_default_xsputn) (f, s+do_write, to_do);
1372     }
1373   return n - to_do;
1374 }
1375 INTDEF2(_IO_new_file_xsputn, _IO_file_xsputn)
1376 
1377 _IO_size_t
1378 _IO_file_xsgetn (fp, data, n)
1379      _IO_FILE *fp;
1380      void *data;
1381      _IO_size_t n;
1382 {
1383   register _IO_size_t want, have;
1384   register _IO_ssize_t count;
1385   register char *s = data;
1386 
1387   want = n;
1388 
1389   if (fp->_IO_buf_base == NULL)
1390     {
1391       /* Maybe we already have a push back pointer.  */
1392       if (fp->_IO_save_base != NULL)
1393 	{
1394 	  free (fp->_IO_save_base);
1395 	  fp->_flags &= ~_IO_IN_BACKUP;
1396 	}
1397       INTUSE(_IO_doallocbuf) (fp);
1398     }
1399 
1400   while (want > 0)
1401     {
1402       have = fp->_IO_read_end - fp->_IO_read_ptr;
1403       if (want <= have)
1404 	{
1405 	  memcpy (s, fp->_IO_read_ptr, want);
1406 	  fp->_IO_read_ptr += want;
1407 	  want = 0;
1408 	}
1409       else
1410 	{
1411 	  if (have > 0)
1412 	    {
1413 #ifdef _LIBC
1414 	      s = __mempcpy (s, fp->_IO_read_ptr, have);
1415 #else
1416 	      memcpy (s, fp->_IO_read_ptr, have);
1417 	      s += have;
1418 #endif
1419 	      want -= have;
1420 	      fp->_IO_read_ptr += have;
1421 	    }
1422 
1423 	  /* Check for backup and repeat */
1424 	  if (_IO_in_backup (fp))
1425 	    {
1426 	      _IO_switch_to_main_get_area (fp);
1427 	      continue;
1428 	    }
1429 
1430 	  /* If we now want less than a buffer, underflow and repeat
1431 	     the copy.  Otherwise, _IO_SYSREAD directly to
1432 	     the user buffer. */
1433 	  if (fp->_IO_buf_base
1434 	      && want < (size_t) (fp->_IO_buf_end - fp->_IO_buf_base))
1435 	    {
1436 	      if (__underflow (fp) == EOF)
1437 		break;
1438 
1439 	      continue;
1440 	    }
1441 
1442 	  /* These must be set before the sysread as we might longjmp out
1443 	     waiting for input. */
1444 	  _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
1445 	  _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
1446 
1447 	  /* Try to maintain alignment: read a whole number of blocks.  */
1448 	  count = want;
1449 	  if (fp->_IO_buf_base)
1450 	    {
1451 	      _IO_size_t block_size = fp->_IO_buf_end - fp->_IO_buf_base;
1452 	      if (block_size >= 128)
1453 		count -= want % block_size;
1454 	    }
1455 
1456 	  count = _IO_SYSREAD (fp, s, count);
1457 	  if (count <= 0)
1458 	    {
1459 	      if (count == 0)
1460 		fp->_flags |= _IO_EOF_SEEN;
1461 	      else
1462 		fp->_flags |= _IO_ERR_SEEN;
1463 
1464 	      break;
1465 	    }
1466 
1467 	  s += count;
1468 	  want -= count;
1469 	  if (fp->_offset != _IO_pos_BAD)
1470 	    _IO_pos_adjust (fp->_offset, count);
1471 	}
1472     }
1473 
1474   return n - want;
1475 }
1476 INTDEF(_IO_file_xsgetn)
1477 
1478 #ifdef HAVE_MMAP
1479 static _IO_size_t _IO_file_xsgetn_mmap __P ((_IO_FILE *, void *, _IO_size_t));
1480 static _IO_size_t
_IO_file_xsgetn_mmap(fp,data,n)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 
1538 static _IO_size_t _IO_file_xsgetn_maybe_mmap __P ((_IO_FILE *, void *,
1539 						   _IO_size_t));
1540 static _IO_size_t
_IO_file_xsgetn_maybe_mmap(fp,data,n)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
1556 versioned_symbol (libc, _IO_new_do_write, _IO_do_write, GLIBC_2_1);
1557 versioned_symbol (libc, _IO_new_file_attach, _IO_file_attach, GLIBC_2_1);
1558 versioned_symbol (libc, _IO_new_file_close_it, _IO_file_close_it, GLIBC_2_1);
1559 versioned_symbol (libc, _IO_new_file_finish, _IO_file_finish, GLIBC_2_1);
1560 versioned_symbol (libc, _IO_new_file_fopen, _IO_file_fopen, GLIBC_2_1);
1561 versioned_symbol (libc, _IO_new_file_init, _IO_file_init, GLIBC_2_1);
1562 versioned_symbol (libc, _IO_new_file_setbuf, _IO_file_setbuf, GLIBC_2_1);
1563 versioned_symbol (libc, _IO_new_file_sync, _IO_file_sync, GLIBC_2_1);
1564 versioned_symbol (libc, _IO_new_file_overflow, _IO_file_overflow, GLIBC_2_1);
1565 versioned_symbol (libc, _IO_new_file_seekoff, _IO_file_seekoff, GLIBC_2_1);
1566 versioned_symbol (libc, _IO_new_file_underflow, _IO_file_underflow, GLIBC_2_1);
1567 versioned_symbol (libc, _IO_new_file_write, _IO_file_write, GLIBC_2_1);
1568 versioned_symbol (libc, _IO_new_file_xsputn, _IO_file_xsputn, GLIBC_2_1);
1569 #endif
1570 
1571 struct _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 };
1594 INTVARDEF(_IO_file_jumps)
1595 
1596 #ifdef HAVE_MMAP
1597 struct _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 
1621 struct _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