[PATCH] vmsplice2: warning fix
[splice.git] / vmsplice.c
CommitLineData
7ee0f27f
JA
1/*
2 * Use vmsplice to fill some user memory into a pipe. vmsplice writes
3 * to stdout, so that must be a pipe.
4 */
5#include <stdio.h>
6#include <stdlib.h>
7#include <unistd.h>
7ee0f27f 8#include <limits.h>
dbcd0883
JA
9#include <string.h>
10#include <getopt.h>
7ee0f27f 11#include <sys/poll.h>
7ee0f27f
JA
12#include <sys/types.h>
13
14#include "splice.h"
15
88a9ff87 16#define ALIGN(buf) (void *) (((unsigned long) (buf) + align_mask) & ~align_mask)
7ee0f27f 17
dbcd0883 18static int do_clear;
88a9ff87 19static int align_mask = 65535;
96897528
JA
20static int force_unalign;
21static int splice_flags;
dbcd0883 22
88a9ff87 23int do_vmsplice(int fd, void *b1, void *b2, int len)
7ee0f27f
JA
24{
25 struct pollfd pfd = { .fd = fd, .events = POLLOUT, };
88a9ff87
JA
26 struct iovec iov[] = {
27 {
28 .iov_base = b1,
29 .iov_len = len / 2,
30 },
31 {
32 .iov_base = b2,
33 .iov_len = len / 2,
34 },
35 };
36 int written, idx = 0;
7ee0f27f
JA
37
38 while (len) {
39 /*
40 * in a real app you'd be more clever with poll of course,
41 * here we are basically just blocking on output room and
42 * not using the free time for anything interesting.
43 */
44 if (poll(&pfd, 1, -1) < 0)
45 return error("poll");
46
96897528 47 written = vmsplice(fd, &iov[idx], 2 - idx, splice_flags);
7ee0f27f
JA
48
49 if (written <= 0)
50 return error("vmsplice");
51
52 len -= written;
88a9ff87
JA
53 if (written >= iov[idx].iov_len) {
54 int extra = written - iov[idx].iov_len;
55
56 idx++;
57 iov[idx].iov_len -= extra;
58 iov[idx].iov_base += extra;
59 } else {
60 iov[idx].iov_len -= written;
61 iov[idx].iov_base += written;
62 }
7ee0f27f
JA
63 }
64
65 return 0;
66}
67
dbcd0883
JA
68static int usage(char *name)
69{
96897528 70 fprintf(stderr, "%s: [-c(lear)] [-u(nalign)] [-g(ift)]| ...\n", name);
dbcd0883
JA
71 return 1;
72}
73
74static int parse_options(int argc, char *argv[])
75{
76 int c, index = 1;
77
96897528 78 while ((c = getopt(argc, argv, "cug")) != -1) {
dbcd0883
JA
79 switch (c) {
80 case 'c':
81 do_clear = 1;
82 index++;
83 break;
88a9ff87 84 case 'u':
96897528
JA
85 force_unalign = 1;
86 index++;
87 break;
88 case 'g':
89 splice_flags = SPLICE_F_GIFT;
88a9ff87
JA
90 index++;
91 break;
dbcd0883
JA
92 default:
93 return -1;
94 }
95 }
96
97 return index;
98}
99
7ee0f27f
JA
100int main(int argc, char *argv[])
101{
88a9ff87 102 unsigned char *b1, *b2;
7ee0f27f 103
dbcd0883
JA
104 if (parse_options(argc, argv) < 0)
105 return usage(argv[0]);
106
76797253 107 if (check_output_pipe())
f91353a3 108 return usage(argv[0]);
7ee0f27f 109
88a9ff87
JA
110 b1 = ALIGN(malloc(SPLICE_SIZE + align_mask));
111 b2 = ALIGN(malloc(SPLICE_SIZE + align_mask));
112
96897528
JA
113 if (force_unalign) {
114 b1 += 1024;
115 b2 += 1024;
116 }
117
88a9ff87
JA
118 memset(b1, 0xaa, SPLICE_SIZE);
119 memset(b2, 0xbb, SPLICE_SIZE);
7ee0f27f
JA
120
121 do {
88a9ff87
JA
122 int half = SPLICE_SIZE / 2;
123
7ee0f27f
JA
124 /*
125 * vmsplice the first half of the buffer into the pipe
126 */
88a9ff87 127 if (do_vmsplice(STDOUT_FILENO, b1, b2, SPLICE_SIZE))
7ee0f27f
JA
128 break;
129
130 /*
131 * first half is now in pipe, but we don't quite know when
132 * we can reuse it.
133 */
134
135 /*
136 * vmsplice second half
137 */
88a9ff87 138 if (do_vmsplice(STDOUT_FILENO, b1 + half, b2 + half, SPLICE_SIZE))
7ee0f27f
JA
139 break;
140
141 /*
142 * We still don't know when we can reuse the second half of
143 * the buffer, but we do now know that all parts of the first
144 * half have been consumed from the pipe - so we can reuse that.
145 */
dbcd0883
JA
146
147 /*
148 * Test option - clear the first half of the buffer, should
149 * be safe now
150 */
88a9ff87
JA
151 if (do_clear) {
152 memset(b1, 0x00, SPLICE_SIZE);
153 memset(b2, 0x00, SPLICE_SIZE);
154 }
7ee0f27f
JA
155 } while (0);
156
157 return 0;
158}