Blame libio/oldfileops.c

Packit 6c4009
/* Copyright (C) 1993-2018 Free Software Foundation, Inc.
Packit 6c4009
   This file is part of the GNU C Library.
Packit 6c4009
   Written by Per Bothner <bothner@cygnus.com>.
Packit 6c4009
Packit 6c4009
   The GNU C Library is free software; you can redistribute it and/or
Packit 6c4009
   modify it under the terms of the GNU Lesser General Public
Packit 6c4009
   License as published by the Free Software Foundation; either
Packit 6c4009
   version 2.1 of the License, or (at your option) any later version.
Packit 6c4009
Packit 6c4009
   The GNU C Library is distributed in the hope that it will be useful,
Packit 6c4009
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 6c4009
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 6c4009
   Lesser General Public License for more details.
Packit 6c4009
Packit 6c4009
   You should have received a copy of the GNU Lesser General Public
Packit 6c4009
   License along with the GNU C Library; if not, see
Packit 6c4009
   <http://www.gnu.org/licenses/>.
Packit 6c4009
Packit 6c4009
   As a special exception, if you link the code in this file with
Packit 6c4009
   files compiled with a GNU compiler to produce an executable,
Packit 6c4009
   that does not cause the resulting executable to be covered by
Packit 6c4009
   the GNU Lesser General Public License.  This exception does not
Packit 6c4009
   however invalidate any other reasons why the executable file
Packit 6c4009
   might be covered by the GNU Lesser General Public License.
Packit 6c4009
   This exception applies to code released by its copyright holders
Packit 6c4009
   in files containing the exception.  */
Packit 6c4009
Packit 6c4009
/* This is a compatibility file.  If we don't build the libc with
Packit 6c4009
   versioning don't compile this file.  */
Packit 6c4009
#include <shlib-compat.h>
Packit 6c4009
#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
Packit 6c4009
Packit 6c4009
#define _IO_USE_OLD_IO_FILE
Packit 6c4009
#include "libioP.h"
Packit 6c4009
#include <fcntl.h>
Packit 6c4009
#include <sys/types.h>
Packit 6c4009
#include <sys/stat.h>
Packit 6c4009
#include <string.h>
Packit 6c4009
#include <errno.h>
Packit 6c4009
#include <stdlib.h>
Packit 6c4009
#include <unistd.h>
Packit 6c4009
Packit 6c4009
/* An fstream can be in at most one of put mode, get mode, or putback mode.
Packit 6c4009
   Putback mode is a variant of get mode.
Packit 6c4009
Packit 6c4009
   In a filebuf, there is only one current position, instead of two
Packit 6c4009
   separate get and put pointers.  In get mode, the current position
Packit 6c4009
   is that of gptr(); in put mode that of pptr().
Packit 6c4009
Packit 6c4009
   The position in the buffer that corresponds to the position
Packit 6c4009
   in external file system is normally _IO_read_end, except in putback
Packit 6c4009
   mode, when it is _IO_save_end.
Packit 6c4009
   If the field _fb._offset is >= 0, it gives the offset in
Packit 6c4009
   the file as a whole corresponding to eGptr(). (?)
Packit 6c4009
Packit 6c4009
   PUT MODE:
Packit 6c4009
   If a filebuf is in put mode, then all of _IO_read_ptr, _IO_read_end,
Packit 6c4009
   and _IO_read_base are equal to each other.  These are usually equal
Packit 6c4009
   to _IO_buf_base, though not necessarily if we have switched from
Packit 6c4009
   get mode to put mode.  (The reason is to maintain the invariant
Packit 6c4009
   that _IO_read_end corresponds to the external file position.)
Packit 6c4009
   _IO_write_base is non-NULL and usually equal to _IO_buf_base.
Packit 6c4009
   We also have _IO_write_end == _IO_buf_end, but only in fully buffered mode.
Packit 6c4009
   The un-flushed character are those between _IO_write_base and _IO_write_ptr.
Packit 6c4009
Packit 6c4009
   GET MODE:
Packit 6c4009
   If a filebuf is in get or putback mode, eback() != egptr().
Packit 6c4009
   In get mode, the unread characters are between gptr() and egptr().
Packit 6c4009
   The OS file position corresponds to that of egptr().
Packit 6c4009
Packit 6c4009
   PUTBACK MODE:
Packit 6c4009
   Putback mode is used to remember "excess" characters that have
Packit 6c4009
   been sputbackc'd in a separate putback buffer.
Packit 6c4009
   In putback mode, the get buffer points to the special putback buffer.
Packit 6c4009
   The unread characters are the characters between gptr() and egptr()
Packit 6c4009
   in the putback buffer, as well as the area between save_gptr()
Packit 6c4009
   and save_egptr(), which point into the original reserve buffer.
Packit 6c4009
   (The pointers save_gptr() and save_egptr() are the values
Packit 6c4009
   of gptr() and egptr() at the time putback mode was entered.)
Packit 6c4009
   The OS position corresponds to that of save_egptr().
Packit 6c4009
Packit 6c4009
   LINE BUFFERED OUTPUT:
Packit 6c4009
   During line buffered output, _IO_write_base==base() && epptr()==base().
Packit 6c4009
   However, ptr() may be anywhere between base() and ebuf().
Packit 6c4009
   This forces a call to filebuf::overflow(int C) on every put.
Packit 6c4009
   If there is more space in the buffer, and C is not a '\n',
Packit 6c4009
   then C is inserted, and pptr() incremented.
Packit 6c4009
Packit 6c4009
   UNBUFFERED STREAMS:
Packit 6c4009
   If a filebuf is unbuffered(), the _shortbuf[1] is used as the buffer.
Packit 6c4009
*/
Packit 6c4009
Packit 6c4009
#define CLOSED_FILEBUF_FLAGS \
Packit 6c4009
  (_IO_IS_FILEBUF+_IO_NO_READS+_IO_NO_WRITES+_IO_TIED_PUT_GET)
