Fix various compile warnings
[splice.git] / vmsplice-touser.c
... / ...
CommitLineData
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
16static int do_dump;
17static int do_ascii;
18static int do_zeromap;
19static int splice_flags;
20static unsigned int splice_size = SPLICE_SIZE;
21
22static 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
32static 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
72static 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
78static 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
121static 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
129static 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
137int 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}