Changeset 95a57280 in rtems


Ignore:
Timestamp:
Dec 16, 2013, 12:12:22 PM (5 years ago)
Author:
Sebastian Huber <sebastian.huber@…>
Branches:
4.11, master
Children:
2f68778
Parents:
7b10f130
git-author:
Sebastian Huber <sebastian.huber@…> (12/16/13 12:12:22)
git-committer:
Sebastian Huber <sebastian.huber@…> (12/20/13 09:31:53)
Message:

libcsupport: Add and use rtems_libio_iovec_eval()

Files:
5 edited

Legend:

Unmodified
Added
Removed
  • cpukit/libcsupport/include/rtems/libio_.h

    r7b10f130 r95a57280  
    2222#define _RTEMS_RTEMS_LIBIO__H
    2323
     24#include <sys/uio.h>
    2425#include <errno.h>
     26#include <limits.h>
    2527
    2628#include <rtems.h>
     
    840842}
    841843
     844static inline ssize_t rtems_libio_iovec_eval(
     845  int fd,
     846  const struct iovec *iov,
     847  int iovcnt,
     848  uint32_t flags,
     849  rtems_libio_t **iopp
     850)
     851{
     852  ssize_t        total;
     853  int            v;
     854  rtems_libio_t *iop;
     855
     856  rtems_libio_check_fd( fd );
     857  iop = rtems_libio_iop( fd );
     858  rtems_libio_check_is_open( iop );
     859  rtems_libio_check_permissions_with_error( iop, flags, EBADF );
     860
     861  *iopp = iop;
     862
     863  /*
     864   *  Argument validation on IO vector
     865   */
     866  if ( iov == NULL )
     867    rtems_set_errno_and_return_minus_one( EINVAL );
     868
     869  if ( iovcnt <= 0 )
     870    rtems_set_errno_and_return_minus_one( EINVAL );
     871
     872  if ( iovcnt > IOV_MAX )
     873    rtems_set_errno_and_return_minus_one( EINVAL );
     874
     875  /*
     876   *  OpenGroup says that you are supposed to return EINVAL if the
     877   *  sum of the iov_len values in the iov array would overflow a
     878   *  ssize_t.
     879   */
     880  total = 0;
     881  for ( v = 0 ; v < iovcnt ; ++v ) {
     882    size_t len = iov[ v ].iov_len;
     883
     884    if ( len > ( size_t ) ( SSIZE_MAX - total ) ) {
     885      rtems_set_errno_and_return_minus_one( EINVAL );
     886    }
     887
     888    total += ( ssize_t ) len;
     889
     890    if ( iov[ v ].iov_base == NULL ) {
     891      rtems_set_errno_and_return_minus_one( EINVAL );
     892    }
     893  }
     894
     895  return total;
     896}
     897
    842898/** @} */
    843899
  • cpukit/libcsupport/src/readv.c

    r7b10f130 r95a57280  
    1919#endif
    2020
    21 #include <sys/types.h>
    2221#include <sys/uio.h>
    2322
    2423#include <rtems/libio_.h>
    25 #include <rtems/seterr.h>
    2624
    2725/**
     
    4038  ssize_t        total;
    4139  int            v;
    42   int            bytes;
    4340  rtems_libio_t *iop;
    44   bool           all_zeros;
    4541
    46   rtems_libio_check_fd( fd );
    47   iop = rtems_libio_iop( fd );
    48   rtems_libio_check_is_open( iop );
    49   rtems_libio_check_permissions_with_error( iop, LIBIO_FLAGS_READ, EBADF );
     42  total = rtems_libio_iovec_eval( fd, iov, iovcnt, LIBIO_FLAGS_READ, &iop );
    5043
    51   /*
    52    *  Argument validation on IO vector
    53    */
    54   if ( !iov )
    55     rtems_set_errno_and_return_minus_one( EINVAL );
     44  if ( total > 0 ) {
     45    /*
     46     *  Now process the readv().
     47     */
     48    total = 0;
     49    for ( v = 0 ; v < iovcnt ; v++ ) {
     50      ssize_t bytes = ( *iop->pathinfo.handlers->read_h )(
     51        iop,
     52        iov[ v ].iov_base,
     53        iov[ v ].iov_len
     54      );
    5655
    57   if ( iovcnt <= 0 )
    58     rtems_set_errno_and_return_minus_one( EINVAL );
     56      if ( bytes < 0 )
     57        return -1;
    5958
    60   if ( iovcnt > IOV_MAX )
    61     rtems_set_errno_and_return_minus_one( EINVAL );
     59      total += bytes;
    6260
    63   /*
    64    *  OpenGroup says that you are supposed to return EINVAL if the
    65    *  sum of the iov_len values in the iov array would overflow a
    66    *  ssize_t.
    67    *
    68    *  Also we would like to ensure that no IO is performed if there
    69    *  are obvious errors in the iovec.  So this extra loop ensures
    70    *  that we do not do anything if there is an argument error.
    71    */
    72 
    73   all_zeros = true;
    74   for ( total=0, v=0 ; v < iovcnt ; v++ ) {
    75     ssize_t old;
    76 
    77     /*
    78      *  iov[v].iov_len cannot be less than 0 because size_t is unsigned.
    79      *  So we only check for zero.
    80      */
    81     if ( iov[v].iov_base == 0 )
    82       rtems_set_errno_and_return_minus_one( EINVAL );
    83 
    84     /* check for wrap */
    85     old    = total;
    86     total += iov[v].iov_len;
    87     if ( total < old )
    88       rtems_set_errno_and_return_minus_one( EINVAL );
    89 
    90     if ( iov[v].iov_len )
    91       all_zeros = false;
    92   }
    93 
    94   /*
    95    *  A readv with all zeros logically has no effect.  Even though
    96    *  OpenGroup didn't address this case as they did with writev(),
    97    *  we will handle it the same way for symmetry.
    98    */
    99   if ( all_zeros == true ) {
    100     return 0;
    101   }
    102 
    103   /*
    104    *  Now process the readv().
    105    */
    106   for ( total=0, v=0 ; v < iovcnt ; v++ ) {
    107     bytes = (*iop->pathinfo.handlers->read_h)(
    108       iop,
    109       iov[v].iov_base,
    110       iov[v].iov_len
    111     );
    112 
    113     if ( bytes < 0 )
    114       return -1;
    115 
    116     if ( bytes > 0 ) {
    117       total       += bytes;
     61      if ( bytes != iov[ v ].iov_len )
     62        break;
    11863    }
    119 
    120     if (bytes != iov[ v ].iov_len)
    121       break;
    12264  }
    12365
  • cpukit/libcsupport/src/writev.c

    r7b10f130 r95a57280  
    11/*
    2  *  writev() - POSIX 1003.1 - Read a Vector
     2 *  writev() - POSIX 1003.1 - Write a Vector
    33 *
    44 *  OpenGroup URL:
     
    1818#endif
    1919
    20 #include <sys/types.h>
    2120#include <sys/uio.h>
    2221
    2322#include <rtems/libio_.h>
    24 #include <rtems/seterr.h>
    2523
    2624ssize_t writev(
     
    3230  ssize_t        total;
    3331  int            v;
    34   int            bytes;
    3532  rtems_libio_t *iop;
    36   ssize_t        old;
    37   bool           all_zeros;
    3833
    39   rtems_libio_check_fd( fd );
    40   iop = rtems_libio_iop( fd );
    41   rtems_libio_check_is_open( iop );
    42   rtems_libio_check_permissions_with_error( iop, LIBIO_FLAGS_WRITE, EBADF );
     34  total = rtems_libio_iovec_eval( fd, iov, iovcnt, LIBIO_FLAGS_WRITE, &iop );
    4335
    44   /*
    45    *  Argument validation on IO vector
    46    */
    47   if ( !iov )
    48     rtems_set_errno_and_return_minus_one( EINVAL );
     36  if ( total > 0 ) {
     37    /*
     38     *  Now process the writev().
     39     */
     40    total = 0;
     41    for ( v = 0 ; v < iovcnt ; v++ ) {
     42      ssize_t bytes = ( *iop->pathinfo.handlers->write_h )(
     43        iop,
     44        iov[ v ].iov_base,
     45        iov[ v ].iov_len
     46      );
    4947
    50   if ( iovcnt <= 0 )
    51     rtems_set_errno_and_return_minus_one( EINVAL );
     48      if ( bytes < 0 )
     49        return -1;
    5250
    53   if ( iovcnt > IOV_MAX )
    54     rtems_set_errno_and_return_minus_one( EINVAL );
     51      total += bytes;
    5552
    56   /*
    57    *  OpenGroup says that you are supposed to return EINVAL if the
    58    *  sum of the iov_len values in the iov array would overflow a
    59    *  ssize_t.
    60    *
    61    *  Also we would like to ensure that no IO is performed if there
    62    *  are obvious errors in the iovec.  So this extra loop ensures
    63    *  that we do not do anything if there is an argument error.
    64    *
    65    *  In addition,the OpenGroup specification says that if all the
    66    *  iov_len entries are zero, then the call has no effect.  So
    67    *  this loop does that check as well and sets "all-zero" appropriately.
    68    *  The variable "all_zero" is used as an early exit point before
    69    *  entering the write loop.
    70    */
    71   all_zeros = true;
    72   for ( old=0, total=0, v=0 ; v < iovcnt ; v++ ) {
    73 
    74     /*
    75      *  iov[v].iov_len cannot be less than 0 because size_t is unsigned.
    76      *  So we only check for zero.
    77      */
    78     if ( iov[v].iov_base == 0 )
    79       rtems_set_errno_and_return_minus_one( EINVAL );
    80 
    81     if ( iov[v].iov_len )
    82       all_zeros = false;
    83 
    84     /* check for wrap */
    85     old    = total;
    86     total += iov[v].iov_len;
    87     if ( total < old || total > SSIZE_MAX )
    88       rtems_set_errno_and_return_minus_one( EINVAL );
    89   }
    90 
    91   /*
    92    * A writev with all zeros is supposed to have no effect per OpenGroup.
    93    */
    94   if ( all_zeros == true ) {
    95     return 0;
    96   }
    97 
    98   /*
    99    *  Now process the writev().
    100    */
    101   for ( total=0, v=0 ; v < iovcnt ; v++ ) {
    102     /* all zero lengths has no effect */
    103     if ( iov[v].iov_len == 0 )
    104       continue;
    105 
    106     bytes = (*iop->pathinfo.handlers->write_h)(
    107       iop,
    108       iov[v].iov_base,
    109       iov[v].iov_len
    110     );
    111 
    112     if ( bytes < 0 )
    113       return -1;
    114 
    115     if ( bytes > 0 ) {
    116       total       += bytes;
     53      if ( bytes != iov[ v ].iov_len )
     54        break;
    11755    }
    118 
    119     if (bytes != iov[ v ].iov_len)
    120       break;
    12156  }
    12257
    12358  return total;
    12459}
    125 
  • testsuites/psxtests/psxrdwrv/psxrdwrv.scn

    r7b10f130 r95a57280  
    44writev bad iovec pointer -- EINVAL
    55readv bad iovec pointer -- EINVAL
    6 readv bad iovcnt of 0 -- EINVAL
     6writev bad iovcnt of 0 -- EINVAL
    77readv bad iovcnt of 0 -- EINVAL
    88writev bad iovcnt negative -- EINVAL
     
    1111readv bad iov[i].iov_base -- EINVAL
    1212writev bad iov[i].iov_len < 0 -- EINVAL
    13 readv bad iov[i].iov_len = 0 -- EINVAL
     13readv bad iov[i].iov_len < 0 -- EINVAL
    1414writev iov_len total overflows -- EINVAL
    1515readv iov_len total overflows -- EINVAL
     16writev iov_len works with no effect -- OK
     17readv iov_len works with no effect -- OK
     18readv bad iovcnt of IOV_MAX + 1 -- EINVAL
     19writev bad iovcnt of IOV_MAX + 1 -- EINVAL
    1620File written using writev .. OK
    1721File read using readv .. OK
  • testsuites/psxtests/psxrdwrv/test.c

    r7b10f130 r95a57280  
    2828#include <string.h>
    2929#include <inttypes.h>
     30#include <limits.h>
    3031
    3132#include <stdio.h>
     
    218219  fd = fileno(fp);
    219220
     221#ifdef __rtems__
    220222  /* writev --  bad iovec pointer */
    221223  puts("writev bad iovec pointer -- EINVAL");
     
    237239
    238240  /* writev --  bad iovcnt 0 */
    239   puts("readv bad iovcnt of 0 -- EINVAL");
     241  puts("writev bad iovcnt of 0 -- EINVAL");
    240242  rc = writev(fd, vec, 0);
    241243  if ( (rc != -1) || (errno != EINVAL) ) {
     
    253255    return FALSE;
    254256  }
     257#endif /* __rtems__ */
    255258
    256259  /* writev --  bad iovcnt negative */
     
    272275  }
    273276
     277#ifdef __rtems__
    274278  /* writev --  bad iov[i].iov_base */
    275279  vec[0].iov_base = vec;
     
    297301    return FALSE;
    298302  }
     303#endif /* __rtems__ */
    299304
    300305  /*  writev --  bad iov[i].iov_len < 0 */
     
    311316  }
    312317
    313   /*  readv --  bad iov[i].iov_len = 0 */
     318  /*  readv --  bad iov[i].iov_len < 0 */
    314319  vec[0].iov_base = vec;
    315320  vec[0].iov_len = 100;
    316321  vec[1].iov_base = vec;
    317322  vec[1].iov_len = -1024;
    318   puts("readv bad iov[i].iov_len = 0 -- EINVAL");
     323  puts("readv bad iov[i].iov_len < 0 -- EINVAL");
    319324  rc = readv(fd, vec, 2);
    320325  if ( (rc != -1) || (errno != EINVAL) ) {
     
    344349  vec[1].iov_base = vec;
    345350  vec[1].iov_len = SIZE_MAX;
     351  vec[2].iov_base = vec;
     352  vec[2].iov_len = SIZE_MAX;
    346353  puts("readv iov_len total overflows -- EINVAL");
    347   rc = readv(fd, vec, 2);
     354  rc = readv(fd, vec, 3);
    348355  if ( (rc != -1) || (errno != EINVAL) ) {
    349356    printf( "read error 7: rc=%d %d=%s\n", rc, errno, strerror(errno) );
     
    377384    return FALSE;
    378385  }
     386
     387#ifdef __rtems__
     388  puts("readv bad iovcnt of IOV_MAX + 1 -- EINVAL");
     389  rc = readv(fd, vec, IOV_MAX + 1);
     390  if ( (rc != -1) || (errno != EINVAL) ) {
     391    printf( "readv error 9: %d=%s\n", errno, strerror(errno) );
     392    fclose(fp);
     393    return FALSE;
     394  }
     395
     396  puts("writev bad iovcnt of IOV_MAX + 1 -- EINVAL");
     397  rc = writev(fd, vec, IOV_MAX + 1);
     398  if ( (rc != -1) || (errno != EINVAL) ) {
     399    printf( "writev error 9: %d=%s\n", errno, strerror(errno) );
     400    fclose(fp);
     401    return FALSE;
     402  }
     403#endif /* __rtems__ */
    379404
    380405  fclose(fp);
Note: See TracChangeset for help on using the changeset viewer.