9static int regular_directions(
void) {
10 int failed = 0, input = -1, output = -1, p[2] = {-1, -1};
11 CHECK((input = pt_file(2 * PT_CAPACITY + 17, 11)) >= 0 && (output = pt_file(0, 0)) >= 0);
14 while (copied < 2 * PT_CAPACITY + 17) {
16 splice(input, NULL, p[1], NULL, 8192, SPLICE_F_MORE | SPLICE_F_MOVE | SPLICE_F_GIFT);
17 CHECK(amount > 0 && amount <= PT_CAPACITY);
18 CHECK(splice(p[0], NULL, output, NULL, amount, 0) == amount);
19 CHECK(!pt_verify(output, copied, amount, copied, 11));
22 CHECK(lseek(input, 0, SEEK_CUR) == (off_t)copied && lseek(output, 0, SEEK_CUR) == (off_t)copied);
23 CHECK(splice(input, NULL, p[1], NULL, 1, 0) == 0);
24 off_t from = 3, to = 7;
25 CHECK(splice(input, &from, p[1], NULL, 9, 0) == 9 && from == 12);
26 CHECK(splice(p[0], NULL, output, &to, 9, 0) == 9 && to == 16);
27 CHECK(!pt_verify(output, 7, 9, 3, 11));
28 CHECK(lseek(input, 0, SEEK_CUR) == (off_t)copied && lseek(output, 0, SEEK_CUR) == (off_t)copied);
29 CHECK(!fcntl(p[0], F_SETFL, O_NONBLOCK));
30 CHECK(splice(p[0], NULL, output, NULL, 1, 0) == -1 && errno == EAGAIN);
33 CHECK(splice(p[0], NULL, output, NULL, 1, 0) == 0);
45static int validation_and_offsets(
void) {
46 int failed = 0, file = -1, device = -1, datagram = -1, p[2] = {-1, -1}, q[2] = {-1, -1};
47 const size_t page = sysconf(_SC_PAGESIZE);
48 off_t* offset = MAP_FAILED;
49 CHECK((file = pt_file(64, 29)) >= 0 && !pipe(p) && !pipe(q));
50 offset = mmap(NULL, page, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
51 CHECK(offset != MAP_FAILED);
53 CHECK(!mprotect(offset, page, PROT_READ));
54 CHECK(splice(file, offset, p[1], NULL, 4, 0) == -1 && errno == EFAULT);
55 CHECK(*offset == 3 && lseek(file, 0, SEEK_CUR) == 0 && !pt_read(p[0], 4, 3, 29));
56 CHECK(!pt_fill(p[1], 4, 53));
57 CHECK(splice(p[0], NULL, file, offset, 4, 0) == -1 && errno == EFAULT);
58 CHECK(*offset == 3 && lseek(file, 0, SEEK_CUR) == 0 && !pt_verify(file, 3, 4, 0, 53));
59 CHECK(splice(p[0], NULL, file, offset, 1, SPLICE_F_NONBLOCK) == -1 && errno == EAGAIN);
60 CHECK(!mprotect(offset, page, PROT_READ | PROT_WRITE));
62 CHECK(!mprotect(offset, page, PROT_READ));
63 CHECK(splice(file, offset, p[1], NULL, 1, 0) == -1 && errno == EFAULT);
64 CHECK(!mprotect(offset, page, PROT_NONE));
65 CHECK(splice(file, offset, p[1], NULL, 1, 0) == -1 && errno == EFAULT);
66 CHECK(splice(p[0], offset, q[1], NULL, 1, 0) == -1 && errno == ESPIPE);
67 CHECK(splice(file, NULL, p[1], offset, 1, 0) == -1 && errno == ESPIPE);
68 CHECK(splice(p[0], NULL, p[1], NULL, 1, 0) == -1 && errno == EINVAL);
69 CHECK(splice(p[1], NULL, q[1], NULL, 1, 0) == -1 && errno == EBADF);
70 CHECK(splice(file, NULL, file, NULL, 1, 0) == -1 && errno == EINVAL);
71 CHECK(splice(-1, NULL, -1, NULL, 0, 0x80000000U) == 0);
72 CHECK(splice(file, NULL, p[1], NULL, 1, 0x80000000U) == -1 && errno == EINVAL);
73 CHECK(!pt_fill(p[1], 8, 71) && !fcntl(file, F_SETFL, O_APPEND));
74 CHECK(splice(p[0], NULL, file, NULL, 8, 0) == -1 && errno == EINVAL);
75 CHECK(!pt_read(p[0], 8, 0, 71));
76 CHECK((device = open(
"/dev/null", O_RDWR)) >= 0 &&
77 (datagram = socket(AF_UNIX, SOCK_DGRAM, 0)) >= 0);
78 CHECK(splice(device, NULL, p[1], NULL, 1, 0) == -1 && errno == EINVAL);
79 CHECK(splice(p[0], NULL, datagram, NULL, 1, 0) == -1 && errno == EINVAL);
85 if (offset != MAP_FAILED)
87 for (
int n = 0; n < 2; ++n) {
97static int sealed_output(
int seal) {
98 int failed = 0, file = -1, p[2] = {-1, -1};
99 CHECK((file = pt_file(8, 13)) >= 0 && !pipe(p) && !pt_fill(p[1], 16, 31));
100 CHECK(!fcntl(file, F_ADD_SEALS, seal));
101 CHECK(splice(p[0], NULL, file, NULL, 16, 0) == -1 && errno == EPERM);
102 CHECK(lseek(file, 0, SEEK_CUR) == 0 && !pt_verify(file, 0, 8, 0, 13));
103 CHECK(!pt_read(p[0], 16, 0, 31));
113static int socket_short(
void) {
114 int failed = 0, p[2] = {-1, -1}, pair[2] = {-1, -1};
115 CHECK(!pipe(p) && !socketpair(AF_UNIX, SOCK_STREAM, 0, pair));
116 CHECK(!pt_fill(p[1], PT_CAPACITY, 41));
117 ssize_t capacity = pt_socket_full(pair[0]);
118 CHECK(capacity > 8 && !pt_read(pair[1], 7, 0, PT_FILLER));
119 CHECK(!fcntl(pair[0], F_SETFL, O_NONBLOCK));
120 ssize_t result = splice(p[0], NULL, pair[0], NULL, PT_CAPACITY, 0);
121 CHECK(result > 0 && result <= 7);
122 CHECK(!pt_read(pair[1], capacity - 7, 0, PT_FILLER));
123 CHECK(!pt_read(pair[1], result, 0, 41));
124 CHECK(!pt_read(p[0], PT_CAPACITY - result, result, 41));
126 for (
int n = 0; n < 2; ++n) {
134int pipe_transfer_splice(
void) {
135 return regular_directions() || validation_and_offsets() || sealed_output(F_SEAL_WRITE) ||
136 sealed_output(F_SEAL_FUTURE_WRITE) || sealed_output(F_SEAL_GROW) || socket_short();