From 68025784b0124a62b2e3e076b562d240bd686b6f Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Mon, 31 Mar 2014 09:47:28 -0600 Subject: [PATCH] Fix ftell() bug: It was not accounting for data buffered in memory. From Macs N --- ChangeLog | 3 +++ libc/stdio/lib_ftell.c | 41 ++++++++++++++++++++++++++++++++++++++--- 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9a439dcb541..50e4f7be564 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 c528c470224..85390c918a3 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 {