[PATCH] vmsplice2: don't allocate memory on stack
[splice.git] / vmsplice2.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 <sys/poll.h>
12 #include <sys/types.h>
13
14 #include "splice.h"
15
16 int do_vmsplice(int fd, struct iovec *iov, unsigned long nr_vecs)
17 {
18         struct pollfd pfd = { .fd = fd, .events = POLLOUT, };
19         long written;
20
21         while (nr_vecs) {
22                 /*
23                  * in a real app you'd be more clever with poll of course,
24                  * here we are basically just blocking on output room and
25                  * not using the free time for anything interesting.
26                  */
27                 if (poll(&pfd, 1, -1) < 0)
28                         return error("poll");
29
30                 written = vmsplice(fd, iov, nr_vecs, 0);
31
32                 if (written <= 0)
33                         return error("vmsplice");
34
35                 while (written) {
36                         int this_len = iov->iov_len;
37
38                         if (this_len > written)
39                                 this_len = written;
40
41                         iov->iov_len -= this_len;
42                         if (!iov->iov_len) {
43                                 nr_vecs--;
44                                 iov++;
45                         }
46
47                         written -= this_len;
48                 }
49         }
50
51         return 0;
52 }
53
54 static int usage(char *name)
55 {
56         fprintf(stderr, "%s | ...\n", name);
57         return 1;
58 }
59
60 #define S1      "header header header header header header header header"
61 #define S2      "body body body body body body body body body body body"
62 #define S3      "footer footer footer footer footer footer footer footer"
63
64 int main(int argc, char *argv[])
65 {
66         struct iovec vecs[3];
67 #if 0
68         /* Dangerous on-stack usage! */
69         char h[] = S1;
70         char b[] = S2;
71         char f[] = S3;
72
73         vecs[0].iov_base = h;
74         vecs[1].iov_base = b;
75         vecs[2].iov_base = f;
76 #else
77         vecs[0].iov_base = strdup(S1);
78         vecs[1].iov_base = strdup(S2);
79         vecs[2].iov_base = strdup(S3);
80
81         vecs[0].iov_len = strlen(vecs[0].iov_base);
82         vecs[1].iov_len = strlen(vecs[1].iov_base);
83         vecs[2].iov_len = strlen(vecs[2].iov_base);
84 #endif
85                 
86         if (check_output_pipe())
87                 return usage(argv[0]);
88
89         return do_vmsplice(STDOUT_FILENO, vecs, 3);
90 }