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