From a00d8e16a19e37fdf9fbed71268fc0d08e0d2f2f Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Wed, 11 Oct 2017 10:18:30 -0600 Subject: [PATCH] Adds OS internal function nx_write() which is functionally equivalent to write() except that it does not set the errno variable and do not cause cancellation points. --- drivers/loop/losetup.c | 11 +- drivers/mtd/filemtd.c | 11 +- drivers/wireless/cc3000/cc3000drv.c | 6 +- fs/vfs/fs_write.c | 172 +++++++++++++++++----------- include/nuttx/fs/fs.h | 39 ++++++- include/nuttx/net/net.h | 8 +- libc/misc/lib_sendfile.c | 25 ++-- libc/netdb/lib_dnsquery.c | 4 +- libc/stdio/lib_fwrite.c | 3 +- libc/stdio/lib_libfflush.c | 4 +- libc/stdio/lib_libfwrite.c | 15 ++- libc/stdio/lib_rawoutstream.c | 14 ++- libc/stdio/lib_rawsostream.c | 12 +- net/local/local_sendpacket.c | 16 +-- 14 files changed, 212 insertions(+), 128 deletions(-) diff --git a/drivers/loop/losetup.c b/drivers/loop/losetup.c index f5d2969a6f..55b61f455e 100644 --- a/drivers/loop/losetup.c +++ b/drivers/loop/losetup.c @@ -299,18 +299,19 @@ static ssize_t loop_write(FAR struct inode *inode, ret = lseek(dev->fd, offset, SEEK_SET); if (ret == (off_t)-1) { - _err("ERROR: Seek failed for offset=%d: %d\n", (int)offset, get_errno()); + _err("ERROR: Seek failed for offset=%d: %d\n", + (int)offset, get_errno()); } /* Then write the requested number of sectors to that position */ do { - nbyteswritten = write(dev->fd, buffer, nsectors * dev->sectsize); - if (nbyteswritten < 0 && get_errno() != EINTR) + nbyteswritten = nx_write(dev->fd, buffer, nsectors * dev->sectsize); + if (nbyteswritten < 0 && nbyteswritten != -EINTR) { - _err("ERROR: Write failed: %d\n", get_errno()); - return -get_errno(); + _err("ERROR: nx_write failed: %d\n", nbyteswritten); + return nbyteswritten; } } while (nbyteswritten < 0); diff --git a/drivers/mtd/filemtd.c b/drivers/mtd/filemtd.c index aee2fb51e2..c68a49c326 100644 --- a/drivers/mtd/filemtd.c +++ b/drivers/mtd/filemtd.c @@ -49,6 +49,7 @@ #include #include +#include #include #include @@ -204,7 +205,7 @@ static ssize_t filemtd_write(FAR struct file_dev_s *priv, size_t offset, if (buflen == 0) { lseek(priv->fd, seekpos, SEEK_SET); - write(priv->fd, buf, sizeof(buf)); + (void)nx_write(priv->fd, buf, sizeof(buf)); seekpos += sizeof(buf); } } @@ -214,7 +215,7 @@ static ssize_t filemtd_write(FAR struct file_dev_s *priv, size_t offset, if (buflen != 0) { lseek(priv->fd, seekpos, SEEK_SET); - write(priv->fd, buf, sizeof(buf)); + (void)nx_write(priv->fd, buf, sizeof(buf)); } return len; @@ -281,7 +282,7 @@ static int filemtd_erase(FAR struct mtd_dev_s *dev, off_t startblock, memset(buffer, CONFIG_FILEMTD_ERASESTATE, sizeof(buffer)); while (nbytes) { - write(priv->fd, buffer, sizeof(buffer)); + (void)nx_write(priv->fd, buffer, sizeof(buffer)); nbytes -= sizeof(buffer); } @@ -333,7 +334,7 @@ static ssize_t filemtd_bread(FAR struct mtd_dev_s *dev, off_t startblock, ****************************************************************************/ static ssize_t filemtd_bwrite(FAR struct mtd_dev_s *dev, off_t startblock, - size_t nblocks, FAR const uint8_t *buf) + size_t nblocks, FAR const uint8_t *buf) { FAR struct file_dev_s *priv = (FAR struct file_dev_s *)dev; off_t offset; @@ -396,7 +397,7 @@ static ssize_t filemtd_byteread(FAR struct mtd_dev_s *dev, off_t offset, #ifdef CONFIG_MTD_BYTE_WRITE static ssize_t file_bytewrite(FAR struct mtd_dev_s *dev, off_t offset, - size_t nbytes, FAR const uint8_t *buf) + size_t nbytes, FAR const uint8_t *buf) { FAR struct file_dev_s *priv = (FAR struct file_dev_s *)dev; off_t maxoffset; diff --git a/drivers/wireless/cc3000/cc3000drv.c b/drivers/wireless/cc3000/cc3000drv.c index cb40a30a36..99d5136f96 100644 --- a/drivers/wireless/cc3000/cc3000drv.c +++ b/drivers/wireless/cc3000/cc3000drv.c @@ -118,8 +118,12 @@ void cc3000_resume(void) long cc3000_write(uint8_t *pUserBuffer, uint16_t usLength) { + ssize_t ret; + DEBUGASSERT(spiconf.cc3000fd >= 0); - return write(spiconf.cc3000fd, pUserBuffer, usLength) == usLength ? 0 : -errno; + + ret = nx_write(spiconf.cc3000fd, pUserBuffer, usLength); + return ret >= 0 ? 0 : ret; } /**************************************************************************** diff --git a/fs/vfs/fs_write.c b/fs/vfs/fs_write.c index cdd1299fc1..f5f9f47438 100644 --- a/fs/vfs/fs_write.c +++ b/fs/vfs/fs_write.c @@ -65,8 +65,24 @@ * * Description: * Equivalent to the standard write() function except that is accepts a - * struct file instance instead of a file descriptor. Currently used - * only by aio_write(); + * struct file instance instead of a file descriptor. It is functionally + * equivalent to write() except that in addition to the differences in + * input paramters: + * + * - It does not modify the errno variable, + * - It is not a cancellation point, and + * - It does not handle socket descriptors. + * + * Input Parameters: + * filep - Instance of struct file to use with the write + * buf - Data to write + * nbytes - Length of data to write + * + * Returned Value: + * On success, the number of bytes written are returned (zero indicates + * nothing was written). On any failure, a negated errno value is returned + * (see comments withwrite() for a description of the appropriate errno + * values). * ****************************************************************************/ @@ -94,6 +110,81 @@ ssize_t file_write(FAR struct file *filep, FAR const void *buf, size_t nbytes) return inode->u.i_ops->write(filep, buf, nbytes); } +/**************************************************************************** + * Name: nx_write + * + * Description: + * nx_write() writes up to nytes bytes to the file referenced by the file + * descriptor fd from the buffer starting at buf. nx_write() is an + * internal OS function. It is functionally equivalent to write() except + * that: + * + * - It does not modify the errno variable, and + * - It is not a cancellation point. + * + * Input Parameters: + * fd - file descriptor (or socket descriptor) to write to + * buf - Data to write + * nbytes - Length of data to write + * + * Returned Value: + * On success, the number of bytes written are returned (zero indicates + * nothing was written). On any failure, a negated errno value is returned + * (see comments withwrite() for a description of the appropriate errno + * values). + * + ****************************************************************************/ + +ssize_t nx_write(int fd, FAR const void *buf, size_t nbytes) +{ +#if CONFIG_NFILE_DESCRIPTORS > 0 + FAR struct file *filep; +#endif + ssize_t ret; + + if (buf == NULL) + { + return -EINVAL; + } + + /* Did we get a valid file descriptor? */ + +#if CONFIG_NFILE_DESCRIPTORS > 0 + if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS) +#endif + { +#if defined(CONFIG_NET_TCP) && CONFIG_NSOCKET_DESCRIPTORS > 0 + /* Write to a socket descriptor is equivalent to send with flags == 0. */ + + ret = nx_send(fd, buf, nbytes, 0); +#else + ret = -EBADF; +#endif + } + +#if CONFIG_NFILE_DESCRIPTORS > 0 + else + { + /* The descriptor is in the right range to be a file descriptor.. + * write to the file. Note that fs_getfilep() will set the errno on + * failure. + */ + + ret = (ssize_t)fs_getfilep(fd, &filep); + if (ret >= 0) + { + /* Perform the write operation using the file descriptor as an + * index. Note that file_write() will set the errno on failure. + */ + + ret = file_write(filep, buf, nbytes); + } + } +#endif + + return ret; +} + /**************************************************************************** * Name: write * @@ -101,13 +192,13 @@ ssize_t file_write(FAR struct file *filep, FAR const void *buf, size_t nbytes) * write() writes up to nytes bytes to the file referenced by the file * descriptor fd from the buffer starting at buf. * - * Parameters: - * fd file descriptor (or socket descriptor) to write to - * buf Data to write - * nbytes Length of data to write + * Input Parameters: + * fd - file descriptor (or socket descriptor) to write to + * buf - Data to write + * nbytes - Length of data to write * * Returned Value: - * On success, the number of bytes written are returned (zero indicates + * On success, the number of bytes written are returned (zero indicates * nothing was written). On error, -1 is returned, and errno is set appro- * priately: * @@ -140,78 +231,25 @@ ssize_t file_write(FAR struct file *filep, FAR const void *buf, size_t nbytes) * signal. (Thus, the write return value is seen only if the program * catches, blocks or ignores this signal.) * - * Assumptions: - * - ********************************************************************************************/ + ****************************************************************************/ ssize_t write(int fd, FAR const void *buf, size_t nbytes) { -#if CONFIG_NFILE_DESCRIPTORS > 0 - FAR struct file *filep; -#endif ssize_t ret; /* write() is a cancellation point */ (void)enter_cancellation_point(); - if (buf == NULL) + /* Let nx_write() do all of the work */ + + ret = nx_write(fd, buf, nbytes); + if (ret < 0) { - ret = -EINVAL; - goto errout; + set_errno(ret); + ret = ERROR; } - /* Did we get a valid file descriptor? */ - -#if CONFIG_NFILE_DESCRIPTORS > 0 - if ((unsigned int)fd >= CONFIG_NFILE_DESCRIPTORS) -#endif - { -#if defined(CONFIG_NET_TCP) && CONFIG_NSOCKET_DESCRIPTORS > 0 - /* Write to a socket descriptor is equivalent to send with flags == 0. */ - - ret = nx_send(fd, buf, nbytes, 0); - if (ret < 0) - { - goto errout; - } -#else - ret = -EBADF; - goto errout; -#endif - } - -#if CONFIG_NFILE_DESCRIPTORS > 0 - else - { - /* The descriptor is in the right range to be a file descriptor.. - * write to the file. Note that fs_getfilep() will set the errno on - * failure. - */ - - ret = (ssize_t)fs_getfilep(fd, &filep); - if (ret < 0) - { - goto errout; - } - - /* Perform the write operation using the file descriptor as an - * index. Note that file_write() will set the errno on failure. - */ - - ret = file_write(filep, buf, nbytes); - if (ret < 0) - { - goto errout; - } - } -#endif - leave_cancellation_point(); return ret; - -errout: - set_errno(-ret); - leave_cancellation_point(); - return ERROR; } diff --git a/include/nuttx/fs/fs.h b/include/nuttx/fs/fs.h index 15dbab0a42..5106e05349 100644 --- a/include/nuttx/fs/fs.h +++ b/include/nuttx/fs/fs.h @@ -84,12 +84,14 @@ #if defined(CONFIG_BUILD_FLAT) || defined(__KERNEL__) # define _NX_WRITE(f,b,s) nx_write(s,b,s) -# define _NX_ERRNO(r) (-(r)) -# define _NX_ERRVAL(r) (r) +# define _NX_GETERRNO(r) (-(r)) +# define _NX_SETERRNO(r) set_errno(-(r)) +# define _NX_GETERRVAL(r) (r) #else -# define _NX_WRITE(f,b,s) rite(s,b,s) -# define _NX_ERRNO(r) errno -# define _NX_ERRVAL(r) (-errno) +# define _NX_WRITE(f,b,s) write(s,b,s) +# define _NX_GETERRNO(r) errno +# define _NX_SETERRNO(r) +# define _NX_GETERRVAL(r) (-errno) #endif /* Stream flags for the fs_flags field of in struct file_struct */ @@ -935,6 +937,33 @@ ssize_t file_read(FAR struct file *filep, FAR void *buf, size_t nbytes); ssize_t file_write(FAR struct file *filep, FAR const void *buf, size_t nbytes); #endif +/**************************************************************************** + * Name: nx_write + * + * Description: + * nx_write() writes up to nytes bytes to the file referenced by the file + * descriptor fd from the buffer starting at buf. nx_write() is an + * internal OS function. It is functionally equivalent to write() except + * that: + * + * - It does not modify the errno variable, and + * - It is not a cancellation point. + * + * Input Parameters: + * fd - file descriptor (or socket descriptor) to write to + * buf - Data to write + * nbytes - Length of data to write + * + * Returned Value: + * On success, the number of bytes written are returned (zero indicates + * nothing was written). On any failure, a negated errno value is returned + * (see comments withwrite() for a description of the appropriate errno + * values). + * + ****************************************************************************/ + +ssize_t nx_write(int fd, FAR const void *buf, size_t nbytes); + /**************************************************************************** * Name: file_pread * diff --git a/include/nuttx/net/net.h b/include/nuttx/net/net.h index 0ba8e0fa87..1a97efb3a0 100644 --- a/include/nuttx/net/net.h +++ b/include/nuttx/net/net.h @@ -76,14 +76,14 @@ # define _NX_SEND(s,b,l,f) nx_send(s,b,l,f) # define _NX_RECV(s,b,l,f) nx_recv(s,b,l,f) # define _NX_RECVFROM(s,b,l,f,a,n) nx_recvfrom(s,b,l,f,a,n) -# define _NX_ERRNO(r) (-(r)) -# define _NX_ERRVAL(r) (r) +# define _NX_GETERRNO(r) (-(r)) +# define _NX_GETERRVAL(r) (r) #else # define _NX_SEND(s,b,l,f) send(s,b,l,f) # define _NX_RECV(s,b,l,f) recv(s,b,l,f) # define _NX_RECVFROM(s,b,l,f,a,n) recvfrom(s,b,l,f,a,n) -# define _NX_ERRNO(r) errno -# define _NX_ERRVAL(r) (-errno) +# define _NX_GETERRNO(r) errno +# define _NX_GETERRVAL(r) (-errno) #endif /* Socket descriptors are the index into the TCB sockets list, offset by the diff --git a/libc/misc/lib_sendfile.c b/libc/misc/lib_sendfile.c index c5c9b5536b..0e3bd7bacd 100644 --- a/libc/misc/lib_sendfile.c +++ b/libc/misc/lib_sendfile.c @@ -45,26 +45,12 @@ #include #include +#include + #include "libc.h" #if CONFIG_NSOCKET_DESCRIPTORS > 0 || CONFIG_NFILE_DESCRIPTORS > 0 -/**************************************************************************** - * Private types - ****************************************************************************/ - -/**************************************************************************** - * Private Data - ****************************************************************************/ - -/**************************************************************************** - * Public Data - ****************************************************************************/ - -/**************************************************************************** - * Private Functions - ****************************************************************************/ - /**************************************************************************** * Public Functions ****************************************************************************/ @@ -217,7 +203,7 @@ ssize_t sendfile(int outfd, int infd, off_t *offset, size_t count) { /* Write the buffer of data to the outfd */ - nbyteswritten = write(outfd, wrbuffer, nbytesread); + nbyteswritten = _NX_WRITE(outfd, wrbuffer, nbytesread); /* Check for a complete (or parial) write. write() should not * return zero. @@ -242,6 +228,8 @@ ssize_t sendfile(int outfd, int infd, off_t *offset, size_t count) else { + int errcode = _NX_GETERRNO(nbyteswritten); + /* Check for a read ERROR. EINTR is a special case. This * function should break out and return an error if EINTR * is returned and no data has been transferred. But what @@ -250,11 +238,12 @@ ssize_t sendfile(int outfd, int infd, off_t *offset, size_t count) */ #ifndef CONFIG_DISABLE_SIGNALS - if (errno != EINTR || ntransferred == 0) + if (errcode != EINTR || ntransferred == 0) #endif { /* Write error. Break out and return the error condition */ + _NX_SETERRNO(nbyteswritten); ntransferred = ERROR; endxfr = true; break; diff --git a/libc/netdb/lib_dnsquery.c b/libc/netdb/lib_dnsquery.c index 9e349ae374..7b3fe158f9 100644 --- a/libc/netdb/lib_dnsquery.c +++ b/libc/netdb/lib_dnsquery.c @@ -255,9 +255,9 @@ static int dns_recv_response(int sd, FAR struct sockaddr *addr, ret = _NX_RECV(sd, buffer, RECV_BUFFER_SIZE, 0); if (ret < 0) { - errcode = _NX_ERRNO(ret); + errcode = -_NX_GETERRNO(ret); nerr("ERROR: recv failed: %d\n", errcode); - return -errcode; + return errcode; } hdr = (FAR struct dns_header_s *)buffer; diff --git a/libc/stdio/lib_fwrite.c b/libc/stdio/lib_fwrite.c index 354cd38098..68278ed3d8 100644 --- a/libc/stdio/lib_fwrite.c +++ b/libc/stdio/lib_fwrite.c @@ -52,7 +52,8 @@ * Name: fwrite ****************************************************************************/ -size_t fwrite(FAR const void *ptr, size_t size, size_t n_items, FAR FILE *stream) +size_t fwrite(FAR const void *ptr, size_t size, size_t n_items, + FAR FILE *stream) { size_t full_size = n_items * (size_t)size; ssize_t bytes_written; diff --git a/libc/stdio/lib_libfflush.c b/libc/stdio/lib_libfflush.c index 3eef605340..29a44cfe22 100644 --- a/libc/stdio/lib_libfflush.c +++ b/libc/stdio/lib_libfflush.c @@ -129,7 +129,7 @@ ssize_t lib_fflush(FAR FILE *stream, bool bforce) { /* Perform the write */ - bytes_written = write(stream->fs_fd, src, nbuffer); + bytes_written = _NX_WRITE(stream->fs_fd, src, nbuffer); if (bytes_written < 0) { /* Write failed. The cause of the failure is in 'errno'. @@ -137,7 +137,7 @@ ssize_t lib_fflush(FAR FILE *stream, bool bforce) */ stream->fs_flags |= __FS_FLAG_ERROR; - ret = -get_errno(); + ret = _NX_GETERRVAL(bytes_written); goto errout_with_sem; } diff --git a/libc/stdio/lib_libfwrite.c b/libc/stdio/lib_libfwrite.c index b8c90277e6..c17747155b 100644 --- a/libc/stdio/lib_libfwrite.c +++ b/libc/stdio/lib_libfwrite.c @@ -46,6 +46,8 @@ #include #include +#include + #include "libc.h" /**************************************************************************** @@ -84,7 +86,15 @@ ssize_t lib_fwrite(FAR const void *ptr, size_t count, FAR FILE *stream) if (stream->fs_bufstart == NULL) { - ret = write(stream->fs_fd, ptr, count); + ret = _NX_WRITE(stream->fs_fd, ptr, count); +#if defined(CONFIG_BUILD_FLAT) || defined(__KERNEL__) + if (ret < 0) + { + _NX_SETERRNO((int)-ret); + ret = ERROR; + } +#endif + goto errout; } @@ -167,10 +177,11 @@ errout: } #else { - ssize_t ret = write(stream->fs_fd, ptr, count); + ssize_t ret = _NX_WRITE(stream->fs_fd, ptr, count); if (ret < 0) { stream->fs_flags |= __FS_FLAG_ERROR; + _NX_SETERRNO(ret); } return ret; diff --git a/libc/stdio/lib_rawoutstream.c b/libc/stdio/lib_rawoutstream.c index ab333147ba..69155fc15c 100644 --- a/libc/stdio/lib_rawoutstream.c +++ b/libc/stdio/lib_rawoutstream.c @@ -37,10 +37,14 @@ * Included Files ****************************************************************************/ +#include + #include #include #include +#include + #include "libc.h" /**************************************************************************** @@ -54,8 +58,9 @@ static void rawsostream_putc(FAR struct lib_sostream_s *this, int ch) { FAR struct lib_rawsostream_s *rthis = (FAR struct lib_rawsostream_s *)this; - int nwritten; char buffer = ch; + int nwritten; + int errcode; DEBUGASSERT(this && rthis->fd >= 0); @@ -65,7 +70,7 @@ static void rawsostream_putc(FAR struct lib_sostream_s *this, int ch) do { - nwritten = write(rthis->fd, &buffer, 1); + nwritten = _NX_WRITE(rthis->fd, &buffer, 1); if (nwritten == 1) { this->nput++; @@ -74,12 +79,13 @@ static void rawsostream_putc(FAR struct lib_sostream_s *this, int ch) /* The only expected error is EINTR, meaning that the write operation * was awakened by a signal. Zero would not be a valid return value - * from write(). + * from _NX_WRITE(). */ + errcode = _NX_GETERRNO(nwritten); DEBUGASSERT(nwritten < 0); } - while (get_errno() == EINTR); + while (errcode == EINTR); } /**************************************************************************** diff --git a/libc/stdio/lib_rawsostream.c b/libc/stdio/lib_rawsostream.c index 30c71cce42..1579e1db6d 100644 --- a/libc/stdio/lib_rawsostream.c +++ b/libc/stdio/lib_rawsostream.c @@ -1,5 +1,5 @@ /**************************************************************************** - * libc/stdio/lib_rawoutstream.c + * libc/stdio/lib_rawsostream.c * * Copyright (C) 2007-2009, 2011-2012, 2014 Gregory Nutt. All rights reserved. * Author: Gregory Nutt @@ -37,10 +37,14 @@ * Included Files ****************************************************************************/ +#include + #include #include #include +#include + #include "libc.h" /**************************************************************************** @@ -66,7 +70,7 @@ static void rawoutstream_putc(FAR struct lib_outstream_s *this, int ch) do { - nwritten = write(rthis->fd, &buffer, 1); + nwritten = _NX_WRITE(rthis->fd, &buffer, 1); if (nwritten == 1) { this->nput++; @@ -75,10 +79,10 @@ static void rawoutstream_putc(FAR struct lib_outstream_s *this, int ch) /* The only expected error is EINTR, meaning that the write operation * was awakened by a signal. Zero or values > 1 would not be valid - * return values from write(). + * return values from _NX_WRITE(). */ - errcode = get_errno(); + errcode = _NX_GETERRNO(nwritten); DEBUGASSERT(nwritten < 0); } while (errcode == EINTR); diff --git a/net/local/local_sendpacket.c b/net/local/local_sendpacket.c index fce8b4fe68..e8491db58e 100644 --- a/net/local/local_sendpacket.c +++ b/net/local/local_sendpacket.c @@ -38,7 +38,6 @@ ****************************************************************************/ #include -#if defined(CONFIG_NET) && defined(CONFIG_NET_LOCAL) #include #include @@ -47,8 +46,12 @@ #include #include +#include + #include "local/local.h" +#if defined(CONFIG_NET) && defined(CONFIG_NET_LOCAL) + /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ @@ -92,16 +95,13 @@ static int local_fifo_write(int fd, FAR const uint8_t *buf, size_t len) while (len > 0) { - nwritten = write(fd, buf, len); + nwritten = nx_write(fd, buf, len); if (nwritten < 0) { - int errcode = get_errno(); - DEBUGASSERT(errcode > 0); - - if (errcode != EINTR) + if (nwritten != -EINTR) { - nerr("ERROR: Write failed: %d\n", errcode); - return -errcode; + nerr("ERROR: nx_write failed: %d\n", nwritten); + return (int)nwritten; } ninfo("Ignoring signal\n");