diff options
author | Joel Sherrill <joel.sherrill@OARcorp.com> | 2007-09-24 21:35:10 +0000 |
---|---|---|
committer | Joel Sherrill <joel.sherrill@OARcorp.com> | 2007-09-24 21:35:10 +0000 |
commit | b5bf8cd163de664f558a5b2b02b01cc8a7722456 (patch) | |
tree | 57f78fc92a0ea83967a9b6074bf43c3afa9a5bf2 /cpukit/libcsupport/src/writev.c | |
parent | 2007-09-24 Joel Sherrill <joel.sherrill@oarcorp.com> (diff) | |
download | rtems-b5bf8cd163de664f558a5b2b02b01cc8a7722456.tar.bz2 |
2007-09-24 Joel Sherrill <joel.sherrill@oarcorp.com>
PR 1262/filesystem
* libcsupport/Makefile.am, libnetworking/libc/herror.c,
libnetworking/libc/res_send.c, libnetworking/sys/uio.h,
telnetd/Makefile.am, telnetd/README, telnetd/preinstall.am,
telnetd/pty.c, telnetd/telnetd.c: Add support for readv() and
writev() including documentation and test case.
* libcsupport/src/readv.c, libcsupport/src/writev.c: New files.
Diffstat (limited to 'cpukit/libcsupport/src/writev.c')
-rw-r--r-- | cpukit/libcsupport/src/writev.c | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/cpukit/libcsupport/src/writev.c b/cpukit/libcsupport/src/writev.c new file mode 100644 index 0000000000..c032f9f6bc --- /dev/null +++ b/cpukit/libcsupport/src/writev.c @@ -0,0 +1,126 @@ +/* + * writev() - POSIX 1003.1 - Read a Vector + * + * OpenGroup URL: + * + * http://www.opengroup.org/onlinepubs/009695399/functions/writev.html + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <sys/types.h> +#include <sys/uio.h> + +#include <rtems/libio_.h> +#include <rtems/seterr.h> + +ssize_t writev( + int fd, + const struct iovec *iov, + int iovcnt +) +{ + ssize_t total; + int v; + int bytes; + rtems_libio_t *iop; + ssize_t old; + boolean all_zeros; + + rtems_libio_check_fd( fd ); + iop = rtems_libio_iop( fd ); + rtems_libio_check_is_open( iop ); + rtems_libio_check_permissions( iop, LIBIO_FLAGS_WRITE ); + + /* + * Argument validation on IO vector + */ + if ( !iov ) + rtems_set_errno_and_return_minus_one( EINVAL ); + + if ( iovcnt <= 0 ) + rtems_set_errno_and_return_minus_one( EINVAL ); + + if ( iovcnt > IOV_MAX ) + rtems_set_errno_and_return_minus_one( EINVAL ); + + if ( !iop->handlers->write_h ) + rtems_set_errno_and_return_minus_one( ENOTSUP ); + + /* + * OpenGroup says that you are supposed to return EINVAL if the + * sum of the iov_len values in the iov array would overflow a + * ssize_t. + * + * Also we would like to ensure that no IO is performed if there + * are obvious errors in the iovec. So this extra loop ensures + * that we do not do anything if there is an argument error. + * + * In addition,the OpenGroup specification says that if all the + * iov_len entries are zero, then the call has no effect. So + * this loop does that check as well and sets "all-zero" appropriately. + * The variable "all_zero" is used as an early exit point before + * entering the write loop. + */ + all_zeros = TRUE; + for ( old=0, total=0, v=0 ; v < iovcnt ; v++ ) { + + if ( !iov[v].iov_base ) + rtems_set_errno_and_return_minus_one( EINVAL ); + + if ( iov[v].iov_len < 0 ) + rtems_set_errno_and_return_minus_one( EINVAL ); + + if ( iov[v].iov_len ) + all_zeros = FALSE; + + /* check for wrap */ + old = total; + total += iov[v].iov_len; + if ( total < old || total > SSIZE_MAX ) + rtems_set_errno_and_return_minus_one( EINVAL ); + } + + /* + * A writev with all zeros is supposed to have no effect per OpenGroup. + */ + if ( all_zeros == TRUE ) { + return 0; + } + + /* + * Now process the writev(). + */ + for ( total=0, v=0 ; v < iovcnt ; v++ ) { + /* all zero lengths has no effect */ + if ( iov[v].iov_len == 0 ) + continue; + + bytes = (*iop->handlers->write_h)( iop, iov[v].iov_base, iov[v].iov_len ); + + if ( bytes < 0 ) + return -1; + + if ( bytes > 0 ) { + iop->offset += bytes; + total += bytes; + } + + if (bytes != iov[ v ].iov_len) + break; + } + + return total; +} + |