Fix various compile warnings
[splice.git] / vmsplice-touser.c
CommitLineData
d07a80dc
JA
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>
0a6ff83b 10#include <fcntl.h>
d07a80dc
JA
11#include <sys/poll.h>
12#include <sys/types.h>
13
14#include "splice.h"
15
16static int do_dump;
ef0e4210
JA
17static int do_ascii;
18static int do_zeromap;
d07a80dc 19static int splice_flags;
fe3a0890 20static unsigned int splice_size = SPLICE_SIZE;
d07a80dc 21
ef0e4210
JA
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
c972eeeb 32static int do_vmsplice(int fd, void **buf, int len)
d07a80dc
JA
33{
34 struct pollfd pfd = { .fd = fd, .events = POLLIN, };
c972eeeb
JA
35 struct iovec iov = {
36 .iov_base = *buf,
37 .iov_len = len,
38 };
d07a80dc 39 int written;
c972eeeb 40 int ret = 0;
d07a80dc
JA
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
13b72067 51 written = svmsplice(fd, &iov, 1, splice_flags);
c972eeeb
JA
52
53 if (!ret)
54 *buf = iov.iov_base;
d07a80dc
JA
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{
fe3a0890 74 fprintf(stderr, "| %s [-s(ize)] [-d(ump)] [-a(ascii)] [-m(ap)] [-z(eromap)] [-n non-block]\n", name);
d07a80dc
JA
75 return 1;
76}
77
78static int parse_options(int argc, char *argv[])
79{
80 int c, index = 1;
81
fe3a0890 82 while ((c = getopt(argc, argv, "admzs:n")) != -1) {
d07a80dc 83 switch (c) {
ef0e4210
JA
84 case 'a':
85 do_ascii = 1;
86 index++;
87 break;
d07a80dc
JA
88 case 'd':
89 do_dump = 1;
90 index++;
91 break;
ef0e4210
JA
92 case 'm':
93 splice_flags |= SPLICE_F_MOVE;
94 index++;
95 break;
96 case 'z':
97 do_zeromap = 1;
98 index++;
99 break;
fe3a0890
JA
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;
d07a80dc
JA
108 default:
109 return -1;
110 }
111 }
112
fe3a0890
JA
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
d07a80dc
JA
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]);
ef0e4210
JA
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]);
d07a80dc
JA
135}
136
137int main(int argc, char *argv[])
138{
c972eeeb 139 void *buf;
d07a80dc
JA
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
ef0e4210 148 if (!do_zeromap) {
fe3a0890
JA
149 buf = malloc(splice_size);
150 memset(buf, 0, splice_size);
ef0e4210
JA
151 } else
152 buf = NULL;
d07a80dc 153
fe3a0890 154 ret = do_vmsplice(STDIN_FILENO, &buf, splice_size);
d07a80dc
JA
155 if (ret < 0)
156 return 1;
fe3a0890
JA
157 else if (!ret)
158 return 0;
d07a80dc 159
d07a80dc
JA
160 if (do_dump)
161 hexdump(buf, ret);
ef0e4210
JA
162 if (do_ascii)
163 asciidump(buf, ret);
d07a80dc 164
ef0e4210 165 if (splice_flags & SPLICE_F_MOVE) {
fe3a0890 166 ret = do_vmsplice_unmap(STDIN_FILENO, buf, ret);
ef0e4210
JA
167 if (ret < 0)
168 perror("vmsplice");
169 }
170
171 return ret;
d07a80dc 172}