[PATCH] vmsplice: remember to update 'buffer' for multiple iterations
[splice.git] / ktee.c
1 /*
2  * A tee implementation using sys_tee. Stores stdin input in the given file
3  * and duplicates that to stdout.
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>
11 #include <sys/stat.h>
12 #include <sys/types.h>
13 #include <errno.h>
14 #include <assert.h>
15 #include <limits.h>
16
17 #include "splice.h"
18
19 static int do_splice(int infd, int outfd, unsigned int len, char *msg)
20 {
21         while (len) {
22                 int written = splice(infd, NULL, outfd, NULL, len, 0);
23
24                 if (written <= 0)
25                         return error(msg);
26
27                 len -= written;
28         }
29
30         return 0;
31 }
32
33 int main(int argc, char *argv[])
34 {
35         struct stat sb;
36         int fd;
37
38         if (argc < 2) {
39                 fprintf(stderr, "%s: outfile\n", argv[0]);
40                 return 1;
41         }
42
43         if (fstat(STDIN_FILENO, &sb) < 0)
44                 return error("stat");
45         if (!S_ISFIFO(sb.st_mode)) {
46                 fprintf(stderr, "stdout must be a pipe\n");
47                 return 1;
48         }
49
50         fd = open(argv[1], O_WRONLY | O_CREAT | O_TRUNC, 0644);
51         if (fd < 0)
52                 return error("open output");
53
54         do {
55                 int tee_len = tee(STDIN_FILENO, STDOUT_FILENO, INT_MAX, SPLICE_F_NONBLOCK);
56
57                 if (tee_len < 0) {
58                         if (errno == EAGAIN) {
59                                 usleep(1000);
60                                 continue;
61                         }
62                         return error("tee");
63                 } else if (!tee_len)
64                         break;
65
66                 /*
67                  * Send output to file, also consumes input pipe.
68                  */
69                 if (do_splice(STDIN_FILENO, fd, tee_len, "splice-file"))
70                         break;
71         } while (1);
72
73         return 0;
74 }