Fix various compile warnings
[splice.git] / vmsplice-touser.c
1 /*
2  * Use vmsplice to splice data from a pipe to user space memory.
3  */
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <unistd.h>
7 #include <limits.h>
8 #include <string.h>
9 #include <getopt.h>
10 #include <fcntl.h>
11 #include <sys/poll.h>
12 #include <sys/types.h>
13
14 #include "splice.h"
15
16 static int do_dump;
17 static int do_ascii;
18 static int do_zeromap;
19 static int splice_flags;
20 static unsigned int splice_size = SPLICE_SIZE;
21
22 static int do_vmsplice_unmap(int fd, unsigned char *buf, int len)
23 {
24         struct iovec iov = {
25                 .iov_base = buf,
26                 .iov_len = len,
27         };
28
29         return svmsplice(fd, &iov, 1, SPLICE_F_UNMAP);
30 }
31
32 static int do_vmsplice(int fd, void **buf, int len)
33 {
34         struct pollfd pfd = { .fd = fd, .events = POLLIN, };
35         struct iovec iov = {
36                 .iov_base = *buf,
37                 .iov_len = len,
38         };
39         int written;
40         int ret = 0;
41
42         while (len) {
43                 /*
44                  * in a real app you'd be more clever with poll of course,
45                  * here we are basically just blocking on output room and
46                  * not using the free time for anything interesting.
47                  */
48                 if (poll(&pfd, 1, -1) < 0)
49                         return error("poll");
50
51                 written = svmsplice(fd, &iov, 1, splice_flags);
52
53                 if (!ret)
54                         *buf = iov.iov_base;
55
56                 if (written < 0)
57                         return error("vmsplice");
58                 else if (!written)
59                         break;
60
61                 len -= written;
62                 ret += written;
63                 if (len) {
64                         iov.iov_len -= written;
65                         iov.iov_base += written;
66                 }
67         }
68
69         return ret;
70 }
71
72 static int usage(char *name)
73 {
74         fprintf(stderr, "| %s [-s(ize)] [-d(ump)] [-a(ascii)] [-m(ap)] [-z(eromap)] [-n non-block]\n", name);
75         return 1;
76 }
77
78 static int parse_options(int argc, char *argv[])
79 {
80         int c, index = 1;
81
82         while ((c = getopt(argc, argv, "admzs:n")) != -1) {
83                 switch (c) {
84                 case 'a':
85                         do_ascii = 1;
86                         index++;
87                         break;
88                 case 'd':
89                         do_dump = 1;
90                         index++;
91                         break;
92                 case 'm':
93                         splice_flags |= SPLICE_F_MOVE;
94                         index++;
95                         break;
96                 case 'z':
97                         do_zeromap = 1;
98                         index++;
99                         break;
100                 case 's':
101                         splice_size = atoi(optarg);
102                         index++;
103                         break;
104                 case 'n':
105                         splice_flags |= SPLICE_F_NONBLOCK;
106                         index++;
107                         break;
108                 default:
109                         return -1;
110                 }
111         }
112
113         if (do_zeromap && !(splice_flags & SPLICE_F_MOVE)) {
114                 fprintf(stderr, "zero map only valid for -m(ove)\n");
115                 return -1;
116         }
117
118         return index;
119 }
120
121 static void hexdump(unsigned char *buf, int len)
122 {
123         int i;
124
125         for (i = 0; i < len; i++)
126                 printf("%02x", buf[i]);
127 }
128
129 static void asciidump(unsigned char *buf, int len)
130 {
131         int i;
132
133         for (i = 0; i < len; i++)
134                 printf("%c", buf[i]);
135 }
136
137 int main(int argc, char *argv[])
138 {
139         void *buf;
140         int ret;
141
142         if (parse_options(argc, argv) < 0)
143                 return usage(argv[0]);
144
145         if (check_input_pipe())
146                 return usage(argv[0]);
147
148         if (!do_zeromap) {
149                 buf = malloc(splice_size);
150                 memset(buf, 0, splice_size);
151         } else
152                 buf = NULL;
153
154         ret = do_vmsplice(STDIN_FILENO, &buf, splice_size);
155         if (ret < 0)
156                 return 1;
157         else if (!ret)
158                 return 0;
159
160         if (do_dump)
161                 hexdump(buf, ret);
162         if (do_ascii)
163                 asciidump(buf, ret);
164
165         if (splice_flags & SPLICE_F_MOVE) {
166                 ret = do_vmsplice_unmap(STDIN_FILENO, buf, ret);
167                 if (ret < 0)
168                         perror("vmsplice");
169         }
170
171         return ret;
172 }