0d02fca93ece4b191e551d4be01d960f09a4b19b
[kopensolaris-gnu/glibc.git] / libio / fileops.c
1 /* Copyright (C) 1993, 1995, 1997-2001, 2002 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Written by Per Bothner <bothner@cygnus.com>.
4
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, write to the Free
17    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18    02111-1307 USA.
19
20    As a special exception, if you link the code in this file with
21    files compiled with a GNU compiler to produce an executable,
22    that does not cause the resulting executable to be covered by
23    the GNU Lesser General Public License.  This exception does not
24    however invalidate any other reasons why the executable file
25    might be covered by the GNU Lesser General Public License.
26    This exception applies to code released by its copyright holders
27    in files containing the exception.  */
28
29
30 #ifndef _POSIX_SOURCE
31 # define _POSIX_SOURCE
32 #endif
33 #include "libioP.h"
34 #include <assert.h>
35 #include <fcntl.h>
36 #include <sys/param.h>
37 #include <sys/types.h>
38 #include <sys/stat.h>
39 #include <string.h>
40 #include <errno.h>
41 #include <unistd.h>
42 #ifdef __STDC__
43 #include <stdlib.h>
44 #endif
45 #if _LIBC
46 # include "../wcsmbs/wcsmbsload.h"
47 # include "../iconv/gconv_charset.h"
48 # include "../iconv/gconv_int.h"
49 # include <shlib-compat.h>
50 #endif
51 #ifndef errno
52 extern int errno;
53 #endif
54 #ifndef __set_errno
55 # define __set_errno(Val) errno = (Val)
56 #endif
57
58
59 #ifdef _LIBC
60 # define open(Name, Flags, Prot) __open (Name, Flags, Prot)
61 # define close(FD) __close (FD)
62 # define lseek(FD, Offset, Whence) __lseek (FD, Offset, Whence)
63 # define read(FD, Buf, NBytes) __read (FD, Buf, NBytes)
64 # define write(FD, Buf, NBytes) __write (FD, Buf, NBytes)
65 #else
66 # define _IO_new_do_write _IO_do_write
67 # define _IO_new_file_attach _IO_file_attach
68 # define _IO_new_file_close_it _IO_file_close_it
69 # define _IO_new_file_finish _IO_file_finish
70 # define _IO_new_file_fopen _IO_file_fopen
71 # define _IO_new_file_init _IO_file_init
72 # define _IO_new_file_setbuf _IO_file_setbuf
73 # define _IO_new_file_sync _IO_file_sync
74 # define _IO_new_file_overflow _IO_file_overflow
75 # define _IO_new_file_seekoff _IO_file_seekoff
76 # define _IO_new_file_underflow _IO_file_underflow
77 # define _IO_new_file_write _IO_file_write
78 # define _IO_new_file_xsputn _IO_file_xsputn
79 #endif
80
81
82 #ifdef _LIBC
83 extern struct __gconv_trans_data __libio_translit;
84 #endif
85
86
87 /* An fstream can be in at most one of put mode, get mode, or putback mode.
88    Putback mode is a variant of get mode.
89
90    In a filebuf, there is only one current position, instead of two
91    separate get and put pointers.  In get mode, the current position
92    is that of gptr(); in put mode that of pptr().
93
94    The position in the buffer that corresponds to the position
95    in external file system is normally _IO_read_end, except in putback
96    mode, when it is _IO_save_end.
97    If the field _fb._offset is >= 0, it gives the offset in
98    the file as a whole corresponding to eGptr(). (?)
99
100    PUT MODE:
101    If a filebuf is in put mode, then all of _IO_read_ptr, _IO_read_end,
102    and _IO_read_base are equal to each other.  These are usually equal
103    to _IO_buf_base, though not necessarily if we have switched from
104    get mode to put mode.  (The reason is to maintain the invariant
105    that _IO_read_end corresponds to the external file position.)
106    _IO_write_base is non-NULL and usually equal to _IO_base_base.
107    We also have _IO_write_end == _IO_buf_end, but only in fully buffered mode.
108    The un-flushed character are those between _IO_write_base and _IO_write_ptr.
109
110    GET MODE:
111    If a filebuf is in get or putback mode, eback() != egptr().
112    In get mode, the unread characters are between gptr() and egptr().
113    The OS file position corresponds to that of egptr().
114
115    PUTBACK MODE:
116    Putback mode is used to remember "excess" characters that have
117    been sputbackc'd in a separate putback buffer.
118    In putback mode, the get buffer points to the special putback buffer.
119    The unread characters are the characters between gptr() and egptr()
120    in the putback buffer, as well as the area between save_gptr()
121    and save_egptr(), which point into the original reserve buffer.
122    (The pointers save_gptr() and save_egptr() are the values
123    of gptr() and egptr() at the time putback mode was entered.)
124    The OS position corresponds to that of save_egptr().
125
126    LINE BUFFERED OUTPUT:
127    During line buffered output, _IO_write_base==base() && epptr()==base().
128    However, ptr() may be anywhere between base() and ebuf().
129    This forces a call to filebuf::overflow(int C) on every put.
130    If there is more space in the buffer, and C is not a '\n',
131    then C is inserted, and pptr() incremented.
132
133    UNBUFFERED STREAMS:
134    If a filebuf is unbuffered(), the _shortbuf[1] is used as the buffer.
135 */
136
137 #define CLOSED_FILEBUF_FLAGS \
138   (_IO_IS_FILEBUF+_IO_NO_READS+_IO_NO_WRITES+_IO_TIED_PUT_GET)
139
140
141 void
142 _IO_new_file_init (fp)
143      struct _IO_FILE_plus *fp;
144 {
145   /* POSIX.1 allows another file handle to be used to change the position
146      of our file descriptor.  Hence we actually don't know the actual
147      position before we do the first fseek (and until a following fflush). */
148   fp->file._offset = _IO_pos_BAD;
149   fp->file._IO_file_flags |= CLOSED_FILEBUF_FLAGS;
150
151   _IO_link_in (fp);
152   fp->file._fileno = -1;
153 }
154
155 int
156 _IO_new_file_close_it (fp)
157      _IO_FILE *fp;
158 {
159   int write_status, close_status;
160   if (!_IO_file_is_open (fp))
161     return EOF;
162
163   write_status = _IO_do_flush (fp);
164
165   _IO_unsave_markers(fp);
166
167   close_status = _IO_SYSCLOSE (fp);
168
169   /* Free buffer. */
170   if (fp->_mode <= 0)
171     {
172       _IO_setb (fp, NULL, NULL, 0);
173       _IO_setg (fp, NULL, NULL, NULL);
174       _IO_setp (fp, NULL, NULL);
175     }
176 #if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T
177   else
178     {
179       _IO_wsetb (fp, NULL, NULL, 0);
180       _IO_wsetg (fp, NULL, NULL, NULL);
181       _IO_wsetp (fp, NULL, NULL);
182     }
183 #endif
184
185   _IO_un_link ((struct _IO_FILE_plus *) fp);
186   fp->_flags = _IO_MAGIC|CLOSED_FILEBUF_FLAGS;
187   fp->_fileno = -1;
188   fp->_offset = _IO_pos_BAD;
189
190   return close_status ? close_status : write_status;
191 }
192
193 void
194 _IO_new_file_finish (fp, dummy)
195      _IO_FILE *fp;
196      int dummy;
197 {
198   if (_IO_file_is_open (fp))
199     {
200       _IO_do_flush (fp);
201       if (!(fp->_flags & _IO_DELETE_DONT_CLOSE))
202         _IO_SYSCLOSE (fp);
203     }
204   _IO_default_finish (fp, 0);
205 }
206
207 #if defined __GNUC__ && __GNUC__ >= 2
208 __inline__
209 #endif
210 _IO_FILE *
211 _IO_file_open (fp, filename, posix_mode, prot, read_write, is32not64)
212      _IO_FILE *fp;
213      const char *filename;
214      int posix_mode;
215      int prot;
216      int read_write;
217      int is32not64;
218 {
219   int fdesc;
220 #ifdef _G_OPEN64
221   fdesc = (is32not64
222            ? open (filename, posix_mode, prot)
223            : _G_OPEN64 (filename, posix_mode, prot));
224 #else
225   fdesc = open (filename, posix_mode, prot);
226 #endif
227   if (fdesc < 0)
228     return NULL;
229   fp->_fileno = fdesc;
230   _IO_mask_flags (fp, read_write,_IO_NO_READS+_IO_NO_WRITES+_IO_IS_APPENDING);
231   if (read_write & _IO_IS_APPENDING)
232     if (_IO_SEEKOFF (fp, (_IO_off64_t)0, _IO_seek_end, _IOS_INPUT|_IOS_OUTPUT)
233         == _IO_pos_BAD && errno != ESPIPE)
234       return NULL;
235   _IO_link_in ((struct _IO_FILE_plus *) fp);
236   return fp;
237 }
238
239 _IO_FILE *
240 _IO_new_file_fopen (fp, filename, mode, is32not64)
241      _IO_FILE *fp;
242      const char *filename;
243      const char *mode;
244      int is32not64;
245 {
246   int oflags = 0, omode;
247   int read_write;
248   int oprot = 0666;
249   int i;
250   _IO_FILE *result;
251 #ifdef _LIBC
252   const char *cs;
253   const char *last_recognized;
254 #endif
255
256   if (_IO_file_is_open (fp))
257     return 0;
258   switch (*mode)
259     {
260     case 'r':
261       omode = O_RDONLY;
262       read_write = _IO_NO_WRITES;
263       break;
264     case 'w':
265       omode = O_WRONLY;
266       oflags = O_CREAT|O_TRUNC;
267       read_write = _IO_NO_READS;
268       break;
269     case 'a':
270       omode = O_WRONLY;
271       oflags = O_CREAT|O_APPEND;
272       read_write = _IO_NO_READS|_IO_IS_APPENDING;
273       break;
274     default:
275       __set_errno (EINVAL);
276       return NULL;
277     }
278 #ifdef _LIBC
279   last_recognized = mode;
280 #endif
281   for (i = 1; i < 4; ++i)
282     {
283       switch (*++mode)
284         {
285         case '\0':
286           break;
287         case '+':
288           omode = O_RDWR;
289           read_write &= _IO_IS_APPENDING;
290 #ifdef _LIBC
291           last_recognized = mode;
292 #endif
293           continue;
294         case 'x':
295           oflags |= O_EXCL;
296 #ifdef _LIBC
297           last_recognized = mode;
298 #endif
299           continue;
300         case 'b':
301 #ifdef _LIBC
302           last_recognized = mode;
303 #endif
304         default:
305           /* Ignore.  */
306           continue;
307         }
308       break;
309     }
310
311   result = _IO_file_open (fp, filename, omode|oflags, oprot, read_write,
312                           is32not64);
313
314
315 #ifdef _LIBC
316   if (result != NULL)
317     {
318       /* Test whether the mode string specifies the conversion.  */
319       cs = strstr (last_recognized + 1, ",ccs=");
320       if (cs != NULL)
321         {
322           /* Yep.  Load the appropriate conversions and set the orientation
323              to wide.  */
324           struct gconv_fcts fcts;
325           struct _IO_codecvt *cc;
326           char *endp = __strchrnul (cs + 5, ',');
327           char ccs[endp - (cs + 5) + 3];
328
329           *((char *) __mempcpy (ccs, cs + 5, endp - (cs + 5))) = '\0';
330           strip (ccs, ccs);
331
332           if (__wcsmbs_named_conv (&fcts, ccs[2] == '\0'
333                                    ? upstr (ccs, cs + 5) : ccs) != 0)
334             {
335               /* Something went wrong, we cannot load the conversion modules.
336                  This means we cannot proceed since the user explicitly asked
337                  for these.  */
338               __set_errno (EINVAL);
339               return NULL;
340             }
341
342           assert (fcts.towc_nsteps == 1);
343           assert (fcts.tomb_nsteps == 1);
344
345           fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_read_end;
346           fp->_wide_data->_IO_write_ptr = fp->_wide_data->_IO_write_base;
347
348           /* Clear the state.  We start all over again.  */
349           memset (&fp->_wide_data->_IO_state, '\0', sizeof (__mbstate_t));
350           memset (&fp->_wide_data->_IO_last_state, '\0', sizeof (__mbstate_t));
351
352           cc = fp->_codecvt = &fp->_wide_data->_codecvt;
353
354           /* The functions are always the same.  */
355           *cc = __libio_codecvt;
356
357           cc->__cd_in.__cd.__nsteps = fcts.towc_nsteps;
358           cc->__cd_in.__cd.__steps = fcts.towc;
359
360           cc->__cd_in.__cd.__data[0].__invocation_counter = 0;
361           cc->__cd_in.__cd.__data[0].__internal_use = 1;
362           cc->__cd_in.__cd.__data[0].__flags = __GCONV_IS_LAST;
363           cc->__cd_in.__cd.__data[0].__statep = &result->_wide_data->_IO_state;
364
365           /* XXX For now no transliteration.  */
366           cc->__cd_in.__cd.__data[0].__trans = NULL;
367
368           cc->__cd_out.__cd.__nsteps = fcts.tomb_nsteps;
369           cc->__cd_out.__cd.__steps = fcts.tomb;
370
371           cc->__cd_out.__cd.__data[0].__invocation_counter = 0;
372           cc->__cd_out.__cd.__data[0].__internal_use = 1;
373           cc->__cd_out.__cd.__data[0].__flags = __GCONV_IS_LAST;
374           cc->__cd_out.__cd.__data[0].__statep =
375             &result->_wide_data->_IO_state;
376
377           /* And now the transliteration.  */
378           cc->__cd_out.__cd.__data[0].__trans = &__libio_translit;
379
380           /* Set the mode now.  */
381           result->_mode = 1;
382
383           /* We don't need the step data structure anymore.  */
384           __gconv_release_cache (fcts.towc, fcts.towc_nsteps);
385           __gconv_release_cache (fcts.tomb, fcts.tomb_nsteps);
386         }
387     }
388 #endif  /* GNU libc */
389
390   return result;
391 }
392
393 _IO_FILE *
394 _IO_new_file_attach (fp, fd)
395      _IO_FILE *fp;
396      int fd;
397 {
398   if (_IO_file_is_open (fp))
399     return NULL;
400   fp->_fileno = fd;
401   fp->_flags &= ~(_IO_NO_READS+_IO_NO_WRITES);
402   fp->_flags |= _IO_DELETE_DONT_CLOSE;
403   /* Get the current position of the file. */
404   /* We have to do that since that may be junk. */
405   fp->_offset = _IO_pos_BAD;
406   if (_IO_SEEKOFF (fp, (_IO_off64_t)0, _IO_seek_cur, _IOS_INPUT|_IOS_OUTPUT)
407       == _IO_pos_BAD && errno != ESPIPE)
408     return NULL;
409   return fp;
410 }
411
412 _IO_FILE *
413 _IO_new_file_setbuf (fp, p, len)
414      _IO_FILE *fp;
415      char *p;
416      _IO_ssize_t len;
417 {
418   if (_IO_default_setbuf (fp, p, len) == NULL)
419     return NULL;
420
421   fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end
422     = fp->_IO_buf_base;
423   _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
424
425   return fp;
426 }
427
428 static int new_do_write __P ((_IO_FILE *, const char *, _IO_size_t));
429
430 /* Write TO_DO bytes from DATA to FP.
431    Then mark FP as having empty buffers. */
432
433 int
434 _IO_new_do_write (fp, data, to_do)
435      _IO_FILE *fp;
436      const char *data;
437      _IO_size_t to_do;
438 {
439   return (to_do == 0 || new_do_write (fp, data, to_do) == to_do) ? 0 : EOF;
440 }
441
442 static
443 int
444 new_do_write (fp, data, to_do)
445      _IO_FILE *fp;
446      const char *data;
447      _IO_size_t to_do;
448 {
449   _IO_size_t count;
450   if (fp->_flags & _IO_IS_APPENDING)
451     /* On a system without a proper O_APPEND implementation,
452        you would need to sys_seek(0, SEEK_END) here, but is
453        is not needed nor desirable for Unix- or Posix-like systems.
454        Instead, just indicate that offset (before and after) is
455        unpredictable. */
456     fp->_offset = _IO_pos_BAD;
457   else if (fp->_IO_read_end != fp->_IO_write_base)
458     {
459       _IO_off64_t new_pos
460         = _IO_SYSSEEK (fp, fp->_IO_write_base - fp->_IO_read_end, 1);
461       if (new_pos == _IO_pos_BAD)
462         return 0;
463       fp->_offset = new_pos;
464     }
465   count = _IO_SYSWRITE (fp, data, to_do);
466   if (fp->_cur_column && count)
467     fp->_cur_column = _IO_adjust_column (fp->_cur_column - 1, data, count) + 1;
468   _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
469   fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_buf_base;
470   fp->_IO_write_end = (fp->_mode <= 0
471                        && (fp->_flags & (_IO_LINE_BUF+_IO_UNBUFFERED))
472                        ? fp->_IO_buf_base : fp->_IO_buf_end);
473   return count;
474 }
475
476 int
477 _IO_new_file_underflow (fp)
478      _IO_FILE *fp;
479 {
480   _IO_ssize_t count;
481 #if 0
482   /* SysV does not make this test; take it out for compatibility */
483   if (fp->_flags & _IO_EOF_SEEN)
484     return (EOF);
485 #endif
486
487   if (fp->_flags & _IO_NO_READS)
488     {
489       fp->_flags |= _IO_ERR_SEEN;
490       __set_errno (EBADF);
491       return EOF;
492     }
493   if (fp->_IO_read_ptr < fp->_IO_read_end)
494     return *(unsigned char *) fp->_IO_read_ptr;
495
496   if (fp->_IO_buf_base == NULL)
497     {
498       /* Maybe we already have a push back pointer.  */
499       if (fp->_IO_save_base != NULL)
500         {
501           free (fp->_IO_save_base);
502           fp->_flags &= ~_IO_IN_BACKUP;
503         }
504       _IO_doallocbuf (fp);
505     }
506
507   /* Flush all line buffered files before reading. */
508   /* FIXME This can/should be moved to genops ?? */
509   if (fp->_flags & (_IO_LINE_BUF|_IO_UNBUFFERED))
510     {
511 #if 0
512       _IO_flush_all_linebuffered ();
513 #else
514       /* We used to flush all line-buffered stream.  This really isn't
515          required by any standard.  My recollection is that
516          traditional Unix systems did this for stdout.  stderr better
517          not be line buffered.  So we do just that here
518          explicitly.  --drepper */
519       _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile,
520                                 _IO_stdout);
521       _IO_flockfile (_IO_stdout);
522
523       if ((_IO_stdout->_flags & (_IO_LINKED | _IO_NO_WRITES | _IO_LINE_BUF))
524           == (_IO_LINKED | _IO_LINE_BUF))
525         _IO_OVERFLOW (_IO_stdout, EOF);
526
527       _IO_funlockfile (_IO_stdout);
528       _IO_cleanup_region_end (0);
529 #endif
530     }
531
532   _IO_switch_to_get_mode (fp);
533
534   /* This is very tricky. We have to adjust those
535      pointers before we call _IO_SYSREAD () since
536      we may longjump () out while waiting for
537      input. Those pointers may be screwed up. H.J. */
538   fp->_IO_read_base = fp->_IO_read_ptr = fp->_IO_buf_base;
539   fp->_IO_read_end = fp->_IO_buf_base;
540   fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end
541     = fp->_IO_buf_base;
542
543   count = _IO_SYSREAD (fp, fp->_IO_buf_base,
544                        fp->_IO_buf_end - fp->_IO_buf_base);
545   if (count <= 0)
546     {
547       if (count == 0)
548         fp->_flags |= _IO_EOF_SEEN;
549       else
550         fp->_flags |= _IO_ERR_SEEN, count = 0;
551   }
552   fp->_IO_read_end += count;
553   if (count == 0)
554     return EOF;
555   if (fp->_offset != _IO_pos_BAD)
556     _IO_pos_adjust (fp->_offset, count);
557   return *(unsigned char *) fp->_IO_read_ptr;
558 }
559
560 /* Special callback replacing the underflow callbacks if we mmap the
561    file.  */
562 int
563 _IO_file_underflow_mmap (_IO_FILE *fp)
564 {
565   if (fp->_IO_read_end < fp->_IO_buf_end)
566     {
567       if (
568 # ifdef _G_LSEEK64
569           _G_LSEEK64 (fp->_fileno, fp->_IO_buf_end - fp->_IO_buf_base,
570                       SEEK_SET)
571 # else
572           __lseek (fp->_fileno, fp->_IO_buf_end - fp->_IO_buf_base, SEEK_SET)
573 # endif
574           != fp->_IO_buf_end - fp->_IO_buf_base)
575         {
576           fp->_flags |= _IO_ERR_SEEN;
577           return EOF;
578         }
579
580       fp->_offset = fp->_IO_buf_end - fp->_IO_buf_base;
581       fp->_IO_read_end = fp->_IO_buf_end;
582       return *(unsigned char *) fp->_IO_read_ptr;
583     }
584
585   fp->_flags |= _IO_EOF_SEEN;
586   return EOF;
587 }
588
589 int
590 _IO_new_file_overflow (f, ch)
591       _IO_FILE *f;
592       int ch;
593 {
594   if (f->_flags & _IO_NO_WRITES) /* SET ERROR */
595     {
596       f->_flags |= _IO_ERR_SEEN;
597       __set_errno (EBADF);
598       return EOF;
599     }
600   /* If currently reading or no buffer allocated. */
601   if ((f->_flags & _IO_CURRENTLY_PUTTING) == 0 || f->_IO_write_base == 0)
602     {
603       /* Allocate a buffer if needed. */
604       if (f->_IO_write_base == 0)
605         {
606           _IO_doallocbuf (f);
607           _IO_setg (f, f->_IO_buf_base, f->_IO_buf_base, f->_IO_buf_base);
608         }
609       /* Otherwise must be currently reading.
610          If _IO_read_ptr (and hence also _IO_read_end) is at the buffer end,
611          logically slide the buffer forwards one block (by setting the
612          read pointers to all point at the beginning of the block).  This
613          makes room for subsequent output.
614          Otherwise, set the read pointers to _IO_read_end (leaving that
615          alone, so it can continue to correspond to the external position). */
616       if (f->_IO_read_ptr == f->_IO_buf_end)
617         f->_IO_read_end = f->_IO_read_ptr = f->_IO_buf_base;
618       f->_IO_write_ptr = f->_IO_read_ptr;
619       f->_IO_write_base = f->_IO_write_ptr;
620       f->_IO_write_end = f->_IO_buf_end;
621       f->_IO_read_base = f->_IO_read_ptr = f->_IO_read_end;
622
623       f->_flags |= _IO_CURRENTLY_PUTTING;
624       if (f->_mode <= 0 && f->_flags & (_IO_LINE_BUF+_IO_UNBUFFERED))
625         f->_IO_write_end = f->_IO_write_ptr;
626     }
627   if (ch == EOF)
628     return _IO_new_do_write(f, f->_IO_write_base,
629                             f->_IO_write_ptr - f->_IO_write_base);
630   if (f->_IO_write_ptr == f->_IO_buf_end ) /* Buffer is really full */
631     if (_IO_do_flush (f) == EOF)
632       return EOF;
633   *f->_IO_write_ptr++ = ch;
634   if ((f->_flags & _IO_UNBUFFERED)
635       || ((f->_flags & _IO_LINE_BUF) && ch == '\n'))
636     if (_IO_new_do_write(f, f->_IO_write_base,
637                          f->_IO_write_ptr - f->_IO_write_base) == EOF)
638       return EOF;
639   return (unsigned char) ch;
640 }
641
642 int
643 _IO_new_file_sync (fp)
644      _IO_FILE *fp;
645 {
646   _IO_ssize_t delta;
647   int retval = 0;
648
649   /*    char* ptr = cur_ptr(); */
650   if (fp->_IO_write_ptr > fp->_IO_write_base)
651     if (_IO_do_flush(fp)) return EOF;
652   delta = fp->_IO_read_ptr - fp->_IO_read_end;
653   if (delta != 0)
654     {
655 #ifdef TODO
656       if (_IO_in_backup (fp))
657         delta -= eGptr () - Gbase ();
658 #endif
659       _IO_off64_t new_pos = _IO_SYSSEEK (fp, delta, 1);
660       if (new_pos != (_IO_off64_t) EOF)
661         fp->_IO_read_end = fp->_IO_read_ptr;
662 #ifdef ESPIPE
663       else if (errno == ESPIPE)
664         ; /* Ignore error from unseekable devices. */
665 #endif
666       else
667         retval = EOF;
668     }
669   if (retval != EOF)
670     fp->_offset = _IO_pos_BAD;
671   /* FIXME: Cleanup - can this be shared? */
672   /*    setg(base(), ptr, ptr); */
673   return retval;
674 }
675
676 _IO_off64_t
677 _IO_new_file_seekoff (fp, offset, dir, mode)
678      _IO_FILE *fp;
679      _IO_off64_t offset;
680      int dir;
681      int mode;
682 {
683   _IO_off64_t result;
684   _IO_off64_t delta, new_offset;
685   long count;
686   /* POSIX.1 8.2.3.7 says that after a call the fflush() the file
687      offset of the underlying file must be exact.  */
688   int must_be_exact = (fp->_IO_read_base == fp->_IO_read_end
689                        && fp->_IO_write_base == fp->_IO_write_ptr);
690
691   if (mode == 0)
692     dir = _IO_seek_cur, offset = 0; /* Don't move any pointers. */
693
694   /* Flush unwritten characters.
695      (This may do an unneeded write if we seek within the buffer.
696      But to be able to switch to reading, we would need to set
697      egptr to ptr.  That can't be done in the current design,
698      which assumes file_ptr() is eGptr.  Anyway, since we probably
699      end up flushing when we close(), it doesn't make much difference.)
700      FIXME: simulate mem-papped files. */
701
702   if (fp->_IO_write_ptr > fp->_IO_write_base || _IO_in_put_mode (fp))
703     if (_IO_switch_to_get_mode (fp))
704       return EOF;
705
706   if (fp->_IO_buf_base == NULL)
707     {
708       /* It could be that we already have a pushback buffer.  */
709       if (fp->_IO_read_base != NULL)
710         {
711           free (fp->_IO_read_base);
712           fp->_flags &= ~_IO_IN_BACKUP;
713         }
714       _IO_doallocbuf (fp);
715       _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
716       _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
717     }
718
719   switch (dir)
720     {
721     case _IO_seek_cur:
722       /* Adjust for read-ahead (bytes is buffer). */
723       offset -= fp->_IO_read_end - fp->_IO_read_ptr;
724       if (fp->_offset == _IO_pos_BAD)
725         goto dumb;
726       /* Make offset absolute, assuming current pointer is file_ptr(). */
727       offset += fp->_offset;
728
729       dir = _IO_seek_set;
730       break;
731     case _IO_seek_set:
732       break;
733     case _IO_seek_end:
734       {
735         struct _G_stat64 st;
736         if (_IO_SYSSTAT (fp, &st) == 0 && S_ISREG (st.st_mode))
737           {
738             offset += st.st_size;
739             dir = _IO_seek_set;
740           }
741         else
742           goto dumb;
743       }
744     }
745   /* At this point, dir==_IO_seek_set. */
746
747   /* If we are only interested in the current position we've found it now.  */
748   if (mode == 0)
749     return offset;
750
751   /* If destination is within current buffer, optimize: */
752   if (fp->_offset != _IO_pos_BAD && fp->_IO_read_base != NULL
753       && !_IO_in_backup (fp))
754     {
755       /* Offset relative to start of main get area. */
756       _IO_off64_t rel_offset = (offset - fp->_offset
757                                 + (fp->_IO_read_end - fp->_IO_read_base));
758       if (rel_offset >= 0)
759         {
760 #if 0
761           if (_IO_in_backup (fp))
762             _IO_switch_to_main_get_area (fp);
763 #endif
764           if (rel_offset <= fp->_IO_read_end - fp->_IO_read_base)
765             {
766               _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base + rel_offset,
767                         fp->_IO_read_end);
768               _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
769               {
770                 _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
771                 goto resync;
772               }
773             }
774 #ifdef TODO
775             /* If we have streammarkers, seek forward by reading ahead. */
776             if (_IO_have_markers (fp))
777               {
778                 int to_skip = rel_offset
779                   - (fp->_IO_read_ptr - fp->_IO_read_base);
780                 if (ignore (to_skip) != to_skip)
781                   goto dumb;
782                 _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
783                 goto resync;
784               }
785 #endif
786         }
787 #ifdef TODO
788       if (rel_offset < 0 && rel_offset >= Bbase () - Bptr ())
789         {
790           if (!_IO_in_backup (fp))
791             _IO_switch_to_backup_area (fp);
792           gbump (fp->_IO_read_end + rel_offset - fp->_IO_read_ptr);
793           _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
794           goto resync;
795         }
796 #endif
797     }
798
799 #ifdef TODO
800   _IO_unsave_markers (fp);
801 #endif
802
803   if (fp->_flags & _IO_NO_READS)
804     goto dumb;
805
806   /* Try to seek to a block boundary, to improve kernel page management. */
807   new_offset = offset & ~(fp->_IO_buf_end - fp->_IO_buf_base - 1);
808   delta = offset - new_offset;
809   if (delta > fp->_IO_buf_end - fp->_IO_buf_base)
810     {
811       new_offset = offset;
812       delta = 0;
813     }
814   result = _IO_SYSSEEK (fp, new_offset, 0);
815   if (result < 0)
816     return EOF;
817   if (delta == 0)
818     count = 0;
819   else
820     {
821       count = _IO_SYSREAD (fp, fp->_IO_buf_base,
822                            (must_be_exact
823                             ? delta : fp->_IO_buf_end - fp->_IO_buf_base));
824       if (count < delta)
825         {
826           /* We weren't allowed to read, but try to seek the remainder. */
827           offset = count == EOF ? delta : delta-count;
828           dir = _IO_seek_cur;
829           goto dumb;
830         }
831     }
832   _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base + delta,
833             fp->_IO_buf_base + count);
834   _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
835   fp->_offset = result + count;
836   _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
837   return offset;
838  dumb:
839
840   _IO_unsave_markers (fp);
841   result = _IO_SYSSEEK (fp, offset, dir);
842   if (result != EOF)
843     {
844       _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
845       fp->_offset = result;
846       _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
847       _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
848     }
849   return result;
850
851 resync:
852   /* We need to do it since it is possible that the file offset in
853      the kernel may be changed behind our back. It may happen when
854      we fopen a file and then do a fork. One process may access the
855      the file and the kernel file offset will be changed. */
856   if (fp->_offset >= 0)
857     _IO_SYSSEEK (fp, fp->_offset, 0);
858
859   return offset;
860 }
861
862 _IO_off64_t
863 _IO_file_seekoff_mmap (fp, offset, dir, mode)
864      _IO_FILE *fp;
865      _IO_off64_t offset;
866      int dir;
867      int mode;
868 {
869   _IO_off64_t result;
870
871   if (mode == 0)
872     dir = _IO_seek_cur, offset = 0; /* Don't move any pointers. */
873
874   switch (dir)
875     {
876     case _IO_seek_cur:
877       /* Adjust for read-ahead (bytes is buffer). */
878       offset += fp->_IO_read_ptr - fp->_IO_read_base;
879       break;
880     case _IO_seek_set:
881       break;
882     case _IO_seek_end:
883       offset += fp->_IO_buf_end - fp->_IO_buf_base;
884       break;
885     }
886   /* At this point, dir==_IO_seek_set. */
887
888   if (offset < 0)
889     /* No negative offsets are valid.  */
890     return EOF;
891
892   /* If we are only interested in the current position we've found it now.  */
893   if (mode == 0)
894     return offset;
895
896   result = _IO_SYSSEEK (fp, offset, 0);
897   if (result < 0)
898     return EOF;
899
900   _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base + offset,
901             fp->_IO_buf_base + offset);
902
903   _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
904
905   return offset;
906 }
907
908 _IO_ssize_t
909 _IO_file_read (fp, buf, size)
910      _IO_FILE *fp;
911      void *buf;
912      _IO_ssize_t size;
913 {
914   return read (fp->_fileno, buf, size);
915 }
916
917 _IO_off64_t
918 _IO_file_seek (fp, offset, dir)
919      _IO_FILE *fp;
920      _IO_off64_t offset;
921      int dir;
922 {
923 #ifdef _G_LSEEK64
924   return _G_LSEEK64 (fp->_fileno, offset, dir);
925 #else
926   return lseek (fp->_fileno, offset, dir);
927 #endif
928 }
929
930 int
931 _IO_file_stat (fp, st)
932      _IO_FILE *fp;
933      void *st;
934 {
935 #ifdef _G_FSTAT64
936   return _G_FSTAT64 (fp->_fileno, (struct _G_stat64 *) st);
937 #else
938   return fstat (fp->_fileno, (struct stat *) st);
939 #endif
940 }
941
942 int
943 _IO_file_close_mmap (fp)
944      _IO_FILE *fp;
945 {
946   /* In addition to closing the file descriptor we have to unmap the
947      file.  */
948   (void) munmap (fp->_IO_buf_base, fp->_IO_buf_end - fp->_IO_buf_base);
949   fp->_IO_buf_base = fp->_IO_buf_end = NULL;
950   return close (fp->_fileno);
951 }
952
953 int
954 _IO_file_close (fp)
955      _IO_FILE *fp;
956 {
957   return close (fp->_fileno);
958 }
959
960 _IO_ssize_t
961 _IO_new_file_write (f, data, n)
962      _IO_FILE *f;
963      const void *data;
964      _IO_ssize_t n;
965 {
966   _IO_ssize_t to_do = n;
967   while (to_do > 0)
968     {
969       _IO_ssize_t count = write (f->_fileno, data, to_do);
970       if (count < 0)
971         {
972           f->_flags |= _IO_ERR_SEEN;
973           break;
974         }
975       to_do -= count;
976       data = (void *) ((char *) data + count);
977     }
978   n -= to_do;
979   if (f->_offset >= 0)
980     f->_offset += n;
981   return n;
982 }
983
984 _IO_size_t
985 _IO_new_file_xsputn (f, data, n)
986      _IO_FILE *f;
987      const void *data;
988      _IO_size_t n;
989 {
990   register const char *s = (const char *) data;
991   _IO_size_t to_do = n;
992   int must_flush = 0;
993   _IO_size_t count;
994
995   if (n <= 0)
996     return 0;
997   /* This is an optimized implementation.
998      If the amount to be written straddles a block boundary
999      (or the filebuf is unbuffered), use sys_write directly. */
1000
1001   /* First figure out how much space is available in the buffer. */
1002   count = f->_IO_write_end - f->_IO_write_ptr; /* Space available. */
1003   if ((f->_flags & _IO_LINE_BUF) && (f->_flags & _IO_CURRENTLY_PUTTING))
1004     {
1005       count = f->_IO_buf_end - f->_IO_write_ptr;
1006       if (count >= n)
1007         {
1008           register const char *p;
1009           for (p = s + n; p > s; )
1010             {
1011               if (*--p == '\n')
1012                 {
1013                   count = p - s + 1;
1014                   must_flush = 1;
1015                   break;
1016                 }
1017             }
1018         }
1019     }
1020   /* Then fill the buffer. */
1021   if (count > 0)
1022     {
1023       if (count > to_do)
1024         count = to_do;
1025       if (count > 20)
1026         {
1027 #ifdef _LIBC
1028           f->_IO_write_ptr = __mempcpy (f->_IO_write_ptr, s, count);
1029 #else
1030           memcpy (f->_IO_write_ptr, s, count);
1031           f->_IO_write_ptr += count;
1032 #endif
1033           s += count;
1034         }
1035       else
1036         {
1037           register char *p = f->_IO_write_ptr;
1038           register int i = (int) count;
1039           while (--i >= 0)
1040             *p++ = *s++;
1041           f->_IO_write_ptr = p;
1042         }
1043       to_do -= count;
1044     }
1045   if (to_do + must_flush > 0)
1046     {
1047       _IO_size_t block_size, do_write;
1048       /* Next flush the (full) buffer. */
1049       if (_IO_OVERFLOW (f, EOF) == EOF)
1050         return n - to_do;
1051
1052       /* Try to maintain alignment: write a whole number of blocks.
1053          dont_write is what gets left over. */
1054       block_size = f->_IO_buf_end - f->_IO_buf_base;
1055       do_write = to_do - (block_size >= 128 ? to_do % block_size : 0);
1056
1057       if (do_write)
1058         {
1059           count = new_do_write (f, s, do_write);
1060           to_do -= count;
1061           if (count < do_write)
1062             return n - to_do;
1063         }
1064
1065       /* Now write out the remainder.  Normally, this will fit in the
1066          buffer, but it's somewhat messier for line-buffered files,
1067          so we let _IO_default_xsputn handle the general case. */
1068       if (to_do)
1069         to_do -= _IO_default_xsputn (f, s+do_write, to_do);
1070     }
1071   return n - to_do;
1072 }
1073
1074 _IO_size_t
1075 _IO_file_xsgetn (fp, data, n)
1076      _IO_FILE *fp;
1077      void *data;
1078      _IO_size_t n;
1079 {
1080   register _IO_size_t want, have;
1081   register _IO_ssize_t count;
1082   register char *s = data;
1083
1084   want = n;
1085
1086   if (fp->_IO_buf_base == NULL)
1087     {
1088       /* Maybe we already have a push back pointer.  */
1089       if (fp->_IO_save_base != NULL)
1090         {
1091           free (fp->_IO_save_base);
1092           fp->_flags &= ~_IO_IN_BACKUP;
1093         }
1094       _IO_doallocbuf (fp);
1095     }
1096
1097   while (want > 0)
1098     {
1099       have = fp->_IO_read_end - fp->_IO_read_ptr;
1100       if (want <= have)
1101         {
1102           memcpy (s, fp->_IO_read_ptr, want);
1103           fp->_IO_read_ptr += want;
1104           want = 0;
1105         }
1106       else
1107         {
1108           if (have > 0)
1109             {
1110 #ifdef _LIBC
1111               s = __mempcpy (s, fp->_IO_read_ptr, have);
1112 #else
1113               memcpy (s, fp->_IO_read_ptr, have);
1114               s += have;
1115 #endif
1116               want -= have;
1117               fp->_IO_read_ptr += have;
1118             }
1119
1120           /* Check for backup and repeat */
1121           if (_IO_in_backup (fp))
1122             {
1123               _IO_switch_to_main_get_area (fp);
1124               continue;
1125             }
1126
1127           /* If we now want less than a buffer, underflow and repeat
1128              the copy.  Otherwise, _IO_SYSREAD directly to
1129              the user buffer. */
1130           if (fp->_IO_buf_base && want < fp->_IO_buf_end - fp->_IO_buf_base)
1131             {
1132               if (__underflow (fp) == EOF)
1133                 break;
1134
1135               continue;
1136             }
1137
1138           /* These must be set before the sysread as we might longjmp out
1139              waiting for input. */
1140           _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
1141           _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
1142
1143           /* Try to maintain alignment: read a whole number of blocks.  */
1144           count = want;
1145           if (fp->_IO_buf_base)
1146             {
1147               _IO_size_t block_size = fp->_IO_buf_end - fp->_IO_buf_base;
1148               if (block_size >= 128)
1149                 count -= want % block_size;
1150             }
1151
1152           count = _IO_SYSREAD (fp, s, count);
1153           if (count <= 0)
1154             {
1155               if (count == 0)
1156                 fp->_flags |= _IO_EOF_SEEN;
1157               else
1158                 fp->_flags |= _IO_ERR_SEEN;
1159
1160               break;
1161             }
1162
1163           s += count;
1164           want -= count;
1165           if (fp->_offset != _IO_pos_BAD)
1166             _IO_pos_adjust (fp->_offset, count);
1167         }
1168     }
1169
1170   return n - want;
1171 }
1172
1173 static _IO_size_t _IO_file_xsgetn_mmap __P ((_IO_FILE *, void *, _IO_size_t));
1174 static _IO_size_t
1175 _IO_file_xsgetn_mmap (fp, data, n)
1176      _IO_FILE *fp;
1177      void *data;
1178      _IO_size_t n;
1179 {
1180   register _IO_size_t have;
1181   char *read_ptr = fp->_IO_read_ptr;
1182
1183   have = fp->_IO_read_end - fp->_IO_read_ptr;
1184
1185   if (have < n)
1186     {
1187       /* Maybe the read buffer is not yet fully set up.  */
1188       fp->_IO_read_ptr = fp->_IO_read_end;
1189       if (fp->_IO_read_end < fp->_IO_buf_end
1190           && _IO_file_underflow_mmap (fp) != EOF)
1191         have = fp->_IO_read_end - read_ptr;
1192     }
1193
1194   if (have == 0)
1195     fp->_flags |= _IO_EOF_SEEN;
1196   else
1197     {
1198       have = MIN (have, n);
1199       memcpy (data, read_ptr, have);
1200       fp->_IO_read_ptr = read_ptr + have;
1201     }
1202
1203   return have;
1204 }
1205
1206 struct _IO_jump_t _IO_file_jumps =
1207 {
1208   JUMP_INIT_DUMMY,
1209   JUMP_INIT(finish, _IO_new_file_finish),
1210   JUMP_INIT(overflow, _IO_new_file_overflow),
1211   JUMP_INIT(underflow, _IO_new_file_underflow),
1212   JUMP_INIT(uflow, _IO_default_uflow),
1213   JUMP_INIT(pbackfail, _IO_default_pbackfail),
1214   JUMP_INIT(xsputn, _IO_new_file_xsputn),
1215   JUMP_INIT(xsgetn, _IO_file_xsgetn),
1216   JUMP_INIT(seekoff, _IO_new_file_seekoff),
1217   JUMP_INIT(seekpos, _IO_default_seekpos),
1218   JUMP_INIT(setbuf, _IO_new_file_setbuf),
1219   JUMP_INIT(sync, _IO_new_file_sync),
1220   JUMP_INIT(doallocate, _IO_file_doallocate),
1221   JUMP_INIT(read, _IO_file_read),
1222   JUMP_INIT(write, _IO_new_file_write),
1223   JUMP_INIT(seek, _IO_file_seek),
1224   JUMP_INIT(close, _IO_file_close),
1225   JUMP_INIT(stat, _IO_file_stat),
1226   JUMP_INIT(showmanyc, _IO_default_showmanyc),
1227   JUMP_INIT(imbue, _IO_default_imbue)
1228 };
1229
1230 struct _IO_jump_t _IO_file_jumps_mmap =
1231 {
1232   JUMP_INIT_DUMMY,
1233   JUMP_INIT(finish, _IO_new_file_finish),
1234   JUMP_INIT(overflow, _IO_new_file_overflow),
1235   JUMP_INIT(underflow, _IO_file_underflow_mmap),
1236   JUMP_INIT(uflow, _IO_default_uflow),
1237   JUMP_INIT(pbackfail, _IO_default_pbackfail),
1238   JUMP_INIT(xsputn, _IO_new_file_xsputn),
1239   JUMP_INIT(xsgetn, _IO_file_xsgetn_mmap),
1240   JUMP_INIT(seekoff, _IO_file_seekoff_mmap),
1241   JUMP_INIT(seekpos, _IO_default_seekpos),
1242   JUMP_INIT(setbuf, _IO_new_file_setbuf),
1243   JUMP_INIT(sync, _IO_new_file_sync),
1244   JUMP_INIT(doallocate, _IO_file_doallocate),
1245   JUMP_INIT(read, _IO_file_read),
1246   JUMP_INIT(write, _IO_new_file_write),
1247   JUMP_INIT(seek, _IO_file_seek),
1248   JUMP_INIT(close, _IO_file_close_mmap),
1249   JUMP_INIT(stat, _IO_file_stat),
1250   JUMP_INIT(showmanyc, _IO_default_showmanyc),
1251   JUMP_INIT(imbue, _IO_default_imbue)
1252 };
1253
1254 #ifdef _LIBC
1255 versioned_symbol (libc, _IO_new_do_write, _IO_do_write, GLIBC_2_1);
1256 versioned_symbol (libc, _IO_new_file_attach, _IO_file_attach, GLIBC_2_1);
1257 versioned_symbol (libc, _IO_new_file_close_it, _IO_file_close_it, GLIBC_2_1);
1258 versioned_symbol (libc, _IO_new_file_finish, _IO_file_finish, GLIBC_2_1);
1259 versioned_symbol (libc, _IO_new_file_fopen, _IO_file_fopen, GLIBC_2_1);
1260 versioned_symbol (libc, _IO_new_file_init, _IO_file_init, GLIBC_2_1);
1261 versioned_symbol (libc, _IO_new_file_setbuf, _IO_file_setbuf, GLIBC_2_1);
1262 versioned_symbol (libc, _IO_new_file_sync, _IO_file_sync, GLIBC_2_1);
1263 versioned_symbol (libc, _IO_new_file_overflow, _IO_file_overflow, GLIBC_2_1);
1264 versioned_symbol (libc, _IO_new_file_seekoff, _IO_file_seekoff, GLIBC_2_1);
1265 versioned_symbol (libc, _IO_new_file_underflow, _IO_file_underflow, GLIBC_2_1);
1266 versioned_symbol (libc, _IO_new_file_write, _IO_file_write, GLIBC_2_1);
1267 versioned_symbol (libc, _IO_new_file_xsputn, _IO_file_xsputn, GLIBC_2_1);
1268 #endif