source: rtems/cpukit/libcsupport/src/writev.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.9 KB
Line 
1/*
2 *  writev() - POSIX 1003.1 - Read a Vector
3 *
4 *  OpenGroup URL:
5 *
6 *  http://www.opengroup.org/onlinepubs/009695399/functions/writev.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 writev(
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  ssize_t        old;
37  bool           all_zeros;
38
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 );
43
44  /*
45   *  Argument validation on IO vector
46   */
47  if ( !iov )
48    rtems_set_errno_and_return_minus_one( EINVAL );
49
50  if ( iovcnt <= 0 )
51    rtems_set_errno_and_return_minus_one( EINVAL );
52
53  if ( iovcnt > IOV_MAX )
54    rtems_set_errno_and_return_minus_one( EINVAL );
55
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;
117    }
118
119    if (bytes != iov[ v ].iov_len)
120      break;
121  }
122
123  return total;
124}
125
Note: See TracBrowser for help on using the repository browser.