diff options
author | ache <ache@FreeBSD.org> | 2014-08-06 10:33:43 +0000 |
---|---|---|
committer | ache <ache@FreeBSD.org> | 2014-08-06 10:33:43 +0000 |
commit | 2d3901a5e0f5f2c82219f95729476541cf7a6c59 (patch) | |
tree | 8e49d60fb222cc8e30658a5d085f0a4385d2b1a4 /lib/libc/stdio/ftell.c | |
parent | 2f0c20a5ee337895d361e5dc12f0a3e70a28244e (diff) | |
download | FreeBSD-src-2d3901a5e0f5f2c82219f95729476541cf7a6c59.zip FreeBSD-src-2d3901a5e0f5f2c82219f95729476541cf7a6c59.tar.gz |
MFC: r268997
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.
Diffstat (limited to 'lib/libc/stdio/ftell.c')
-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 |