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 11:12:59 +0000 (12:12 +0100)
source/lib/util_sock.c

index e64b0036bfd4b1088873af68393c93257c2c9b80..c0e947b06cbb7f40a0881d5a4ee7683efad2130c 100644 (file)
@@ -1036,6 +1036,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.
 ****************************************************************************/