mirror of
https://github.com/apache/nuttx.git
synced 2026-06-06 16:50:55 +08:00
setvbuf: Add support for disabling I/O buffering. Initially cut; untested.
This commit is contained in:
+12
-2
@@ -5,12 +5,22 @@
|
||||
|
||||
comment "Standard C Library Options"
|
||||
|
||||
config STDIO_DISABLE_BUFFERING
|
||||
bool "Disable I/O Buffering"
|
||||
default n
|
||||
---help---
|
||||
Tiny systems may need to disable all support for I/O buffering in
|
||||
order to minimum footprint.
|
||||
|
||||
config STDIO_BUFFER_SIZE
|
||||
int "C STDIO buffer size"
|
||||
default 64
|
||||
depends on !STDIO_DISABLE_BUFFERING
|
||||
---help---
|
||||
Size of buffers using within the C buffered I/O interfaces.
|
||||
(printf, putchar, fwrite, etc.).
|
||||
Size of buffers using within the C buffered I/O interfaces (printf,
|
||||
putchar, fwrite, etc.). This function sets the initial I/O buffer
|
||||
size. Zero disables I/O buffering. That size may be subsequently
|
||||
modified using setvbuf().
|
||||
|
||||
config STDIO_LINEBUFFER
|
||||
bool "STDIO line buffering"
|
||||
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
* libc/libc.h
|
||||
*
|
||||
* Copyright (C) 2007-2014, 2016 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2007-2014, 2016-2017 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -67,7 +67,7 @@
|
||||
* protection.
|
||||
*/
|
||||
|
||||
#if CONFIG_STDIO_BUFFER_SIZE <= 0
|
||||
#ifdef CONFIG_STDIO_DISABLE_BUFFERING
|
||||
# define lib_sem_initialize(s)
|
||||
# define lib_take_semaphore(s)
|
||||
# define lib_give_semaphore(s)
|
||||
@@ -186,7 +186,7 @@ int lib_wrflush(FAR FILE *stream);
|
||||
|
||||
/* Defined in lib_sem.c */
|
||||
|
||||
#if CONFIG_STDIO_BUFFER_SIZE > 0
|
||||
#ifndef CONFIG_STDIO_DISABLE_BUFFERING
|
||||
void lib_sem_initialize(FAR struct file_struct *stream);
|
||||
void lib_take_semaphore(FAR struct file_struct *stream);
|
||||
void lib_give_semaphore(FAR struct file_struct *stream);
|
||||
|
||||
+5
-1
@@ -35,9 +35,13 @@
|
||||
|
||||
# Add the internal C files to the build
|
||||
|
||||
CSRCS += lib_stream.c lib_filesem.c lib_utsname.c
|
||||
CSRCS += lib_stream.c lib_utsname.c
|
||||
CSRCS += lib_xorshift128.c lib_tea_encrypt.c lib_tea_decrypt.c
|
||||
|
||||
ifneq ($(CONFIG_STDIO_DISABLE_BUFFERING),y)
|
||||
CSRCS += lib_filesem.c
|
||||
endif
|
||||
|
||||
# Support for platforms that do not have long long types
|
||||
|
||||
CSRCS += lib_umul32.c lib_umul64.c lib_umul32x64.c
|
||||
|
||||
+4
-11
@@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
* libc/misc/lib_filesem.c
|
||||
*
|
||||
* Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2007, 2009, 2011, 2017 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -47,15 +47,7 @@
|
||||
|
||||
#include "libc.h"
|
||||
|
||||
#if CONFIG_STDIO_BUFFER_SIZE > 0
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
#ifndef CONFIG_STDIO_DISABLE_BUFFERING
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
@@ -142,4 +134,5 @@ void lib_give_semaphore(FAR struct file_struct *stream)
|
||||
ASSERT(sem_post(&stream->fs_sem) == 0);
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_STDIO_BUFFER_SIZE */
|
||||
|
||||
#endif /* CONFIG_STDIO_DISABLE_BUFFERING */
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
* libc/misc/lib_stream.c
|
||||
*
|
||||
* Copyright (C) 2007, 2011, 2013-2014 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2007, 2011, 2013-2014, 2017 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -109,7 +109,7 @@ void lib_stream_initialize(FAR struct task_group_s *group)
|
||||
#endif /* CONFIG_NFILE_STREAMS > 0 */
|
||||
|
||||
/****************************************************************************
|
||||
* Name: lib_stream_init
|
||||
* Name: lib_stream_release
|
||||
*
|
||||
* Description:
|
||||
* This function is called when a TCB is destroyed. Note that it does not
|
||||
@@ -122,7 +122,7 @@ void lib_stream_initialize(FAR struct task_group_s *group)
|
||||
void lib_stream_release(FAR struct task_group_s *group)
|
||||
{
|
||||
FAR struct streamlist *list;
|
||||
#if CONFIG_STDIO_BUFFER_SIZE > 0
|
||||
#ifndef CONFIG_STDIO_DISABLE_BUFFERING
|
||||
int i;
|
||||
#endif
|
||||
|
||||
@@ -139,9 +139,9 @@ void lib_stream_release(FAR struct task_group_s *group)
|
||||
|
||||
(void)sem_destroy(&list->sl_sem);
|
||||
|
||||
#ifndef CONFIG_STDIO_DISABLE_BUFFERING
|
||||
/* Release each stream in the list */
|
||||
|
||||
#if CONFIG_STDIO_BUFFER_SIZE > 0
|
||||
for (i = 0; i < CONFIG_NFILE_STREAMS; i++)
|
||||
{
|
||||
FAR struct file_struct *stream = &list->sl_streams[i];
|
||||
@@ -177,6 +177,6 @@ void lib_stream_release(FAR struct task_group_s *group)
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif /* CONFIG_NFILE_STREAMS > 0 */
|
||||
|
||||
#endif /* CONFIG_NFILE_STREAMS > 0 */
|
||||
#endif /* (!CONFIG_BUILD_PROTECTED &&7 !CONFIG_BUILD_KERNEL) || __KERNEL__ */
|
||||
|
||||
@@ -65,13 +65,17 @@ CSRCS += lib_rdflush.c lib_wrflush.c lib_fputc.c lib_puts.c lib_fputs.c
|
||||
CSRCS += lib_ungetc.c lib_vprintf.c lib_fprintf.c lib_vfprintf.c
|
||||
CSRCS += lib_stdinstream.c lib_stdoutstream.c lib_stdsistream.c
|
||||
CSRCS += lib_stdsostream.c lib_perror.c lib_feof.c lib_ferror.c
|
||||
CSRCS += lib_clearerr.c lib_setvbuf.c lib_libnoflush.c lib_libsnoflush.c
|
||||
CSRCS += lib_clearerr.c lib_libnoflush.c lib_libsnoflush.c
|
||||
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_FS_WRITABLE),y)
|
||||
CSRCS += lib_tempnam.c lib_tmpnam.c
|
||||
endif
|
||||
|
||||
ifneq ($(CONFIG_STDIO_DISABLE_BUFFERING),y)
|
||||
CSRCS += lib_setvbuf.c
|
||||
endif
|
||||
endif
|
||||
|
||||
# Other support that depends on specific, configured features.
|
||||
|
||||
@@ -107,7 +107,7 @@ int fclose(FAR FILE *stream)
|
||||
}
|
||||
}
|
||||
|
||||
#if CONFIG_STDIO_BUFFER_SIZE > 0
|
||||
#ifndef CONFIG_STDIO_DISABLE_BUFFERING
|
||||
/* Destroy the semaphore */
|
||||
|
||||
sem_destroy(&stream->fs_sem);
|
||||
@@ -123,6 +123,7 @@ int fclose(FAR FILE *stream)
|
||||
/* Clear the whole structure */
|
||||
|
||||
memset(stream, 0, sizeof(FILE));
|
||||
|
||||
#else
|
||||
#if CONFIG_NUNGET_CHARS > 0
|
||||
/* Reset the number of ungetc characters */
|
||||
@@ -133,6 +134,7 @@ int fclose(FAR FILE *stream)
|
||||
|
||||
stream->fs_oflags = 0;
|
||||
#endif
|
||||
|
||||
/* Setting the file descriptor to -1 makes the stream available for reuse */
|
||||
|
||||
stream->fs_fd = -1;
|
||||
|
||||
+11
-9
@@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
* libc/stdio/lib_fseek.c
|
||||
*
|
||||
* Copyright (C) 2007, 2008, 2011, 2013 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2007, 2008, 2011, 2013, 2017 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -71,14 +71,7 @@
|
||||
|
||||
int fseek(FAR FILE *stream, long int offset, int whence)
|
||||
{
|
||||
#if CONFIG_STDIO_BUFFER_SIZE > 0
|
||||
/* Flush any valid read/write data in the buffer (also verifies stream) */
|
||||
|
||||
if (lib_rdflush(stream) < 0 || lib_wrflush(stream) < 0)
|
||||
{
|
||||
return ERROR;
|
||||
}
|
||||
#else
|
||||
#ifdef CONFIG_DEBUG_FEATURES
|
||||
/* Verify that we were provided with a stream */
|
||||
|
||||
if (!stream)
|
||||
@@ -88,6 +81,15 @@ int fseek(FAR FILE *stream, long int offset, int whence)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_STDIO_DISABLE_BUFFERING
|
||||
/* Flush any valid read/write data in the buffer (also verifies stream) */
|
||||
|
||||
if (lib_rdflush(stream) < 0 || lib_wrflush(stream) < 0)
|
||||
{
|
||||
return ERROR;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* On success or failure, discard any characters saved by ungetc() */
|
||||
|
||||
#if CONFIG_NUNGET_CHARS > 0
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
* libc/stdio/lib_ftell.c
|
||||
*
|
||||
* Copyright (C) 2008, 2011, 2013 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2008, 2011, 2013, 2017 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -64,13 +64,13 @@
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#if CONFIG_STDIO_BUFFER_SIZE > 0
|
||||
#ifndef CONFIG_STDIO_DISABLE_BUFFERING
|
||||
static off_t lib_getrdoffset(FAR FILE *stream)
|
||||
{
|
||||
off_t rdoffset = 0;
|
||||
lib_take_semaphore(stream);
|
||||
|
||||
if (stream->fs_bufread != stream->fs_bufstart)
|
||||
if (stream->fs_bufstart != NULL && stream->fs_bufread != stream->fs_bufstart)
|
||||
{
|
||||
#if CONFIG_NUNGET_CHARS > 0
|
||||
rdoffset = stream->fs_bufread - stream->fs_bufpos + stream->fs_nungotten;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
* libc/stdio/lib_libfflush.c
|
||||
*
|
||||
* Copyright (C) 2007-2008, 2011-2014 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2007-2008, 2011-2014, 2017 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -73,10 +73,11 @@
|
||||
|
||||
ssize_t lib_fflush(FAR FILE *stream, bool bforce)
|
||||
{
|
||||
#if CONFIG_STDIO_BUFFER_SIZE > 0
|
||||
#ifndef CONFIG_STDIO_DISABLE_BUFFERING
|
||||
FAR const unsigned char *src;
|
||||
ssize_t bytes_written;
|
||||
ssize_t nbuffer;
|
||||
int ret;
|
||||
|
||||
/* Return EBADF if the file is not opened for writing */
|
||||
|
||||
@@ -89,9 +90,19 @@ ssize_t lib_fflush(FAR FILE *stream, bool bforce)
|
||||
|
||||
lib_take_semaphore(stream);
|
||||
|
||||
/* Check if there is an allocated I/O buffer */
|
||||
|
||||
if (stream->fs_bufstart == NULL)
|
||||
{
|
||||
/* No, then there can be nothing remaining in the buffer. */
|
||||
|
||||
ret = 0;
|
||||
goto errout_with_sem;
|
||||
}
|
||||
|
||||
/* Make sure that the buffer holds valid data */
|
||||
|
||||
if (stream->fs_bufpos != stream->fs_bufstart)
|
||||
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.
|
||||
@@ -103,8 +114,8 @@ ssize_t lib_fflush(FAR FILE *stream, bool bforce)
|
||||
* remaining in the buffer."
|
||||
*/
|
||||
|
||||
lib_give_semaphore(stream);
|
||||
return 0;
|
||||
ret = 0;
|
||||
goto errout_with_sem;
|
||||
}
|
||||
|
||||
/* How many bytes of write data are used in the buffer now */
|
||||
@@ -126,8 +137,8 @@ ssize_t lib_fflush(FAR FILE *stream, bool bforce)
|
||||
*/
|
||||
|
||||
stream->fs_flags |= __FS_FLAG_ERROR;
|
||||
lib_give_semaphore(stream);
|
||||
return -get_errno();
|
||||
ret = -get_errno();;
|
||||
goto errout_with_sem;
|
||||
}
|
||||
|
||||
/* Handle partial writes. fflush() must either return with
|
||||
@@ -162,6 +173,11 @@ ssize_t lib_fflush(FAR FILE *stream, bool bforce)
|
||||
|
||||
lib_give_semaphore(stream);
|
||||
return stream->fs_bufpos - stream->fs_bufstart;
|
||||
|
||||
errout_with_sem:
|
||||
lib_give_semaphore(stream);
|
||||
return ret;
|
||||
|
||||
#else
|
||||
/* Return no bytes remaining in the buffer */
|
||||
|
||||
|
||||
+132
-125
@@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
* libc/stdio/lib_libfread.c
|
||||
*
|
||||
* Copyright (C) 2007-2009, 2011-2014 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2007-2009, 2011-2014, 2017 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -60,7 +60,7 @@ ssize_t lib_fread(FAR void *ptr, size_t count, FAR FILE *stream)
|
||||
{
|
||||
FAR unsigned char *dest = (FAR unsigned char*)ptr;
|
||||
ssize_t bytes_read;
|
||||
#if CONFIG_STDIO_BUFFER_SIZE > 0
|
||||
#ifndef CONFIG_STDIO_DISABLE_BUFFERING
|
||||
int ret;
|
||||
#endif
|
||||
|
||||
@@ -96,170 +96,177 @@ ssize_t lib_fread(FAR void *ptr, size_t count, FAR FILE *stream)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CONFIG_STDIO_BUFFER_SIZE > 0
|
||||
/* If the buffer is currently being used for write access, then
|
||||
* flush all of the buffered write data. We do not support concurrent
|
||||
* buffered read/write access.
|
||||
*/
|
||||
#ifndef CONFIG_STDIO_DISABLE_BUFFERING
|
||||
/* Is there an I/O buffer? */
|
||||
|
||||
ret = lib_wrflush(stream);
|
||||
if (ret < 0)
|
||||
if (stream->bufstart != NULL)
|
||||
{
|
||||
lib_give_semaphore(stream);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Now get any other needed chars from the buffer or the file. */
|
||||
|
||||
while (count > 0)
|
||||
{
|
||||
/* Is there readable data in the buffer? */
|
||||
|
||||
while ((count > 0) && (stream->fs_bufpos < stream->fs_bufread))
|
||||
{
|
||||
/* Yes, copy a byte into the user buffer */
|
||||
|
||||
*dest++ = *stream->fs_bufpos++;
|
||||
count--;
|
||||
}
|
||||
|
||||
/* The buffer is empty OR we have already supplied the number of
|
||||
* bytes requested in the read. Check if we need to read
|
||||
* more from the file.
|
||||
/* If the buffer is currently being used for write access, then
|
||||
* flush all of the buffered write data. We do not support concurrent
|
||||
* buffered read/write access.
|
||||
*/
|
||||
|
||||
if (count > 0)
|
||||
ret = lib_wrflush(stream);
|
||||
if (ret < 0)
|
||||
{
|
||||
size_t buffer_available;
|
||||
lib_give_semaphore(stream);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* We need to read more data into the buffer from the file */
|
||||
/* Now get any other needed chars from the buffer or the file. */
|
||||
|
||||
/* Mark the buffer empty */
|
||||
while (count > 0)
|
||||
{
|
||||
/* Is there readable data in the buffer? */
|
||||
|
||||
stream->fs_bufpos = stream->fs_bufread = stream->fs_bufstart;
|
||||
while ((count > 0) && (stream->fs_bufpos < stream->fs_bufread))
|
||||
{
|
||||
/* Yes, copy a byte into the user buffer */
|
||||
|
||||
/* How much space is available in the buffer? */
|
||||
*dest++ = *stream->fs_bufpos++;
|
||||
count--;
|
||||
}
|
||||
|
||||
buffer_available = stream->fs_bufend - stream->fs_bufread;
|
||||
|
||||
/* Will the number of bytes that we need to read fit into
|
||||
* the buffer space that is available? If the read size is
|
||||
* larger than the buffer, then read some of the data
|
||||
* directly into the user's buffer.
|
||||
/* The buffer is empty OR we have already supplied the number of
|
||||
* bytes requested in the read. Check if we need to read
|
||||
* more from the file.
|
||||
*/
|
||||
|
||||
if (count > buffer_available)
|
||||
if (count > 0)
|
||||
{
|
||||
bytes_read = read(stream->fs_fd, dest, count);
|
||||
if (bytes_read < 0)
|
||||
size_t buffer_available;
|
||||
|
||||
/* We need to read more data into the buffer from the file */
|
||||
|
||||
/* Mark the buffer empty */
|
||||
|
||||
stream->fs_bufpos = stream->fs_bufread = stream->fs_bufstart;
|
||||
|
||||
/* How much space is available in the buffer? */
|
||||
|
||||
buffer_available = stream->fs_bufend - stream->fs_bufread;
|
||||
|
||||
/* Will the number of bytes that we need to read fit into
|
||||
* the buffer space that is available? If the read size is
|
||||
* larger than the buffer, then read some of the data
|
||||
* directly into the user's buffer.
|
||||
*/
|
||||
|
||||
if (count > buffer_available)
|
||||
{
|
||||
/* An error occurred on the read. The error code is
|
||||
* in the 'errno' variable.
|
||||
*/
|
||||
|
||||
goto errout_with_errno;
|
||||
}
|
||||
else if (bytes_read == 0)
|
||||
{
|
||||
/* We are at the end of the file. But we may already
|
||||
* have buffered data. In that case, we will report
|
||||
* the EOF indication later.
|
||||
*/
|
||||
|
||||
goto shortread;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Some bytes were read. Adjust the dest pointer */
|
||||
|
||||
dest += bytes_read;
|
||||
|
||||
/* Were all of the requested bytes read? */
|
||||
|
||||
if ((size_t)bytes_read < count)
|
||||
bytes_read = read(stream->fs_fd, dest, count);
|
||||
if (bytes_read < 0)
|
||||
{
|
||||
/* No. We must be at the end of file. */
|
||||
/* An error occurred on the read. The error code is
|
||||
* in the 'errno' variable.
|
||||
*/
|
||||
|
||||
goto errout_with_errno;
|
||||
}
|
||||
else if (bytes_read == 0)
|
||||
{
|
||||
/* We are at the end of the file. But we may already
|
||||
* have buffered data. In that case, we will report
|
||||
* the EOF indication later.
|
||||
*/
|
||||
|
||||
goto shortread;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Yes. We are done. */
|
||||
/* Some bytes were read. Adjust the dest pointer */
|
||||
|
||||
count = 0;
|
||||
dest += bytes_read;
|
||||
|
||||
/* Were all of the requested bytes read? */
|
||||
|
||||
if ((size_t)bytes_read < count)
|
||||
{
|
||||
/* No. We must be at the end of file. */
|
||||
|
||||
goto shortread;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Yes. We are done. */
|
||||
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The number of bytes required to satisfy the read
|
||||
* is less than or equal to the size of the buffer
|
||||
* space that we have left. Read as much as we can
|
||||
* into the buffer.
|
||||
*/
|
||||
|
||||
bytes_read = read(stream->fs_fd, stream->fs_bufread, buffer_available);
|
||||
if (bytes_read < 0)
|
||||
{
|
||||
/* An error occurred on the read. The error code is
|
||||
* in the 'errno' variable.
|
||||
*/
|
||||
|
||||
goto errout_with_errno;
|
||||
}
|
||||
else if (bytes_read == 0)
|
||||
{
|
||||
/* We are at the end of the file. But we may already
|
||||
* have buffered data. In that case, we will report
|
||||
* the EOF indication later.
|
||||
*/
|
||||
|
||||
goto shortread;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Some bytes were read */
|
||||
/* The number of bytes required to satisfy the read
|
||||
* is less than or equal to the size of the buffer
|
||||
* space that we have left. Read as much as we can
|
||||
* into the buffer.
|
||||
*/
|
||||
|
||||
stream->fs_bufread += bytes_read;
|
||||
bytes_read = read(stream->fs_fd, stream->fs_bufread, buffer_available);
|
||||
if (bytes_read < 0)
|
||||
{
|
||||
/* An error occurred on the read. The error code is
|
||||
* in the 'errno' variable.
|
||||
*/
|
||||
|
||||
goto errout_with_errno;
|
||||
}
|
||||
else if (bytes_read == 0)
|
||||
{
|
||||
/* We are at the end of the file. But we may already
|
||||
* have buffered data. In that case, we will report
|
||||
* the EOF indication later.
|
||||
*/
|
||||
|
||||
goto shortread;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Some bytes were read */
|
||||
|
||||
stream->fs_bufread += bytes_read;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
/* Now get any other needed chars from the file. */
|
||||
/* Now get any other needed chars from the file. */
|
||||
|
||||
while (count > 0)
|
||||
{
|
||||
bytes_read = read(stream->fs_fd, dest, count);
|
||||
if (bytes_read < 0)
|
||||
while (count > 0)
|
||||
{
|
||||
/* An error occurred on the read. The error code is
|
||||
* in the 'errno' variable.
|
||||
*/
|
||||
bytes_read = read(stream->fs_fd, dest, count);
|
||||
if (bytes_read < 0)
|
||||
{
|
||||
/* An error occurred on the read. The error code is
|
||||
* in the 'errno' variable.
|
||||
*/
|
||||
|
||||
goto errout_with_errno;
|
||||
}
|
||||
else if (bytes_read == 0)
|
||||
{
|
||||
/* We are at the end of the file. But we may already
|
||||
* have buffered data. In that case, we will report
|
||||
* the EOF indication later.
|
||||
*/
|
||||
goto errout_with_errno;
|
||||
}
|
||||
else if (bytes_read == 0)
|
||||
{
|
||||
/* We are at the end of the file. But we may already
|
||||
* have buffered data. In that case, we will report
|
||||
* the EOF indication later.
|
||||
*/
|
||||
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
dest += bytes_read;
|
||||
count -= bytes_read;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
dest += bytes_read;
|
||||
count -= bytes_read;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Here after a successful (but perhaps short) read */
|
||||
|
||||
#if CONFIG_STDIO_BUFFER_SIZE > 0
|
||||
#ifndef CONFIG_STDIO_DISABLE_BUFFERING
|
||||
shortread:
|
||||
#endif
|
||||
|
||||
bytes_read = dest - (FAR unsigned char *)ptr;
|
||||
|
||||
/* Set or clear the EOF indicator. If we get here because of a
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
* libc/stdio/lib_libfwrite.c
|
||||
*
|
||||
* Copyright (C) 2007-2009, 2011, 2013-2014 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2007-2009, 2011, 2013-2014, 2017 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -57,12 +57,13 @@
|
||||
****************************************************************************/
|
||||
|
||||
ssize_t lib_fwrite(FAR const void *ptr, size_t count, FAR FILE *stream)
|
||||
#if CONFIG_STDIO_BUFFER_SIZE > 0
|
||||
#ifndef CONFIG_STDIO_DISABLE_BUFFERING
|
||||
{
|
||||
FAR const unsigned char *start = ptr;
|
||||
FAR const unsigned char *src = ptr;
|
||||
ssize_t ret = ERROR;
|
||||
unsigned char *dest;
|
||||
int ret;
|
||||
|
||||
/* Make sure that writing to this stream is allowed */
|
||||
|
||||
@@ -72,12 +73,22 @@ ssize_t lib_fwrite(FAR const void *ptr, size_t count, FAR FILE *stream)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Check if write access is permitted */
|
||||
|
||||
if ((stream->fs_oflags & O_WROK) == 0)
|
||||
{
|
||||
set_errno(EBADF);
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* If there is no I/O buffer, then output data immediately */
|
||||
|
||||
if (stream->fs_bufstart == NULL)
|
||||
{
|
||||
ret = write(stream->fs_fd, ptr, count);
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Get exclusive access to the stream */
|
||||
|
||||
lib_take_semaphore(stream);
|
||||
@@ -165,4 +176,4 @@ errout:
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_STDIO_BUFFER_SIZE */
|
||||
#endif /* CONFIG_STDIO_DISABLE_BUFFERING */
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
* libc/stdio/lib_rdflush.c
|
||||
*
|
||||
* Copyright (C) 2008, 2011 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2008, 2011, 2017 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -46,6 +46,8 @@
|
||||
|
||||
#include "libc.h"
|
||||
|
||||
#ifndef CONFIG_STDIO_DISABLE_BUFFERING
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
@@ -59,15 +61,23 @@
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#if CONFIG_STDIO_BUFFER_SIZE > 0
|
||||
int lib_rdflush(FAR FILE *stream)
|
||||
{
|
||||
if (!stream)
|
||||
/* Sanity checking */
|
||||
|
||||
if (stream =- NULL)
|
||||
{
|
||||
set_errno(EBADF);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* Do nothing if there is no I/O buffer */
|
||||
|
||||
if (stream->fs_bufstart == NULL)
|
||||
{
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* Get exclusive access to the stream */
|
||||
|
||||
lib_take_semaphore(stream);
|
||||
@@ -108,5 +118,5 @@ int lib_rdflush(FAR FILE *stream)
|
||||
lib_give_semaphore(stream);
|
||||
return OK;
|
||||
}
|
||||
#endif /* CONFIG_STDIO_BUFFER_SIZE */
|
||||
|
||||
#endif /* CONFIG_STDIO_DISABLE_BUFFERING */
|
||||
|
||||
@@ -74,11 +74,6 @@
|
||||
* by the setvbuf() function. The contents of the array at any time are
|
||||
* unspecified.
|
||||
*
|
||||
* REVISIT: This initial version of setvbuf has some limitations and not
|
||||
* all features features required by the specification are available.
|
||||
* Specifically, this current implementation cannot support sisabling
|
||||
* stream buffering if CONFIG_STDIO_BUFFER_SIZE > 0
|
||||
*
|
||||
* Parmeters:
|
||||
* stream - the stream to flush
|
||||
* buffer - the user allocate buffer. If NULL, will allocates a buffer of
|
||||
@@ -95,7 +90,7 @@
|
||||
|
||||
int setvbuf(FAR FILE *stream, FAR char *buffer, int mode, size_t size)
|
||||
{
|
||||
#if CONFIG_STDIO_BUFFER_SIZE > 0
|
||||
#ifndef CONFIG_STDIO_DISABLE_BUFFERING
|
||||
FAR unsigned char *newbuf;
|
||||
uint8_t flags;
|
||||
int errcode;
|
||||
@@ -127,18 +122,6 @@ int setvbuf(FAR FILE *stream, FAR char *buffer, int mode, size_t size)
|
||||
goto errout;
|
||||
}
|
||||
|
||||
#if 1 /* REVISIT: _IONBF not yet supported */
|
||||
/* Not all features are be available. Without some additional logic,
|
||||
* we cannot disable buffering if CONFIG_STDIO_BUFFER_SIZE > 0
|
||||
*/
|
||||
|
||||
if (mode == _IONBF)
|
||||
{
|
||||
errcode = ENOSYS;
|
||||
goto errout;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* My assumption is that if size is zero for modes {_IOFBF, _IOLBF} the
|
||||
* caller is only attempting to change the buffering mode. In this case,
|
||||
* the existing buffer should be re-used (if there is one). If there is no
|
||||
@@ -149,7 +132,7 @@ int setvbuf(FAR FILE *stream, FAR char *buffer, int mode, size_t size)
|
||||
if ((mode == _IOFBF || mode == _IOLBF) && size == 0 &&
|
||||
stream->fs_bufstart == NULL)
|
||||
{
|
||||
size = CONFIG_STDIO_BUFFER_SIZE;
|
||||
size = BUFSIZE;
|
||||
}
|
||||
|
||||
/* Make sure that we have exclusive access to the stream */
|
||||
@@ -186,11 +169,7 @@ int setvbuf(FAR FILE *stream, FAR char *buffer, int mode, size_t size)
|
||||
* successful.
|
||||
*/
|
||||
|
||||
#if 1 /* REVISIT: _IONBF not yet supported */
|
||||
flags = stream->fs_flags & ~(__FS_FLAG_LBF | __FS_FLAG_UBF);
|
||||
#else
|
||||
flags = stream->fs_flags & ~(__FS_FLAG_LBF | __FS_FLAG_NBF | __FS_FLAG_UBF);
|
||||
#endif
|
||||
|
||||
/* Allocate a new buffer if one is needed or reuse the existing buffer it
|
||||
* is appropriate to do so.
|
||||
@@ -247,14 +226,12 @@ int setvbuf(FAR FILE *stream, FAR char *buffer, int mode, size_t size)
|
||||
break;
|
||||
|
||||
case _IONBF:
|
||||
#if 0 /* REVISIT: _IONBF not yet supported */
|
||||
/* No buffer needed... We must be performing unbuffered I/O */
|
||||
|
||||
DEBUGASSERT(size == 0);
|
||||
newbuf = NULL;
|
||||
flags |= __FS_FLAG_NBF;
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
PANIC();
|
||||
@@ -299,3 +276,5 @@ errout:
|
||||
return ERROR;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* !CONFIG_STDIO_DISABLE_BUFFERING */
|
||||
|
||||
@@ -82,11 +82,23 @@ static void stdoutstream_putc(FAR struct lib_outstream_s *this, int ch)
|
||||
* Name: stdoutstream_flush
|
||||
****************************************************************************/
|
||||
|
||||
#if CONFIG_STDIO_BUFFER_SIZE > 0
|
||||
#ifndef CONFIG_STDIO_DISABLE_BUFFERING
|
||||
static int stdoutstream_flush(FAR struct lib_outstream_s *this)
|
||||
{
|
||||
FAR struct lib_stdoutstream_s *sthis = (FAR struct lib_stdoutstream_s *)this;
|
||||
return lib_fflush(sthis->stream, true);
|
||||
FAR struct file *stream;
|
||||
|
||||
DEBUGASSERT(sthis != NULL && sthis->stream != NULL);
|
||||
stream = sthis->stream;
|
||||
|
||||
if (stream->fs_bufstart != NULL)
|
||||
{
|
||||
return lib_fflush(sthis->stream, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
return OK;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -125,8 +137,8 @@ void lib_stdoutstream(FAR struct lib_stdoutstream_s *outstream,
|
||||
* meaning.
|
||||
*/
|
||||
|
||||
#if CONFIG_STDIO_BUFFER_SIZE > 0
|
||||
if ((stream->fs_oflags & O_BINARY) == 0)
|
||||
#ifndef CONFIG_STDIO_DISABLE_BUFFERING
|
||||
if (stream->fs_bufstart != NULL && (stream->fs_oflags & O_BINARY) == 0)
|
||||
{
|
||||
outstream->public.flush = stdoutstream_flush;
|
||||
}
|
||||
|
||||
@@ -82,11 +82,23 @@ static void stdsostream_putc(FAR struct lib_sostream_s *this, int ch)
|
||||
* Name: stdsostream_flush
|
||||
****************************************************************************/
|
||||
|
||||
#if CONFIG_STDIO_BUFFER_SIZE > 0
|
||||
#ifndef CONFIG_STDIO_DISABLE_BUFFERING
|
||||
static int stdsostream_flush(FAR struct lib_sostream_s *this)
|
||||
{
|
||||
FAR struct lib_stdsostream_s *sthis = (FAR struct lib_stdsostream_s *)this;
|
||||
return lib_fflush(sthis->stream, true);
|
||||
FAR struct lib_stdsostream_s *sthis = (FAR struct lib_stdoutstream_s *)this;
|
||||
FAR struct file *stream;
|
||||
|
||||
DEBUGASSERT(sthis != NULL && sthis->stream != NULL);
|
||||
stream = sthis->stream;
|
||||
|
||||
if (stream->fs_bufstart != NULL)
|
||||
{
|
||||
return lib_fflush(sthis->stream, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
return OK;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -138,8 +150,8 @@ void lib_stdsostream(FAR struct lib_stdsostream_s *outstream,
|
||||
* meaning.
|
||||
*/
|
||||
|
||||
#if CONFIG_STDIO_BUFFER_SIZE > 0
|
||||
if ((stream->fs_oflags & O_BINARY) == 0)
|
||||
#ifndef CONFIG_STDIO_DISABLE_BUFFERING
|
||||
if (stream->fs_bufstart != NULL && (stream->fs_oflags & O_BINARY) == 0)
|
||||
{
|
||||
outstream->public.flush = stdsostream_flush;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
* libc/stdio/lib_wrflush.c
|
||||
*
|
||||
* Copyright (C) 2008-2009, 2011-2012 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2008-2009, 2011-2012, 2017 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -60,16 +60,23 @@
|
||||
|
||||
int lib_wrflush(FAR FILE *stream)
|
||||
{
|
||||
#if CONFIG_STDIO_BUFFER_SIZE > 0
|
||||
#ifndef CONFIG_STDIO_DISABLE_BUFFERING
|
||||
/* Verify that we were passed a valid (i.e., non-NULL) stream */
|
||||
|
||||
#ifdef CONFIG_DEBUG_FEATURES
|
||||
if (!stream)
|
||||
if (stream == NULL)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Do nothing if there is no I/O buffer */
|
||||
|
||||
if (stream->fs_bufstart == NULL)
|
||||
{
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* Verify that the stream is opened for writing... lib_fflush will
|
||||
* return an error if it is called for a stream that is not opened for
|
||||
* writing. Check that first so that this function will not fail in
|
||||
@@ -91,6 +98,7 @@ int lib_wrflush(FAR FILE *stream)
|
||||
*/
|
||||
|
||||
return lib_fflush(stream, true);
|
||||
|
||||
#else
|
||||
/* Verify that we were passed a valid (i.e., non-NULL) stream */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user