diff options
author | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2008-02-05 18:13:13 +0000 |
---|---|---|
committer | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2008-02-05 18:13:13 +0000 |
commit | d1f1e007f149be8a8c3084d144599a7456d15aba (patch) | |
tree | dc4794aec1816bddcdf86ad50da6c7ebe86b4d51 /nuttx/lib/lib_fflush.c | |
parent | e05c8208701c52f71abfda389c5dbbea8cf380a7 (diff) | |
download | px4-nuttx-d1f1e007f149be8a8c3084d144599a7456d15aba.tar.gz px4-nuttx-d1f1e007f149be8a8c3084d144599a7456d15aba.tar.bz2 px4-nuttx-d1f1e007f149be8a8c3084d144599a7456d15aba.zip |
Various fixes for buffered R/W I/O and seeking
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@630 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'nuttx/lib/lib_fflush.c')
-rw-r--r-- | nuttx/lib/lib_fflush.c | 207 |
1 files changed, 149 insertions, 58 deletions
diff --git a/nuttx/lib/lib_fflush.c b/nuttx/lib/lib_fflush.c index c9751df61..929597ea8 100644 --- a/nuttx/lib/lib_fflush.c +++ b/nuttx/lib/lib_fflush.c @@ -1,5 +1,5 @@ /**************************************************************************** - * lib_fflush.c + * lib/lib_fflush.c * * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved. * Author: Gregory Nutt <spudmonkey@racsa.co.cr> @@ -42,11 +42,15 @@ ****************************************************************************/ #include <nuttx/config.h> /* for CONFIG_STDIO_BUFFER_SIZE */ + +#include <sys/types.h> #include <stdio.h> #include <unistd.h> #include <fcntl.h> #include <errno.h> + #include <nuttx/fs.h> + #include "lib_internal.h" /**************************************************************************** @@ -78,6 +82,115 @@ ****************************************************************************/ /**************************************************************************** + * Name: fflush_internal + * + * Description: + * The function fflush() forces a write of all user-space buffered data for + * the given output or update stream via the stream's underlying write + * function. The open status of the stream is unaffected. + * + * Parmeters: + * stream - the stream to flush + * bforce - flush must be complete. + * + * Return: + * ERROR on failure, otherwise the number of bytes remaining in the buffer. + * If bforce is set, then only the values ERROR and 0 will be returned. + * + ****************************************************************************/ + +ssize_t fflush_internal(FILE *stream, boolean bforce) +{ +#if CONFIG_STDIO_BUFFER_SIZE > 0 + const unsigned char *src; + size_t bytes_written; + size_t nbuffer; + + /* Return EBADF if the file is not opened for writing */ + + if (stream->fs_filedes < 0 || (stream->fs_oflags & O_WROK) == 0) + { + *get_errno_ptr() = EBADF; + return ERROR; + } + + /* Make sure that we have exclusive access to the stream */ + + lib_take_semaphore(stream); + + /* Make sure tht the buffer holds valid data */ + + if (stream->fs_bufpos != stream->fs_bufstart) + { + /* Make sure that the buffer holds buffered write data. We do not + * support concurrent read/write buffer usage. + */ + + if (stream->fs_bufread != stream->fs_bufstart) + { + /* The buffer holds read data... just return zero */ + + return 0; + } + + /* How many bytes of write data are used in the buffer now */ + + nbuffer = stream->fs_bufpos - stream->fs_bufstart; + + /* Try to write that amount */ + + src = stream->fs_bufstart; + do + { + /* Perform the write */ + + bytes_written = write(stream->fs_filedes, src, nbuffer); + if (bytes_written < 0) + { + lib_give_semaphore(stream); + return ERROR; + } + + /* Handle partial writes. fflush() must either return with + * an error condition or with the data successfully flushed + * from the buffer. + */ + + src += bytes_written; + nbuffer -= bytes_written; + } + while (bforce && nbuffer > 0); + + /* Reset the buffer position to the beginning of the buffer */ + + stream->fs_bufpos = stream->fs_bufstart; + + /* For the case of an incomplete write, nbuffer will be non-zero + * It will hold the number of bytes that were not written. + * Move the data down in the buffer to handle this (rare) case + */ + + while (nbuffer) + { + *stream->fs_bufpos++ = *src++; + --nbuffer; + } + } + + /* Restore normal access to the stream and return the number of bytes + * remaining in the buffer. + */ + + lib_give_semaphore(stream); + return stream->fs_bufpos - stream->fs_bufstart; +#else + /* Return no bytes remaining in the buffer */ + + return 0; +#endif +} + +/**************************************************************************** * Global Functions ****************************************************************************/ @@ -85,11 +198,16 @@ * Name: lib_fflushall * * Description: - * Called by the OS when a task exits + * Called either (1) by the OS when a task exits, or (2) from fflush() + * when a NULL stream argument is provided. + * ****************************************************************************/ -void lib_flushall(FAR struct streamlist *list) +int lib_flushall(FAR struct streamlist *list) { + int lasterrno = OK; + int ret; + /* Make sure that there are streams associated with this thread */ if (list) @@ -101,81 +219,54 @@ void lib_flushall(FAR struct streamlist *list) stream_semtake(list); for (i = 0; i < CONFIG_NFILE_STREAMS; i++) { - /* If the stream is open (i.e., assigned a non- - * negative file descriptor), then flush the + /* If the stream is open (i.e., assigned a non-negative file + * descriptor), then flush all of the pending write data in the * stream. */ if (list->sl_streams[i].fs_filedes >= 0) { - (void)fflush(&list->sl_streams[i]); + if (fflush_internal(&list->sl_streams[i], TRUE) != 0) + { + lasterrno = *get_errno_ptr(); + ret = ERROR; + } } } stream_semgive(list); } + + /* If any flush failed, return that last failed flush */ + + *get_errno_ptr() = lasterrno; + return ret; } /**************************************************************************** * Name: fflush + * + * Description: + * The function fflush() forces a write of all user-space buffered data for + * the given output or update stream via the stream's underlying write + * function. The open status of the stream is unaffected. + * + * If the stream argument is NULL, fflush() flushes all open output streams. + * + * Return: + * OK on success EOF on failure (with errno set appropriately) + * ****************************************************************************/ int fflush(FILE *stream) { -#if CONFIG_STDIO_BUFFER_SIZE > 0 - const unsigned char *src; - size_t bytes_written; - size_t nbuffer; - - if (stream->fs_filedes < 0 || (stream->fs_oflags & O_WROK) == 0) - { - *get_errno_ptr() = EBADF; - return ERROR; - } - - /* Make sure that we have exclusive access to the stream */ - - lib_take_semaphore(stream); - - /* How many bytes are used in the buffer now */ - - nbuffer = stream->fs_bufpos - stream->fs_bufstart; - - /* Try to write that amount */ - - src = stream->fs_bufstart; - bytes_written = write(stream->fs_filedes, src, nbuffer); - if (bytes_written < 0) + if (!stream) { - lib_give_semaphore(stream); - return bytes_written; + return lib_flushall(sched_getstreams()); } - - /* Update pointers and counts */ - - src += bytes_written; - nbuffer -= bytes_written; - - /* Reset the buffer position to the beginning of the buffer */ - - stream->fs_bufpos = stream->fs_bufstart; - - /* For the case of an incomplete write, nbuffer will be non-zero - * It will hold the number of bytes that were not written. - * Move the data down in the buffer to handle this (rare) case - */ - - while (nbuffer) + else if (fflush_internal(stream, TRUE) != 0) { - *stream->fs_bufpos++ = *src++; - --nbuffer; + return EOF; } - - /* Return the number of bytes remaining in the buffer */ - - lib_give_semaphore(stream); - return stream->fs_bufpos - stream->fs_bufstart; -#else - return 0; -#endif + return OK; } |