From 6a14fe48c61536241f4071b75df0bf8773c72e42 Mon Sep 17 00:00:00 2001 From: patacongo Date: Wed, 18 Apr 2012 15:57:45 +0000 Subject: Disable line buffering if the file is opened in binary mode; Also fix a couple of fopen/fdopen bugs git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@4630 42af7a65-404d-4744-a932-0658087f49c3 --- nuttx/lib/lib_internal.h | 5 + nuttx/lib/stdio/lib_fopen.c | 231 +++++++++++++++++++++++++++--------- nuttx/lib/stdio/lib_fputc.c | 4 +- nuttx/lib/stdio/lib_fputs.c | 4 +- nuttx/lib/stdio/lib_libnoflush.c | 4 +- nuttx/lib/stdio/lib_lowoutstream.c | 4 +- nuttx/lib/stdio/lib_memoutstream.c | 4 +- nuttx/lib/stdio/lib_nulloutstream.c | 4 +- nuttx/lib/stdio/lib_puts.c | 6 +- nuttx/lib/stdio/lib_rawoutstream.c | 4 +- nuttx/lib/stdio/lib_stdoutstream.c | 26 +++- 11 files changed, 220 insertions(+), 76 deletions(-) (limited to 'nuttx/lib') diff --git a/nuttx/lib/lib_internal.h b/nuttx/lib/lib_internal.h index 29d49303d..c3d9bfd18 100644 --- a/nuttx/lib/lib_internal.h +++ b/nuttx/lib/lib_internal.h @@ -53,6 +53,11 @@ /**************************************************************************** * Definitions ****************************************************************************/ +/* This configuration directory is used in environment variable processing + * when we need to reference the user's home directory. There are no user + * directories in NuttX so, by default, this always refers to the root + * directory. + */ #ifndef CONFIG_LIB_HOMEDIR # define CONFIG_LIB_HOMEDIR "/" diff --git a/nuttx/lib/stdio/lib_fopen.c b/nuttx/lib/stdio/lib_fopen.c index f90951fe2..52e44c59d 100644 --- a/nuttx/lib/stdio/lib_fopen.c +++ b/nuttx/lib/stdio/lib_fopen.c @@ -1,8 +1,8 @@ /**************************************************************************** * lib/stdio/lib_fopen.c * - * Copyright (C) 2007-2011 Gregory Nutt. All rights reserved. - * Author: Gregory Nutt + * Copyright (C) 2007-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -48,6 +48,25 @@ #include "lib_internal.h" +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +enum open_mode_e +{ + MODE_NONE = 0, /* No access mode determined */ + MODE_R, /* "r" or "rb" open for reading */ + MODE_W, /* "w" or "wb" open for writing, truncating or creating file */ + MODE_A, /* "a" or "ab" open for writing, appending to file */ + MODE_RPLUS, /* "r+", "rb+", or "r+b" open for update (reading and writing) */ + MODE_WPLUS, /* "w+", "wb+", or "w+b" open for update, truncating or creating file */ + MODE_APLUS, /* "a+", "ab+", or "a+b" open for update, appending to file */ +}; + /**************************************************************************** * Private Functions ****************************************************************************/ @@ -58,77 +77,159 @@ static int lib_mode2oflags(FAR const char *mode) { - int oflags = 0; - if (mode) + enum open_mode_e state; + int oflags; + + /* Verify that a mode string was provided. No error is */ + + if (!mode) + { + goto errout; + } + + /* Parse the mode string to determine the corresponding open flags */ + + state = MODE_NONE; + oflags = 0; + + for (; *mode; mode++) { - while(*mode) + switch (*mode) { - switch (*mode) - { - /* Open for read access */ + /* Open for read access ("r", "r[+]", "r[b]", "r[b+]", or "r[+b]") */ - case 'r' : - if (*(mode + 1) == '+') - { - /* Open for read/write access */ + case 'r' : + if (state == MODE_NONE) + { + /* Open for read access */ - oflags |= O_RDWR; - mode++; - } - else - { - /* Open for read access */ + oflags = O_RDOK; + state = MODE_R; + } + else + { + goto errout; + } + break; - oflags |= O_RDOK; - } - break; + /* Open for write access ("w", "w[+]", "w[b]", "w[b+]", or "w[+b]") */ - /* Open for write access? */ + case 'w' : + if (state == MODE_NONE) + { + /* Open for write access, truncating any existing file */ - case 'w' : - if (*(mode + 1) == '+') - { - /* Open for write read/access, truncating any existing file */ + oflags = O_WROK|O_CREAT|O_TRUNC; + state = MODE_W; + } + else + { + goto errout; + } + break; - oflags |= O_RDWR|O_CREAT|O_TRUNC; - mode++; - } - else - { - /* Open for write access, truncating any existing file */ + /* Open for write/append access ("a", "a[+]", "a[b]", "a[b+]", or "a[+b]") */ - oflags |= O_WROK|O_CREAT|O_TRUNC; - } - break; + case 'a' : + if (state == MODE_NONE) + { + /* Write to the end of the file */ + + oflags = O_WROK|O_CREAT|O_APPEND; + state = MODE_A; + } + else + { + goto errout; + } + break; - /* Open for write/append access? */ + /* Open for update access ("[r]+", "[rb]+]", "[r]+[b]", "[w]+", + * "[wb]+]", "[w]+[b]", "[a]+", "[ab]+]", "[a]+[b]") + */ - case 'a' : - if (*(mode + 1) == '+') - { - /* Read from the beginning of the file; write to the end */ + case '+' : + switch (state) + { + case MODE_R: + { + /* Retain any binary mode selection */ - oflags |= O_RDWR|O_CREAT|O_APPEND; - mode++; - } - else - { - /* Write to the end of the file */ + oflags &= O_BINARY; - oflags |= O_WROK|O_CREAT|O_APPEND; + /* Open for read/write access */ + + oflags |= O_RDWR; + state = MODE_RPLUS; } - break; + break; + + case MODE_W: + { + /* Retain any binary mode selection */ + + oflags &= O_BINARY; + + /* Open for write read/access, truncating any existing file */ + + oflags |= O_RDWR|O_CREAT|O_TRUNC; + state = MODE_WPLUS; + } + break; - /* Open for binary access? */ + case MODE_A: + { + /* Retain any binary mode selection */ - case 'b' : - default: - break; - } - mode++; + oflags &= O_BINARY; + + /* Read from the beginning of the file; write to the end */ + + oflags |= O_RDWR|O_CREAT|O_APPEND; + state = MODE_APLUS; + } + break; + + default: + goto errout; + break; + } + break; + + /* Open for binary access ("[r]b", "[r]b[+]", "[r+]b", "[w]b", + * "[w]b[+]", "[w+]b", "[a]b", "[a]b[+]", "[a+]b") + */ + + case 'b' : + if (state != MODE_NONE) + { + /* The file is opened in binary mode */ + + oflags |= O_BINARY; + } + else + { + goto errout; + } + break; + + /* Unrecognized or unsupported mode */ + + default: + goto errout; + break; } } + return oflags; + +/* Both fopen and fdopen should fail with errno == EINVAL if the mode + * string is invalid. + */ + +errout: + set_errno(EINVAL); + return ERROR; } /**************************************************************************** @@ -141,7 +242,18 @@ static int lib_mode2oflags(FAR const char *mode) FAR FILE *fdopen(int fd, FAR const char *mode) { - return fs_fdopen(fd, lib_mode2oflags(mode), NULL); + FAR FILE *ret = NULL; + int oflags; + + /* Map the open mode string to open flags */ + + oflags = lib_mode2oflags(mode); + if (oflags >= 0) + { + ret = fs_fdopen(fd, oflags, NULL); + } + + return ret; } /**************************************************************************** @@ -154,9 +266,16 @@ FAR FILE *fopen(FAR const char *path, FAR const char *mode) int oflags; int fd; - /* Open the file */ + /* Map the open mode string to open flags */ oflags = lib_mode2oflags(mode); + if (oflags < 0) + { + return NULL; + } + + /* Open the file */ + fd = open(path, oflags, 0666); /* If the open was successful, then fdopen() the fil using the file diff --git a/nuttx/lib/stdio/lib_fputc.c b/nuttx/lib/stdio/lib_fputc.c index 917fcc10a..121161f10 100644 --- a/nuttx/lib/stdio/lib_fputc.c +++ b/nuttx/lib/stdio/lib_fputc.c @@ -1,8 +1,8 @@ /**************************************************************************** * lib/stdio/lib_fputc.c * - * Copyright (C) 2007, 2008, 2011 Gregory Nutt. All rights reserved. - * Author: Gregory Nutt + * Copyright (C) 2007, 2008, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/nuttx/lib/stdio/lib_fputs.c b/nuttx/lib/stdio/lib_fputs.c index 34d12c15e..2d6217d4a 100644 --- a/nuttx/lib/stdio/lib_fputs.c +++ b/nuttx/lib/stdio/lib_fputs.c @@ -1,8 +1,8 @@ /**************************************************************************** * lib/stdio/lib_fputs.c * - * Copyright (C) 2007, 2008, 2011 Gregory Nutt. All rights reserved. - * Author: Gregory Nutt + * Copyright (C) 2007, 2008, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/nuttx/lib/stdio/lib_libnoflush.c b/nuttx/lib/stdio/lib_libnoflush.c index 370a1e8f7..e3b891153 100644 --- a/nuttx/lib/stdio/lib_libnoflush.c +++ b/nuttx/lib/stdio/lib_libnoflush.c @@ -1,8 +1,8 @@ /**************************************************************************** * lib/stdio/lib_libnoflush.c * - * Copyright (C) 2011 Gregory Nutt. All rights reserved. - * Author: Gregory Nutt + * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/nuttx/lib/stdio/lib_lowoutstream.c b/nuttx/lib/stdio/lib_lowoutstream.c index 3b3d467b2..726bd84d7 100644 --- a/nuttx/lib/stdio/lib_lowoutstream.c +++ b/nuttx/lib/stdio/lib_lowoutstream.c @@ -1,8 +1,8 @@ /**************************************************************************** * lib/stdio/lib_lowoutstream.c * - * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. - * Author: Gregory Nutt + * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/nuttx/lib/stdio/lib_memoutstream.c b/nuttx/lib/stdio/lib_memoutstream.c index dca8456e8..007ab8976 100644 --- a/nuttx/lib/stdio/lib_memoutstream.c +++ b/nuttx/lib/stdio/lib_memoutstream.c @@ -1,8 +1,8 @@ /**************************************************************************** * lib/stdio/lib_memoutstream.c * - * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. - * Author: Gregory Nutt + * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/nuttx/lib/stdio/lib_nulloutstream.c b/nuttx/lib/stdio/lib_nulloutstream.c index f92cb0f33..520df459e 100644 --- a/nuttx/lib/stdio/lib_nulloutstream.c +++ b/nuttx/lib/stdio/lib_nulloutstream.c @@ -1,8 +1,8 @@ /**************************************************************************** * lib/stdio/lib_nulloutstream.c * - * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. - * Author: Gregory Nutt + * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/nuttx/lib/stdio/lib_puts.c b/nuttx/lib/stdio/lib_puts.c index 088d0f043..e63a63917 100644 --- a/nuttx/lib/stdio/lib_puts.c +++ b/nuttx/lib/stdio/lib_puts.c @@ -1,8 +1,8 @@ /**************************************************************************** * lib/stdio/lib_puts.c * - * Copyright (C) 2007, 2008, 2011 Gregory Nutt. All rights reserved. - * Author: Gregory Nutt + * Copyright (C) 2007, 2008, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -112,7 +112,7 @@ int puts(FAR const char *s) { nput = nwritten + 1; - /* Flush the buffer after the newline is output */ + /* Flush the buffer after the newline is output. */ #ifdef CONFIG_STDIO_LINEBUFFER ret = lib_fflush(stream, true); diff --git a/nuttx/lib/stdio/lib_rawoutstream.c b/nuttx/lib/stdio/lib_rawoutstream.c index bea47f3ce..ce9d33280 100644 --- a/nuttx/lib/stdio/lib_rawoutstream.c +++ b/nuttx/lib/stdio/lib_rawoutstream.c @@ -1,8 +1,8 @@ /**************************************************************************** * lib/stdio/lib_rawoutstream.c * - * Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved. - * Author: Gregory Nutt + * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/nuttx/lib/stdio/lib_stdoutstream.c b/nuttx/lib/stdio/lib_stdoutstream.c index 99fae11b2..12e78ce53 100644 --- a/nuttx/lib/stdio/lib_stdoutstream.c +++ b/nuttx/lib/stdio/lib_stdoutstream.c @@ -37,6 +37,8 @@ * Included Files ****************************************************************************/ +#include + #include "lib_internal.h" /**************************************************************************** @@ -95,14 +97,32 @@ int stdoutstream_flush(FAR struct lib_outstream_s *this) void lib_stdoutstream(FAR struct lib_stdoutstream_s *stdoutstream, FAR FILE *stream) { + /* Select the put operation */ + stdoutstream->public.put = stdoutstream_putc; + + /* Select the correct flush operation. This flush is only called when + * a newline is encountered in the output stream. However, we do not + * want to support this line buffering behavior if the stream was + * opened in binary mode. In binary mode, the newline has no special + * meaning. + */ + #ifdef CONFIG_STDIO_LINEBUFFER #if CONFIG_STDIO_BUFFER_SIZE > 0 - stdoutstream->public.flush = stdoutstream_flush; -#else - stdoutstream->public.flush = lib_noflush; + if ((stream->fs_oflags & O_BINARY) == 0) + { + stdoutstream->public.flush = stdoutstream_flush; + } + else #endif + { + stdoutstream->public.flush = lib_noflush; + } #endif + + /* Set the number of bytes put to zero and remember the stream */ + stdoutstream->public.nput = 0; stdoutstream->stream = stream; } -- cgit v1.2.3