xref: /aosp_15_r20/external/ltp/testcases/kernel/syscalls/inotify/inotify01.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (c) 2007 SWSoft.  All Rights Reserved.
4  * Author: Andrew Vagin <[email protected]>
5  */
6 
7 /*\
8  * [Description]
9  *
10  * Basic test for inotify events on file.
11  */
12 
13 #include "config.h"
14 
15 #include <stdio.h>
16 #include <sys/stat.h>
17 #include <sys/types.h>
18 #include <fcntl.h>
19 #include <errno.h>
20 #include <string.h>
21 #include <sys/syscall.h>
22 #include "tst_test.h"
23 #include "inotify.h"
24 
25 #if defined(HAVE_SYS_INOTIFY_H)
26 #include <sys/inotify.h>
27 
28 #define EVENT_MAX 1024
29 /* size of the event structure, not counting name */
30 #define EVENT_SIZE  (sizeof (struct inotify_event))
31 /* reasonable guess as to size of 1024 events */
32 #define EVENT_BUF_LEN        (EVENT_MAX * (EVENT_SIZE + 16))
33 
34 #define BUF_SIZE 256
35 
36 static char fname[BUF_SIZE];
37 static char buf[BUF_SIZE];
38 static int fd, fd_notify;
39 static int wd, reap_wd;
40 
41 static unsigned int event_set[EVENT_MAX];
42 
43 static char event_buf[EVENT_BUF_LEN];
44 
verify_inotify(void)45 void verify_inotify(void)
46 {
47 	int test_cnt = 0;
48 
49 	/*
50 	 * generate sequence of events
51 	 */
52 	SAFE_CHMOD(fname, 0755);
53 	event_set[test_cnt] = IN_ATTRIB;
54 	test_cnt++;
55 
56 	fd = SAFE_OPEN(fname, O_RDONLY);
57 	event_set[test_cnt] = IN_OPEN;
58 	test_cnt++;
59 
60 	if (read(fd, buf, BUF_SIZE) == -1) {
61 		tst_brk(TBROK | TERRNO,
62 			"read(%d, buf, %d) failed", fd, BUF_SIZE);
63 	}
64 	event_set[test_cnt] = IN_ACCESS;
65 	test_cnt++;
66 
67 	SAFE_CLOSE(fd);
68 	event_set[test_cnt] = IN_CLOSE_NOWRITE;
69 	test_cnt++;
70 
71 	fd = SAFE_OPEN(fname, O_RDWR | O_CREAT, 0700);
72 	event_set[test_cnt] = IN_OPEN;
73 	test_cnt++;
74 
75 	if (write(fd, buf, BUF_SIZE) == -1) {
76 		tst_brk(TBROK,
77 			"write(%d, %s, 1) failed", fd, fname);
78 	}
79 	event_set[test_cnt] = IN_MODIFY;
80 	test_cnt++;
81 
82 	SAFE_CLOSE(fd);
83 	event_set[test_cnt] = IN_CLOSE_WRITE;
84 	test_cnt++;
85 
86 	/*
87 	 * get list of events
88 	 */
89 	int len, i = 0, test_num = 0;
90 	if ((len = read(fd_notify, event_buf, EVENT_BUF_LEN)) < 0) {
91 		tst_brk(TBROK,
92 			"read(%d, buf, %zu) failed",
93 			fd_notify, EVENT_BUF_LEN);
94 
95 	}
96 
97 	/*
98 	 * check events
99 	 */
100 	while (i < len) {
101 		struct inotify_event *event;
102 		event = (struct inotify_event *)&event_buf[i];
103 		if (test_num >= test_cnt) {
104 			tst_res(TFAIL,
105 				"get unnecessary event: wd=%d mask=%02x "
106 				"cookie=%u len=%u",
107 				event->wd, event->mask,
108 				event->cookie, event->len);
109 		} else if (event_set[test_num] == event->mask) {
110 			if (event->cookie != 0) {
111 				tst_res(TFAIL,
112 					"get event: wd=%d mask=%02x "
113 					"cookie=%u (expected 0) len=%u",
114 					event->wd, event->mask,
115 					event->cookie, event->len);
116 			} else {
117 				tst_res(TPASS, "get event: wd=%d "
118 					"mask=%02x cookie=%u len=%u",
119 					event->wd, event->mask,
120 					event->cookie, event->len);
121 			}
122 
123 		} else {
124 			tst_res(TFAIL, "get event: wd=%d mask=%02x "
125 				"(expected %x) cookie=%u len=%u",
126 				event->wd, event->mask,
127 				event_set[test_num],
128 				event->cookie, event->len);
129 		}
130 		test_num++;
131 		i += EVENT_SIZE + event->len;
132 	}
133 	for (; test_num < test_cnt; test_num++) {
134 		tst_res(TFAIL, "didn't get event: mask=%02x",
135 			event_set[test_num]);
136 
137 	}
138 }
139 
setup(void)140 static void setup(void)
141 {
142 	sprintf(fname, "tfile_%d", getpid());
143 
144 	SAFE_FILE_PRINTF(fname, "%s", fname);
145 
146 	fd_notify = SAFE_MYINOTIFY_INIT();
147 
148 	wd = SAFE_MYINOTIFY_ADD_WATCH(fd_notify, fname, IN_ALL_EVENTS);
149 	reap_wd = 1;
150 }
151 
cleanup(void)152 static void cleanup(void)
153 {
154 	if (reap_wd && myinotify_rm_watch(fd_notify, wd) < 0) {
155 		tst_res(TWARN | TERRNO, "inotify_rm_watch (%d, %d) failed",
156 			fd_notify, wd);
157 	}
158 
159 	if (fd_notify > 0)
160 		SAFE_CLOSE(fd_notify);
161 }
162 
163 static struct tst_test test = {
164 	.needs_tmpdir = 1,
165 	.setup = setup,
166 	.cleanup = cleanup,
167 	.test_all = verify_inotify,
168 };
169 
170 #else
171 	TST_TEST_TCONF("system doesn't have required inotify support");
172 #endif
173