The Pedigree Project 0.1
tee.c
1#define _GNU_SOURCE
2#include <poll.h>
3#include <unistd.h>
4
5#include "contract.h"
6
7int pipe_transfer_tee(void) {
8 int failed = 0, p[2] = {-1, -1}, q[2] = {-1, -1}, alias = -1, file = -1;
9 CHECK(!pipe(p) && !pipe(q) && !pt_fill(p[1], PT_CAPACITY, 17));
10 CHECK(tee(p[0], q[1], 13, SPLICE_F_MORE | SPLICE_F_MOVE | SPLICE_F_GIFT) == 13);
11 CHECK(!pt_read(q[0], 13, 0, 17));
12 CHECK(tee(p[0], q[1], 13, 0) == 13);
13 CHECK(!pt_read(q[0], 13, 0, 17));
14 CHECK(!pt_fill(q[1], PT_CAPACITY - 7, 73));
15 ssize_t copied = tee(p[0], q[1], PT_CAPACITY, 0);
16 CHECK(copied > 0 && copied <= 7);
17 CHECK(!pt_read(q[0], PT_CAPACITY - 7, 0, 73));
18 CHECK(!pt_read(q[0], copied, 0, 17));
19 CHECK(!pt_fill(q[1], PT_CAPACITY, 91));
20 CHECK(tee(p[0], q[1], 1, SPLICE_F_NONBLOCK) == -1 && errno == EAGAIN);
21 CHECK(!fcntl(q[1], F_SETFL, O_NONBLOCK));
22 CHECK(tee(p[0], q[1], 1, 0) == -1 && errno == EAGAIN);
23 CHECK(!pt_read(p[0], PT_CAPACITY, 0, 17) && !pt_read(q[0], PT_CAPACITY, 0, 91));
24 CHECK(tee(p[0], q[1], 1, SPLICE_F_NONBLOCK) == -1 && errno == EAGAIN);
25 CHECK(!close(p[1]));
26 p[1] = -1;
27 CHECK(tee(p[0], q[1], 1, 0) == 0);
28 CHECK((alias = dup(q[0])) >= 0);
29 CHECK(tee(alias, q[1], 1, 0) == -1 && errno == EINVAL);
30 CHECK(tee(q[1], q[0], 1, 0) == -1 && errno == EBADF);
31 CHECK((file = pt_file(1, 0)) >= 0);
32 CHECK(tee(file, q[1], 1, 0) == -1 && errno == EINVAL);
33 CHECK(tee(q[0], p[0], 1, 0x80000000U) == -1 && errno == EINVAL);
34 CHECK(tee(-1, -1, 0, 0) == 0);
35 CHECK(tee(-1, -1, 0, 0x80000000U) == -1 && errno == EINVAL);
36out:
37 if (file >= 0)
38 close(file);
39 if (alias >= 0)
40 close(alias);
41 for (int n = 0; n < 2; ++n) {
42 if (p[n] >= 0)
43 close(p[n]);
44 if (q[n] >= 0)
45 close(q[n]);
46 }
47 return failed;
48}