diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2013-12-16 13:12:22 +0100 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2013-12-20 10:31:53 +0100 |
commit | 95a57280ebc3996547fccd6065a5652a846d1447 (patch) | |
tree | 9a39803381927d9acf8b426ff995248455b19184 /cpukit/libcsupport/include/rtems/libio_.h | |
parent | arm/gba: doxygen improvement (diff) | |
download | rtems-95a57280ebc3996547fccd6065a5652a846d1447.tar.bz2 |
libcsupport: Add and use rtems_libio_iovec_eval()
Diffstat (limited to '')
-rw-r--r-- | cpukit/libcsupport/include/rtems/libio_.h | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/cpukit/libcsupport/include/rtems/libio_.h b/cpukit/libcsupport/include/rtems/libio_.h index bf01cd5659..995d621f79 100644 --- a/cpukit/libcsupport/include/rtems/libio_.h +++ b/cpukit/libcsupport/include/rtems/libio_.h @@ -21,7 +21,9 @@ #ifndef _RTEMS_RTEMS_LIBIO__H #define _RTEMS_RTEMS_LIBIO__H +#include <sys/uio.h> #include <errno.h> +#include <limits.h> #include <rtems.h> #include <rtems/libio.h> @@ -839,6 +841,60 @@ static inline bool rtems_filesystem_is_parent_directory( return tokenlen == 2 && token [0] == '.' && token [1] == '.'; } +static inline ssize_t rtems_libio_iovec_eval( + int fd, + const struct iovec *iov, + int iovcnt, + uint32_t flags, + rtems_libio_t **iopp +) +{ + ssize_t total; + int v; + rtems_libio_t *iop; + + rtems_libio_check_fd( fd ); + iop = rtems_libio_iop( fd ); + rtems_libio_check_is_open( iop ); + rtems_libio_check_permissions_with_error( iop, flags, EBADF ); + + *iopp = iop; + + /* + * Argument validation on IO vector + */ + if ( iov == NULL ) + 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 ); + + /* + * 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. + */ + total = 0; + for ( v = 0 ; v < iovcnt ; ++v ) { + size_t len = iov[ v ].iov_len; + + if ( len > ( size_t ) ( SSIZE_MAX - total ) ) { + rtems_set_errno_and_return_minus_one( EINVAL ); + } + + total += ( ssize_t ) len; + + if ( iov[ v ].iov_base == NULL ) { + rtems_set_errno_and_return_minus_one( EINVAL ); + } + } + + return total; +} + /** @} */ #ifdef __cplusplus |