• 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 <sys/fcntl.h>
37 #include <errno.h>
38 #include <string.h>
39 #include <sys/syscall.h>
40 #include "test.h"
41 #include "linux_syscall_numbers.h"
42 #include "inotify.h"
43 
44 #if defined(HAVE_SYS_INOTIFY_H)
45 #include <sys/inotify.h>
46 
47 #define EVENT_MAX 1024
48 /* size of the event structure, not counting name */
49 #define EVENT_SIZE  (sizeof (struct inotify_event))
50 /* reasonable guess as to size of 1024 events */
51 #define EVENT_BUF_LEN        (EVENT_MAX * (EVENT_SIZE + 16))
52 
53 char *TCID = "inotify01";
54 int TST_TOTAL = 7;
55 
56 static void setup(void);
57 static void cleanup(void);
58 
59 #define BUF_SIZE 256
60 static char fname[BUF_SIZE];
61 static char buf[BUF_SIZE];
62 static int fd, fd_notify;
63 static int wd, reap_wd;
64 
65 static int event_set[EVENT_MAX];
66 
67 static char event_buf[EVENT_BUF_LEN];
68 
main(int ac,char ** av)69 int main(int ac, char **av)
70 {
71 	int lc;
72 
73 	tst_parse_opts(ac, av, NULL, NULL);
74 
75 	setup();
76 
77 	for (lc = 0; TEST_LOOPING(lc); lc++) {
78 		tst_count = 0;
79 
80 		/*
81 		 * generate sequence of events
82 		 */
83 		if (chmod(fname, 0755) < 0) {
84 			tst_brkm(TBROK | TERRNO, cleanup,
85 				 "chmod(%s, 0755) failed", fname);
86 		}
87 		event_set[tst_count] = IN_ATTRIB;
88 		tst_count++;
89 
90 		if ((fd = open(fname, O_RDONLY)) == -1) {
91 			tst_brkm(TBROK | TERRNO, cleanup,
92 				 "open(%s, O_RDWR|O_CREAT,0700) failed", fname);
93 		}
94 		event_set[tst_count] = IN_OPEN;
95 		tst_count++;
96 
97 		if (read(fd, buf, BUF_SIZE) == -1) {
98 			tst_brkm(TBROK | TERRNO, cleanup,
99 				 "read(%d, buf, %d) failed", fd, BUF_SIZE);
100 		}
101 		event_set[tst_count] = IN_ACCESS;
102 		tst_count++;
103 
104 		if (close(fd) == -1) {
105 			tst_brkm(TBROK, cleanup, "close(%s) failed", fname);
106 		}
107 		event_set[tst_count] = IN_CLOSE_NOWRITE;
108 		tst_count++;
109 
110 		if ((fd = open(fname, O_RDWR | O_CREAT, 0700)) == -1) {
111 			tst_brkm(TBROK, cleanup,
112 				 "open(%s, O_RDWR|O_CREAT,0700) failed", fname);
113 		}
114 		event_set[tst_count] = IN_OPEN;
115 		tst_count++;
116 
117 		if (write(fd, buf, BUF_SIZE) == -1) {
118 			tst_brkm(TBROK, cleanup,
119 				 "write(%d, %s, 1) failed", fd, fname);
120 		}
121 		event_set[tst_count] = IN_MODIFY;
122 		tst_count++;
123 
124 		if (close(fd) == -1) {
125 			tst_brkm(TBROK, cleanup, "close(%s) failed", fname);
126 		}
127 		event_set[tst_count] = IN_CLOSE_WRITE;
128 		tst_count++;
129 
130 		if (TST_TOTAL != tst_count) {
131 			tst_brkm(TBROK, cleanup,
132 				 "TST_TOTAL and tst_count are not equal");
133 		}
134 		tst_count = 0;
135 
136 		/*
137 		 * get list on events
138 		 */
139 		int len, i = 0, test_num = 0;
140 		if ((len = read(fd_notify, event_buf, EVENT_BUF_LEN)) < 0) {
141 			tst_brkm(TBROK, cleanup,
142 				 "read(%d, buf, %zu) failed",
143 				 fd_notify, EVENT_BUF_LEN);
144 
145 		}
146 
147 		/*
148 		 * check events
149 		 */
150 		while (i < len) {
151 			struct inotify_event *event;
152 			event = (struct inotify_event *)&event_buf[i];
153 			if (test_num >= TST_TOTAL) {
154 				tst_resm(TFAIL,
155 					 "get unnecessary event: wd=%d mask=%x "
156 					 "cookie=%u len=%u",
157 					 event->wd, event->mask,
158 					 event->cookie, event->len);
159 			} else if (event_set[test_num] == event->mask) {
160 				if (event->cookie != 0) {
161 					tst_resm(TFAIL,
162 						 "get event: wd=%d mask=%x "
163 						 "cookie=%u (expected 0) len=%u",
164 						 event->wd, event->mask,
165 						 event->cookie, event->len);
166 				} else {
167 					tst_resm(TPASS, "get event: wd=%d "
168 						 "mask=%x cookie=%u len=%u",
169 						 event->wd, event->mask,
170 						 event->cookie, event->len);
171 				}
172 
173 			} else {
174 				tst_resm(TFAIL, "get event: wd=%d mask=%x "
175 					 "(expected %x) cookie=%u len=%u",
176 					 event->wd, event->mask,
177 					 event_set[test_num],
178 					 event->cookie, event->len);
179 			}
180 			test_num++;
181 			i += EVENT_SIZE + event->len;
182 		}
183 		for (; test_num < TST_TOTAL; test_num++) {
184 			tst_resm(TFAIL, "didn't get event: mask=%x",
185 				 event_set[test_num]);
186 
187 		}
188 
189 	}
190 
191 	cleanup();
192 	tst_exit();
193 }
194 
setup(void)195 static void setup(void)
196 {
197 
198 	tst_sig(NOFORK, DEF_HANDLER, cleanup);
199 
200 	TEST_PAUSE;
201 
202 	tst_tmpdir();
203 
204 	sprintf(fname, "tfile_%d", getpid());
205 	if ((fd = open(fname, O_RDWR | O_CREAT, 0700)) == -1) {
206 		tst_brkm(TBROK | TERRNO, cleanup,
207 			 "open(%s, O_RDWR|O_CREAT,0700) failed", fname);
208 	}
209 	if ((write(fd, fname, 1)) == -1) {
210 		tst_brkm(TBROK | TERRNO, cleanup, "write(%d, %s, 1) failed",
211 			 fd, fname);
212 	}
213 
214 	/* close the file we have open */
215 	if (close(fd) == -1) {
216 		tst_brkm(TBROK, cleanup, "close(%s) failed", fname);
217 	}
218 	if ((fd_notify = myinotify_init()) < 0) {
219 		if (errno == ENOSYS) {
220 			tst_brkm(TCONF, cleanup,
221 				 "inotify is not configured in this kernel.");
222 		} else {
223 			tst_brkm(TBROK | TERRNO, cleanup,
224 				 "inotify_init failed");
225 		}
226 	}
227 
228 	if ((wd = myinotify_add_watch(fd_notify, fname, IN_ALL_EVENTS)) < 0) {
229 		tst_brkm(TBROK | TERRNO, cleanup,
230 			 "inotify_add_watch (%d, %s, IN_ALL_EVENTS) failed",
231 			 fd_notify, fname);
232 		reap_wd = 1;
233 	};
234 
235 }
236 
cleanup(void)237 static void cleanup(void)
238 {
239 	if (reap_wd && myinotify_rm_watch(fd_notify, wd) < 0) {
240 		tst_resm(TWARN | TERRNO, "inotify_rm_watch (%d, %d) failed",
241 			 fd_notify, wd);
242 
243 	}
244 
245 	if (fd_notify > 0 && close(fd_notify))
246 		tst_resm(TWARN, "close(%d) failed", fd_notify);
247 
248 	tst_rmdir();
249 }
250 
251 #else
252 
253 char *TCID = "inotify01";
254 int TST_TOTAL = 0;
255 
main(void)256 int main(void)
257 {
258 	tst_brkm(TCONF, NULL, "system doesn't have required inotify support");
259 }
260 
261 #endif
262