1*49cdfc7eSAndroid Build Coastguard Worker // SPDX-License-Identifier: GPL-2.0-or-later
2*49cdfc7eSAndroid Build Coastguard Worker /*
3*49cdfc7eSAndroid Build Coastguard Worker * Copyright (c) 2007 SWSoft. All Rights Reserved.
4*49cdfc7eSAndroid Build Coastguard Worker * Author: Andrew Vagin <[email protected]>
5*49cdfc7eSAndroid Build Coastguard Worker */
6*49cdfc7eSAndroid Build Coastguard Worker
7*49cdfc7eSAndroid Build Coastguard Worker /*\
8*49cdfc7eSAndroid Build Coastguard Worker * [Description]
9*49cdfc7eSAndroid Build Coastguard Worker *
10*49cdfc7eSAndroid Build Coastguard Worker * Basic test for inotify events on directory.
11*49cdfc7eSAndroid Build Coastguard Worker */
12*49cdfc7eSAndroid Build Coastguard Worker
13*49cdfc7eSAndroid Build Coastguard Worker #include "config.h"
14*49cdfc7eSAndroid Build Coastguard Worker
15*49cdfc7eSAndroid Build Coastguard Worker #include <stdio.h>
16*49cdfc7eSAndroid Build Coastguard Worker #include <sys/stat.h>
17*49cdfc7eSAndroid Build Coastguard Worker #include <sys/types.h>
18*49cdfc7eSAndroid Build Coastguard Worker #include <fcntl.h>
19*49cdfc7eSAndroid Build Coastguard Worker #include <errno.h>
20*49cdfc7eSAndroid Build Coastguard Worker #include <string.h>
21*49cdfc7eSAndroid Build Coastguard Worker #include <sys/syscall.h>
22*49cdfc7eSAndroid Build Coastguard Worker #include <limits.h>
23*49cdfc7eSAndroid Build Coastguard Worker #include "tst_test.h"
24*49cdfc7eSAndroid Build Coastguard Worker #include "inotify.h"
25*49cdfc7eSAndroid Build Coastguard Worker
26*49cdfc7eSAndroid Build Coastguard Worker #if defined(HAVE_SYS_INOTIFY_H)
27*49cdfc7eSAndroid Build Coastguard Worker #include <sys/inotify.h>
28*49cdfc7eSAndroid Build Coastguard Worker
29*49cdfc7eSAndroid Build Coastguard Worker #ifndef IN_MOVE_SELF
30*49cdfc7eSAndroid Build Coastguard Worker #define IN_MOVE_SELF 0x00000800
31*49cdfc7eSAndroid Build Coastguard Worker #endif
32*49cdfc7eSAndroid Build Coastguard Worker
33*49cdfc7eSAndroid Build Coastguard Worker #define EVENT_MAX 1024
34*49cdfc7eSAndroid Build Coastguard Worker /* size of the event structure, not counting name */
35*49cdfc7eSAndroid Build Coastguard Worker #define EVENT_SIZE (sizeof (struct inotify_event))
36*49cdfc7eSAndroid Build Coastguard Worker /* reasonable guess as to size of 1024 events */
37*49cdfc7eSAndroid Build Coastguard Worker #define EVENT_BUF_LEN (EVENT_MAX * (EVENT_SIZE + 16))
38*49cdfc7eSAndroid Build Coastguard Worker
39*49cdfc7eSAndroid Build Coastguard Worker #define BUF_SIZE 256
40*49cdfc7eSAndroid Build Coastguard Worker static char fname1[BUF_SIZE], fname2[BUF_SIZE], fname3[BUF_SIZE];
41*49cdfc7eSAndroid Build Coastguard Worker static int fd, fd_notify, reap_wd;
42*49cdfc7eSAndroid Build Coastguard Worker static int wd;
43*49cdfc7eSAndroid Build Coastguard Worker
44*49cdfc7eSAndroid Build Coastguard Worker struct event_t {
45*49cdfc7eSAndroid Build Coastguard Worker char name[BUF_SIZE];
46*49cdfc7eSAndroid Build Coastguard Worker unsigned int mask;
47*49cdfc7eSAndroid Build Coastguard Worker };
48*49cdfc7eSAndroid Build Coastguard Worker #define FILE_NAME1 "test_file1"
49*49cdfc7eSAndroid Build Coastguard Worker #define FILE_NAME2 "test_file2"
50*49cdfc7eSAndroid Build Coastguard Worker
51*49cdfc7eSAndroid Build Coastguard Worker static struct event_t event_set[EVENT_MAX];
52*49cdfc7eSAndroid Build Coastguard Worker
53*49cdfc7eSAndroid Build Coastguard Worker static char event_buf[EVENT_BUF_LEN];
54*49cdfc7eSAndroid Build Coastguard Worker
verify_inotify(void)55*49cdfc7eSAndroid Build Coastguard Worker void verify_inotify(void)
56*49cdfc7eSAndroid Build Coastguard Worker {
57*49cdfc7eSAndroid Build Coastguard Worker unsigned int stored_cookie = UINT_MAX;
58*49cdfc7eSAndroid Build Coastguard Worker
59*49cdfc7eSAndroid Build Coastguard Worker int test_cnt = 0;
60*49cdfc7eSAndroid Build Coastguard Worker
61*49cdfc7eSAndroid Build Coastguard Worker /*
62*49cdfc7eSAndroid Build Coastguard Worker * generate sequence of events
63*49cdfc7eSAndroid Build Coastguard Worker */
64*49cdfc7eSAndroid Build Coastguard Worker SAFE_CHMOD(".", 0755);
65*49cdfc7eSAndroid Build Coastguard Worker event_set[test_cnt].mask = IN_ISDIR | IN_ATTRIB;
66*49cdfc7eSAndroid Build Coastguard Worker strcpy(event_set[test_cnt].name, "");
67*49cdfc7eSAndroid Build Coastguard Worker test_cnt++;
68*49cdfc7eSAndroid Build Coastguard Worker
69*49cdfc7eSAndroid Build Coastguard Worker if ((fd = creat(FILE_NAME1, 0755)) == -1) {
70*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TBROK | TERRNO,
71*49cdfc7eSAndroid Build Coastguard Worker "creat(\"%s\", 755) failed", FILE_NAME1);
72*49cdfc7eSAndroid Build Coastguard Worker }
73*49cdfc7eSAndroid Build Coastguard Worker
74*49cdfc7eSAndroid Build Coastguard Worker event_set[test_cnt].mask = IN_CREATE;
75*49cdfc7eSAndroid Build Coastguard Worker strcpy(event_set[test_cnt].name, FILE_NAME1);
76*49cdfc7eSAndroid Build Coastguard Worker test_cnt++;
77*49cdfc7eSAndroid Build Coastguard Worker event_set[test_cnt].mask = IN_OPEN;
78*49cdfc7eSAndroid Build Coastguard Worker strcpy(event_set[test_cnt].name, FILE_NAME1);
79*49cdfc7eSAndroid Build Coastguard Worker test_cnt++;
80*49cdfc7eSAndroid Build Coastguard Worker
81*49cdfc7eSAndroid Build Coastguard Worker SAFE_CLOSE(fd);
82*49cdfc7eSAndroid Build Coastguard Worker event_set[test_cnt].mask = IN_CLOSE_WRITE;
83*49cdfc7eSAndroid Build Coastguard Worker strcpy(event_set[test_cnt].name, FILE_NAME1);
84*49cdfc7eSAndroid Build Coastguard Worker test_cnt++;
85*49cdfc7eSAndroid Build Coastguard Worker
86*49cdfc7eSAndroid Build Coastguard Worker SAFE_RENAME(FILE_NAME1, FILE_NAME2);
87*49cdfc7eSAndroid Build Coastguard Worker event_set[test_cnt].mask = IN_MOVED_FROM;
88*49cdfc7eSAndroid Build Coastguard Worker strcpy(event_set[test_cnt].name, FILE_NAME1);
89*49cdfc7eSAndroid Build Coastguard Worker test_cnt++;
90*49cdfc7eSAndroid Build Coastguard Worker event_set[test_cnt].mask = IN_MOVED_TO;
91*49cdfc7eSAndroid Build Coastguard Worker strcpy(event_set[test_cnt].name, FILE_NAME2);
92*49cdfc7eSAndroid Build Coastguard Worker test_cnt++;
93*49cdfc7eSAndroid Build Coastguard Worker
94*49cdfc7eSAndroid Build Coastguard Worker if (getcwd(fname1, BUF_SIZE) == NULL) {
95*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TBROK | TERRNO,
96*49cdfc7eSAndroid Build Coastguard Worker "getcwd(%p, %d) failed", fname1, BUF_SIZE);
97*49cdfc7eSAndroid Build Coastguard Worker }
98*49cdfc7eSAndroid Build Coastguard Worker
99*49cdfc7eSAndroid Build Coastguard Worker snprintf(fname2, BUF_SIZE, "%s.rename1", fname1);
100*49cdfc7eSAndroid Build Coastguard Worker SAFE_RENAME(fname1, fname2);
101*49cdfc7eSAndroid Build Coastguard Worker event_set[test_cnt].mask = IN_MOVE_SELF;
102*49cdfc7eSAndroid Build Coastguard Worker strcpy(event_set[test_cnt].name, "");
103*49cdfc7eSAndroid Build Coastguard Worker test_cnt++;
104*49cdfc7eSAndroid Build Coastguard Worker
105*49cdfc7eSAndroid Build Coastguard Worker SAFE_UNLINK(FILE_NAME2);
106*49cdfc7eSAndroid Build Coastguard Worker event_set[test_cnt].mask = IN_DELETE;
107*49cdfc7eSAndroid Build Coastguard Worker strcpy(event_set[test_cnt].name, FILE_NAME2);
108*49cdfc7eSAndroid Build Coastguard Worker test_cnt++;
109*49cdfc7eSAndroid Build Coastguard Worker
110*49cdfc7eSAndroid Build Coastguard Worker /*
111*49cdfc7eSAndroid Build Coastguard Worker * test that duplicate events will be coalesced into
112*49cdfc7eSAndroid Build Coastguard Worker * a single event. This test case should be last, that
113*49cdfc7eSAndroid Build Coastguard Worker * we can correct determine kernel bug which exist before
114*49cdfc7eSAndroid Build Coastguard Worker * 2.6.25. See comment below.
115*49cdfc7eSAndroid Build Coastguard Worker */
116*49cdfc7eSAndroid Build Coastguard Worker snprintf(fname3, BUF_SIZE, "%s.rename2", fname1);
117*49cdfc7eSAndroid Build Coastguard Worker SAFE_RENAME(fname2, fname3);
118*49cdfc7eSAndroid Build Coastguard Worker
119*49cdfc7eSAndroid Build Coastguard Worker SAFE_RENAME(fname3, fname1);
120*49cdfc7eSAndroid Build Coastguard Worker event_set[test_cnt].mask = IN_MOVE_SELF;
121*49cdfc7eSAndroid Build Coastguard Worker strcpy(event_set[test_cnt].name, "");
122*49cdfc7eSAndroid Build Coastguard Worker test_cnt++;
123*49cdfc7eSAndroid Build Coastguard Worker
124*49cdfc7eSAndroid Build Coastguard Worker int len, i = 0, test_num = 0;
125*49cdfc7eSAndroid Build Coastguard Worker if ((len = read(fd_notify, event_buf, EVENT_BUF_LEN)) == -1) {
126*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TBROK | TERRNO,
127*49cdfc7eSAndroid Build Coastguard Worker "read(%d, buf, %zu) failed",
128*49cdfc7eSAndroid Build Coastguard Worker fd_notify, EVENT_BUF_LEN);
129*49cdfc7eSAndroid Build Coastguard Worker
130*49cdfc7eSAndroid Build Coastguard Worker }
131*49cdfc7eSAndroid Build Coastguard Worker
132*49cdfc7eSAndroid Build Coastguard Worker while (i < len) {
133*49cdfc7eSAndroid Build Coastguard Worker struct inotify_event *event;
134*49cdfc7eSAndroid Build Coastguard Worker event = (struct inotify_event *)&event_buf[i];
135*49cdfc7eSAndroid Build Coastguard Worker if (test_num >= test_cnt) {
136*49cdfc7eSAndroid Build Coastguard Worker tst_res(TFAIL,
137*49cdfc7eSAndroid Build Coastguard Worker "get unnecessary event: "
138*49cdfc7eSAndroid Build Coastguard Worker "wd=%d mask=%08x cookie=%-5u len=%-2u "
139*49cdfc7eSAndroid Build Coastguard Worker "name=\"%.*s\"", event->wd, event->mask,
140*49cdfc7eSAndroid Build Coastguard Worker event->cookie, event->len, event->len,
141*49cdfc7eSAndroid Build Coastguard Worker event->name);
142*49cdfc7eSAndroid Build Coastguard Worker
143*49cdfc7eSAndroid Build Coastguard Worker } else if ((event_set[test_num].mask == event->mask)
144*49cdfc7eSAndroid Build Coastguard Worker &&
145*49cdfc7eSAndroid Build Coastguard Worker (!strncmp
146*49cdfc7eSAndroid Build Coastguard Worker (event_set[test_num].name, event->name,
147*49cdfc7eSAndroid Build Coastguard Worker event->len))) {
148*49cdfc7eSAndroid Build Coastguard Worker int fail = 0;
149*49cdfc7eSAndroid Build Coastguard Worker
150*49cdfc7eSAndroid Build Coastguard Worker if (event->mask == IN_MOVED_FROM) {
151*49cdfc7eSAndroid Build Coastguard Worker if (event->cookie == 0)
152*49cdfc7eSAndroid Build Coastguard Worker fail = 1;
153*49cdfc7eSAndroid Build Coastguard Worker else
154*49cdfc7eSAndroid Build Coastguard Worker stored_cookie = event->cookie;
155*49cdfc7eSAndroid Build Coastguard Worker } else if (event->mask == IN_MOVED_TO) {
156*49cdfc7eSAndroid Build Coastguard Worker if (event->cookie != stored_cookie)
157*49cdfc7eSAndroid Build Coastguard Worker fail = 1;
158*49cdfc7eSAndroid Build Coastguard Worker else
159*49cdfc7eSAndroid Build Coastguard Worker stored_cookie = UINT_MAX;
160*49cdfc7eSAndroid Build Coastguard Worker } else {
161*49cdfc7eSAndroid Build Coastguard Worker if (event->cookie != 0)
162*49cdfc7eSAndroid Build Coastguard Worker fail = 1;
163*49cdfc7eSAndroid Build Coastguard Worker }
164*49cdfc7eSAndroid Build Coastguard Worker if (!fail) {
165*49cdfc7eSAndroid Build Coastguard Worker tst_res(TPASS,
166*49cdfc7eSAndroid Build Coastguard Worker "get event: wd=%d mask=%08x "
167*49cdfc7eSAndroid Build Coastguard Worker "cookie=%-5u len=%-2u name=\"%.*s\"",
168*49cdfc7eSAndroid Build Coastguard Worker event->wd, event->mask,
169*49cdfc7eSAndroid Build Coastguard Worker event->cookie, event->len,
170*49cdfc7eSAndroid Build Coastguard Worker event->len, event->name);
171*49cdfc7eSAndroid Build Coastguard Worker } else {
172*49cdfc7eSAndroid Build Coastguard Worker tst_res(TFAIL,
173*49cdfc7eSAndroid Build Coastguard Worker "get event: wd=%d mask=%08x "
174*49cdfc7eSAndroid Build Coastguard Worker "cookie=%-5u (wrong) len=%-2u "
175*49cdfc7eSAndroid Build Coastguard Worker "name=\"%s\"",
176*49cdfc7eSAndroid Build Coastguard Worker event->wd, event->mask,
177*49cdfc7eSAndroid Build Coastguard Worker event->cookie, event->len,
178*49cdfc7eSAndroid Build Coastguard Worker event->name);
179*49cdfc7eSAndroid Build Coastguard Worker }
180*49cdfc7eSAndroid Build Coastguard Worker } else {
181*49cdfc7eSAndroid Build Coastguard Worker tst_res(TFAIL, "get event: wd=%d mask=%08x "
182*49cdfc7eSAndroid Build Coastguard Worker "(expected %x) cookie=%-5u len=%-2u "
183*49cdfc7eSAndroid Build Coastguard Worker "name=\"%s\" (expected \"%s\") %d",
184*49cdfc7eSAndroid Build Coastguard Worker event->wd, event->mask,
185*49cdfc7eSAndroid Build Coastguard Worker event_set[test_num].mask,
186*49cdfc7eSAndroid Build Coastguard Worker event->cookie, event->len, event->name,
187*49cdfc7eSAndroid Build Coastguard Worker event_set[test_num].name,
188*49cdfc7eSAndroid Build Coastguard Worker strcmp(event_set[test_num].name,
189*49cdfc7eSAndroid Build Coastguard Worker event->name));
190*49cdfc7eSAndroid Build Coastguard Worker }
191*49cdfc7eSAndroid Build Coastguard Worker test_num++;
192*49cdfc7eSAndroid Build Coastguard Worker i += EVENT_SIZE + event->len;
193*49cdfc7eSAndroid Build Coastguard Worker }
194*49cdfc7eSAndroid Build Coastguard Worker
195*49cdfc7eSAndroid Build Coastguard Worker for (; test_num < test_cnt; test_num++) {
196*49cdfc7eSAndroid Build Coastguard Worker tst_res(TFAIL, "didn't get event: mask=%08x ",
197*49cdfc7eSAndroid Build Coastguard Worker event_set[test_num].mask);
198*49cdfc7eSAndroid Build Coastguard Worker }
199*49cdfc7eSAndroid Build Coastguard Worker }
200*49cdfc7eSAndroid Build Coastguard Worker
setup(void)201*49cdfc7eSAndroid Build Coastguard Worker static void setup(void)
202*49cdfc7eSAndroid Build Coastguard Worker {
203*49cdfc7eSAndroid Build Coastguard Worker fd_notify = SAFE_MYINOTIFY_INIT();
204*49cdfc7eSAndroid Build Coastguard Worker
205*49cdfc7eSAndroid Build Coastguard Worker wd = SAFE_MYINOTIFY_ADD_WATCH(fd_notify, ".", IN_ALL_EVENTS);
206*49cdfc7eSAndroid Build Coastguard Worker reap_wd = 1;
207*49cdfc7eSAndroid Build Coastguard Worker }
208*49cdfc7eSAndroid Build Coastguard Worker
cleanup(void)209*49cdfc7eSAndroid Build Coastguard Worker static void cleanup(void)
210*49cdfc7eSAndroid Build Coastguard Worker {
211*49cdfc7eSAndroid Build Coastguard Worker if (reap_wd && myinotify_rm_watch(fd_notify, wd) < 0) {
212*49cdfc7eSAndroid Build Coastguard Worker tst_res(TWARN,
213*49cdfc7eSAndroid Build Coastguard Worker "inotify_rm_watch (%d, %d) failed,", fd_notify, wd);
214*49cdfc7eSAndroid Build Coastguard Worker }
215*49cdfc7eSAndroid Build Coastguard Worker
216*49cdfc7eSAndroid Build Coastguard Worker if (fd_notify > 0)
217*49cdfc7eSAndroid Build Coastguard Worker SAFE_CLOSE(fd_notify);
218*49cdfc7eSAndroid Build Coastguard Worker }
219*49cdfc7eSAndroid Build Coastguard Worker
220*49cdfc7eSAndroid Build Coastguard Worker static struct tst_test test = {
221*49cdfc7eSAndroid Build Coastguard Worker .needs_tmpdir = 1,
222*49cdfc7eSAndroid Build Coastguard Worker .setup = setup,
223*49cdfc7eSAndroid Build Coastguard Worker .cleanup = cleanup,
224*49cdfc7eSAndroid Build Coastguard Worker .test_all = verify_inotify,
225*49cdfc7eSAndroid Build Coastguard Worker };
226*49cdfc7eSAndroid Build Coastguard Worker
227*49cdfc7eSAndroid Build Coastguard Worker #else
228*49cdfc7eSAndroid Build Coastguard Worker TST_TEST_TCONF("system doesn't have required inotify support");
229*49cdfc7eSAndroid Build Coastguard Worker #endif
230