source: rtems/cpukit/libcsupport/src/readv.c @ 53da07e

4.11
Last change on this file since 53da07e was 53da07e, checked in by Sebastian Huber <sebastian.huber@…>, on May 14, 2012 at 1:21:30 PM

Filesystem: PR1255: Move offset update to handlers

It is now the responsibility of the read() and write() handler to update
the offset field of the IO descriptor (rtems_libio_t). This change
makes it possible to protect the IO descriptor from concurrent access by
per file locks.

  • Property mode set to 100644
File size: 2.6 KB
Line 
1/*
2 *  readv() - POSIX 1003.1 - Read a Vector
3 *
4 *  OpenGroup URL:
5 *
6 *  http://www.opengroup.org/onlinepubs/009695399/functions/readv.html
7 *
8 *  COPYRIGHT (c) 1989-2011.
9 *  On-Line Applications Research Corporation (OAR).
10 *
11 *  The license and distribution terms for this file may be
12 *  found in the file LICENSE in this distribution or at
13 *  http://www.rtems.com/license/LICENSE.
14 */
15
16#if HAVE_CONFIG_H
17#include "config.h"
18#endif
19
20#include <sys/types.h>
21#include <sys/uio.h>
22
23#include <rtems/libio_.h>
24#include <rtems/seterr.h>
25
26ssize_t readv(
27  int                 fd,
28  const struct iovec *iov,
29  int                 iovcnt
30)
31{
32  ssize_t        total;
33  int            v;
34  int            bytes;
35  rtems_libio_t *iop;
36  bool           all_zeros;
37
38  rtems_libio_check_fd( fd );
39  iop = rtems_libio_iop( fd );
40  rtems_libio_check_is_open( iop );
41  rtems_libio_check_permissions_with_error( iop, LIBIO_FLAGS_READ, EBADF );
42
43  /*
44   *  Argument validation on IO vector
45   */
46  if ( !iov )
47    rtems_set_errno_and_return_minus_one( EINVAL );
48
49  if ( iovcnt <= 0 )
50    rtems_set_errno_and_return_minus_one( EINVAL );
51
52  if ( iovcnt > IOV_MAX )
53    rtems_set_errno_and_return_minus_one( EINVAL );
54
55  /*
56   *  OpenGroup says that you are supposed to return EINVAL if the
57   *  sum of the iov_len values in the iov array would overflow a
58   *  ssize_t.
59   *
60   *  Also we would like to ensure that no IO is performed if there
61   *  are obvious errors in the iovec.  So this extra loop ensures
62   *  that we do not do anything if there is an argument error.
63   */
64
65  all_zeros = true;
66  for ( total=0, v=0 ; v < iovcnt ; v++ ) {
67    ssize_t old;
68
69    /*
70     *  iov[v].iov_len cannot be less than 0 because size_t is unsigned.
71     *  So we only check for zero.
72     */
73    if ( iov[v].iov_base == 0 )
74      rtems_set_errno_and_return_minus_one( EINVAL );
75
76    /* check for wrap */
77    old    = total;
78    total += iov[v].iov_len;
79    if ( total < old )
80      rtems_set_errno_and_return_minus_one( EINVAL );
81
82    if ( iov[v].iov_len )
83      all_zeros = false;
84  }
85
86  /*
87   *  A readv with all zeros logically has no effect.  Even though
88   *  OpenGroup didn't address this case as they did with writev(),
89   *  we will handle it the same way for symmetry.
90   */
91  if ( all_zeros == true ) {
92    return 0;
93  }
94
95  /*
96   *  Now process the readv().
97   */
98  for ( total=0, v=0 ; v < iovcnt ; v++ ) {
99    bytes = (*iop->pathinfo.handlers->read_h)(
100      iop,
101      iov[v].iov_base,
102      iov[v].iov_len
103    );
104
105    if ( bytes < 0 )
106      return -1;
107
108    if ( bytes > 0 ) {
109      total       += bytes;
110    }
111
112    if (bytes != iov[ v ].iov_len)
113      break;
114  }
115
116  return total;
117}
Note: See TracBrowser for help on using the repository browser.