Fix various compile warnings
[splice.git] / vmsplice2.c
CommitLineData
648a7fef
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>
8#include <limits.h>
9#include <string.h>
10#include <getopt.h>
11#include <sys/poll.h>
12#include <sys/types.h>
13
14#include "splice.h"
15
257812cf
JA
16#define PAGE_SIZE 4096
17#define PAGE_MASK (PAGE_SIZE - 1)
257812cf 18
9649cd9b 19static int alloc_stack;
257812cf 20static int cross_page;
fa26bccb
JA
21static int force_align;
22static int full_page;
23static int gift;
9649cd9b 24
648a7fef
JA
25int do_vmsplice(int fd, struct iovec *iov, unsigned long nr_vecs)
26{
27 struct pollfd pfd = { .fd = fd, .events = POLLOUT, };
28 long written;
29
30 while (nr_vecs) {
31 /*
32 * in a real app you'd be more clever with poll of course,
33 * here we are basically just blocking on output room and
34 * not using the free time for anything interesting.
35 */
36 if (poll(&pfd, 1, -1) < 0)
37 return error("poll");
38
13b72067 39 written = svmsplice(fd, iov, nr_vecs, gift ? SPLICE_F_GIFT : 0);
648a7fef
JA
40
41 if (written <= 0)
42 return error("vmsplice");
43
44 while (written) {
45 int this_len = iov->iov_len;
46
47 if (this_len > written)
48 this_len = written;
49
50 iov->iov_len -= this_len;
51 if (!iov->iov_len) {
52 nr_vecs--;
53 iov++;
54 }
55
56 written -= this_len;
57 }
58 }
59
60 return 0;
61}
62
63static int usage(char *name)
64{
fa26bccb 65 fprintf(stderr, "%s [-s(tack)] [-c(ross page)] [-a(lign)] [-f(ull page)] [-g(ift)] | ...\n", name);
648a7fef
JA
66 return 1;
67}
68
9649cd9b
JA
69static int parse_options(int argc, char *argv[])
70{
71 int c, index = 1;
72
fa26bccb 73 while ((c = getopt(argc, argv, "scafg")) != -1) {
9649cd9b
JA
74 switch (c) {
75 case 's':
76 alloc_stack = 1;
77 index++;
78 break;
257812cf
JA
79 case 'c':
80 cross_page = 1;
81 index++;
82 break;
fa26bccb
JA
83 case 'a':
84 force_align = 1;
85 index++;
86 break;
87 case 'f':
88 full_page = 1;
89 index++;
90 break;
91 case 'g':
92 gift = 1;
93 index++;
94 break;
9649cd9b
JA
95 default:
96 return -1;
97 }
98 }
99
fa26bccb
JA
100 if (cross_page && force_align) {
101 fprintf(stderr, "Can't get both aligning and cross page spanning\n");
102 return -1;
103 }
257812cf 104
9649cd9b
JA
105 return index;
106}
107
fa26bccb 108#define ASIZE (3 * PAGE_SIZE)
238a8608
JA
109#define S1 "header header header header header header header header "
110#define S2 "body body body body body body body body body body body "
e346936e
JA
111#define S3 "footer footer footer footer footer footer footer footer"
112
fa26bccb
JA
113static void check_address(void *addr, void *start, void *end, int len,char *msg)
114{
115 if (addr < start || (addr + len - 1) > end)
116 fprintf(stderr, "%s: bad: %p < %p < %p false\n", msg, start, addr, end);
117}
118
648a7fef
JA
119int main(int argc, char *argv[])
120{
648a7fef 121 struct iovec vecs[3];
fa26bccb
JA
122 char stack1[ASIZE], stack2[ASIZE], stack3[ASIZE];
123 char *h_s, *h_e, *b_s, *b_e, *f_s, *f_e;
9649cd9b 124 char *h, *b, *f;
fa26bccb
JA
125
126 if (check_output_pipe())
127 return usage(argv[0]);
9649cd9b
JA
128
129 if (parse_options(argc, argv) < 0)
130 return usage(argv[0]);
131
132 if (alloc_stack) {
fa26bccb
JA
133 h = stack1;
134 b = stack2;
135 f = stack3;
9649cd9b 136 } else {
fa26bccb
JA
137 h = malloc(ASIZE);
138 b = malloc(ASIZE);
139 f = malloc(ASIZE);
140 }
141
142 memset(h, 0, ASIZE);
143 memset(b, 0, ASIZE);
144 memset(f, 0, ASIZE);
145
146 h_s = h;
147 h_e = h_s + 2 * PAGE_SIZE - 1;
148 b_s = b;
149 b_e = b_s + 2 * PAGE_SIZE - 1;
150 f_s = f;
151 f_e = f_s + 2 * PAGE_SIZE - 1;
152
153 if (force_align || cross_page) {
154 /* align forward to start of 2nd page */
155 unsigned long off;
156
157 off = PAGE_SIZE - ((unsigned long) h & PAGE_MASK);
158 h += off;
159 off = PAGE_SIZE - ((unsigned long) b & PAGE_MASK);
160 b += off;
161 off = PAGE_SIZE - ((unsigned long) f & PAGE_MASK);
162 f += off;
257812cf 163 if (cross_page) {
fa26bccb
JA
164 /* this puts half the string in both pages */
165 h -= strlen(S1) / 2;
166 b -= strlen(S2) / 2;
167 f -= strlen(S3) / 2;
257812cf 168 }
9649cd9b 169 }
648a7fef 170
fa26bccb
JA
171 strcpy(h, S1);
172 strcpy(b, S2);
173 strcpy(f, S3);
174
648a7fef 175 vecs[0].iov_base = h;
648a7fef 176 vecs[1].iov_base = b;
648a7fef 177 vecs[2].iov_base = f;
fa26bccb
JA
178 if (!full_page) {
179 vecs[0].iov_len = strlen(vecs[0].iov_base);
180 vecs[1].iov_len = strlen(vecs[1].iov_base);
181 vecs[2].iov_len = strlen(vecs[2].iov_base);
182 } else {
183 vecs[0].iov_len = PAGE_SIZE;
184 vecs[1].iov_len = PAGE_SIZE;
185 vecs[2].iov_len = PAGE_SIZE;
186 }
187
188 check_address(h, h_s, h_e, vecs[0].iov_len, "header");
189 check_address(b, b_s, b_e, vecs[1].iov_len, "body");
190 check_address(f, f_s, f_e, vecs[2].iov_len, "footer");
648a7fef
JA
191
192 return do_vmsplice(STDOUT_FILENO, vecs, 3);
193}