vmsplice-touser: cleanup
[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
JA
19static int splice_flags;
20
ef0e4210
JA
21static int do_vmsplice_unmap(int fd, unsigned char *buf, int len)
22{
23 struct iovec iov = {
24 .iov_base = buf,
25 .iov_len = len,
26 };
27
28 return svmsplice(fd, &iov, 1, SPLICE_F_UNMAP);
29}
30
c972eeeb 31static int do_vmsplice(int fd, void **buf, int len)
d07a80dc
JA
32{
33 struct pollfd pfd = { .fd = fd, .events = POLLIN, };
c972eeeb
JA
34 struct iovec iov = {
35 .iov_base = *buf,
36 .iov_len = len,
37 };
d07a80dc 38 int written;
c972eeeb 39 int ret = 0;
d07a80dc
JA
40
41 while (len) {
42 /*
43 * in a real app you'd be more clever with poll of course,
44 * here we are basically just blocking on output room and
45 * not using the free time for anything interesting.
46 */
47 if (poll(&pfd, 1, -1) < 0)
48 return error("poll");
49
13b72067 50 written = svmsplice(fd, &iov, 1, splice_flags);
c972eeeb
JA
51
52 if (!ret)
53 *buf = iov.iov_base;
d07a80dc
JA
54
55 if (written < 0)
56 return error("vmsplice");
57 else if (!written)
58 break;
59
60 len -= written;
61 ret += written;
62 if (len) {
63 iov.iov_len -= written;
64 iov.iov_base += written;
65 }
66 }
67
68 return ret;
69}
70
71static int usage(char *name)
72{
ef0e4210 73 fprintf(stderr, "| %s [-d(ump)] [-a(ascii)] [-m(ap)] [-z(eromap)]\n", name);
d07a80dc
JA
74 return 1;
75}
76
77static int parse_options(int argc, char *argv[])
78{
79 int c, index = 1;
80
ef0e4210 81 while ((c = getopt(argc, argv, "admz")) != -1) {
d07a80dc 82 switch (c) {
ef0e4210
JA
83 case 'a':
84 do_ascii = 1;
85 index++;
86 break;
d07a80dc
JA
87 case 'd':
88 do_dump = 1;
89 index++;
90 break;
ef0e4210
JA
91 case 'm':
92 splice_flags |= SPLICE_F_MOVE;
93 index++;
94 break;
95 case 'z':
96 do_zeromap = 1;
97 index++;
98 break;
d07a80dc
JA
99 default:
100 return -1;
101 }
102 }
103
104 return index;
105}
106
107static void hexdump(unsigned char *buf, int len)
108{
109 int i;
110
111 for (i = 0; i < len; i++)
112 printf("%02x", buf[i]);
ef0e4210
JA
113}
114
115static void asciidump(unsigned char *buf, int len)
116{
117 int i;
118
119 for (i = 0; i < len; i++)
120 printf("%c", buf[i]);
d07a80dc
JA
121}
122
123int main(int argc, char *argv[])
124{
c972eeeb 125 void *buf;
d07a80dc
JA
126 int ret;
127
128 if (parse_options(argc, argv) < 0)
129 return usage(argv[0]);
130
131 if (check_input_pipe())
132 return usage(argv[0]);
133
1e404f5c
JA
134 if (do_zeromap && !(splice_flags & SPLICE_F_MOVE)) {
135 fprintf(stderr, "zero map only valid for -m(ove)\n");
136 return usage(argv[0]);
137 }
138
ef0e4210
JA
139 if (!do_zeromap) {
140 buf = malloc(4096);
141 memset(buf, 0, 4096);
142 } else
143 buf = NULL;
d07a80dc 144
ef0e4210 145 ret = do_vmsplice(STDIN_FILENO, &buf, 4096);
d07a80dc
JA
146 if (ret < 0)
147 return 1;
148
d07a80dc
JA
149 if (do_dump)
150 hexdump(buf, ret);
ef0e4210
JA
151 if (do_ascii)
152 asciidump(buf, ret);
d07a80dc 153
ef0e4210
JA
154 if (splice_flags & SPLICE_F_MOVE) {
155 ret = do_vmsplice_unmap(STDIN_FILENO, buf, 4096);
156 if (ret < 0)
157 perror("vmsplice");
158 }
159
160 return ret;
d07a80dc 161}