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