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