• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2007 SWSoft.  All Rights Reserved.
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of version 2 of the GNU General Public License as
6  * published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it would be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11  *
12  * Further, this software is distributed without any warranty that it is
13  * free of the rightful claim of any third person regarding infringement
14  * or the like.  Any license provided herein, whether implied or
15  * otherwise, applies only to this software file.  Patent licenses, if
16  * any, provided herein do not apply to combinations of this program with
17  * other software, or any other product whatsoever.
18  *
19  * You should have received a copy of the GNU General Public License along
20  * with this program; if not, write the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22  *
23  * Started by Andrew Vagin <avagin@sw.ru>
24  *
25  * DESCRIPTION
26  *     Check that inotify work for a file
27  *
28  * ALGORITHM
29  *     Execute sequence file's operation and check return events
30  */
31 #include "config.h"
32 
33 #include <stdio.h>
34 #include <sys/stat.h>
35 #include <sys/types.h>
36 #include <fcntl.h>
37 #include <errno.h>
38 #include <string.h>
39 #include <sys/syscall.h>
40 #include "tst_test.h"
41 #include "inotify.h"
42 
43 #if defined(HAVE_SYS_INOTIFY_H)
44 #include <sys/inotify.h>
45 
46 #define EVENT_MAX 1024
47 /* size of the event structure, not counting name */
48 #define EVENT_SIZE  (sizeof (struct inotify_event))
49 /* reasonable guess as to size of 1024 events */
50 #define EVENT_BUF_LEN        (EVENT_MAX * (EVENT_SIZE + 16))
51 
52 #define BUF_SIZE 256
53 
54 static char fname[BUF_SIZE];
55 static char buf[BUF_SIZE];
56 static int fd, fd_notify;
57 static int wd, reap_wd;
58 
59 static unsigned int event_set[EVENT_MAX];
60 
61 static char event_buf[EVENT_BUF_LEN];
62 
verify_inotify(void)63 void verify_inotify(void)
64 {
65 	int test_cnt = 0;
66 
67 	/*
68 	 * generate sequence of events
69 	 */
70 	SAFE_CHMOD(fname, 0755);
71 	event_set[test_cnt] = IN_ATTRIB;
72 	test_cnt++;
73 
74 	if ((fd = open(fname, O_RDONLY)) == -1) {
75 		tst_brk(TBROK | TERRNO,
76 			"open(%s, O_RDWR|O_CREAT,0700) failed", fname);
77 	}
78 	event_set[test_cnt] = IN_OPEN;
79 	test_cnt++;
80 
81 	if (read(fd, buf, BUF_SIZE) == -1) {
82 		tst_brk(TBROK | TERRNO,
83 			"read(%d, buf, %d) failed", fd, BUF_SIZE);
84 	}
85 	event_set[test_cnt] = IN_ACCESS;
86 	test_cnt++;
87 
88 	SAFE_CLOSE(fd);
89 	event_set[test_cnt] = IN_CLOSE_NOWRITE;
90 	test_cnt++;
91 
92 	if ((fd = open(fname, O_RDWR | O_CREAT, 0700)) == -1) {
93 		tst_brk(TBROK,
94 			"open(%s, O_RDWR|O_CREAT,0700) failed", fname);
95 	}
96 	event_set[test_cnt] = IN_OPEN;
97 	test_cnt++;
98 
99 	if (write(fd, buf, BUF_SIZE) == -1) {
100 		tst_brk(TBROK,
101 			"write(%d, %s, 1) failed", fd, fname);
102 	}
103 	event_set[test_cnt] = IN_MODIFY;
104 	test_cnt++;
105 
106 	SAFE_CLOSE(fd);
107 	event_set[test_cnt] = IN_CLOSE_WRITE;
108 	test_cnt++;
109 
110 	/*
111 	 * get list of events
112 	 */
113 	int len, i = 0, test_num = 0;
114 	if ((len = read(fd_notify, event_buf, EVENT_BUF_LEN)) < 0) {
115 		tst_brk(TBROK,
116 			"read(%d, buf, %zu) failed",
117 			fd_notify, EVENT_BUF_LEN);
118 
119 	}
120 
121 	/*
122 	 * check events
123 	 */
124 	while (i < len) {
125 		struct inotify_event *event;
126 		event = (struct inotify_event *)&event_buf[i];
127 		if (test_num >= test_cnt) {
128 			tst_res(TFAIL,
129 				"get unnecessary event: wd=%d mask=%02x "
130 				"cookie=%u len=%u",
131 				event->wd, event->mask,
132 				event->cookie, event->len);
133 		} else if (event_set[test_num] == event->mask) {
134 			if (event->cookie != 0) {
135 				tst_res(TFAIL,
136 					"get event: wd=%d mask=%02x "
137 					"cookie=%u (expected 0) len=%u",
138 					event->wd, event->mask,
139 					event->cookie, event->len);
140 			} else {
141 				tst_res(TPASS, "get event: wd=%d "
142 					"mask=%02x cookie=%u len=%u",
143 					event->wd, event->mask,
144 					event->cookie, event->len);
145 			}
146 
147 		} else {
148 			tst_res(TFAIL, "get event: wd=%d mask=%02x "
149 				"(expected %x) cookie=%u len=%u",
150 				event->wd, event->mask,
151 				event_set[test_num],
152 				event->cookie, event->len);
153 		}
154 		test_num++;
155 		i += EVENT_SIZE + event->len;
156 	}
157 	for (; test_num < test_cnt; test_num++) {
158 		tst_res(TFAIL, "didn't get event: mask=%02x",
159 			event_set[test_num]);
160 
161 	}
162 }
163 
setup(void)164 static void setup(void)
165 {
166 	sprintf(fname, "tfile_%d", getpid());
167 
168 	SAFE_FILE_PRINTF(fname, "%s", fname);
169 
170 	if ((fd_notify = myinotify_init()) < 0) {
171 		if (errno == ENOSYS) {
172 			tst_brk(TCONF,
173 				"inotify is not configured in this kernel.");
174 		} else {
175 			tst_brk(TBROK | TERRNO,
176 				"inotify_init failed");
177 		}
178 	}
179 
180 	if ((wd = myinotify_add_watch(fd_notify, fname, IN_ALL_EVENTS)) < 0) {
181 		tst_brk(TBROK | TERRNO,
182 			"inotify_add_watch (%d, %s, IN_ALL_EVENTS) failed",
183 			fd_notify, fname);
184 		reap_wd = 1;
185 	};
186 
187 }
188 
cleanup(void)189 static void cleanup(void)
190 {
191 	if (reap_wd && myinotify_rm_watch(fd_notify, wd) < 0) {
192 		tst_res(TWARN | TERRNO, "inotify_rm_watch (%d, %d) failed",
193 			fd_notify, wd);
194 	}
195 
196 	if (fd_notify > 0)
197 		SAFE_CLOSE(fd_notify);
198 }
199 
200 static struct tst_test test = {
201 	.needs_tmpdir = 1,
202 	.setup = setup,
203 	.cleanup = cleanup,
204 	.test_all = verify_inotify,
205 };
206 
207 #else
208 	TST_TEST_TCONF("system doesn't have required inotify support");
209 #endif
210