Fix various compile warnings
[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>
0a6ff83b 11#include <fcntl.h>
7ee0f27f 12#include <sys/poll.h>
7ee0f27f
JA
13#include <sys/types.h>
14
15#include "splice.h"
16
88a9ff87 17#define ALIGN(buf) (void *) (((unsigned long) (buf) + align_mask) & ~align_mask)
7ee0f27f 18
dbcd0883 19static int do_clear;
88a9ff87 20static int align_mask = 65535;
96897528
JA
21static int force_unalign;
22static int splice_flags;
dbcd0883 23
88a9ff87 24int do_vmsplice(int fd, void *b1, void *b2, int len)
7ee0f27f
JA
25{
26 struct pollfd pfd = { .fd = fd, .events = POLLOUT, };
88a9ff87
JA
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;
7ee0f27f
JA
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
13b72067 48 written = svmsplice(fd, &iov[idx], 2 - idx, splice_flags);
7ee0f27f
JA
49
50 if (written <= 0)
51 return error("vmsplice");
52
53 len -= written;
000b72a8 54 if ((size_t) written >= iov[idx].iov_len) {
88a9ff87
JA
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 }
7ee0f27f
JA
64 }
65
66 return 0;
67}
68
dbcd0883
JA
69static int usage(char *name)
70{
96897528 71 fprintf(stderr, "%s: [-c(lear)] [-u(nalign)] [-g(ift)]| ...\n", name);
dbcd0883
JA
72 return 1;
73}
74
75static int parse_options(int argc, char *argv[])
76{
77 int c, index = 1;
78
96897528 79 while ((c = getopt(argc, argv, "cug")) != -1) {
dbcd0883
JA
80 switch (c) {
81 case 'c':
82 do_clear = 1;
83 index++;
84 break;
88a9ff87 85 case 'u':
96897528
JA
86 force_unalign = 1;
87 index++;
88 break;
89 case 'g':
90 splice_flags = SPLICE_F_GIFT;
88a9ff87
JA
91 index++;
92 break;
dbcd0883
JA
93 default:
94 return -1;
95 }
96 }
97
98 return index;
99}
100
7ee0f27f
JA
101int main(int argc, char *argv[])
102{
88a9ff87 103 unsigned char *b1, *b2;
7ee0f27f 104
dbcd0883
JA
105 if (parse_options(argc, argv) < 0)
106 return usage(argv[0]);
107
76797253 108 if (check_output_pipe())
f91353a3 109 return usage(argv[0]);
7ee0f27f 110
88a9ff87
JA
111 b1 = ALIGN(malloc(SPLICE_SIZE + align_mask));
112 b2 = ALIGN(malloc(SPLICE_SIZE + align_mask));
113
96897528
JA
114 if (force_unalign) {
115 b1 += 1024;
116 b2 += 1024;
117 }
118
88a9ff87
JA
119 memset(b1, 0xaa, SPLICE_SIZE);
120 memset(b2, 0xbb, SPLICE_SIZE);
7ee0f27f
JA
121
122 do {
88a9ff87
JA
123 int half = SPLICE_SIZE / 2;
124
7ee0f27f
JA
125 /*
126 * vmsplice the first half of the buffer into the pipe
127 */
88a9ff87 128 if (do_vmsplice(STDOUT_FILENO, b1, b2, SPLICE_SIZE))
7ee0f27f
JA
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 */
88a9ff87 139 if (do_vmsplice(STDOUT_FILENO, b1 + half, b2 + half, SPLICE_SIZE))
7ee0f27f
JA
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 */
dbcd0883
JA
147
148 /*
149 * Test option - clear the first half of the buffer, should
150 * be safe now
151 */
88a9ff87
JA
152 if (do_clear) {
153 memset(b1, 0x00, SPLICE_SIZE);
154 memset(b2, 0x00, SPLICE_SIZE);
155 }
7ee0f27f
JA
156 } while (0);
157
158 return 0;
159}