some coverity fixes.
[minix.git] / lib / libc / sys-minix / vectorio.c
blob6a7fcf4361676afbdff2868a3cf3ac35ba54d72d
1 #include <sys/cdefs.h>
2 #include <lib.h>
3 #include "namespace.h"
5 #include <assert.h>
6 #include <errno.h>
7 #include <limits.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <sys/stat.h>
11 #include <sys/param.h>
12 #include <sys/uio.h>
13 #include <unistd.h>
15 #define VECTORIO_READ 1
16 #define VECTORIO_WRITE 2
18 #ifdef __weak_alias
19 __weak_alias(writev, _writev)
20 __weak_alias(readv, _readv)
21 #endif
23 static ssize_t vectorio_buffer(int fildes, const struct iovec *iov,
24 int iovcnt, int readwrite, ssize_t totallen)
26 char *buffer;
27 int iovidx, errno_saved;
28 ssize_t copied, len, r;
30 /* allocate buffer */
31 buffer = (char *) malloc(totallen);
32 if (!buffer)
33 return -1;
35 /* perform the actual read/write for the entire buffer */
36 switch (readwrite)
38 case VECTORIO_READ:
39 /* first read, then copy buffers (only part read) */
40 r = read(fildes, buffer, totallen);
42 copied = 0;
43 iovidx = 0;
44 while (copied < r)
46 assert(iovidx < iovcnt);
47 len = MIN(r - copied, iov[iovidx].iov_len);
48 memcpy(iov[iovidx++].iov_base, buffer + copied, len);
49 copied += len;
51 assert(r < 0 || r == copied);
52 break;
54 case VECTORIO_WRITE:
55 /* first copy buffers, then write */
56 copied = 0;
57 for (iovidx = 0; iovidx < iovcnt; iovidx++)
59 memcpy(buffer + copied, iov[iovidx].iov_base,
60 iov[iovidx].iov_len);
61 copied += iov[iovidx].iov_len;
63 assert(copied == totallen);
65 r = write(fildes, buffer, totallen);
66 break;
68 default:
69 assert(0);
70 errno = EINVAL;
71 r = -1;
74 /* free the buffer, keeping errno unchanged */
75 errno_saved = errno;
76 free(buffer);
77 errno = errno_saved;
79 return r;
82 static ssize_t vectorio(int fildes, const struct iovec *iov,
83 int iovcnt, int readwrite)
85 int i;
86 ssize_t totallen;
88 /* parameter sanity checks */
89 if (iovcnt > IOV_MAX)
91 errno = EINVAL;
92 return -1;
95 totallen = 0;
96 for (i = 0; i < iovcnt; i++)
98 /* don't read/write anything in case of possible overflow */
99 if ((ssize_t) (totallen + iov[i].iov_len) < totallen)
101 errno = EINVAL;
102 return -1;
104 totallen += iov[i].iov_len;
106 /* report on NULL pointers */
107 if (iov[i].iov_len && !iov[i].iov_base)
109 errno = EFAULT;
110 return -1;
114 /* anything to do? */
115 if (totallen == 0)
116 return 0;
119 * there aught to be a system call here; instead we use an intermediate
120 * buffer; this is preferred over multiple read/write calls because
121 * this function has to be atomic
123 return vectorio_buffer(fildes, iov, iovcnt, readwrite, totallen);
126 ssize_t readv(int fildes, const struct iovec *iov, int iovcnt)
128 return vectorio(fildes, iov, iovcnt, VECTORIO_READ);
131 ssize_t writev(int fildes, const struct iovec *iov, int iovcnt)
133 return vectorio(fildes, iov, iovcnt, VECTORIO_WRITE);