1 /* Copyright (C) 1993-2018 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Written by Per Bothner <bothner@cygnus.com>.
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.
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.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <http://www.gnu.org/licenses/>.
19 As a special exception, if you link the code in this file with
20 files compiled with a GNU compiler to produce an executable,
21 that does not cause the resulting executable to be covered by
22 the GNU Lesser General Public License. This exception does not
23 however invalidate any other reasons why the executable file
24 might be covered by the GNU Lesser General Public License.
25 This exception applies to code released by its copyright holders
26 in files containing the exception. */
28 /* This is a compatibility file. If we don't build the libc with
29 versioning don't compile this file. */
30 #include <shlib-compat.h>
31 #if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
33 #define _IO_USE_OLD_IO_FILE
36 #include <sys/types.h>
43 /* An fstream can be in at most one of put mode, get mode, or putback mode.
44 Putback mode is a variant of get mode.
46 In a filebuf, there is only one current position, instead of two
47 separate get and put pointers. In get mode, the current position
48 is that of gptr(); in put mode that of pptr().
50 The position in the buffer that corresponds to the position
51 in external file system is normally _IO_read_end, except in putback
52 mode, when it is _IO_save_end.
53 If the field _fb._offset is >= 0, it gives the offset in
54 the file as a whole corresponding to eGptr(). (?)
57 If a filebuf is in put mode, then all of _IO_read_ptr, _IO_read_end,
58 and _IO_read_base are equal to each other. These are usually equal
59 to _IO_buf_base, though not necessarily if we have switched from
60 get mode to put mode. (The reason is to maintain the invariant
61 that _IO_read_end corresponds to the external file position.)
62 _IO_write_base is non-NULL and usually equal to _IO_buf_base.
63 We also have _IO_write_end == _IO_buf_end, but only in fully buffered mode.
64 The un-flushed character are those between _IO_write_base and _IO_write_ptr.
67 If a filebuf is in get or putback mode, eback() != egptr().
68 In get mode, the unread characters are between gptr() and egptr().
69 The OS file position corresponds to that of egptr().
72 Putback mode is used to remember "excess" characters that have
73 been sputbackc'd in a separate putback buffer.
74 In putback mode, the get buffer points to the special putback buffer.
75 The unread characters are the characters between gptr() and egptr()
76 in the putback buffer, as well as the area between save_gptr()
77 and save_egptr(), which point into the original reserve buffer.
78 (The pointers save_gptr() and save_egptr() are the values
79 of gptr() and egptr() at the time putback mode was entered.)
80 The OS position corresponds to that of save_egptr().
83 During line buffered output, _IO_write_base==base() && epptr()==base().
84 However, ptr() may be anywhere between base() and ebuf().
85 This forces a call to filebuf::overflow(int C) on every put.
86 If there is more space in the buffer, and C is not a '\n',
87 then C is inserted, and pptr() incremented.
90 If a filebuf is unbuffered(), the _shortbuf[1] is used as the buffer.
93 #define CLOSED_FILEBUF_FLAGS \
94 (_IO_IS_FILEBUF+_IO_NO_READS+_IO_NO_WRITES+_IO_TIED_PUT_GET)
98 attribute_compat_text_section
99 _IO_old_file_init_internal (struct _IO_FILE_plus *fp)
101 /* POSIX.1 allows another file handle to be used to change the position
102 of our file descriptor. Hence we actually don't know the actual
103 position before we do the first fseek (and until a following fflush). */
104 fp->file._old_offset = _IO_pos_BAD;
105 fp->file._flags |= CLOSED_FILEBUF_FLAGS;
108 fp->file._vtable_offset = ((int) sizeof (struct _IO_FILE)
109 - (int) sizeof (struct _IO_FILE_complete));
110 fp->file._fileno = -1;
112 if (__builtin_expect (&_IO_stdin_used != NULL, 1)
113 || (fp != (struct _IO_FILE_plus *) _IO_stdin
114 && fp != (struct _IO_FILE_plus *) _IO_stdout
115 && fp != (struct _IO_FILE_plus *) _IO_stderr))
116 /* The object is dynamically allocated and large enough. Initialize
117 the _mode element as well. */
118 ((struct _IO_FILE_complete *) fp)->_mode = -1;
122 attribute_compat_text_section
123 _IO_old_file_init (struct _IO_FILE_plus *fp)
125 IO_set_accept_foreign_vtables (&_IO_vtable_check);
126 _IO_old_file_init_internal (fp);
130 attribute_compat_text_section
131 _IO_old_file_close_it (FILE *fp)
133 int write_status, close_status;
134 if (!_IO_file_is_open (fp))
137 write_status = _IO_old_do_flush (fp);
139 _IO_unsave_markers (fp);
141 close_status = ((fp->_flags2 & _IO_FLAGS2_NOCLOSE) == 0
142 ? _IO_SYSCLOSE (fp) : 0);
145 _IO_setb (fp, NULL, NULL, 0);
146 _IO_setg (fp, NULL, NULL, NULL);
147 _IO_setp (fp, NULL, NULL);
149 _IO_un_link ((struct _IO_FILE_plus *) fp);
150 fp->_flags = _IO_MAGIC|CLOSED_FILEBUF_FLAGS;
152 fp->_old_offset = _IO_pos_BAD;
154 return close_status ? close_status : write_status;
158 attribute_compat_text_section
159 _IO_old_file_finish (FILE *fp, int dummy)
161 if (_IO_file_is_open (fp))
163 _IO_old_do_flush (fp);
164 if (!(fp->_flags & _IO_DELETE_DONT_CLOSE))
167 _IO_default_finish (fp, 0);
171 attribute_compat_text_section
172 _IO_old_file_fopen (FILE *fp, const char *filename, const char *mode)
174 int oflags = 0, omode;
175 int read_write, fdesc;
177 if (_IO_file_is_open (fp))
183 read_write = _IO_NO_WRITES;
187 oflags = O_CREAT|O_TRUNC;
188 read_write = _IO_NO_READS;
192 oflags = O_CREAT|O_APPEND;
193 read_write = _IO_NO_READS|_IO_IS_APPENDING;
196 __set_errno (EINVAL);
199 if (mode[0] == '+' || (mode[0] == 'b' && mode[1] == '+'))
202 read_write &= _IO_IS_APPENDING;
204 fdesc = __open (filename, omode|oflags, oprot);
208 _IO_mask_flags (fp, read_write,_IO_NO_READS+_IO_NO_WRITES+_IO_IS_APPENDING);
209 if (read_write & _IO_IS_APPENDING)
210 if (_IO_SEEKOFF (fp, (off_t)0, _IO_seek_end, _IOS_INPUT|_IOS_OUTPUT)
211 == _IO_pos_BAD && errno != ESPIPE)
213 _IO_link_in ((struct _IO_FILE_plus *) fp);
218 attribute_compat_text_section
219 _IO_old_file_attach (FILE *fp, int fd)
221 if (_IO_file_is_open (fp))
224 fp->_flags &= ~(_IO_NO_READS+_IO_NO_WRITES);
225 fp->_flags |= _IO_DELETE_DONT_CLOSE;
226 /* Get the current position of the file. */
227 /* We have to do that since that may be junk. */
228 fp->_old_offset = _IO_pos_BAD;
229 if (_IO_SEEKOFF (fp, (off_t)0, _IO_seek_cur, _IOS_INPUT|_IOS_OUTPUT)
230 == _IO_pos_BAD && errno != ESPIPE)
236 attribute_compat_text_section
237 _IO_old_file_setbuf (FILE *fp, char *p, ssize_t len)
239 if (_IO_default_setbuf (fp, p, len) == NULL)
242 fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end
244 _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
249 static int old_do_write (FILE *, const char *, size_t);
251 /* Write TO_DO bytes from DATA to FP.
252 Then mark FP as having empty buffers. */
255 attribute_compat_text_section
256 _IO_old_do_write (FILE *fp, const char *data, size_t to_do)
258 return (to_do == 0 || (size_t) old_do_write (fp, data, to_do) == to_do)
263 attribute_compat_text_section
264 old_do_write (FILE *fp, const char *data, size_t to_do)
267 if (fp->_flags & _IO_IS_APPENDING)
268 /* On a system without a proper O_APPEND implementation,
269 you would need to sys_seek(0, SEEK_END) here, but is
270 not needed nor desirable for Unix- or Posix-like systems.
271 Instead, just indicate that offset (before and after) is
273 fp->_old_offset = _IO_pos_BAD;
274 else if (fp->_IO_read_end != fp->_IO_write_base)
277 = _IO_SYSSEEK (fp, fp->_IO_write_base - fp->_IO_read_end, 1);
278 if (new_pos == _IO_pos_BAD)
280 fp->_old_offset = new_pos;
282 count = _IO_SYSWRITE (fp, data, to_do);
283 if (fp->_cur_column && count)
284 fp->_cur_column = _IO_adjust_column (fp->_cur_column - 1, data, count) + 1;
285 _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
286 fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_buf_base;
287 fp->_IO_write_end = ((fp->_flags & (_IO_LINE_BUF | _IO_UNBUFFERED))
288 ? fp->_IO_buf_base : fp->_IO_buf_end);
293 attribute_compat_text_section
294 _IO_old_file_underflow (FILE *fp)
298 /* C99 requires EOF to be "sticky". */
299 if (fp->_flags & _IO_EOF_SEEN)
302 if (fp->_flags & _IO_NO_READS)
304 fp->_flags |= _IO_ERR_SEEN;
308 if (fp->_IO_read_ptr < fp->_IO_read_end)
309 return *(unsigned char *) fp->_IO_read_ptr;
311 if (fp->_IO_buf_base == NULL)
313 /* Maybe we already have a push back pointer. */
314 if (fp->_IO_save_base != NULL)
316 free (fp->_IO_save_base);
317 fp->_flags &= ~_IO_IN_BACKUP;
322 /* Flush all line buffered files before reading. */
323 /* FIXME This can/should be moved to genops ?? */
324 if (fp->_flags & (_IO_LINE_BUF|_IO_UNBUFFERED))
325 _IO_flush_all_linebuffered ();
327 _IO_switch_to_get_mode (fp);
329 /* This is very tricky. We have to adjust those
330 pointers before we call _IO_SYSREAD () since
331 we may longjump () out while waiting for
332 input. Those pointers may be screwed up. H.J. */
333 fp->_IO_read_base = fp->_IO_read_ptr = fp->_IO_buf_base;
334 fp->_IO_read_end = fp->_IO_buf_base;
335 fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end
338 count = _IO_SYSREAD (fp, fp->_IO_buf_base,
339 fp->_IO_buf_end - fp->_IO_buf_base);
343 fp->_flags |= _IO_EOF_SEEN;
345 fp->_flags |= _IO_ERR_SEEN, count = 0;
347 fp->_IO_read_end += count;
350 if (fp->_old_offset != _IO_pos_BAD)
351 _IO_pos_adjust (fp->_old_offset, count);
352 return *(unsigned char *) fp->_IO_read_ptr;
356 attribute_compat_text_section
357 _IO_old_file_overflow (FILE *f, int ch)
359 if (f->_flags & _IO_NO_WRITES) /* SET ERROR */
361 f->_flags |= _IO_ERR_SEEN;
365 /* If currently reading or no buffer allocated. */
366 if ((f->_flags & _IO_CURRENTLY_PUTTING) == 0)
368 /* Allocate a buffer if needed. */
369 if (f->_IO_write_base == 0)
372 _IO_setg (f, f->_IO_buf_base, f->_IO_buf_base, f->_IO_buf_base);
374 /* Otherwise must be currently reading.
375 If _IO_read_ptr (and hence also _IO_read_end) is at the buffer end,
376 logically slide the buffer forwards one block (by setting the
377 read pointers to all point at the beginning of the block). This
378 makes room for subsequent output.
379 Otherwise, set the read pointers to _IO_read_end (leaving that
380 alone, so it can continue to correspond to the external position). */
381 if (f->_IO_read_ptr == f->_IO_buf_end)
382 f->_IO_read_end = f->_IO_read_ptr = f->_IO_buf_base;
383 f->_IO_write_ptr = f->_IO_read_ptr;
384 f->_IO_write_base = f->_IO_write_ptr;
385 f->_IO_write_end = f->_IO_buf_end;
386 f->_IO_read_base = f->_IO_read_ptr = f->_IO_read_end;
388 if (f->_flags & (_IO_LINE_BUF | _IO_UNBUFFERED))
389 f->_IO_write_end = f->_IO_write_ptr;
390 f->_flags |= _IO_CURRENTLY_PUTTING;
393 return _IO_old_do_flush (f);
394 if (f->_IO_write_ptr == f->_IO_buf_end ) /* Buffer is really full */
395 if (_IO_old_do_flush (f) == EOF)
397 *f->_IO_write_ptr++ = ch;
398 if ((f->_flags & _IO_UNBUFFERED)
399 || ((f->_flags & _IO_LINE_BUF) && ch == '\n'))
400 if (_IO_old_do_flush (f) == EOF)
402 return (unsigned char) ch;
406 attribute_compat_text_section
407 _IO_old_file_sync (FILE *fp)
412 /* char* ptr = cur_ptr(); */
413 if (fp->_IO_write_ptr > fp->_IO_write_base)
414 if (_IO_old_do_flush(fp)) return EOF;
415 delta = fp->_IO_read_ptr - fp->_IO_read_end;
419 if (_IO_in_backup (fp))
420 delta -= eGptr () - Gbase ();
422 off_t new_pos = _IO_SYSSEEK (fp, delta, 1);
423 if (new_pos != (off_t) EOF)
424 fp->_IO_read_end = fp->_IO_read_ptr;
425 else if (errno == ESPIPE)
426 ; /* Ignore error from unseekable devices. */
431 fp->_old_offset = _IO_pos_BAD;
432 /* FIXME: Cleanup - can this be shared? */
433 /* setg(base(), ptr, ptr); */
438 attribute_compat_text_section
439 _IO_old_file_seekoff (FILE *fp, off64_t offset, int dir, int mode)
442 off64_t delta, new_offset;
444 /* POSIX.1 8.2.3.7 says that after a call the fflush() the file
445 offset of the underlying file must be exact. */
446 int must_be_exact = (fp->_IO_read_base == fp->_IO_read_end
447 && fp->_IO_write_base == fp->_IO_write_ptr);
450 dir = _IO_seek_cur, offset = 0; /* Don't move any pointers. */
452 /* Flush unwritten characters.
453 (This may do an unneeded write if we seek within the buffer.
454 But to be able to switch to reading, we would need to set
455 egptr to pptr. That can't be done in the current design,
456 which assumes file_ptr() is eGptr. Anyway, since we probably
457 end up flushing when we close(), it doesn't make much difference.)
458 FIXME: simulate mem-mapped files. */
460 if (fp->_IO_write_ptr > fp->_IO_write_base || _IO_in_put_mode (fp))
461 if (_IO_switch_to_get_mode (fp))
464 if (fp->_IO_buf_base == NULL)
466 /* It could be that we already have a pushback buffer. */
467 if (fp->_IO_read_base != NULL)
469 free (fp->_IO_read_base);
470 fp->_flags &= ~_IO_IN_BACKUP;
473 _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
474 _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
480 /* Adjust for read-ahead (bytes is buffer). */
481 offset -= fp->_IO_read_end - fp->_IO_read_ptr;
482 if (fp->_old_offset == _IO_pos_BAD)
484 /* Make offset absolute, assuming current pointer is file_ptr(). */
485 offset += fp->_old_offset;
494 if (_IO_SYSSTAT (fp, &st) == 0 && S_ISREG (st.st_mode))
496 offset += st.st_size;
503 /* At this point, dir==_IO_seek_set. */
505 /* If we are only interested in the current position we've found it now. */
509 /* If destination is within current buffer, optimize: */
510 if (fp->_old_offset != _IO_pos_BAD && fp->_IO_read_base != NULL
511 && !_IO_in_backup (fp))
513 /* Offset relative to start of main get area. */
514 off_t rel_offset = (offset - fp->_old_offset
515 + (fp->_IO_read_end - fp->_IO_read_base));
518 if (rel_offset <= fp->_IO_read_end - fp->_IO_read_base)
520 _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base + rel_offset,
522 _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
524 _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
529 /* If we have streammarkers, seek forward by reading ahead. */
530 if (_IO_have_markers (fp))
532 int to_skip = rel_offset
533 - (fp->_IO_read_ptr - fp->_IO_read_base);
534 if (ignore (to_skip) != to_skip)
536 _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
542 if (rel_offset < 0 && rel_offset >= Bbase () - Bptr ())
544 if (!_IO_in_backup (fp))
545 _IO_switch_to_backup_area (fp);
546 gbump (fp->_IO_read_end + rel_offset - fp->_IO_read_ptr);
547 _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
554 _IO_unsave_markers (fp);
557 if (fp->_flags & _IO_NO_READS)
560 /* Try to seek to a block boundary, to improve kernel page management. */
561 new_offset = offset & ~(fp->_IO_buf_end - fp->_IO_buf_base - 1);
562 delta = offset - new_offset;
563 if (delta > fp->_IO_buf_end - fp->_IO_buf_base)
568 result = _IO_SYSSEEK (fp, new_offset, 0);
575 count = _IO_SYSREAD (fp, fp->_IO_buf_base,
577 ? delta : fp->_IO_buf_end - fp->_IO_buf_base));
580 /* We weren't allowed to read, but try to seek the remainder. */
581 offset = count == EOF ? delta : delta-count;
586 _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base + delta,
587 fp->_IO_buf_base + count);
588 _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
589 fp->_old_offset = result + count;
590 _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
594 _IO_unsave_markers (fp);
595 result = _IO_SYSSEEK (fp, offset, dir);
598 _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
599 fp->_old_offset = result;
600 _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
601 _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
606 /* We need to do it since it is possible that the file offset in
607 the kernel may be changed behind our back. It may happen when
608 we fopen a file and then do a fork. One process may access the
609 file and the kernel file offset will be changed. */
610 if (fp->_old_offset >= 0)
611 _IO_SYSSEEK (fp, fp->_old_offset, 0);
617 attribute_compat_text_section
618 _IO_old_file_write (FILE *f, const void *data, ssize_t n)
623 ssize_t count = __write (f->_fileno, data, to_do);
626 f->_flags |= _IO_ERR_SEEN;
630 data = (void *) ((char *) data + count);
633 if (f->_old_offset >= 0)
639 attribute_compat_text_section
640 _IO_old_file_xsputn (FILE *f, const void *data, size_t n)
642 const char *s = (char *) data;
649 /* This is an optimized implementation.
650 If the amount to be written straddles a block boundary
651 (or the filebuf is unbuffered), use sys_write directly. */
653 /* First figure out how much space is available in the buffer. */
654 if ((f->_flags & _IO_LINE_BUF) && (f->_flags & _IO_CURRENTLY_PUTTING))
656 count = f->_IO_buf_end - f->_IO_write_ptr;
660 for (p = s + n; p > s; )
671 else if (f->_IO_write_end > f->_IO_write_ptr)
672 count = f->_IO_write_end - f->_IO_write_ptr; /* Space available. */
674 /* Then fill the buffer. */
681 f->_IO_write_ptr = __mempcpy (f->_IO_write_ptr, s, count);
686 char *p = f->_IO_write_ptr;
690 f->_IO_write_ptr = p;
694 if (to_do + must_flush > 0)
696 size_t block_size, do_write;
697 /* Next flush the (full) buffer. */
698 if (__overflow (f, EOF) == EOF)
699 return to_do == 0 ? EOF : n - to_do;
701 /* Try to maintain alignment: write a whole number of blocks.
702 dont_write is what gets left over. */
703 block_size = f->_IO_buf_end - f->_IO_buf_base;
704 do_write = to_do - (block_size >= 128 ? to_do % block_size : 0);
708 count = old_do_write (f, s, do_write);
710 if (count < do_write)
714 /* Now write out the remainder. Normally, this will fit in the
715 buffer, but it's somewhat messier for line-buffered files,
716 so we let _IO_default_xsputn handle the general case. */
718 to_do -= _IO_default_xsputn (f, s+do_write, to_do);
724 const struct _IO_jump_t _IO_old_file_jumps libio_vtable =
727 JUMP_INIT(finish, _IO_old_file_finish),
728 JUMP_INIT(overflow, _IO_old_file_overflow),
729 JUMP_INIT(underflow, _IO_old_file_underflow),
730 JUMP_INIT(uflow, _IO_default_uflow),
731 JUMP_INIT(pbackfail, _IO_default_pbackfail),
732 JUMP_INIT(xsputn, _IO_old_file_xsputn),
733 JUMP_INIT(xsgetn, _IO_default_xsgetn),
734 JUMP_INIT(seekoff, _IO_old_file_seekoff),
735 JUMP_INIT(seekpos, _IO_default_seekpos),
736 JUMP_INIT(setbuf, _IO_old_file_setbuf),
737 JUMP_INIT(sync, _IO_old_file_sync),
738 JUMP_INIT(doallocate, _IO_file_doallocate),
739 JUMP_INIT(read, _IO_file_read),
740 JUMP_INIT(write, _IO_old_file_write),
741 JUMP_INIT(seek, _IO_file_seek),
742 JUMP_INIT(close, _IO_file_close),
743 JUMP_INIT(stat, _IO_file_stat)
746 compat_symbol (libc, _IO_old_do_write, _IO_do_write, GLIBC_2_0);
747 compat_symbol (libc, _IO_old_file_attach, _IO_file_attach, GLIBC_2_0);
748 compat_symbol (libc, _IO_old_file_close_it, _IO_file_close_it, GLIBC_2_0);
749 compat_symbol (libc, _IO_old_file_finish, _IO_file_finish, GLIBC_2_0);
750 compat_symbol (libc, _IO_old_file_fopen, _IO_file_fopen, GLIBC_2_0);
751 compat_symbol (libc, _IO_old_file_init, _IO_file_init, GLIBC_2_0);
752 compat_symbol (libc, _IO_old_file_setbuf, _IO_file_setbuf, GLIBC_2_0);
753 compat_symbol (libc, _IO_old_file_sync, _IO_file_sync, GLIBC_2_0);
754 compat_symbol (libc, _IO_old_file_overflow, _IO_file_overflow, GLIBC_2_0);
755 compat_symbol (libc, _IO_old_file_seekoff, _IO_file_seekoff, GLIBC_2_0);
756 compat_symbol (libc, _IO_old_file_underflow, _IO_file_underflow, GLIBC_2_0);
757 compat_symbol (libc, _IO_old_file_write, _IO_file_write, GLIBC_2_0);
758 compat_symbol (libc, _IO_old_file_xsputn, _IO_file_xsputn, GLIBC_2_0);