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)
18 #define ALIGN(buf) (void *) (((unsigned long) (buf) + PAGE_MASK) & ~PAGE_MASK)
20 static int alloc_stack;
21 static int cross_page;
23 int do_vmsplice(int fd, struct iovec *iov, unsigned long nr_vecs)
25 struct pollfd pfd = { .fd = fd, .events = POLLOUT, };
30 * in a real app you'd be more clever with poll of course,
31 * here we are basically just blocking on output room and
32 * not using the free time for anything interesting.
34 if (poll(&pfd, 1, -1) < 0)
37 written = vmsplice(fd, iov, nr_vecs, 0);
40 return error("vmsplice");
43 int this_len = iov->iov_len;
45 if (this_len > written)
48 iov->iov_len -= this_len;
61 static int usage(char *name)
63 fprintf(stderr, "%s [-s(tack)] [-c(ross page)]| ...\n", name);
67 static int parse_options(int argc, char *argv[])
71 while ((c = getopt(argc, argv, "sc")) != -1) {
86 if (alloc_stack && cross_page)
87 fprintf(stderr, "Stack alloc and cross page are mutually exclusive\n");
92 #define S1 "header header header header header header header header "
93 #define S2 "body body body body body body body body body body body "
94 #define S3 "footer footer footer footer footer footer footer footer"
96 int main(int argc, char *argv[])
101 if (parse_options(argc, argv) < 0)
102 return usage(argv[0]);
112 ptr = ALIGN(malloc(3 * PAGE_SIZE));
113 h = ptr + PAGE_SIZE - (strlen(S1) / 2);
116 ptr = ALIGN(malloc(3 * PAGE_SIZE));
117 b = ptr + PAGE_SIZE - (strlen(S2) / 2);
120 ptr = ALIGN(malloc(3 * PAGE_SIZE));
121 f = ptr + PAGE_SIZE - (strlen(S3) / 2);
130 vecs[0].iov_base = h;
131 vecs[1].iov_base = b;
132 vecs[2].iov_base = f;
133 vecs[0].iov_len = strlen(vecs[0].iov_base);
134 vecs[1].iov_len = strlen(vecs[1].iov_base);
135 vecs[2].iov_len = strlen(vecs[2].iov_base);
137 if (check_output_pipe())
138 return usage(argv[0]);
140 return do_vmsplice(STDOUT_FILENO, vecs, 3);