diff options
author | ache <ache@FreeBSD.org> | 2014-07-22 22:49:37 +0000 |
---|---|---|
committer | ache <ache@FreeBSD.org> | 2014-07-22 22:49:37 +0000 |
commit | d6173adab312458b875426f2f3c0ac9da1b2d761 (patch) | |
tree | 0555146f27bc4a7d40da489877f17f3e38a3ed92 | |
parent | 91bb0ce910f13963bdd5c1d139816cba8865d432 (diff) | |
download | FreeBSD-src-d6173adab312458b875426f2f3c0ac9da1b2d761.zip FreeBSD-src-d6173adab312458b875426f2f3c0ac9da1b2d761.tar.gz |
For "a"-mode files and rewind/fseek + fwrite combination return meaningful
value now, like Apple does, but avoid their __sflush physical write
performance degradation as much as possible.
-rw-r--r-- | lib/libc/stdio/ftell.c | 18 |
1 files changed, 18 insertions, 0 deletions
diff --git a/lib/libc/stdio/ftell.c b/lib/libc/stdio/ftell.c index 2c8800c..745d500 100644 --- a/lib/libc/stdio/ftell.c +++ b/lib/libc/stdio/ftell.c @@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$"); #include "namespace.h" #include <sys/types.h> #include <errno.h> +#include <fcntl.h> #include <limits.h> #include <stdio.h> #include "un-namespace.h" @@ -87,6 +88,7 @@ _ftello(FILE *fp, fpos_t *offset) { fpos_t pos; size_t n; + int dflags; if (fp->_seek == NULL) { errno = ESPIPE; /* historic practice */ @@ -118,6 +120,22 @@ _ftello(FILE *fp, fpos_t *offset) if (HASUB(fp)) pos -= fp->_r; /* Can be negative at this point. */ } else if ((fp->_flags & __SWR) && fp->_p != NULL) { + dflags = 0; + if (fp->_flags & __SAPP) + dflags = O_APPEND; + else if (fp->_file != -1 && + (dflags = _fcntl(fp->_file, F_GETFL)) < 0) + return (1); + if ((dflags & O_APPEND) && + (pos = _sseek(fp, (fpos_t)0, SEEK_END)) == -1) { + if ((fp->_flags & __SOPT) || __sflush(fp) || + (pos = _sseek(fp, (fpos_t)0, SEEK_CUR)) == -1) + return (1); + else { + *offset = pos; + return (0); + } + } /* * Writing. Any buffered characters cause the * position to be greater than that in the |