diff options
author | Robert Mustacchi <rm@fingolfin.org> | 2020-03-02 05:43:45 +0000 |
---|---|---|
committer | Robert Mustacchi <rm@fingolfin.org> | 2020-03-26 07:42:53 +0000 |
commit | cd62a92d4a964bfe61d35ba2301b69e65e22a509 (patch) | |
tree | 8e346d9037f7c654ffe58ed0d5e27f34025dd672 /usr/src/lib/libc/port/stdio/ftell.c | |
parent | 1470234269f4edea4cbf270cb2475e4988b788d5 (diff) | |
download | illumos-gate-cd62a92d4a964bfe61d35ba2301b69e65e22a509.tar.gz |
7092 Want support for stdio memory streams
12360 fwrite can loop forever on zero byte write
12392 ftello64 doesn't handle ungetc() correctly when unbuffered
Reviewed by: John Levon <john.levon@joyent.com>
Reviewed by: Yuri Pankov <ypankov@fastmail.com>
Approved by: Dan McDonald <danmcd@joyent.com>
Diffstat (limited to 'usr/src/lib/libc/port/stdio/ftell.c')
-rw-r--r-- | usr/src/lib/libc/port/stdio/ftell.c | 44 |
1 files changed, 32 insertions, 12 deletions
diff --git a/usr/src/lib/libc/port/stdio/ftell.c b/usr/src/lib/libc/port/stdio/ftell.c index 45c0b841d6..dae2abea03 100644 --- a/usr/src/lib/libc/port/stdio/ftell.c +++ b/usr/src/lib/libc/port/stdio/ftell.c @@ -25,9 +25,7 @@ */ /* Copyright (c) 1988 AT&T */ -/* All Rights Reserved */ - -#pragma ident "%Z%%M% %I% %E% SMI" +/* All Rights Reserved */ /* * Return file offset. @@ -49,41 +47,63 @@ #include <sys/types.h> #include "stdiom.h" -long -ftell(FILE *iop) +off64_t +ftell_common(FILE *iop) { ptrdiff_t adjust; off64_t tres; rmutex_t *lk; FLOCKFILE(lk, iop); + + /* + * If we're dealing with a memory stream, we need to flush the internal + * state before we try and determine the location. This is especially + * important for open_wmemstream() as it will have buffered bytes, but + * we need to convert that to wide characters before we proceed. If we + * have no file descriptor, then the units that the backing store are in + * can be arbitrary. + */ + if (_get_fd(iop) == -1) { + (void) _fflush_u(iop); + } + if (iop->_cnt < 0) iop->_cnt = 0; - if (iop->_flag & _IOREAD) + if (iop->_flag & _IOREAD) { adjust = (ptrdiff_t)-iop->_cnt; - else if (iop->_flag & (_IOWRT | _IORW)) { + } else if (iop->_flag & (_IOWRT | _IORW)) { adjust = 0; if (((iop->_flag & (_IOWRT | _IONBF)) == _IOWRT) && - (iop->_base != 0)) + (iop->_base != 0)) { adjust = iop->_ptr - iop->_base; - else if ((iop->_flag & _IORW) && (iop->_base != 0)) + } else if ((iop->_flag & _IORW) && (iop->_base != 0)) { adjust = (ptrdiff_t)-iop->_cnt; + } } else { errno = EBADF; /* file descriptor refers to no open file */ FUNLOCKFILE(lk); return (EOF); } - tres = lseek64(FILENO(iop), 0, SEEK_CUR); + tres = _xseek64(iop, 0, SEEK_CUR); if (tres >= 0) tres += adjust; + FUNLOCKFILE(lk); + return ((long)tres); +} + +long +ftell(FILE *iop) +{ + off64_t tres; + + tres = ftell_common(iop); if (tres > LONG_MAX) { errno = EOVERFLOW; - FUNLOCKFILE(lk); return (EOF); } - FUNLOCKFILE(lk); return ((long)tres); } |