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