[PATCH] Formalize input/output pipe checking
[splice.git] / ktee.c
CommitLineData
d8525fbd 1/*
d633e577
JA
2 * A tee implementation using sys_tee. Stores stdin input in the given file
3 * and duplicates that to stdout.
d8525fbd
JA
4 */
5#include <stdio.h>
6#include <stdlib.h>
7#include <unistd.h>
8#include <string.h>
9#include <fcntl.h>
10#include <string.h>
d8525fbd
JA
11#include <sys/types.h>
12#include <errno.h>
13#include <assert.h>
14#include <limits.h>
15
16#include "splice.h"
17
18static int do_splice(int infd, int outfd, unsigned int len, char *msg)
19{
20 while (len) {
21 int written = splice(infd, NULL, outfd, NULL, len, 0);
22
23 if (written <= 0)
24 return error(msg);
25
26 len -= written;
27 }
28
29 return 0;
30}
31
f91353a3
JA
32static int usage(char *name)
33{
34 fprintf(stderr, "... | %s: outfile\n", name);
35 return 1;
36}
37
d8525fbd
JA
38int main(int argc, char *argv[])
39{
d8525fbd
JA
40 int fd;
41
f91353a3
JA
42 if (argc < 2)
43 return usage(argv[0]);
d8525fbd 44
76797253 45 if (check_input_pipe())
f91353a3 46 return usage(argv[0]);
d8525fbd
JA
47
48 fd = open(argv[1], O_WRONLY | O_CREAT | O_TRUNC, 0644);
49 if (fd < 0)
50 return error("open output");
51
52 do {
53 int tee_len = tee(STDIN_FILENO, STDOUT_FILENO, INT_MAX, SPLICE_F_NONBLOCK);
54
55 if (tee_len < 0) {
56 if (errno == EAGAIN) {
57 usleep(1000);
58 continue;
59 }
60 return error("tee");
61 } else if (!tee_len)
62 break;
63
64 /*
65 * Send output to file, also consumes input pipe.
66 */
67 if (do_splice(STDIN_FILENO, fd, tee_len, "splice-file"))
68 break;
69 } while (1);
70
71 return 0;
72}