diff --git a/ChangeLog b/ChangeLog index 9a439dcb54..50e4f7be56 100644 --- a/ChangeLog +++ b/ChangeLog @@ -7092,3 +7092,6 @@ * libc/stdio/lib_ferror.c, lib_fread.c, lib_libfflush.c, lib_libfread.c, and lib_libfwrite.c: Finish incomplete support for ferror(). From Macs N (2014-3-14). + * libc/stdio/lib_ftell.c: Fix a logic error in ftell(). It was + simply using the file offset and did not take into account data + buffered in memory. From Macs N (2013-3-31). diff --git a/libc/stdio/lib_ftell.c b/libc/stdio/lib_ftell.c index c528c47022..85390c918a 100644 --- a/libc/stdio/lib_ftell.c +++ b/libc/stdio/lib_ftell.c @@ -52,7 +52,7 @@ #include "lib_internal.h" /**************************************************************************** - * Definitions + * Pre-processor Definitions ****************************************************************************/ /**************************************************************************** @@ -83,6 +83,41 @@ * Private Functions ****************************************************************************/ +/**************************************************************************** + * Name: lib_getrdoffset + * + * Description: + * It is insufficient to simply use the file offset; we must also account + * for the data offset in the any buffered data. This function calculates + * that offset. + * + * Returned Value: + * The file position offset due to buffered data. + * + ****************************************************************************/ + +#if CONFIG_STDIO_BUFFER_SIZE > 0 +static off_t lib_getrdoffset(FAR FILE *stream) +{ + off_t rdoffset = 0; + lib_take_semaphore(stream); + + if (stream->fs_bufread != stream->fs_bufstart) + { +#if CONFIG_NUNGET_CHARS > 0 + rdoffset = stream->fs_bufread - stream->fs_bufpos + stream->fs_nungotten; +#else + rdoffset = stream->fs_bufread - stream->fs_bufpos; +#endif + } + + lib_give_semaphore(stream); + return rdoffset; +} +#else +# define lib_getrdoffset(stream) (0) +#endif + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -95,7 +130,7 @@ * stream pointed to by stream. * * Returned Value: - * Zero on succes; -1 on failure with errno set appropriately. + * Zero on success; -1 on failure with errno set appropriately. * ****************************************************************************/ @@ -118,7 +153,7 @@ long ftell(FAR FILE *stream) position = lseek(stream->fs_fd, 0, SEEK_CUR); if (position != (off_t)-1) { - return (long)position; + return (long)(position - lib_getrdoffset(stream)); } else {