xref: /aosp_15_r20/external/ltp/testcases/kernel/syscalls/inotify/inotify02.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
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