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