diff options
Diffstat (limited to 'libio/wstrops.c')
-rw-r--r-- | libio/wstrops.c | 159 |
1 files changed, 93 insertions, 66 deletions
diff --git a/libio/wstrops.c b/libio/wstrops.c index 2b9d0368f3..6626f2f711 100644 --- a/libio/wstrops.c +++ b/libio/wstrops.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993-2016 Free Software Foundation, Inc. +/* Copyright (C) 1993-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -32,19 +32,19 @@ #include <stdio_ext.h> void -_IO_wstr_init_static (_IO_FILE *fp, wchar_t *ptr, _IO_size_t size, +_IO_wstr_init_static (FILE *fp, wchar_t *ptr, size_t size, wchar_t *pstart) { wchar_t *end; if (size == 0) end = ptr + __wcslen (ptr); - else if ((_IO_size_t) ptr + size * sizeof (wchar_t) > (_IO_size_t) ptr) + else if ((size_t) ptr + size * sizeof (wchar_t) > (size_t) ptr) end = ptr + size; else /* Even for misaligned ptr make sure there is integral number of wide characters. */ - end = ptr + (-1 - (_IO_size_t) ptr) / sizeof (wchar_t); + end = ptr + (-1 - (size_t) ptr) / sizeof (wchar_t); _IO_wsetb (fp, ptr, end, 0); fp->_wide_data->_IO_write_base = ptr; @@ -63,14 +63,14 @@ _IO_wstr_init_static (_IO_FILE *fp, wchar_t *ptr, _IO_size_t size, fp->_wide_data->_IO_read_end = end; } /* A null _allocate_buffer function flags the strfile as being static. */ - (((_IO_strfile *) fp)->_s._allocate_buffer) = (_IO_alloc_type)0; + (((_IO_strfile *) fp)->_s._allocate_buffer_unused) = (_IO_alloc_type)0; } -_IO_wint_t -_IO_wstr_overflow (_IO_FILE *fp, _IO_wint_t c) +wint_t +_IO_wstr_overflow (FILE *fp, wint_t c) { int flush_only = c == WEOF; - _IO_size_t pos; + size_t pos; if (fp->_flags & _IO_NO_WRITES) return flush_only ? 0 : WEOF; if ((fp->_flags & _IO_TIED_PUT_GET) && !(fp->_flags & _IO_CURRENTLY_PUTTING)) @@ -80,7 +80,7 @@ _IO_wstr_overflow (_IO_FILE *fp, _IO_wint_t c) fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_read_end; } pos = fp->_wide_data->_IO_write_ptr - fp->_wide_data->_IO_write_base; - if (pos >= (_IO_size_t) (_IO_wblen (fp) + flush_only)) + if (pos >= (size_t) (_IO_wblen (fp) + flush_only)) { if (fp->_flags2 & _IO_FLAGS2_USER_WBUF) /* not allowed to enlarge */ return WEOF; @@ -89,15 +89,13 @@ _IO_wstr_overflow (_IO_FILE *fp, _IO_wint_t c) wchar_t *new_buf; wchar_t *old_buf = fp->_wide_data->_IO_buf_base; size_t old_wblen = _IO_wblen (fp); - _IO_size_t new_size = 2 * old_wblen + 100; + size_t new_size = 2 * old_wblen + 100; if (__glibc_unlikely (new_size < old_wblen) || __glibc_unlikely (new_size > SIZE_MAX / sizeof (wchar_t))) return EOF; - new_buf - = (wchar_t *) (*((_IO_strfile *) fp)->_s._allocate_buffer) (new_size - * sizeof (wchar_t)); + new_buf = malloc (new_size * sizeof (wchar_t)); if (new_buf == NULL) { /* __ferror(fp) = 1; */ @@ -106,12 +104,12 @@ _IO_wstr_overflow (_IO_FILE *fp, _IO_wint_t c) if (old_buf) { __wmemcpy (new_buf, old_buf, old_wblen); - (*((_IO_strfile *) fp)->_s._free_buffer) (old_buf); + free (old_buf); /* Make sure _IO_setb won't try to delete _IO_buf_base. */ fp->_wide_data->_IO_buf_base = NULL; } - wmemset (new_buf + old_wblen, L'\0', new_size - old_wblen); + __wmemset (new_buf + old_wblen, L'\0', new_size - old_wblen); _IO_wsetb (fp, new_buf, new_buf + new_size, 1); fp->_wide_data->_IO_read_base = @@ -136,8 +134,8 @@ _IO_wstr_overflow (_IO_FILE *fp, _IO_wint_t c) } -_IO_wint_t -_IO_wstr_underflow (_IO_FILE *fp) +wint_t +_IO_wstr_underflow (FILE *fp) { if (fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_read_end) fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_write_ptr; @@ -155,8 +153,8 @@ _IO_wstr_underflow (_IO_FILE *fp) /* The size of the valid part of the buffer. */ -_IO_ssize_t -_IO_wstr_count (_IO_FILE *fp) +ssize_t +_IO_wstr_count (FILE *fp) { struct _IO_wide_data *wd = fp->_wide_data; @@ -167,35 +165,33 @@ _IO_wstr_count (_IO_FILE *fp) static int -enlarge_userbuf (_IO_FILE *fp, _IO_off64_t offset, int reading) +enlarge_userbuf (FILE *fp, off64_t offset, int reading) { - if ((_IO_ssize_t) offset <= _IO_blen (fp)) + if ((ssize_t) offset <= _IO_wblen (fp)) return 0; struct _IO_wide_data *wd = fp->_wide_data; - _IO_ssize_t oldend = wd->_IO_write_end - wd->_IO_write_base; + ssize_t oldend = wd->_IO_write_end - wd->_IO_write_base; /* Try to enlarge the buffer. */ if (fp->_flags2 & _IO_FLAGS2_USER_WBUF) /* User-provided buffer. */ return 1; - _IO_size_t newsize = offset + 100; + size_t newsize = offset + 100; if (__glibc_unlikely (newsize > SIZE_MAX / sizeof (wchar_t))) return 1; wchar_t *oldbuf = wd->_IO_buf_base; - wchar_t *newbuf - = (wchar_t *) (*((_IO_strfile *) fp)->_s._allocate_buffer) (newsize - * sizeof (wchar_t)); + wchar_t *newbuf = malloc (newsize * sizeof (wchar_t)); if (newbuf == NULL) return 1; if (oldbuf != NULL) { __wmemcpy (newbuf, oldbuf, _IO_wblen (fp)); - (*((_IO_strfile *) fp)->_s._free_buffer) (oldbuf); + free (oldbuf); /* Make sure _IO_setb won't try to delete _IO_buf_base. */ wd->_IO_buf_base = NULL; @@ -228,59 +224,83 @@ enlarge_userbuf (_IO_FILE *fp, _IO_off64_t offset, int reading) new position. */ assert (offset >= oldend); if (reading) - wmemset (wd->_IO_read_base + oldend, L'\0', offset - oldend); + __wmemset (wd->_IO_read_base + oldend, L'\0', offset - oldend); else - wmemset (wd->_IO_write_base + oldend, L'\0', offset - oldend); + __wmemset (wd->_IO_write_base + oldend, L'\0', offset - oldend); return 0; } +static void +_IO_wstr_switch_to_get_mode (FILE *fp) +{ + if (_IO_in_backup (fp)) + fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_backup_base; + else + { + fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_buf_base; + if (fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_read_end) + fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_write_ptr; + } + fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_write_ptr; + fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_write_ptr; -_IO_off64_t -_IO_wstr_seekoff (_IO_FILE *fp, _IO_off64_t offset, int dir, int mode) + fp->_flags &= ~_IO_CURRENTLY_PUTTING; +} + +off64_t +_IO_wstr_seekoff (FILE *fp, off64_t offset, int dir, int mode) { - _IO_off64_t new_pos; + off64_t new_pos; if (mode == 0 && (fp->_flags & _IO_TIED_PUT_GET)) mode = (fp->_flags & _IO_CURRENTLY_PUTTING ? _IOS_OUTPUT : _IOS_INPUT); + bool was_writing = (fp->_wide_data->_IO_write_ptr > + fp->_wide_data->_IO_write_base + || _IO_in_put_mode (fp)); + if (was_writing) + _IO_wstr_switch_to_get_mode (fp); + if (mode == 0) { - /* Don't move any pointers. But there is no clear indication what - mode FP is in. Let's guess. */ - if (fp->_IO_file_flags & _IO_NO_WRITES) - new_pos = fp->_wide_data->_IO_read_ptr - fp->_wide_data->_IO_read_base; - else - new_pos = (fp->_wide_data->_IO_write_ptr - - fp->_wide_data->_IO_write_base); + new_pos = (fp->_wide_data->_IO_write_ptr + - fp->_wide_data->_IO_write_base); } else { - _IO_ssize_t cur_size = _IO_wstr_count (fp); + ssize_t cur_size = _IO_wstr_count (fp); new_pos = EOF; /* Move the get pointer, if requested. */ if (mode & _IOS_INPUT) { + ssize_t base; switch (dir) { - case _IO_seek_end: - offset += cur_size; + case _IO_seek_set: + base = 0; break; case _IO_seek_cur: - offset += (fp->_wide_data->_IO_read_ptr - - fp->_wide_data->_IO_read_base); + base = (fp->_wide_data->_IO_read_ptr + - fp->_wide_data->_IO_read_base); break; - default: /* case _IO_seek_set: */ + default: /* case _IO_seek_end: */ + base = cur_size; break; } - if (offset < 0) - return EOF; - if ((_IO_ssize_t) offset > cur_size - && enlarge_userbuf (fp, offset, 1) != 0) + ssize_t maxval = SSIZE_MAX/sizeof (wchar_t) - base; + if (offset < -base || offset > maxval) + { + __set_errno (EINVAL); + return EOF; + } + base += offset; + if (base > cur_size + && enlarge_userbuf (fp, base, 1) != 0) return EOF; fp->_wide_data->_IO_read_ptr = (fp->_wide_data->_IO_read_base - + offset); + + base); fp->_wide_data->_IO_read_end = (fp->_wide_data->_IO_read_base + cur_size); new_pos = offset; @@ -289,33 +309,40 @@ _IO_wstr_seekoff (_IO_FILE *fp, _IO_off64_t offset, int dir, int mode) /* Move the put pointer, if requested. */ if (mode & _IOS_OUTPUT) { + ssize_t base; switch (dir) { - case _IO_seek_end: - offset += cur_size; + case _IO_seek_set: + base = 0; break; case _IO_seek_cur: - offset += (fp->_wide_data->_IO_write_ptr - - fp->_wide_data->_IO_write_base); + base = (fp->_wide_data->_IO_write_ptr + - fp->_wide_data->_IO_write_base); break; - default: /* case _IO_seek_set: */ + default: /* case _IO_seek_end: */ + base = cur_size; break; } - if (offset < 0) - return EOF; - if ((_IO_ssize_t) offset > cur_size - && enlarge_userbuf (fp, offset, 0) != 0) + ssize_t maxval = SSIZE_MAX/sizeof (wchar_t) - base; + if (offset < -base || offset > maxval) + { + __set_errno (EINVAL); + return EOF; + } + base += offset; + if (base > cur_size + && enlarge_userbuf (fp, base, 0) != 0) return EOF; fp->_wide_data->_IO_write_ptr = (fp->_wide_data->_IO_write_base - + offset); - new_pos = offset; + + base); + new_pos = base; } } return new_pos; } -_IO_wint_t -_IO_wstr_pbackfail (_IO_FILE *fp, _IO_wint_t c) +wint_t +_IO_wstr_pbackfail (FILE *fp, wint_t c) { if ((fp->_flags & _IO_NO_WRITES) && c != WEOF) return WEOF; @@ -323,16 +350,16 @@ _IO_wstr_pbackfail (_IO_FILE *fp, _IO_wint_t c) } void -_IO_wstr_finish (_IO_FILE *fp, int dummy) +_IO_wstr_finish (FILE *fp, int dummy) { if (fp->_wide_data->_IO_buf_base && !(fp->_flags2 & _IO_FLAGS2_USER_WBUF)) - (((_IO_strfile *) fp)->_s._free_buffer) (fp->_wide_data->_IO_buf_base); + free (fp->_wide_data->_IO_buf_base); fp->_wide_data->_IO_buf_base = NULL; _IO_wdefault_finish (fp, 0); } -const struct _IO_jump_t _IO_wstr_jumps = +const struct _IO_jump_t _IO_wstr_jumps libio_vtable = { JUMP_INIT_DUMMY, JUMP_INIT(finish, _IO_wstr_finish), |