2 * Use vmsplice to fill some user memory into a pipe. vmsplice writes
3 * to stdout, so that must be a pipe.
12 #include <sys/types.h>
16 #define PAGE_SIZE 4096
17 #define PAGE_MASK (PAGE_SIZE - 1)
19 static int alloc_stack;
20 static int cross_page;
21 static int force_align;
25 int do_vmsplice(int fd, struct iovec *iov, unsigned long nr_vecs)
27 struct pollfd pfd = { .fd = fd, .events = POLLOUT, };
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.
36 if (poll(&pfd, 1, -1) < 0)
39 written = svmsplice(fd, iov, nr_vecs, gift ? SPLICE_F_GIFT : 0);
42 return error("vmsplice");
45 int this_len = iov->iov_len;
47 if (this_len > written)
50 iov->iov_len -= this_len;
63 static int usage(char *name)
65 fprintf(stderr, "%s [-s(tack)] [-c(ross page)] [-a(lign)] [-f(ull page)] [-g(ift)] | ...\n", name);
69 static int parse_options(int argc, char *argv[])
73 while ((c = getopt(argc, argv, "scafg")) != -1) {
100 if (cross_page && force_align) {
101 fprintf(stderr, "Can't get both aligning and cross page spanning\n");
108 #define ASIZE (3 * PAGE_SIZE)
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 "
111 #define S3 "footer footer footer footer footer footer footer footer"
113 static void check_address(void *addr, void *start, void *end, int len,char *msg)
115 if (addr < start || (addr + len - 1) > end)
116 fprintf(stderr, "%s: bad: %p < %p < %p false\n", msg, start, addr, end);
119 int main(int argc, char *argv[])
121 struct iovec vecs[3];
122 char stack1[ASIZE], stack2[ASIZE], stack3[ASIZE];
123 char *h_s, *h_e, *b_s, *b_e, *f_s, *f_e;
126 if (check_output_pipe())
127 return usage(argv[0]);
129 if (parse_options(argc, argv) < 0)
130 return usage(argv[0]);
147 h_e = h_s + 2 * PAGE_SIZE - 1;
149 b_e = b_s + 2 * PAGE_SIZE - 1;
151 f_e = f_s + 2 * PAGE_SIZE - 1;
153 if (force_align || cross_page) {
154 /* align forward to start of 2nd page */
157 off = PAGE_SIZE - ((unsigned long) h & PAGE_MASK);
159 off = PAGE_SIZE - ((unsigned long) b & PAGE_MASK);
161 off = PAGE_SIZE - ((unsigned long) f & PAGE_MASK);
164 /* this puts half the string in both pages */
175 vecs[0].iov_base = h;
176 vecs[1].iov_base = b;
177 vecs[2].iov_base = f;
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);
183 vecs[0].iov_len = PAGE_SIZE;
184 vecs[1].iov_len = PAGE_SIZE;
185 vecs[2].iov_len = PAGE_SIZE;
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");
192 return do_vmsplice(STDOUT_FILENO, vecs, 3);