X-Git-Url: https://git.kernel.dk/?a=blobdiff_plain;f=vmsplice.c;h=2cfe6b29b1e544b609aec6b4d27a34320043fa7e;hb=refs%2Fheads%2Fmaster;hp=7a037b1b4862ef612d29811685c27765f5ba899a;hpb=15b01c16c2c7a8f6f95cf5cd058d4a764de48f34;p=splice.git diff --git a/vmsplice.c b/vmsplice.c index 7a037b1..2cfe6b2 100644 --- a/vmsplice.c +++ b/vmsplice.c @@ -8,35 +8,35 @@ #include #include #include +#include #include -#include #include #include "splice.h" -#define ALIGN_BUF - -#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 +#define ALIGN(buf) (void *) (((unsigned long) (buf) + align_mask) & ~align_mask) 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) { - struct iovec iov = { - .iov_base = buffer, - .iov_len = min(SPLICE_SIZE, len), - }; - /* * in a real app you'd be more clever with poll of course, * here we are basically just blocking on output room and @@ -45,13 +45,22 @@ int do_vmsplice(int fd, void *buffer, int len) if (poll(&pfd, 1, -1) < 0) return error("poll"); - written = vmsplice(fd, &iov, 1, 0); + written = svmsplice(fd, &iov[idx], 2 - idx, splice_flags); if (written <= 0) return error("vmsplice"); len -= written; - buffer += 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; @@ -59,7 +68,7 @@ int do_vmsplice(int fd, void *buffer, int len) static int usage(char *name) { - fprintf(stderr, "%s: [-c]\n", name); + fprintf(stderr, "%s: [-c(lear)] [-u(nalign)] [-g(ift)]| ...\n", name); return 1; } @@ -67,12 +76,20 @@ static int parse_options(int argc, char *argv[]) { int c, index = 1; - while ((c = getopt(argc, argv, "c")) != -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; } @@ -83,29 +100,32 @@ static int parse_options(int argc, char *argv[]) int main(int argc, char *argv[]) { - unsigned char *buffer; - struct stat sb; - int i; + unsigned char *b1, *b2; if (parse_options(argc, argv) < 0) return usage(argv[0]); - 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; + if (check_output_pipe()) + return usage(argv[0]); + + b1 = ALIGN(malloc(SPLICE_SIZE + align_mask)); + b2 = ALIGN(malloc(SPLICE_SIZE + align_mask)); + + 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; /* @@ -116,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; /* @@ -129,9 +149,10 @@ int main(int argc, char *argv[]) * Test option - clear the first half of the buffer, should * be safe now */ - if (do_clear) - memset(buffer, 0x00, SPLICE_SIZE); - + if (do_clear) { + memset(b1, 0x00, SPLICE_SIZE); + memset(b2, 0x00, SPLICE_SIZE); + } } while (0); return 0;