8static int aliases_and_marks(
void) {
9 int failed = 0, group = -1, alias_fd = -1, opened = -1;
10 struct fh_file file = {.fd = -1};
13 char alias[224] = {0};
15 CHECK(!fh_create(&file));
16 snprintf(alias,
sizeof(alias),
"%s.alias", file.path);
17 CHECK(!link(file.path, alias));
18 alias_fd = open(alias, O_RDONLY | O_CLOEXEC);
19 CHECK(alias_fd >= 0 && !fh_export(alias_fd, &alias_handle, &mount_id));
20 CHECK(fh_equal(&alias_handle, &file.handle));
22 CHECK(group >= 0 && !fh_mark(group, &file, FAN_MARK_ADD, FAN_MODIFY));
23 CHECK(!fanotify_mark(group, FAN_MARK_ADD, FAN_ATTRIB, alias_fd, NULL));
24 CHECK(!fchmod(alias_fd, 0644) && !fh_modify(&file));
25 CHECK(!fh_take(group, &file.handle, &record));
26 CHECK(record.mask == (FAN_ATTRIB | FAN_MODIFY) && record.pid == getpid());
27 CHECK(fh_equal(&record.handle, &file.handle) && fh_readable(group, 0) == 0);
28 opened = open_by_handle_at(file.fd, (
struct file_handle*)&record.handle, O_RDONLY);
30 CHECK(opened >= 0 && pread(opened, &
byte, 1, 0) == 1 &&
byte ==
'!');
31 CHECK(!close(opened));
33 CHECK(!fanotify_mark(group, FAN_MARK_REMOVE, FAN_MODIFY, alias_fd, NULL));
34 CHECK(!fh_modify(&file) && fh_readable(group, 0) == 0);
35 CHECK(!fchmod(file.fd, 0600));
36 CHECK(!fh_event(group, &file, FAN_ATTRIB, getpid()));
37 CHECK(!fh_mark(group, &file, FAN_MARK_REMOVE, FAN_ATTRIB));
39 CHECK(fh_mark(group, &file, FAN_MARK_REMOVE, FAN_ATTRIB) == -1 && errno == ENOENT);
40 CHECK(!fh_mark(group, &file, FAN_MARK_ADD, FAN_OPEN | FAN_CLOSE));
41 opened = open(alias, O_RDONLY | O_CLOEXEC);
42 CHECK(opened >= 0 && !fh_event(group, &file, FAN_OPEN, getpid()));
43 CHECK(!close(opened));
45 CHECK(!fh_event(group, &file, FAN_CLOSE_NOWRITE, getpid()));
46 opened = open(file.path, O_RDWR | O_CLOEXEC);
47 CHECK(opened >= 0 && !fh_event(group, &file, FAN_OPEN, getpid()));
48 CHECK(!close(opened));
50 CHECK(!fh_event(group, &file, FAN_CLOSE_WRITE, getpid()));
51 CHECK(!fanotify_mark(group, FAN_MARK_FLUSH, UINT64_MAX, -1, (
const char*)1));
52 CHECK(!fh_mark(group, &file, FAN_MARK_ADD, FAN_MODIFY));
53 CHECK(!fh_modify(&file));
54 CHECK(!fh_mark(group, &file, FAN_MARK_REMOVE, FAN_MODIFY));
55 CHECK(!fh_event(group, &file, FAN_MODIFY, getpid()));
56 CHECK(!fh_modify(&file) && fh_readable(group, 0) == 0);
70static int producer_exit(
void) {
71 int failed = 0, group = -1, gate[2] = {-1, -1}, completed[2] = {-1, -1};
73 struct fh_file file = {.fd = -1};
74 CHECK(!fh_create(&file));
76 CHECK(group >= 0 && !fh_mark(group, &file, FAN_MARK_ADD, FAN_MODIFY));
77 CHECK(!pipe(gate) && !pipe(completed));
84 if (fh_receive(gate[0],
'g') || fh_modify(&file) || fh_send(completed[1],
'd'))
88 CHECK(!fh_send(gate[1],
'g') && !fh_receive(completed[0],
'd'));
89 pid_t producer = child;
90 CHECK(!fh_reap(child, 12000));
92 CHECK(!fh_event(group, &file, FAN_MODIFY, producer));
93 CHECK(fh_readable(group, 0) == 0);
97 for (
int n = 0; n < 2; ++n) {
100 if (completed[n] >= 0)
109 return aliases_and_marks() || producer_exit();