]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - contrib/netbsd-tests/kernel/kqueue/t_vnode.c
MFC r314450,r313439:
[FreeBSD/stable/10.git] / contrib / netbsd-tests / kernel / kqueue / t_vnode.c
1 #include <sys/event.h>
2 #include <sys/stat.h>
3 #include <sys/time.h>
4 #include <fcntl.h>
5 #include <stdio.h>
6 #include <unistd.h>
7
8 #include <atf-c.h>
9
10 /*
11  * Test cases for events triggered by manipulating a target directory
12  * content.  Using EVFILT_VNODE filter on the target directory descriptor.
13  *
14  */
15
16 static const char *dir_target = "foo";
17 static const char *dir_inside1 = "foo/bar1";
18 static const char *dir_inside2 = "foo/bar2";
19 static const char *dir_outside = "bar";
20 static const char *file_inside1 = "foo/baz1";
21 static const char *file_inside2 = "foo/baz2";
22 static const char *file_outside = "qux";
23 static const struct timespec ts = {0, 0};
24 static int kq = -1;
25 static int target = -1;
26
27 int init_target(void);
28 int init_kqueue(void);
29 int create_file(const char *);
30 void cleanup(void);
31
32 int
33 init_target(void)
34 {
35         if (mkdir(dir_target, S_IRWXU) < 0) {
36                 return -1;
37         }
38         target = open(dir_target, O_RDONLY, 0);
39         return target;
40 }
41
42 int
43 init_kqueue(void)
44 {
45         struct kevent eventlist[1];
46
47         kq = kqueue();
48         if (kq < 0) {
49                 return -1;
50         }
51         EV_SET(&eventlist[0], (uintptr_t)target, EVFILT_VNODE,
52                 EV_ADD | EV_ONESHOT, NOTE_DELETE |
53                 NOTE_WRITE | NOTE_EXTEND | NOTE_ATTRIB |
54                 NOTE_LINK | NOTE_RENAME | NOTE_REVOKE, 0, 0);
55         return kevent(kq, eventlist, 1, NULL, 0, NULL);
56 }
57
58 int
59 create_file(const char *file)
60 {
61         int fd;
62
63         fd = open(file, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
64         if (fd < 0) {
65                 return -1;
66         }
67         return close(fd);
68 }
69
70 void
71 cleanup(void)
72 {
73         (void)unlink(file_inside1);
74         (void)unlink(file_inside2);
75         (void)unlink(file_outside);
76         (void)rmdir(dir_inside1);
77         (void)rmdir(dir_inside2);
78         (void)rmdir(dir_outside);
79         (void)rmdir(dir_target);
80         (void)close(kq);
81         (void)close(target);
82 }
83
84 ATF_TC_WITH_CLEANUP(dir_no_note_link_create_file_in);
85 ATF_TC_HEAD(dir_no_note_link_create_file_in, tc)
86 {
87         atf_tc_set_md_var(tc, "descr", "This test case ensures "
88                 "that kevent(2) does not return NOTE_LINK for the directory "
89                 "'foo' if a file 'foo/baz' is created.");
90 }
91 ATF_TC_BODY(dir_no_note_link_create_file_in, tc)
92 {
93         struct kevent changelist[1];
94
95         ATF_REQUIRE(init_target() != -1);
96         ATF_REQUIRE(init_kqueue() != -1);
97
98         ATF_REQUIRE(create_file(file_inside1) != -1);
99         ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
100         ATF_CHECK_EQ(changelist[0].fflags & NOTE_LINK, 0);
101 }
102 ATF_TC_CLEANUP(dir_no_note_link_create_file_in, tc)
103 {
104         cleanup();
105 }
106
107 ATF_TC_WITH_CLEANUP(dir_no_note_link_delete_file_in);
108 ATF_TC_HEAD(dir_no_note_link_delete_file_in, tc)
109 {
110         atf_tc_set_md_var(tc, "descr", "This test case ensures "
111                 "that kevent(2) does not return NOTE_LINK for the directory "
112                 "'foo' if a file 'foo/baz' is deleted.");
113 }
114 ATF_TC_BODY(dir_no_note_link_delete_file_in, tc)
115 {
116         struct kevent changelist[1];
117
118         ATF_REQUIRE(init_target() != -1);
119         ATF_REQUIRE(create_file(file_inside1) != -1);
120         ATF_REQUIRE(init_kqueue() != -1);
121
122         ATF_REQUIRE(unlink(file_inside1) != -1);
123         ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
124         ATF_CHECK_EQ(changelist[0].fflags & NOTE_LINK, 0);
125 }
126 ATF_TC_CLEANUP(dir_no_note_link_delete_file_in, tc)
127 {
128         cleanup();
129 }
130
131 ATF_TC_WITH_CLEANUP(dir_no_note_link_mv_dir_within);
132 ATF_TC_HEAD(dir_no_note_link_mv_dir_within, tc)
133 {
134         atf_tc_set_md_var(tc, "descr", "This test case ensures "
135                 "that kevent(2) does not return NOTE_LINK for the directory "
136                 "'foo' if a directory 'foo/bar' is renamed to 'foo/baz'.");
137 }
138 ATF_TC_BODY(dir_no_note_link_mv_dir_within, tc)
139 {
140         struct kevent changelist[1];
141
142         ATF_REQUIRE(init_target() != -1);
143         ATF_REQUIRE(mkdir(dir_inside1, S_IRWXU) != -1);
144         ATF_REQUIRE(init_kqueue() != -1);
145
146         ATF_REQUIRE(rename(dir_inside1, dir_inside2) != -1);
147         ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
148         ATF_CHECK_EQ(changelist[0].fflags & NOTE_LINK, 0);
149 }
150 ATF_TC_CLEANUP(dir_no_note_link_mv_dir_within, tc)
151 {
152         cleanup();
153 }
154
155 ATF_TC_WITH_CLEANUP(dir_no_note_link_mv_file_within);
156 ATF_TC_HEAD(dir_no_note_link_mv_file_within, tc)
157 {
158         atf_tc_set_md_var(tc, "descr", "This test case ensures "
159                 "that kevent(2) does not return NOTE_LINK for the directory "
160                 "'foo' if a file 'foo/baz' is renamed to 'foo/qux'.");
161 }
162 ATF_TC_BODY(dir_no_note_link_mv_file_within, tc)
163 {
164         struct kevent changelist[1];
165
166         ATF_REQUIRE(init_target() != -1);
167         ATF_REQUIRE(create_file(file_inside1) != -1);
168         ATF_REQUIRE(init_kqueue() != -1);
169
170         ATF_REQUIRE(rename(file_inside1, file_inside2) != -1);
171         ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
172         ATF_CHECK_EQ(changelist[0].fflags & NOTE_LINK, 0);
173 }
174 ATF_TC_CLEANUP(dir_no_note_link_mv_file_within, tc)
175 {
176         cleanup();
177 }
178
179 ATF_TC_WITH_CLEANUP(dir_note_link_create_dir_in);
180 ATF_TC_HEAD(dir_note_link_create_dir_in, tc)
181 {
182         atf_tc_set_md_var(tc, "descr", "This test case ensures "
183                 "that kevent(2) returns NOTE_LINK for the directory "
184                 "'foo' if a directory 'foo/bar' is created.");
185 }
186 ATF_TC_BODY(dir_note_link_create_dir_in, tc)
187 {
188         struct kevent changelist[1];
189
190         ATF_REQUIRE(init_target() != -1);
191         ATF_REQUIRE(init_kqueue() != -1);
192
193         ATF_REQUIRE(mkdir(dir_inside1, S_IRWXU) != -1);
194         ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
195         ATF_CHECK_EQ(changelist[0].fflags & NOTE_LINK, NOTE_LINK);
196 }
197 ATF_TC_CLEANUP(dir_note_link_create_dir_in, tc)
198 {
199         cleanup();
200 }
201
202 ATF_TC_WITH_CLEANUP(dir_note_link_delete_dir_in);
203 ATF_TC_HEAD(dir_note_link_delete_dir_in, tc)
204 {
205         atf_tc_set_md_var(tc, "descr", "This test case ensures "
206                 "that kevent(2) returns NOTE_LINK for the directory "
207                 "'foo' if a directory 'foo/bar' is deleted.");
208 }
209 ATF_TC_BODY(dir_note_link_delete_dir_in, tc)
210 {
211         struct kevent changelist[1];
212
213         ATF_REQUIRE(init_target() != -1);
214         ATF_REQUIRE(mkdir(dir_inside1, S_IRWXU) != -1);
215         ATF_REQUIRE(init_kqueue() != -1);
216
217         ATF_REQUIRE(rmdir(dir_inside1) != -1);
218         ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
219         ATF_CHECK_EQ(changelist[0].fflags & NOTE_LINK, NOTE_LINK);
220 }
221 ATF_TC_CLEANUP(dir_note_link_delete_dir_in, tc)
222 {
223         cleanup();
224 }
225
226 ATF_TC_WITH_CLEANUP(dir_note_link_mv_dir_in);
227 ATF_TC_HEAD(dir_note_link_mv_dir_in, tc)
228 {
229         atf_tc_set_md_var(tc, "descr", "This test case ensures "
230                 "that kevent(2) returns NOTE_LINK for the directory "
231                 "'foo' if a directory 'bar' is renamed to 'foo/bar'.");
232 }
233 ATF_TC_BODY(dir_note_link_mv_dir_in, tc)
234 {
235         struct kevent changelist[1];
236
237         ATF_REQUIRE(init_target() != -1);
238         ATF_REQUIRE(mkdir(dir_outside, S_IRWXU) != -1);
239         ATF_REQUIRE(init_kqueue() != -1);
240
241         ATF_REQUIRE(rename(dir_outside, dir_inside1) != -1);
242         ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
243         ATF_CHECK_EQ(changelist[0].fflags & NOTE_LINK, NOTE_LINK);
244 }
245 ATF_TC_CLEANUP(dir_note_link_mv_dir_in, tc)
246 {
247         cleanup();
248 }
249
250 ATF_TC_WITH_CLEANUP(dir_note_link_mv_dir_out);
251 ATF_TC_HEAD(dir_note_link_mv_dir_out, tc)
252 {
253         atf_tc_set_md_var(tc, "descr", "This test case ensures "
254                 "that kevent(2) returns NOTE_LINK for the directory "
255                 "'foo' if a directory 'foo/bar' is renamed to 'bar'.");
256 }
257 ATF_TC_BODY(dir_note_link_mv_dir_out, tc)
258 {
259         struct kevent changelist[1];
260
261         ATF_REQUIRE(init_target() != -1);
262         ATF_REQUIRE(mkdir(dir_inside1, S_IRWXU) != -1);
263         ATF_REQUIRE(init_kqueue() != -1);
264
265         ATF_REQUIRE(rename(dir_inside1, dir_outside) != -1);
266         ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
267         ATF_CHECK_EQ(changelist[0].fflags & NOTE_LINK, NOTE_LINK);
268 }
269 ATF_TC_CLEANUP(dir_note_link_mv_dir_out, tc)
270 {
271         cleanup();
272 }
273
274 ATF_TC_WITH_CLEANUP(dir_note_write_create_dir_in);
275 ATF_TC_HEAD(dir_note_write_create_dir_in, tc)
276 {
277         atf_tc_set_md_var(tc, "descr", "This test case ensures "
278                 "that kevent(2) returns NOTE_WRITE for the directory "
279                 "'foo' if a directory 'foo/bar' is created.");
280 }
281 ATF_TC_BODY(dir_note_write_create_dir_in, tc)
282 {
283         struct kevent changelist[1];
284
285         ATF_REQUIRE(init_target() != -1);
286         ATF_REQUIRE(init_kqueue() != -1);
287
288         ATF_REQUIRE(mkdir(dir_inside1, S_IRWXU) != -1);
289         ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
290         ATF_CHECK_EQ(changelist[0].fflags & NOTE_WRITE, NOTE_WRITE);
291 }
292 ATF_TC_CLEANUP(dir_note_write_create_dir_in, tc)
293 {
294         cleanup();
295 }
296
297 ATF_TC_WITH_CLEANUP(dir_note_write_create_file_in);
298 ATF_TC_HEAD(dir_note_write_create_file_in, tc)
299 {
300         atf_tc_set_md_var(tc, "descr", "This test case ensures "
301                 "that kevent(2) returns NOTE_WRITE for the directory "
302                 "'foo' if a file 'foo/baz' is created.");
303 }
304 ATF_TC_BODY(dir_note_write_create_file_in, tc)
305 {
306         struct kevent changelist[1];
307
308         ATF_REQUIRE(init_target() != -1);
309         ATF_REQUIRE(init_kqueue() != -1);
310
311         ATF_REQUIRE(create_file(file_inside1) != -1);
312         ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
313         ATF_CHECK_EQ(changelist[0].fflags & NOTE_WRITE, NOTE_WRITE);
314 }
315 ATF_TC_CLEANUP(dir_note_write_create_file_in, tc)
316 {
317         cleanup();
318 }
319
320 ATF_TC_WITH_CLEANUP(dir_note_write_delete_dir_in);
321 ATF_TC_HEAD(dir_note_write_delete_dir_in, tc)
322 {
323         atf_tc_set_md_var(tc, "descr", "This test case ensures "
324                 "that kevent(2) returns NOTE_WRITE for the directory "
325                 "'foo' if a directory 'foo/bar' is deleted.");
326 }
327 ATF_TC_BODY(dir_note_write_delete_dir_in, tc)
328 {
329         struct kevent changelist[1];
330
331         ATF_REQUIRE(init_target() != -1);
332         ATF_REQUIRE(mkdir(dir_inside1, S_IRWXU) != -1);
333         ATF_REQUIRE(init_kqueue() != -1);
334
335         ATF_REQUIRE(rmdir(dir_inside1) != -1);
336         ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
337         ATF_CHECK_EQ(changelist[0].fflags & NOTE_WRITE, NOTE_WRITE);
338 }
339 ATF_TC_CLEANUP(dir_note_write_delete_dir_in, tc)
340 {
341         cleanup();
342 }
343
344 ATF_TC_WITH_CLEANUP(dir_note_write_delete_file_in);
345 ATF_TC_HEAD(dir_note_write_delete_file_in, tc)
346 {
347         atf_tc_set_md_var(tc, "descr", "This test case ensures "
348                 "that kevent(2) returns NOTE_WRITE for the directory "
349                 "'foo' if a file 'foo/baz' is deleted.");
350 }
351 ATF_TC_BODY(dir_note_write_delete_file_in, tc)
352 {
353         struct kevent changelist[1];
354
355         ATF_REQUIRE(init_target() != -1);
356         ATF_REQUIRE(create_file(file_inside1) != -1);
357         ATF_REQUIRE(init_kqueue() != -1);
358
359         ATF_REQUIRE(unlink(file_inside1) != -1);
360         ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
361         ATF_CHECK_EQ(changelist[0].fflags & NOTE_WRITE, NOTE_WRITE);
362 }
363 ATF_TC_CLEANUP(dir_note_write_delete_file_in, tc)
364 {
365         cleanup();
366 }
367
368 ATF_TC_WITH_CLEANUP(dir_note_write_mv_dir_in);
369 ATF_TC_HEAD(dir_note_write_mv_dir_in, tc)
370 {
371         atf_tc_set_md_var(tc, "descr", "This test case ensures "
372                 "that kevent(2) returns NOTE_WRITE for the directory "
373                 "'foo' if a directory 'bar' is renamed to 'foo/bar'.");
374 }
375 ATF_TC_BODY(dir_note_write_mv_dir_in, tc)
376 {
377         struct kevent changelist[1];
378
379         ATF_REQUIRE(init_target() != -1);
380         ATF_REQUIRE(mkdir(dir_outside, S_IRWXU) != -1);
381         ATF_REQUIRE(init_kqueue() != -1);
382
383         ATF_REQUIRE(rename(dir_outside, dir_inside1) != -1);
384         ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
385         ATF_CHECK_EQ(changelist[0].fflags & NOTE_WRITE, NOTE_WRITE);
386 }
387 ATF_TC_CLEANUP(dir_note_write_mv_dir_in, tc)
388 {
389         cleanup();
390 }
391
392 ATF_TC_WITH_CLEANUP(dir_note_write_mv_dir_out);
393 ATF_TC_HEAD(dir_note_write_mv_dir_out, tc)
394 {
395         atf_tc_set_md_var(tc, "descr", "This test case ensures "
396                 "that kevent(2) returns NOTE_WRITE for the directory "
397                 "'foo' if a directory 'foo/bar' is renamed to 'bar'.");
398 }
399 ATF_TC_BODY(dir_note_write_mv_dir_out, tc)
400 {
401         struct kevent changelist[1];
402
403         ATF_REQUIRE(init_target() != -1);
404         ATF_REQUIRE(mkdir(dir_inside1, S_IRWXU) != -1);
405         ATF_REQUIRE(init_kqueue() != -1);
406
407         ATF_REQUIRE(rename(dir_inside1, dir_outside) != -1);
408         ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
409         ATF_CHECK_EQ(changelist[0].fflags & NOTE_WRITE, NOTE_WRITE);
410 }
411 ATF_TC_CLEANUP(dir_note_write_mv_dir_out, tc)
412 {
413         cleanup();
414 }
415
416 ATF_TC_WITH_CLEANUP(dir_note_write_mv_dir_within);
417 ATF_TC_HEAD(dir_note_write_mv_dir_within, tc)
418 {
419         atf_tc_set_md_var(tc, "descr", "This test case ensures "
420                 "that kevent(2) returns NOTE_WRITE for the directory "
421                 "'foo' if a directory 'foo/bar' is renamed to 'foo/baz'.");
422 }
423 ATF_TC_BODY(dir_note_write_mv_dir_within, tc)
424 {
425         struct kevent changelist[1];
426
427         ATF_REQUIRE(init_target() != -1);
428         ATF_REQUIRE(mkdir(dir_inside1, S_IRWXU) != -1);
429         ATF_REQUIRE(init_kqueue() != -1);
430
431         ATF_REQUIRE(rename(dir_inside1, dir_inside2) != -1);
432         ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
433         ATF_CHECK_EQ(changelist[0].fflags & NOTE_WRITE, NOTE_WRITE);
434 }
435 ATF_TC_CLEANUP(dir_note_write_mv_dir_within, tc)
436 {
437         cleanup();
438 }
439
440 ATF_TC_WITH_CLEANUP(dir_note_write_mv_file_in);
441 ATF_TC_HEAD(dir_note_write_mv_file_in, tc)
442 {
443         atf_tc_set_md_var(tc, "descr", "This test case ensures "
444                 "that kevent(2) returns NOTE_WRITE for the directory "
445                 "'foo' if a file 'qux' is renamed to 'foo/baz'.");
446 }
447 ATF_TC_BODY(dir_note_write_mv_file_in, tc)
448 {
449         struct kevent changelist[1];
450
451         ATF_REQUIRE(init_target() != -1);
452         ATF_REQUIRE(create_file(file_outside) != -1);
453         ATF_REQUIRE(init_kqueue() != -1);
454
455         ATF_REQUIRE(rename(file_outside, file_inside1) != -1);
456         ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
457         ATF_CHECK_EQ(changelist[0].fflags & NOTE_WRITE, NOTE_WRITE);
458 }
459 ATF_TC_CLEANUP(dir_note_write_mv_file_in, tc)
460 {
461         cleanup();
462 }
463
464 ATF_TC_WITH_CLEANUP(dir_note_write_mv_file_out);
465 ATF_TC_HEAD(dir_note_write_mv_file_out, tc)
466 {
467         atf_tc_set_md_var(tc, "descr", "This test case ensures "
468                 "that kevent(2) returns NOTE_WRITE for the directory "
469                 "'foo' if a file 'foo/baz' is renamed to 'qux'.");
470 }
471 ATF_TC_BODY(dir_note_write_mv_file_out, tc)
472 {
473         struct kevent changelist[1];
474
475         ATF_REQUIRE(init_target() != -1);
476         ATF_REQUIRE(create_file(file_inside1) != -1);
477         ATF_REQUIRE(init_kqueue() != -1);
478
479         ATF_REQUIRE(rename(file_inside1, file_outside) != -1);
480         ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
481         ATF_CHECK_EQ(changelist[0].fflags & NOTE_WRITE, NOTE_WRITE);
482 }
483 ATF_TC_CLEANUP(dir_note_write_mv_file_out, tc)
484 {
485         cleanup();
486 }
487
488 ATF_TC_WITH_CLEANUP(dir_note_write_mv_file_within);
489 ATF_TC_HEAD(dir_note_write_mv_file_within, tc)
490 {
491         atf_tc_set_md_var(tc, "descr", "This test case ensures "
492                 "that kevent(2) returns NOTE_WRITE for the directory "
493                 "'foo' if a file 'foo/baz' is renamed to 'foo/qux'.");
494 }
495 ATF_TC_BODY(dir_note_write_mv_file_within, tc)
496 {
497         struct kevent changelist[1];
498
499         ATF_REQUIRE(init_target() != -1);
500         ATF_REQUIRE(create_file(file_inside1) != -1);
501         ATF_REQUIRE(init_kqueue() != -1);
502
503         ATF_REQUIRE(rename(file_inside1, file_inside2) != -1);
504         ATF_REQUIRE(kevent(kq, NULL, 0, changelist, 1, &ts) != -1);
505         ATF_CHECK_EQ(changelist[0].fflags & NOTE_WRITE, NOTE_WRITE);
506 }
507 ATF_TC_CLEANUP(dir_note_write_mv_file_within, tc)
508 {
509         cleanup();
510 }
511
512 ATF_TP_ADD_TCS(tp)
513 {
514         ATF_TP_ADD_TC(tp, dir_no_note_link_create_file_in);
515         ATF_TP_ADD_TC(tp, dir_no_note_link_delete_file_in);
516         ATF_TP_ADD_TC(tp, dir_no_note_link_mv_dir_within);
517         ATF_TP_ADD_TC(tp, dir_no_note_link_mv_file_within);
518         ATF_TP_ADD_TC(tp, dir_note_link_create_dir_in);
519         ATF_TP_ADD_TC(tp, dir_note_link_delete_dir_in);
520         ATF_TP_ADD_TC(tp, dir_note_link_mv_dir_in);
521         ATF_TP_ADD_TC(tp, dir_note_link_mv_dir_out);
522         ATF_TP_ADD_TC(tp, dir_note_write_create_dir_in);
523         ATF_TP_ADD_TC(tp, dir_note_write_create_file_in);
524         ATF_TP_ADD_TC(tp, dir_note_write_delete_dir_in);
525         ATF_TP_ADD_TC(tp, dir_note_write_delete_file_in);
526         ATF_TP_ADD_TC(tp, dir_note_write_mv_dir_in);
527         ATF_TP_ADD_TC(tp, dir_note_write_mv_dir_out);
528         ATF_TP_ADD_TC(tp, dir_note_write_mv_dir_within);
529         ATF_TP_ADD_TC(tp, dir_note_write_mv_file_in);
530         ATF_TP_ADD_TC(tp, dir_note_write_mv_file_out);
531         ATF_TP_ADD_TC(tp, dir_note_write_mv_file_within);
532         return atf_no_error();
533 }