summaryrefslogtreecommitdiff
path: root/nuttx/lib/lib_fflush.c
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2008-02-05 18:13:13 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2008-02-05 18:13:13 +0000
commitd1f1e007f149be8a8c3084d144599a7456d15aba (patch)
treedc4794aec1816bddcdf86ad50da6c7ebe86b4d51 /nuttx/lib/lib_fflush.c
parente05c8208701c52f71abfda389c5dbbea8cf380a7 (diff)
downloadpx4-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.c207
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;
}