• 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 	fd = SAFE_OPEN(fname, O_RDONLY);
56 	event_set[test_cnt] = IN_OPEN;
57 	test_cnt++;
58 
59 	if (read(fd, buf, BUF_SIZE) == -1) {
60 		tst_brk(TBROK | TERRNO,
61 			"read(%d, buf, %d) failed", fd, BUF_SIZE);
62 	}
63 	event_set[test_cnt] = IN_ACCESS;
64 	test_cnt++;
65 
66 	SAFE_CLOSE(fd);
67 	event_set[test_cnt] = IN_CLOSE_NOWRITE;
68 	test_cnt++;
69 
70 	fd = SAFE_OPEN(fname, O_RDWR | O_CREAT, 0700);
71 	event_set[test_cnt] = IN_OPEN;
72 	test_cnt++;
73 
74 	if (write(fd, buf, BUF_SIZE) == -1) {
75 		tst_brk(TBROK,
76 			"write(%d, %s, 1) failed", fd, fname);
77 	}
78 	event_set[test_cnt] = IN_MODIFY;
79 	test_cnt++;
80 
81 	SAFE_CLOSE(fd);
82 	event_set[test_cnt] = IN_CLOSE_WRITE;
83 	test_cnt++;
84 
85 	/*
86 	 * get list of events
87 	 */
88 	int len, i = 0, test_num = 0;
89 	if ((len = read(fd_notify, event_buf, EVENT_BUF_LEN)) < 0) {
90 		tst_brk(TBROK,
91 			"read(%d, buf, %zu) failed",
92 			fd_notify, EVENT_BUF_LEN);
93 
94 	}
95 
96 	/*
97 	 * check events
98 	 */
99 	while (i < len) {
100 		struct inotify_event *event;
101 		event = (struct inotify_event *)&event_buf[i];
102 		if (test_num >= test_cnt) {
103 			tst_res(TFAIL,
104 				"get unnecessary event: wd=%d mask=%02x "
105 				"cookie=%u len=%u",
106 				event->wd, event->mask,
107 				event->cookie, event->len);
108 		} else if (event_set[test_num] == event->mask) {
109 			if (event->cookie != 0) {
110 				tst_res(TFAIL,
111 					"get event: wd=%d mask=%02x "
112 					"cookie=%u (expected 0) len=%u",
113 					event->wd, event->mask,
114 					event->cookie, event->len);
115 			} else {
116 				tst_res(TPASS, "get event: wd=%d "
117 					"mask=%02x cookie=%u len=%u",
118 					event->wd, event->mask,
119 					event->cookie, event->len);
120 			}
121 
122 		} else {
123 			tst_res(TFAIL, "get event: wd=%d mask=%02x "
124 				"(expected %x) cookie=%u len=%u",
125 				event->wd, event->mask,
126 				event_set[test_num],
127 				event->cookie, event->len);
128 		}
129 		test_num++;
130 		i += EVENT_SIZE + event->len;
131 	}
132 	for (; test_num < test_cnt; test_num++) {
133 		tst_res(TFAIL, "didn't get event: mask=%02x",
134 			event_set[test_num]);
135 
136 	}
137 }
138 
setup(void)139 static void setup(void)
140 {
141 	sprintf(fname, "tfile_%d", getpid());
142 
143 	SAFE_FILE_PRINTF(fname, "%s", fname);
144 
145 	fd_notify = SAFE_MYINOTIFY_INIT();
146 
147 	wd = SAFE_MYINOTIFY_ADD_WATCH(fd_notify, fname, IN_ALL_EVENTS);
148 	reap_wd = 1;
149 }
150 
cleanup(void)151 static void cleanup(void)
152 {
153 	if (reap_wd && myinotify_rm_watch(fd_notify, wd) < 0) {
154 		tst_res(TWARN | TERRNO, "inotify_rm_watch (%d, %d) failed",
155 			fd_notify, wd);
156 	}
157 
158 	if (fd_notify > 0)
159 		SAFE_CLOSE(fd_notify);
160 }
161 
162 static struct tst_test test = {
163 	.needs_tmpdir = 1,
164 	.setup = setup,
165 	.cleanup = cleanup,
166 	.test_all = verify_inotify,
167 };
168 
169 #else
170 	TST_TEST_TCONF("system doesn't have required inotify support");
171 #endif
172