Add write_data_iov
authorVolker Lendecke <vl@samba.org>
Mon, 22 Dec 2008 21:17:28 +0000 (22:17 +0100)
committerVolker Lendecke <vl@samba.org>
Mon, 29 Dec 2008 12:24:27 +0000 (13:24 +0100)
source3/include/proto.h
source3/lib/util_sock.c

index f1be1874bf4dce412f6781da707cf1f846480b72..08260517ff0f702c8d605e5aafc9ee74a1983297 100644 (file)
@@ -1441,6 +1441,7 @@ NTSTATUS read_socket_with_timeout(int fd, char *buf,
                                  size_t *size_ret);
 NTSTATUS read_data(int fd, char *buffer, size_t N);
 ssize_t write_data(int fd, const char *buffer, size_t N);
+ssize_t write_data_iov(int fd, const struct iovec *orig_iov, int iovcnt);
 bool send_keepalive(int client);
 NTSTATUS read_smb_length_return_keepalive(int fd, char *inbuf,
                                          unsigned int timeout,
index 7fe8ed82a21b82ecca5205c4bd060d396b14f844..a362938fd3bd22112c21efba1fb825d645c4f8da 100644 (file)
@@ -634,6 +634,75 @@ NTSTATUS read_data(int fd, char *buffer, size_t N)
        return read_socket_with_timeout(fd, buffer, N, N, 0, NULL);
 }
 
+/****************************************************************************
+ Write all data from an iov array
+****************************************************************************/
+
+ssize_t write_data_iov(int fd, const struct iovec *orig_iov, int iovcnt)
+{
+       int i;
+       size_t to_send;
+       ssize_t thistime;
+       size_t sent;
+       struct iovec *iov_copy, *iov;
+
+       to_send = 0;
+       for (i=0; i<iovcnt; i++) {
+               to_send += orig_iov[i].iov_len;
+       }
+
+       thistime = sys_writev(fd, orig_iov, iovcnt);
+       if ((thistime <= 0) || (thistime == to_send)) {
+               return thistime;
+       }
+       sent = thistime;
+
+       /*
+        * We could not send everything in one call. Make a copy of iov that
+        * we can mess with. We keep a copy of the array start in iov_copy for
+        * the TALLOC_FREE, because we're going to modify iov later on,
+        * discarding elements.
+        */
+
+       iov_copy = (struct iovec *)TALLOC_MEMDUP(
+               talloc_tos(), orig_iov, sizeof(struct iovec) * iovcnt);
+
+       if (iov_copy == NULL) {
+               errno = ENOMEM;
+               return -1;
+       }
+       iov = iov_copy;
+
+       while (sent < to_send) {
+               /*
+                * We have to discard "thistime" bytes from the beginning
+                * iov array, "thistime" contains the number of bytes sent
+                * via writev last.
+                */
+               while (thistime > 0) {
+                       if (thistime < iov[0].iov_len) {
+                               char *new_base =
+                                       (char *)iov[0].iov_base + thistime;
+                               iov[0].iov_base = new_base;
+                               iov[0].iov_len -= thistime;
+                               break;
+                       }
+                       thistime -= iov[0].iov_len;
+                       iov += 1;
+                       iovcnt -= 1;
+               }
+
+               thistime = sys_writev(fd, iov, iovcnt);
+               if (thistime <= 0) {
+                       break;
+               }
+               sent += thistime;
+       }
+
+       TALLOC_FREE(iov_copy);
+       return sent;
+}
+
 /****************************************************************************
  Write data to a fd.
 ****************************************************************************/