Fix various compile warnings
[splice.git] / vmsplice.c
index be775346cf4cd28db74b00d7062586e386fda16d..2cfe6b29b1e544b609aec6b4d27a34320043fa7e 100644 (file)
@@ -5,28 +5,36 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
-#include <fcntl.h>
 #include <limits.h>
+#include <string.h>
+#include <getopt.h>
+#include <fcntl.h>
 #include <sys/poll.h>
-#include <sys/stat.h>
 #include <sys/types.h>
 
 #include "splice.h"
 
-#define ALIGN_BUF
+#define ALIGN(buf)     (void *) (((unsigned long) (buf) + align_mask) & ~align_mask)
 
-#ifdef ALIGN_BUF
-#define ALIGN_MASK     (65535) /* 64k-1, should just be PAGE_SIZE - 1 */
-#define ALIGN(buf)     (void *) (((unsigned long) (buf) + ALIGN_MASK) & ~ALIGN_MASK)
-#else
-#define ALIGN_MASK     (0)
-#define ALIGN(buf)     (buf)
-#endif
+static int do_clear;
+static int align_mask = 65535;
+static int force_unalign;
+static int splice_flags;
 
-int do_vmsplice(int fd, void *buffer, int len)
+int do_vmsplice(int fd, void *b1, void *b2, int len)
 {
        struct pollfd pfd = { .fd = fd, .events = POLLOUT, };
-       int written;
+       struct iovec iov[] = {
+               {
+                       .iov_base = b1,
+                       .iov_len = len / 2,
+               },
+               {
+                       .iov_base = b2,
+                       .iov_len = len / 2,
+               },
+       };
+       int written, idx = 0;
 
        while (len) {
                /*
@@ -37,50 +45,87 @@ int do_vmsplice(int fd, void *buffer, int len)
                if (poll(&pfd, 1, -1) < 0)
                        return error("poll");
 
-               written = vmsplice(fd, buffer, min(SPLICE_SIZE, len), 0);
+               written = svmsplice(fd, &iov[idx], 2 - idx, splice_flags);
 
                if (written <= 0)
                        return error("vmsplice");
 
                len -= written;
+               if ((size_t) written >= iov[idx].iov_len) {
+                       int extra = written - iov[idx].iov_len;
+
+                       idx++;
+                       iov[idx].iov_len -= extra;
+                       iov[idx].iov_base += extra;
+               } else {
+                       iov[idx].iov_len -= written;
+                       iov[idx].iov_base += written;
+               }
        }
 
        return 0;
 }
 
-int main(int argc, char *argv[])
+static int usage(char *name)
+{
+       fprintf(stderr, "%s: [-c(lear)] [-u(nalign)] [-g(ift)]| ...\n", name);
+       return 1;
+}
+
+static int parse_options(int argc, char *argv[])
 {
-       unsigned char *buffer;
-       struct stat sb;
-       long page_size;
-       int i, ret;
-
-       if (fstat(STDOUT_FILENO, &sb) < 0)
-               return error("stat");
-       if (!S_ISFIFO(sb.st_mode)) {
-               fprintf(stderr, "stdout must be a pipe\n");
-               return 1;
+       int c, index = 1;
+
+       while ((c = getopt(argc, argv, "cug")) != -1) {
+               switch (c) {
+               case 'c':
+                       do_clear = 1;
+                       index++;
+                       break;
+               case 'u':
+                       force_unalign = 1;
+                       index++;
+                       break;
+               case 'g':
+                       splice_flags = SPLICE_F_GIFT;
+                       index++;
+                       break;
+               default:
+                       return -1;
+               }
        }
 
-       ret = fcntl(STDOUT_FILENO, F_GETPSZ);
-       if (ret < 0)
-               return error("F_GETPSZ");
+       return index;
+}
 
-       page_size = sysconf(_SC_PAGESIZE);
-       if (page_size < 0)
-               return error("_SC_PAGESIZE");
+int main(int argc, char *argv[])
+{
+       unsigned char *b1, *b2;
+
+       if (parse_options(argc, argv) < 0)
+               return usage(argv[0]);
+
+       if (check_output_pipe())
+               return usage(argv[0]);
+
+       b1 = ALIGN(malloc(SPLICE_SIZE + align_mask));
+       b2 = ALIGN(malloc(SPLICE_SIZE + align_mask));
 
-       fprintf(stderr, "Pipe size: %d pages / %ld bytes\n", ret, ret * page_size);
+       if (force_unalign) {
+               b1 += 1024;
+               b2 += 1024;
+       }
 
-       buffer = ALIGN(malloc(2 * SPLICE_SIZE + ALIGN_MASK));
-       for (i = 0; i < 2 * SPLICE_SIZE; i++)
-               buffer[i] = (i & 0xff);
+       memset(b1, 0xaa, SPLICE_SIZE);
+       memset(b2, 0xbb, SPLICE_SIZE);
 
        do {
+               int half = SPLICE_SIZE / 2;
+
                /*
                 * vmsplice the first half of the buffer into the pipe
                 */
-               if (do_vmsplice(STDOUT_FILENO, buffer, SPLICE_SIZE))
+               if (do_vmsplice(STDOUT_FILENO, b1, b2, SPLICE_SIZE))
                        break;
 
                /*
@@ -91,7 +136,7 @@ int main(int argc, char *argv[])
                /*
                 * vmsplice second half
                 */
-               if (do_vmsplice(STDOUT_FILENO, buffer + SPLICE_SIZE, SPLICE_SIZE))
+               if (do_vmsplice(STDOUT_FILENO, b1 + half, b2 + half, SPLICE_SIZE))
                        break;
 
                /*
@@ -99,6 +144,15 @@ int main(int argc, char *argv[])
                 * the buffer, but we do now know that all parts of the first
                 * half have been consumed from the pipe - so we can reuse that.
                 */
+
+               /*
+                * Test option - clear the first half of the buffer, should
+                * be safe now
+                */
+               if (do_clear) {
+                       memset(b1, 0x00, SPLICE_SIZE);
+                       memset(b2, 0x00, SPLICE_SIZE);
+               }
        } while (0);
 
        return 0;