Packit 6c4009
Packit 6c4009
Packit 6c4009
void
Packit 6c4009
attribute_compat_text_section
Packit 6c4009
_IO_old_file_init_internal (struct _IO_FILE_plus *fp)
Packit 6c4009
{
Packit 6c4009
  /* POSIX.1 allows another file handle to be used to change the position
Packit 6c4009
     of our file descriptor.  Hence we actually don't know the actual
Packit 6c4009
     position before we do the first fseek (and until a following fflush). */
Packit 6c4009
  fp->file._old_offset = _IO_pos_BAD;
Packit 6c4009
  fp->file._flags |= CLOSED_FILEBUF_FLAGS;
Packit 6c4009
Packit 6c4009
  _IO_link_in (fp);
Packit 6c4009
  fp->file._vtable_offset = ((int) sizeof (struct _IO_FILE)
Packit 6c4009
			     - (int) sizeof (struct _IO_FILE_complete));
Packit 6c4009
  fp->file._fileno = -1;
Packit 6c4009
Packit 6c4009
  if (__builtin_expect (&_IO_stdin_used != NULL, 1)
Packit 6c4009
      || (fp != (struct _IO_FILE_plus *) _IO_stdin
Packit 6c4009
	  && fp != (struct _IO_FILE_plus *) _IO_stdout
Packit 6c4009
	  && fp != (struct _IO_FILE_plus *) _IO_stderr))
Packit 6c4009
    /* The object is dynamically allocated and large enough.  Initialize
Packit 6c4009
       the _mode element as well.  */
Packit 6c4009
    ((struct _IO_FILE_complete *) fp)->_mode = -1;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
void
Packit 6c4009
attribute_compat_text_section
Packit 6c4009
_IO_old_file_init (struct _IO_FILE_plus *fp)
Packit 6c4009
{
Packit 6c4009
  IO_set_accept_foreign_vtables (&_IO_vtable_check);
Packit 6c4009
  _IO_old_file_init_internal (fp);
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
int
Packit 6c4009
attribute_compat_text_section
Packit 6c4009
_IO_old_file_close_it (FILE *fp)
Packit 6c4009
{
Packit 6c4009
  int write_status, close_status;
Packit 6c4009
  if (!_IO_file_is_open (fp))
Packit 6c4009
    return EOF;
Packit 6c4009
Packit 6c4009
  write_status = _IO_old_do_flush (fp);
Packit 6c4009
Packit 6c4009
  _IO_unsave_markers (fp);
Packit 6c4009
Packit 6c4009
  close_status = ((fp->_flags2 & _IO_FLAGS2_NOCLOSE) == 0
Packit 6c4009
		  ? _IO_SYSCLOSE (fp) : 0);
Packit 6c4009
Packit 6c4009
  /* Free buffer. */
Packit 6c4009
  _IO_setb (fp, NULL, NULL, 0);
Packit 6c4009
  _IO_setg (fp, NULL, NULL, NULL);
Packit 6c4009
  _IO_setp (fp, NULL, NULL);
Packit 6c4009
Packit 6c4009
  _IO_un_link ((struct _IO_FILE_plus *) fp);
Packit 6c4009
  fp->_flags = _IO_MAGIC|CLOSED_FILEBUF_FLAGS;
Packit 6c4009
  fp->_fileno = -1;
Packit 6c4009
  fp->_old_offset = _IO_pos_BAD;
Packit 6c4009
Packit 6c4009
  return close_status ? close_status : write_status;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
void
Packit 6c4009
attribute_compat_text_section
Packit 6c4009
_IO_old_file_finish (FILE *fp, int dummy)
Packit 6c4009
{
Packit 6c4009
  if (_IO_file_is_open (fp))
Packit 6c4009
    {
Packit 6c4009
      _IO_old_do_flush (fp);
Packit 6c4009
      if (!(fp->_flags & _IO_DELETE_DONT_CLOSE))
Packit 6c4009
	_IO_SYSCLOSE (fp);
Packit 6c4009
    }
Packit 6c4009
  _IO_default_finish (fp, 0);
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
FILE *
Packit 6c4009
attribute_compat_text_section
Packit 6c4009
_IO_old_file_fopen (FILE *fp, const char *filename, const char *mode)
Packit 6c4009
{
Packit 6c4009
  int oflags = 0, omode;
Packit 6c4009
  int read_write, fdesc;
Packit 6c4009
  int oprot = 0666;
Packit 6c4009
  if (_IO_file_is_open (fp))
Packit 6c4009
    return 0;
Packit 6c4009
  switch (*mode++)
Packit 6c4009
    {
Packit 6c4009
    case 'r':
Packit 6c4009
      omode = O_RDONLY;
Packit 6c4009
      read_write = _IO_NO_WRITES;
Packit 6c4009
      break;
Packit 6c4009
    case 'w':
Packit 6c4009
      omode = O_WRONLY;
Packit 6c4009
      oflags = O_CREAT|O_TRUNC;
Packit 6c4009
      read_write = _IO_NO_READS;
Packit 6c4009
      break;
Packit 6c4009
    case 'a':
Packit 6c4009
      omode = O_WRONLY;
Packit 6c4009
      oflags = O_CREAT|O_APPEND;
Packit 6c4009
      read_write = _IO_NO_READS|_IO_IS_APPENDING;
Packit 6c4009
      break;
Packit 6c4009
    default:
Packit 6c4009
      __set_errno (EINVAL);
Packit 6c4009
      return NULL;
Packit 6c4009
    }
Packit 6c4009
  if (mode[0] == '+' || (mode[0] == 'b' && mode[1] == '+'))
Packit 6c4009
    {
Packit 6c4009
      omode = O_RDWR;
Packit 6c4009
      read_write &= _IO_IS_APPENDING;
Packit 6c4009
    }
Packit 6c4009
  fdesc = __open (filename, omode|oflags, oprot);
Packit 6c4009
  if (fdesc < 0)
Packit 6c4009
    return NULL;
Packit 6c4009
  fp->_fileno = fdesc;
Packit 6c4009
  _IO_mask_flags (fp, read_write,_IO_NO_READS+_IO_NO_WRITES+_IO_IS_APPENDING);
Packit 6c4009
  if (read_write & _IO_IS_APPENDING)
Packit 6c4009
    if (_IO_SEEKOFF (fp, (off_t)0, _IO_seek_end, _IOS_INPUT|_IOS_OUTPUT)
Packit 6c4009
	== _IO_pos_BAD && errno != ESPIPE)
Packit 6c4009
      return NULL;
Packit 6c4009
  _IO_link_in ((struct _IO_FILE_plus *) fp);
Packit 6c4009
  return fp;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
FILE *
Packit 6c4009
attribute_compat_text_section
Packit 6c4009
_IO_old_file_attach (FILE *fp, int fd)
Packit 6c4009
{
Packit 6c4009
  if (_IO_file_is_open (fp))
Packit 6c4009
    return NULL;
Packit 6c4009
  fp->_fileno = fd;
Packit 6c4009
  fp->_flags &= ~(_IO_NO_READS+_IO_NO_WRITES);
Packit 6c4009
  fp->_flags |= _IO_DELETE_DONT_CLOSE;
Packit 6c4009
  /* Get the current position of the file. */
Packit 6c4009
  /* We have to do that since that may be junk. */
Packit 6c4009
  fp->_old_offset = _IO_pos_BAD;
Packit 6c4009
  if (_IO_SEEKOFF (fp, (off_t)0, _IO_seek_cur, _IOS_INPUT|_IOS_OUTPUT)
Packit 6c4009
      == _IO_pos_BAD && errno != ESPIPE)
Packit 6c4009
    return NULL;
Packit 6c4009
  return fp;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
FILE *
Packit 6c4009
attribute_compat_text_section
Packit 6c4009
_IO_old_file_setbuf (FILE *fp, char *p, ssize_t len)
Packit 6c4009
{
Packit 6c4009
    if (_IO_default_setbuf (fp, p, len) == NULL)
Packit 6c4009
      return NULL;
Packit 6c4009
Packit 6c4009
    fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end
Packit 6c4009
      = fp->_IO_buf_base;
Packit 6c4009
    _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
Packit 6c4009
Packit 6c4009
    return fp;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
static int old_do_write (FILE *, const char *, size_t);
Packit 6c4009
Packit 6c4009
/* Write TO_DO bytes from DATA to FP.
Packit 6c4009
   Then mark FP as having empty buffers. */
Packit 6c4009
Packit 6c4009
int
Packit 6c4009
attribute_compat_text_section
Packit 6c4009
_IO_old_do_write (FILE *fp, const char *data, size_t to_do)
Packit 6c4009
{
Packit 6c4009
  return (to_do == 0 || (size_t) old_do_write (fp, data, to_do) == to_do)
Packit 6c4009
	 ? 0 : EOF;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
static int
Packit 6c4009
attribute_compat_text_section
Packit 6c4009
old_do_write (FILE *fp, const char *data, size_t to_do)
Packit 6c4009
{
Packit 6c4009
  size_t count;
Packit 6c4009
  if (fp->_flags & _IO_IS_APPENDING)
Packit 6c4009
    /* On a system without a proper O_APPEND implementation,
Packit 6c4009
       you would need to sys_seek(0, SEEK_END) here, but is
Packit 6c4009
       not needed nor desirable for Unix- or Posix-like systems.
Packit 6c4009
       Instead, just indicate that offset (before and after) is
Packit 6c4009
       unpredictable. */
Packit 6c4009
    fp->_old_offset = _IO_pos_BAD;
Packit 6c4009
  else if (fp->_IO_read_end != fp->_IO_write_base)
Packit 6c4009
    {
Packit 6c4009
      off_t new_pos
Packit 6c4009
	= _IO_SYSSEEK (fp, fp->_IO_write_base - fp->_IO_read_end, 1);
Packit 6c4009
      if (new_pos == _IO_pos_BAD)
Packit 6c4009
	return 0;
Packit 6c4009
      fp->_old_offset = new_pos;
Packit 6c4009
    }
Packit 6c4009
  count = _IO_SYSWRITE (fp, data, to_do);
Packit 6c4009
  if (fp->_cur_column && count)
Packit 6c4009
    fp->_cur_column = _IO_adjust_column (fp->_cur_column - 1, data, count) + 1;
Packit 6c4009
  _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
Packit 6c4009
  fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_buf_base;
Packit 6c4009
  fp->_IO_write_end = ((fp->_flags & (_IO_LINE_BUF | _IO_UNBUFFERED))
Packit 6c4009
		       ? fp->_IO_buf_base : fp->_IO_buf_end);
Packit 6c4009
  return count;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
int
Packit 6c4009
attribute_compat_text_section
Packit 6c4009
_IO_old_file_underflow (FILE *fp)
Packit 6c4009
{
Packit 6c4009
  ssize_t count;
Packit 6c4009
Packit 6c4009
  /* C99 requires EOF to be "sticky".  */
Packit 6c4009
  if (fp->_flags & _IO_EOF_SEEN)
Packit 6c4009
    return EOF;
Packit 6c4009
Packit 6c4009
  if (fp->_flags & _IO_NO_READS)
Packit 6c4009
    {
Packit 6c4009
      fp->_flags |= _IO_ERR_SEEN;
Packit 6c4009
      __set_errno (EBADF);
Packit 6c4009
      return EOF;
Packit 6c4009
    }
Packit 6c4009
  if (fp->_IO_read_ptr < fp->_IO_read_end)
Packit 6c4009
    return *(unsigned char *) fp->_IO_read_ptr;
Packit 6c4009
Packit 6c4009
  if (fp->_IO_buf_base == NULL)
Packit 6c4009
    {
Packit 6c4009
      /* Maybe we already have a push back pointer.  */
Packit 6c4009
      if (fp->_IO_save_base != NULL)
Packit 6c4009
	{
Packit 6c4009
	  free (fp->_IO_save_base);
Packit 6c4009
	  fp->_flags &= ~_IO_IN_BACKUP;
Packit 6c4009
	}
Packit 6c4009
      _IO_doallocbuf (fp);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  /* Flush all line buffered files before reading. */
Packit 6c4009
  /* FIXME This can/should be moved to genops ?? */
Packit 6c4009
  if (fp->_flags & (_IO_LINE_BUF|_IO_UNBUFFERED))
Packit 6c4009
    _IO_flush_all_linebuffered ();
Packit 6c4009
Packit 6c4009
  _IO_switch_to_get_mode (fp);
Packit 6c4009
Packit 6c4009
  /* This is very tricky. We have to adjust those
Packit 6c4009
     pointers before we call _IO_SYSREAD () since
Packit 6c4009
     we may longjump () out while waiting for
Packit 6c4009
     input. Those pointers may be screwed up. H.J. */
Packit 6c4009
  fp->_IO_read_base = fp->_IO_read_ptr = fp->_IO_buf_base;
Packit 6c4009
  fp->_IO_read_end = fp->_IO_buf_base;
Packit 6c4009
  fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_write_end
Packit 6c4009
    = fp->_IO_buf_base;
Packit 6c4009
Packit 6c4009
  count = _IO_SYSREAD (fp, fp->_IO_buf_base,
Packit 6c4009
		       fp->_IO_buf_end - fp->_IO_buf_base);
Packit 6c4009
  if (count <= 0)
Packit 6c4009
    {
Packit 6c4009
      if (count == 0)
Packit 6c4009
	fp->_flags |= _IO_EOF_SEEN;
Packit 6c4009
      else
Packit 6c4009
	fp->_flags |= _IO_ERR_SEEN, count = 0;
Packit 6c4009
  }
Packit 6c4009
  fp->_IO_read_end += count;
Packit 6c4009
  if (count == 0)
Packit 6c4009
    return EOF;
Packit 6c4009
  if (fp->_old_offset != _IO_pos_BAD)
Packit 6c4009
    _IO_pos_adjust (fp->_old_offset, count);
Packit 6c4009
  return *(unsigned char *) fp->_IO_read_ptr;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
int
Packit 6c4009
attribute_compat_text_section
Packit 6c4009
_IO_old_file_overflow (FILE *f, int ch)
Packit 6c4009
{
Packit 6c4009
  if (f->_flags & _IO_NO_WRITES) /* SET ERROR */
Packit 6c4009
    {
Packit 6c4009
      f->_flags |= _IO_ERR_SEEN;
Packit 6c4009
      __set_errno (EBADF);
Packit 6c4009
      return EOF;
Packit 6c4009
    }
Packit 6c4009
  /* If currently reading or no buffer allocated. */
Packit 6c4009
  if ((f->_flags & _IO_CURRENTLY_PUTTING) == 0)
Packit 6c4009
    {
Packit 6c4009
      /* Allocate a buffer if needed. */
Packit 6c4009
      if (f->_IO_write_base == 0)
Packit 6c4009
	{
Packit 6c4009
	  _IO_doallocbuf (f);
Packit 6c4009
	  _IO_setg (f, f->_IO_buf_base, f->_IO_buf_base, f->_IO_buf_base);
Packit 6c4009
	}
Packit 6c4009
      /* Otherwise must be currently reading.
Packit 6c4009
	 If _IO_read_ptr (and hence also _IO_read_end) is at the buffer end,
Packit 6c4009
	 logically slide the buffer forwards one block (by setting the
Packit 6c4009
	 read pointers to all point at the beginning of the block).  This
Packit 6c4009
	 makes room for subsequent output.
Packit 6c4009
	 Otherwise, set the read pointers to _IO_read_end (leaving that
Packit 6c4009
	 alone, so it can continue to correspond to the external position). */
Packit 6c4009
      if (f->_IO_read_ptr == f->_IO_buf_end)
Packit 6c4009
	f->_IO_read_end = f->_IO_read_ptr = f->_IO_buf_base;
Packit 6c4009
      f->_IO_write_ptr = f->_IO_read_ptr;
Packit 6c4009
      f->_IO_write_base = f->_IO_write_ptr;
Packit 6c4009
      f->_IO_write_end = f->_IO_buf_end;
Packit 6c4009
      f->_IO_read_base = f->_IO_read_ptr = f->_IO_read_end;
Packit 6c4009
Packit 6c4009
      if (f->_flags & (_IO_LINE_BUF | _IO_UNBUFFERED))
Packit 6c4009
	f->_IO_write_end = f->_IO_write_ptr;
Packit 6c4009
      f->_flags |= _IO_CURRENTLY_PUTTING;
Packit 6c4009
    }
Packit 6c4009
  if (ch == EOF)
Packit 6c4009
    return _IO_old_do_flush (f);
Packit 6c4009
  if (f->_IO_write_ptr == f->_IO_buf_end ) /* Buffer is really full */
Packit 6c4009
    if (_IO_old_do_flush (f) == EOF)
Packit 6c4009
      return EOF;
Packit 6c4009
  *f->_IO_write_ptr++ = ch;
Packit 6c4009
  if ((f->_flags & _IO_UNBUFFERED)
Packit 6c4009
      || ((f->_flags & _IO_LINE_BUF) && ch == '\n'))
Packit 6c4009
    if (_IO_old_do_flush (f) == EOF)
Packit 6c4009
      return EOF;
Packit 6c4009
  return (unsigned char) ch;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
int
Packit 6c4009
attribute_compat_text_section
Packit 6c4009
_IO_old_file_sync (FILE *fp)
Packit 6c4009
{
Packit 6c4009
  ssize_t delta;
Packit 6c4009
  int retval = 0;
Packit 6c4009
Packit 6c4009
  /*    char* ptr = cur_ptr(); */
Packit 6c4009
  if (fp->_IO_write_ptr > fp->_IO_write_base)
Packit 6c4009
    if (_IO_old_do_flush(fp)) return EOF;
Packit 6c4009
  delta = fp->_IO_read_ptr - fp->_IO_read_end;
Packit 6c4009
  if (delta != 0)
Packit 6c4009
    {
Packit 6c4009
#ifdef TODO
Packit 6c4009
      if (_IO_in_backup (fp))
Packit 6c4009
	delta -= eGptr () - Gbase ();
Packit 6c4009
#endif
Packit 6c4009
      off_t new_pos = _IO_SYSSEEK (fp, delta, 1);
Packit 6c4009
      if (new_pos != (off_t) EOF)
Packit 6c4009
	fp->_IO_read_end = fp->_IO_read_ptr;
Packit 6c4009
      else if (errno == ESPIPE)
Packit 6c4009
	; /* Ignore error from unseekable devices. */
Packit 6c4009
      else
Packit 6c4009
	retval = EOF;
Packit 6c4009
    }
Packit 6c4009
  if (retval != EOF)
Packit 6c4009
    fp->_old_offset = _IO_pos_BAD;
Packit 6c4009
  /* FIXME: Cleanup - can this be shared? */
Packit 6c4009
  /*    setg(base(), ptr, ptr); */
Packit 6c4009
  return retval;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
off64_t
Packit 6c4009
attribute_compat_text_section
Packit 6c4009
_IO_old_file_seekoff (FILE *fp, off64_t offset, int dir, int mode)
Packit 6c4009
{
Packit 6c4009
  off_t result;
Packit 6c4009
  off64_t delta, new_offset;
Packit 6c4009
  long count;
Packit 6c4009
  /* POSIX.1 8.2.3.7 says that after a call the fflush() the file
Packit 6c4009
     offset of the underlying file must be exact.  */
Packit 6c4009
  int must_be_exact = (fp->_IO_read_base == fp->_IO_read_end
Packit 6c4009
		       && fp->_IO_write_base == fp->_IO_write_ptr);
Packit 6c4009
Packit 6c4009
  if (mode == 0)
Packit 6c4009
    dir = _IO_seek_cur, offset = 0; /* Don't move any pointers. */
Packit 6c4009
Packit 6c4009
  /* Flush unwritten characters.
Packit 6c4009
     (This may do an unneeded write if we seek within the buffer.
Packit 6c4009
     But to be able to switch to reading, we would need to set
Packit 6c4009
     egptr to pptr.  That can't be done in the current design,
Packit 6c4009
     which assumes file_ptr() is eGptr.  Anyway, since we probably
Packit 6c4009
     end up flushing when we close(), it doesn't make much difference.)
Packit 6c4009
     FIXME: simulate mem-mapped files. */
Packit 6c4009
Packit 6c4009
  if (fp->_IO_write_ptr > fp->_IO_write_base || _IO_in_put_mode (fp))
Packit 6c4009
    if (_IO_switch_to_get_mode (fp))
Packit 6c4009
      return EOF;
Packit 6c4009
Packit 6c4009
  if (fp->_IO_buf_base == NULL)
Packit 6c4009
    {
Packit 6c4009
      /* It could be that we already have a pushback buffer.  */
Packit 6c4009
      if (fp->_IO_read_base != NULL)
Packit 6c4009
	{
Packit 6c4009
	  free (fp->_IO_read_base);
Packit 6c4009
	  fp->_flags &= ~_IO_IN_BACKUP;
Packit 6c4009
	}
Packit 6c4009
      _IO_doallocbuf (fp);
Packit 6c4009
      _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
Packit 6c4009
      _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  switch (dir)
Packit 6c4009
    {
Packit 6c4009
    case _IO_seek_cur:
Packit 6c4009
      /* Adjust for read-ahead (bytes is buffer). */
Packit 6c4009
      offset -= fp->_IO_read_end - fp->_IO_read_ptr;
Packit 6c4009
      if (fp->_old_offset == _IO_pos_BAD)
Packit 6c4009
	goto dumb;
Packit 6c4009
      /* Make offset absolute, assuming current pointer is file_ptr(). */
Packit 6c4009
      offset += fp->_old_offset;
Packit 6c4009
Packit 6c4009
      dir = _IO_seek_set;
Packit 6c4009
      break;
Packit 6c4009
    case _IO_seek_set:
Packit 6c4009
      break;
Packit 6c4009
    case _IO_seek_end:
Packit 6c4009
      {
Packit 6c4009
	struct stat64 st;
Packit 6c4009
	if (_IO_SYSSTAT (fp, &st) == 0 && S_ISREG (st.st_mode))
Packit 6c4009
	  {
Packit 6c4009
	    offset += st.st_size;
Packit 6c4009
	    dir = _IO_seek_set;
Packit 6c4009
	  }
Packit 6c4009
	else
Packit 6c4009
	  goto dumb;
Packit 6c4009
      }
Packit 6c4009
    }
Packit 6c4009
  /* At this point, dir==_IO_seek_set. */
Packit 6c4009
Packit 6c4009
  /* If we are only interested in the current position we've found it now.  */
Packit 6c4009
  if (mode == 0)
Packit 6c4009
    return offset;
Packit 6c4009
Packit 6c4009
  /* If destination is within current buffer, optimize: */
Packit 6c4009
  if (fp->_old_offset != _IO_pos_BAD && fp->_IO_read_base != NULL
Packit 6c4009
      && !_IO_in_backup (fp))
Packit 6c4009
    {
Packit 6c4009
      /* Offset relative to start of main get area. */
Packit 6c4009
      off_t rel_offset = (offset - fp->_old_offset
Packit 6c4009
                          + (fp->_IO_read_end - fp->_IO_read_base));
Packit 6c4009
      if (rel_offset >= 0)
Packit 6c4009
	{
Packit 6c4009
	  if (rel_offset <= fp->_IO_read_end - fp->_IO_read_base)
Packit 6c4009
	    {
Packit 6c4009
	      _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base + rel_offset,
Packit 6c4009
			fp->_IO_read_end);
Packit 6c4009
	      _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
Packit 6c4009
	      {
Packit 6c4009
		_IO_mask_flags (fp, 0, _IO_EOF_SEEN);
Packit 6c4009
		goto resync;
Packit 6c4009
	      }
Packit 6c4009
	    }
Packit 6c4009
#ifdef TODO
Packit 6c4009
	    /* If we have streammarkers, seek forward by reading ahead. */
Packit 6c4009
	    if (_IO_have_markers (fp))
Packit 6c4009
	      {
Packit 6c4009
		int to_skip = rel_offset
Packit 6c4009
		  - (fp->_IO_read_ptr - fp->_IO_read_base);
Packit 6c4009
		if (ignore (to_skip) != to_skip)
Packit 6c4009
		  goto dumb;
Packit 6c4009
		_IO_mask_flags (fp, 0, _IO_EOF_SEEN);
Packit 6c4009
		goto resync;
Packit 6c4009
	      }
Packit 6c4009
#endif
Packit 6c4009
	}
Packit 6c4009
#ifdef TODO
Packit 6c4009
      if (rel_offset < 0 && rel_offset >= Bbase () - Bptr ())
Packit 6c4009
	{
Packit 6c4009
	  if (!_IO_in_backup (fp))
Packit 6c4009
	    _IO_switch_to_backup_area (fp);
Packit 6c4009
	  gbump (fp->_IO_read_end + rel_offset - fp->_IO_read_ptr);
Packit 6c4009
	  _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
Packit 6c4009
	  goto resync;
Packit 6c4009
	}
Packit 6c4009
#endif
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
#ifdef TODO
Packit 6c4009
  _IO_unsave_markers (fp);
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
  if (fp->_flags & _IO_NO_READS)
Packit 6c4009
    goto dumb;
Packit 6c4009
Packit 6c4009
  /* Try to seek to a block boundary, to improve kernel page management. */
Packit 6c4009
  new_offset = offset & ~(fp->_IO_buf_end - fp->_IO_buf_base - 1);
Packit 6c4009
  delta = offset - new_offset;
Packit 6c4009
  if (delta > fp->_IO_buf_end - fp->_IO_buf_base)
Packit 6c4009
    {
Packit 6c4009
      new_offset = offset;
Packit 6c4009
      delta = 0;
Packit 6c4009
    }
Packit 6c4009
  result = _IO_SYSSEEK (fp, new_offset, 0);
Packit 6c4009
  if (result < 0)
Packit 6c4009
    return EOF;
Packit 6c4009
  if (delta == 0)
Packit 6c4009
    count = 0;
Packit 6c4009
  else
Packit 6c4009
    {
Packit 6c4009
      count = _IO_SYSREAD (fp, fp->_IO_buf_base,
Packit 6c4009
			   (must_be_exact
Packit 6c4009
			    ? delta : fp->_IO_buf_end - fp->_IO_buf_base));
Packit 6c4009
      if (count < delta)
Packit 6c4009
	{
Packit 6c4009
	  /* We weren't allowed to read, but try to seek the remainder. */
Packit 6c4009
	  offset = count == EOF ? delta : delta-count;
Packit 6c4009
	  dir = _IO_seek_cur;
Packit 6c4009
	  goto dumb;
Packit 6c4009
	}
Packit 6c4009
    }
Packit 6c4009
  _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base + delta,
Packit 6c4009
	    fp->_IO_buf_base + count);
Packit 6c4009
  _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
Packit 6c4009
  fp->_old_offset = result + count;
Packit 6c4009
  _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
Packit 6c4009
  return offset;
Packit 6c4009
 dumb:
Packit 6c4009
Packit 6c4009
  _IO_unsave_markers (fp);
Packit 6c4009
  result = _IO_SYSSEEK (fp, offset, dir);
Packit 6c4009
  if (result != EOF)
Packit 6c4009
    {
Packit 6c4009
      _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
Packit 6c4009
      fp->_old_offset = result;
Packit 6c4009
      _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
Packit 6c4009
      _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
Packit 6c4009
    }
Packit 6c4009
  return result;
Packit 6c4009
Packit 6c4009
resync:
Packit 6c4009
  /* We need to do it since it is possible that the file offset in
Packit 6c4009
     the kernel may be changed behind our back. It may happen when
Packit 6c4009
     we fopen a file and then do a fork. One process may access the
Packit 6c4009
     file and the kernel file offset will be changed. */
Packit 6c4009
  if (fp->_old_offset >= 0)
Packit 6c4009
    _IO_SYSSEEK (fp, fp->_old_offset, 0);
Packit 6c4009
Packit 6c4009
  return offset;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
ssize_t
Packit 6c4009
attribute_compat_text_section
Packit 6c4009
_IO_old_file_write (FILE *f, const void *data, ssize_t n)
Packit 6c4009
{
Packit 6c4009
  ssize_t to_do = n;
Packit 6c4009
  while (to_do > 0)
Packit 6c4009
    {
Packit 6c4009
      ssize_t count = __write (f->_fileno, data, to_do);
Packit 6c4009
      if (count == EOF)
Packit 6c4009
	{
Packit 6c4009
	  f->_flags |= _IO_ERR_SEEN;
Packit 6c4009
	  break;
Packit 6c4009
	}
Packit 6c4009
      to_do -= count;
Packit 6c4009
      data = (void *) ((char *) data + count);
Packit 6c4009
    }
Packit 6c4009
  n -= to_do;
Packit 6c4009
  if (f->_old_offset >= 0)
Packit 6c4009
    f->_old_offset += n;
Packit 6c4009
  return n;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
size_t
Packit 6c4009
attribute_compat_text_section
Packit 6c4009
_IO_old_file_xsputn (FILE *f, const void *data, size_t n)
Packit 6c4009
{
Packit 6c4009
  const char *s = (char *) data;
Packit 6c4009
  size_t to_do = n;
Packit 6c4009
  int must_flush = 0;
Packit 6c4009
  size_t count = 0;
Packit 6c4009
Packit 6c4009
  if (n <= 0)
Packit 6c4009
    return 0;
Packit 6c4009
  /* This is an optimized implementation.
Packit 6c4009
     If the amount to be written straddles a block boundary
Packit 6c4009
     (or the filebuf is unbuffered), use sys_write directly. */
Packit 6c4009
Packit 6c4009
  /* First figure out how much space is available in the buffer. */
Packit 6c4009
  if ((f->_flags & _IO_LINE_BUF) && (f->_flags & _IO_CURRENTLY_PUTTING))
Packit 6c4009
    {
Packit 6c4009
      count = f->_IO_buf_end - f->_IO_write_ptr;
Packit 6c4009
      if (count >= n)
Packit 6c4009
	{
Packit 6c4009
	  const char *p;
Packit 6c4009
	  for (p = s + n; p > s; )
Packit 6c4009
	    {
Packit 6c4009
	      if (*--p == '\n')
Packit 6c4009
		{
Packit 6c4009
		  count = p - s + 1;
Packit 6c4009
		  must_flush = 1;
Packit 6c4009
		  break;
Packit 6c4009
		}
Packit 6c4009
	    }
Packit 6c4009
	}
Packit 6c4009
    }
Packit 6c4009
  else if (f->_IO_write_end > f->_IO_write_ptr)
Packit 6c4009
    count = f->_IO_write_end - f->_IO_write_ptr; /* Space available. */
Packit 6c4009
Packit 6c4009
  /* Then fill the buffer. */
Packit 6c4009
  if (count > 0)
Packit 6c4009
    {
Packit 6c4009
      if (count > to_do)
Packit 6c4009
	count = to_do;
Packit 6c4009
      if (count > 20)
Packit 6c4009
	{
Packit 6c4009
	  f->_IO_write_ptr = __mempcpy (f->_IO_write_ptr, s, count);
Packit 6c4009
	  s += count;
Packit 6c4009
	}
Packit 6c4009
      else
Packit 6c4009
	{
Packit 6c4009
	  char *p = f->_IO_write_ptr;
Packit 6c4009
	  int i = (int) count;
Packit 6c4009
	  while (--i >= 0)
Packit 6c4009
	    *p++ = *s++;
Packit 6c4009
	  f->_IO_write_ptr = p;
Packit 6c4009
	}
Packit 6c4009
      to_do -= count;
Packit 6c4009
    }
Packit 6c4009
  if (to_do + must_flush > 0)
Packit 6c4009
    {
Packit 6c4009
      size_t block_size, do_write;
Packit 6c4009
      /* Next flush the (full) buffer. */
Packit 6c4009
      if (__overflow (f, EOF) == EOF)
Packit 6c4009
	return to_do == 0 ? EOF : n - to_do;
Packit 6c4009
Packit 6c4009
      /* Try to maintain alignment: write a whole number of blocks.
Packit 6c4009
	 dont_write is what gets left over. */
Packit 6c4009
      block_size = f->_IO_buf_end - f->_IO_buf_base;
Packit 6c4009
      do_write = to_do - (block_size >= 128 ? to_do % block_size : 0);
Packit 6c4009
Packit 6c4009
      if (do_write)
Packit 6c4009
	{
Packit 6c4009
	  count = old_do_write (f, s, do_write);
Packit 6c4009
	  to_do -= count;
Packit 6c4009
	  if (count < do_write)
Packit 6c4009
	    return n - to_do;
Packit 6c4009
	}
Packit 6c4009
Packit 6c4009
      /* Now write out the remainder.  Normally, this will fit in the
Packit 6c4009
	 buffer, but it's somewhat messier for line-buffered files,
Packit 6c4009
	 so we let _IO_default_xsputn handle the general case. */
Packit 6c4009
      if (to_do)
Packit 6c4009
	to_do -= _IO_default_xsputn (f, s+do_write, to_do);
Packit 6c4009
    }
Packit 6c4009
  return n - to_do;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
Packit 6c4009
const struct _IO_jump_t _IO_old_file_jumps libio_vtable =
Packit 6c4009
{
Packit 6c4009
  JUMP_INIT_DUMMY,
Packit 6c4009
  JUMP_INIT(finish, _IO_old_file_finish),
Packit 6c4009
  JUMP_INIT(overflow, _IO_old_file_overflow),
Packit 6c4009
  JUMP_INIT(underflow, _IO_old_file_underflow),
Packit 6c4009
  JUMP_INIT(uflow, _IO_default_uflow),
Packit 6c4009
  JUMP_INIT(pbackfail, _IO_default_pbackfail),
Packit 6c4009
  JUMP_INIT(xsputn, _IO_old_file_xsputn),
Packit 6c4009
  JUMP_INIT(xsgetn, _IO_default_xsgetn),
Packit 6c4009
  JUMP_INIT(seekoff, _IO_old_file_seekoff),
Packit 6c4009
  JUMP_INIT(seekpos, _IO_default_seekpos),
Packit 6c4009
  JUMP_INIT(setbuf, _IO_old_file_setbuf),
Packit 6c4009
  JUMP_INIT(sync, _IO_old_file_sync),
Packit 6c4009
  JUMP_INIT(doallocate, _IO_file_doallocate),
Packit 6c4009
  JUMP_INIT(read, _IO_file_read),
Packit 6c4009
  JUMP_INIT(write, _IO_old_file_write),
Packit 6c4009
  JUMP_INIT(seek, _IO_file_seek),
Packit 6c4009
  JUMP_INIT(close, _IO_file_close),
Packit 6c4009
  JUMP_INIT(stat, _IO_file_stat)
Packit 6c4009
};
Packit 6c4009
Packit 6c4009
compat_symbol (libc, _IO_old_do_write, _IO_do_write, GLIBC_2_0);
Packit 6c4009
compat_symbol (libc, _IO_old_file_attach, _IO_file_attach, GLIBC_2_0);
Packit 6c4009
compat_symbol (libc, _IO_old_file_close_it, _IO_file_close_it, GLIBC_2_0);
Packit 6c4009
compat_symbol (libc, _IO_old_file_finish, _IO_file_finish, GLIBC_2_0);
Packit 6c4009
compat_symbol (libc, _IO_old_file_fopen, _IO_file_fopen, GLIBC_2_0);
Packit 6c4009
compat_symbol (libc, _IO_old_file_init, _IO_file_init, GLIBC_2_0);
Packit 6c4009
compat_symbol (libc, _IO_old_file_setbuf, _IO_file_setbuf, GLIBC_2_0);
Packit 6c4009
compat_symbol (libc, _IO_old_file_sync, _IO_file_sync, GLIBC_2_0);
Packit 6c4009
compat_symbol (libc, _IO_old_file_overflow, _IO_file_overflow, GLIBC_2_0);
Packit 6c4009
compat_symbol (libc, _IO_old_file_seekoff, _IO_file_seekoff, GLIBC_2_0);
Packit 6c4009
compat_symbol (libc, _IO_old_file_underflow, _IO_file_underflow, GLIBC_2_0);
Packit 6c4009
compat_symbol (libc, _IO_old_file_write, _IO_file_write, GLIBC_2_0);
Packit 6c4009
compat_symbol (libc, _IO_old_file_xsputn, _IO_file_xsputn, GLIBC_2_0);
Packit 6c4009
Packit 6c4009
#endif