-/* Copyright (C) 1993,95,97,98,99,2000 Free Software Foundation, Inc.
+/* Copyright (C) 1993-2016 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Written by Per Bothner <bothner@cygnus.com>.
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307 USA.
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>.
As a special exception, if you link the code in this file with
files compiled with a GNU compiler to produce an executable,
#include <sys/stat.h>
#include <string.h>
#include <errno.h>
-#ifdef __STDC__
#include <stdlib.h>
-#endif
+#include <unistd.h>
#ifndef errno
extern int errno;
#endif
to _IO_buf_base, though not necessarily if we have switched from
get mode to put mode. (The reason is to maintain the invariant
that _IO_read_end corresponds to the external file position.)
- _IO_write_base is non-NULL and usually equal to _IO_base_base.
+ _IO_write_base is non-NULL and usually equal to _IO_buf_base.
We also have _IO_write_end == _IO_buf_end, but only in fully buffered mode.
The un-flushed character are those between _IO_write_base and _IO_write_ptr.
void
-_IO_old_file_init (fp)
- struct _IO_FILE_plus *fp;
+attribute_compat_text_section
+_IO_old_file_init (struct _IO_FILE_plus *fp)
{
/* POSIX.1 allows another file handle to be used to change the position
of our file descriptor. Hence we actually don't know the actual
fp->file._vtable_offset = ((int) sizeof (struct _IO_FILE)
- (int) sizeof (struct _IO_FILE_complete));
fp->file._fileno = -1;
+
+#if defined SHARED && defined _LIBC
+ if (__builtin_expect (&_IO_stdin_used != NULL, 1)
+ || (fp != (struct _IO_FILE_plus *) _IO_stdin
+ && fp != (struct _IO_FILE_plus *) _IO_stdout
+ && fp != (struct _IO_FILE_plus *) _IO_stderr))
+ /* The object is dynamically allocated and large enough. Initialize
+ the _mode element as well. */
+ ((struct _IO_FILE_complete *) fp)->_mode = -1;
+#endif
}
int
-_IO_old_file_close_it (fp)
- _IO_FILE *fp;
+attribute_compat_text_section
+_IO_old_file_close_it (_IO_FILE *fp)
{
int write_status, close_status;
if (!_IO_file_is_open (fp))
write_status = _IO_old_do_flush (fp);
- _IO_unsave_markers(fp);
+ _IO_unsave_markers (fp);
- close_status = _IO_SYSCLOSE (fp);
+ close_status = ((fp->_flags2 & _IO_FLAGS2_NOCLOSE) == 0
+ ? _IO_SYSCLOSE (fp) : 0);
/* Free buffer. */
_IO_setb (fp, NULL, NULL, 0);
}
void
-_IO_old_file_finish (fp, dummy)
- _IO_FILE *fp;
- int dummy;
+attribute_compat_text_section
+_IO_old_file_finish (_IO_FILE *fp, int dummy)
{
if (_IO_file_is_open (fp))
{
}
_IO_FILE *
-_IO_old_file_fopen (fp, filename, mode)
- _IO_FILE *fp;
- const char *filename;
- const char *mode;
+attribute_compat_text_section
+_IO_old_file_fopen (_IO_FILE *fp, const char *filename, const char *mode)
{
int oflags = 0, omode;
int read_write, fdesc;
}
_IO_FILE *
-_IO_old_file_attach (fp, fd)
- _IO_FILE *fp;
- int fd;
+attribute_compat_text_section
+_IO_old_file_attach (_IO_FILE *fp, int fd)
{
if (_IO_file_is_open (fp))
return NULL;
}
_IO_FILE *
-_IO_old_file_setbuf (fp, p, len)
- _IO_FILE *fp;
- char *p;
- _IO_ssize_t len;
+attribute_compat_text_section
+_IO_old_file_setbuf (_IO_FILE *fp, char *p, _IO_ssize_t len)
{
if (_IO_default_setbuf (fp, p, len) == NULL)
return NULL;
return fp;
}
-static int old_do_write __P ((_IO_FILE *, const char *, _IO_size_t));
+static int old_do_write (_IO_FILE *, const char *, _IO_size_t);
/* Write TO_DO bytes from DATA to FP.
Then mark FP as having empty buffers. */
int
-_IO_old_do_write (fp, data, to_do)
- _IO_FILE *fp;
- const char *data;
- _IO_size_t to_do;
+attribute_compat_text_section
+_IO_old_do_write (_IO_FILE *fp, const char *data, _IO_size_t to_do)
{
- return (to_do == 0 || old_do_write (fp, data, to_do) == to_do)
+ return (to_do == 0 || (_IO_size_t) old_do_write (fp, data, to_do) == to_do)
? 0 : EOF;
}
-static
-int
-old_do_write (fp, data, to_do)
- _IO_FILE *fp;
- const char *data;
- _IO_size_t to_do;
+static int
+attribute_compat_text_section
+old_do_write (_IO_FILE *fp, const char *data, _IO_size_t to_do)
{
_IO_size_t count;
if (fp->_flags & _IO_IS_APPENDING)
/* On a system without a proper O_APPEND implementation,
you would need to sys_seek(0, SEEK_END) here, but is
- is not needed nor desirable for Unix- or Posix-like systems.
+ not needed nor desirable for Unix- or Posix-like systems.
Instead, just indicate that offset (before and after) is
unpredictable. */
fp->_old_offset = _IO_pos_BAD;
fp->_cur_column = _IO_adjust_column (fp->_cur_column - 1, data, count) + 1;
_IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
fp->_IO_write_base = fp->_IO_write_ptr = fp->_IO_buf_base;
- fp->_IO_write_end = ((fp->_flags & (_IO_LINE_BUF+_IO_UNBUFFERED))
+ fp->_IO_write_end = ((fp->_flags & (_IO_LINE_BUF | _IO_UNBUFFERED))
? fp->_IO_buf_base : fp->_IO_buf_end);
return count;
}
int
-_IO_old_file_underflow (fp)
- _IO_FILE *fp;
+attribute_compat_text_section
+_IO_old_file_underflow (_IO_FILE *fp)
{
_IO_ssize_t count;
#if 0
}
int
-_IO_old_file_overflow (f, ch)
- _IO_FILE *f;
- int ch;
+attribute_compat_text_section
+_IO_old_file_overflow (_IO_FILE *f, int ch)
{
if (f->_flags & _IO_NO_WRITES) /* SET ERROR */
{
f->_IO_write_end = f->_IO_buf_end;
f->_IO_read_base = f->_IO_read_ptr = f->_IO_read_end;
- if (f->_flags & (_IO_LINE_BUF+_IO_UNBUFFERED))
+ if (f->_flags & (_IO_LINE_BUF | _IO_UNBUFFERED))
f->_IO_write_end = f->_IO_write_ptr;
f->_flags |= _IO_CURRENTLY_PUTTING;
}
}
int
-_IO_old_file_sync (fp)
- _IO_FILE *fp;
+attribute_compat_text_section
+_IO_old_file_sync (_IO_FILE *fp)
{
_IO_ssize_t delta;
int retval = 0;
}
_IO_off64_t
-_IO_old_file_seekoff (fp, offset, dir, mode)
- _IO_FILE *fp;
- _IO_off64_t offset;
- int dir;
- int mode;
+attribute_compat_text_section
+_IO_old_file_seekoff (_IO_FILE *fp, _IO_off64_t offset, int dir, int mode)
{
_IO_off_t result;
_IO_off64_t delta, new_offset;
/* Flush unwritten characters.
(This may do an unneeded write if we seek within the buffer.
But to be able to switch to reading, we would need to set
- egptr to ptr. That can't be done in the current design,
+ egptr to pptr. That can't be done in the current design,
which assumes file_ptr() is eGptr. Anyway, since we probably
end up flushing when we close(), it doesn't make much difference.)
- FIXME: simulate mem-papped files. */
+ FIXME: simulate mem-mapped files. */
if (fp->_IO_write_ptr > fp->_IO_write_base || _IO_in_put_mode (fp))
if (_IO_switch_to_get_mode (fp))
break;
case _IO_seek_end:
{
- struct _G_stat64 st;
+ struct stat64 st;
if (_IO_SYSSTAT (fp, &st) == 0 && S_ISREG (st.st_mode))
{
offset += st.st_size;
/* We need to do it since it is possible that the file offset in
the kernel may be changed behind our back. It may happen when
we fopen a file and then do a fork. One process may access the
- the file and the kernel file offset will be changed. */
+ file and the kernel file offset will be changed. */
if (fp->_old_offset >= 0)
_IO_SYSSEEK (fp, fp->_old_offset, 0);
}
_IO_ssize_t
-_IO_old_file_write (f, data, n)
- _IO_FILE *f;
- const void *data;
- _IO_ssize_t n;
+attribute_compat_text_section
+_IO_old_file_write (_IO_FILE *f, const void *data, _IO_ssize_t n)
{
_IO_ssize_t to_do = n;
while (to_do > 0)
{
f->_flags |= _IO_ERR_SEEN;
break;
- }
+ }
to_do -= count;
data = (void *) ((char *) data + count);
}
}
_IO_size_t
-_IO_old_file_xsputn (f, data, n)
- _IO_FILE *f;
- const void *data;
- _IO_size_t n;
+attribute_compat_text_section
+_IO_old_file_xsputn (_IO_FILE *f, const void *data, _IO_size_t n)
{
- register const char *s = (char *) data;
+ const char *s = (char *) data;
_IO_size_t to_do = n;
int must_flush = 0;
- _IO_size_t count;
+ _IO_size_t count = 0;
if (n <= 0)
return 0;
(or the filebuf is unbuffered), use sys_write directly. */
/* First figure out how much space is available in the buffer. */
- count = f->_IO_write_end - f->_IO_write_ptr; /* Space available. */
if ((f->_flags & _IO_LINE_BUF) && (f->_flags & _IO_CURRENTLY_PUTTING))
{
count = f->_IO_buf_end - f->_IO_write_ptr;
if (count >= n)
{
- register const char *p;
+ const char *p;
for (p = s + n; p > s; )
{
if (*--p == '\n')
}
}
}
+ else if (f->_IO_write_end > f->_IO_write_ptr)
+ count = f->_IO_write_end - f->_IO_write_ptr; /* Space available. */
+
/* Then fill the buffer. */
if (count > 0)
{
}
else
{
- register char *p = f->_IO_write_ptr;
- register int i = (int) count;
+ char *p = f->_IO_write_ptr;
+ int i = (int) count;
while (--i >= 0)
*p++ = *s++;
f->_IO_write_ptr = p;
_IO_size_t block_size, do_write;
/* Next flush the (full) buffer. */
if (__overflow (f, EOF) == EOF)
- return n - to_do;
+ return to_do == 0 ? EOF : n - to_do;
/* Try to maintain alignment: write a whole number of blocks.
dont_write is what gets left over. */
do_write = to_do - (block_size >= 128 ? to_do % block_size : 0);
if (do_write)
- {
+ {
count = old_do_write (f, s, do_write);
to_do -= count;
if (count < do_write)
return n - to_do;
- }
+ }
/* Now write out the remainder. Normally, this will fit in the
buffer, but it's somewhat messier for line-buffered files,
}
-struct _IO_jump_t _IO_old_file_jumps =
+const struct _IO_jump_t _IO_old_file_jumps =
{
JUMP_INIT_DUMMY,
JUMP_INIT(finish, _IO_old_file_finish),