1cb5fe245SEnji Cooper /*
2cb5fe245SEnji Cooper  * Copyright (c) 2009 Mark Heily <[email protected]>
3cb5fe245SEnji Cooper  *
4cb5fe245SEnji Cooper  * Permission to use, copy, modify, and distribute this software for any
5cb5fe245SEnji Cooper  * purpose with or without fee is hereby granted, provided that the above
6cb5fe245SEnji Cooper  * copyright notice and this permission notice appear in all copies.
7cb5fe245SEnji Cooper  *
8cb5fe245SEnji Cooper  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9cb5fe245SEnji Cooper  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10cb5fe245SEnji Cooper  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11cb5fe245SEnji Cooper  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12cb5fe245SEnji Cooper  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13cb5fe245SEnji Cooper  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14cb5fe245SEnji Cooper  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15cb5fe245SEnji Cooper  *
16cb5fe245SEnji Cooper  * $FreeBSD$
17cb5fe245SEnji Cooper  */
18cb5fe245SEnji Cooper 
19cb5fe245SEnji Cooper #include "common.h"
20cb5fe245SEnji Cooper 
21cb5fe245SEnji Cooper int vnode_fd;
22cb5fe245SEnji Cooper 
23*c9c283bdSAlex Richardson static void
test_kevent_vnode_add(void)24cb5fe245SEnji Cooper test_kevent_vnode_add(void)
25cb5fe245SEnji Cooper {
26cb5fe245SEnji Cooper     const char *test_id = "kevent(EVFILT_VNODE, EV_ADD)";
27cb5fe245SEnji Cooper     const char *testfile = "./kqueue-test.tmp";
28cb5fe245SEnji Cooper     struct kevent kev;
29cb5fe245SEnji Cooper 
30cb5fe245SEnji Cooper     test_begin(test_id);
31cb5fe245SEnji Cooper 
32cb5fe245SEnji Cooper     system("touch ./kqueue-test.tmp");
33cb5fe245SEnji Cooper     vnode_fd = open(testfile, O_RDONLY);
34cb5fe245SEnji Cooper     if (vnode_fd < 0)
35cb5fe245SEnji Cooper         err(1, "open of %s", testfile);
36cb5fe245SEnji Cooper     else
37cb5fe245SEnji Cooper         printf("vnode_fd = %d\n", vnode_fd);
38cb5fe245SEnji Cooper 
39cb5fe245SEnji Cooper     EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD,
40cb5fe245SEnji Cooper             NOTE_WRITE | NOTE_ATTRIB | NOTE_RENAME | NOTE_DELETE, 0, NULL);
41cb5fe245SEnji Cooper     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
42cb5fe245SEnji Cooper         err(1, "%s", test_id);
43cb5fe245SEnji Cooper 
44cb5fe245SEnji Cooper     success();
45cb5fe245SEnji Cooper }
46cb5fe245SEnji Cooper 
47*c9c283bdSAlex Richardson static void
test_kevent_vnode_note_delete(void)48cb5fe245SEnji Cooper test_kevent_vnode_note_delete(void)
49cb5fe245SEnji Cooper {
50cb5fe245SEnji Cooper     const char *test_id = "kevent(EVFILT_VNODE, NOTE_DELETE)";
51cb5fe245SEnji Cooper     struct kevent kev;
52cb5fe245SEnji Cooper 
53cb5fe245SEnji Cooper     test_begin(test_id);
54cb5fe245SEnji Cooper 
55cb5fe245SEnji Cooper     EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_DELETE, 0, NULL);
56cb5fe245SEnji Cooper     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
57cb5fe245SEnji Cooper         err(1, "%s", test_id);
58cb5fe245SEnji Cooper 
59cb5fe245SEnji Cooper     if (unlink("./kqueue-test.tmp") < 0)
60cb5fe245SEnji Cooper         err(1, "unlink");
61cb5fe245SEnji Cooper 
62cb5fe245SEnji Cooper     kevent_cmp(&kev, kevent_get(kqfd));
63cb5fe245SEnji Cooper 
64cb5fe245SEnji Cooper     success();
65cb5fe245SEnji Cooper }
66cb5fe245SEnji Cooper 
67*c9c283bdSAlex Richardson static void
test_kevent_vnode_note_write(void)68cb5fe245SEnji Cooper test_kevent_vnode_note_write(void)
69cb5fe245SEnji Cooper {
70cb5fe245SEnji Cooper     const char *test_id = "kevent(EVFILT_VNODE, NOTE_WRITE)";
71cb5fe245SEnji Cooper     struct kevent kev;
72cb5fe245SEnji Cooper 
73cb5fe245SEnji Cooper     test_begin(test_id);
74cb5fe245SEnji Cooper 
75cb5fe245SEnji Cooper     EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_WRITE, 0, NULL);
76cb5fe245SEnji Cooper     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
77cb5fe245SEnji Cooper         err(1, "%s", test_id);
78cb5fe245SEnji Cooper 
79cb5fe245SEnji Cooper     if (system("echo hello >> ./kqueue-test.tmp") < 0)
80cb5fe245SEnji Cooper         err(1, "system");
81cb5fe245SEnji Cooper 
82cb5fe245SEnji Cooper     /* BSD kqueue adds NOTE_EXTEND even though it was not requested */
83cb5fe245SEnji Cooper     /* BSD kqueue removes EV_ENABLE */
84cb5fe245SEnji Cooper     kev.flags &= ~EV_ENABLE; // XXX-FIXME compatibility issue
85cb5fe245SEnji Cooper     kev.fflags |= NOTE_EXTEND; // XXX-FIXME compatibility issue
86cb5fe245SEnji Cooper     kevent_cmp(&kev, kevent_get(kqfd));
87cb5fe245SEnji Cooper 
88cb5fe245SEnji Cooper     success();
89cb5fe245SEnji Cooper }
90cb5fe245SEnji Cooper 
91*c9c283bdSAlex Richardson static void
test_kevent_vnode_note_attrib(void)92cb5fe245SEnji Cooper test_kevent_vnode_note_attrib(void)
93cb5fe245SEnji Cooper {
94cb5fe245SEnji Cooper     const char *test_id = "kevent(EVFILT_VNODE, NOTE_ATTRIB)";
95cb5fe245SEnji Cooper     struct kevent kev;
96cb5fe245SEnji Cooper     int nfds;
97cb5fe245SEnji Cooper 
98cb5fe245SEnji Cooper     test_begin(test_id);
99cb5fe245SEnji Cooper 
100cb5fe245SEnji Cooper     EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_ATTRIB, 0, NULL);
101cb5fe245SEnji Cooper     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
102cb5fe245SEnji Cooper         err(1, "%s", test_id);
103cb5fe245SEnji Cooper 
104cb5fe245SEnji Cooper     if (system("touch ./kqueue-test.tmp") < 0)
105cb5fe245SEnji Cooper         err(1, "system");
106cb5fe245SEnji Cooper 
107cb5fe245SEnji Cooper     nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL);
108cb5fe245SEnji Cooper     if (nfds < 1)
109cb5fe245SEnji Cooper         err(1, "%s", test_id);
110*c9c283bdSAlex Richardson     if (kev.ident != (uintptr_t)vnode_fd ||
111cb5fe245SEnji Cooper             kev.filter != EVFILT_VNODE ||
112cb5fe245SEnji Cooper             kev.fflags != NOTE_ATTRIB)
113cb5fe245SEnji Cooper         err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)",
114cb5fe245SEnji Cooper                 test_id, (unsigned int)kev.ident, kev.filter, kev.flags);
115cb5fe245SEnji Cooper 
116cb5fe245SEnji Cooper     success();
117cb5fe245SEnji Cooper }
118cb5fe245SEnji Cooper 
119*c9c283bdSAlex Richardson static void
test_kevent_vnode_note_rename(void)120cb5fe245SEnji Cooper test_kevent_vnode_note_rename(void)
121cb5fe245SEnji Cooper {
122cb5fe245SEnji Cooper     const char *test_id = "kevent(EVFILT_VNODE, NOTE_RENAME)";
123cb5fe245SEnji Cooper     struct kevent kev;
124cb5fe245SEnji Cooper     int nfds;
125cb5fe245SEnji Cooper 
126cb5fe245SEnji Cooper     test_begin(test_id);
127cb5fe245SEnji Cooper 
128cb5fe245SEnji Cooper     EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_RENAME, 0, NULL);
129cb5fe245SEnji Cooper     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
130cb5fe245SEnji Cooper         err(1, "%s", test_id);
131cb5fe245SEnji Cooper 
132cb5fe245SEnji Cooper     if (system("mv ./kqueue-test.tmp ./kqueue-test2.tmp") < 0)
133cb5fe245SEnji Cooper         err(1, "system");
134cb5fe245SEnji Cooper 
135cb5fe245SEnji Cooper     nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL);
136cb5fe245SEnji Cooper     if (nfds < 1)
137cb5fe245SEnji Cooper         err(1, "%s", test_id);
138*c9c283bdSAlex Richardson     if (kev.ident != (uintptr_t)vnode_fd ||
139cb5fe245SEnji Cooper             kev.filter != EVFILT_VNODE ||
140cb5fe245SEnji Cooper             kev.fflags != NOTE_RENAME)
141cb5fe245SEnji Cooper         err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)",
142cb5fe245SEnji Cooper                 test_id, (unsigned int)kev.ident, kev.filter, kev.flags);
143cb5fe245SEnji Cooper 
144cb5fe245SEnji Cooper     if (system("mv ./kqueue-test2.tmp ./kqueue-test.tmp") < 0)
145cb5fe245SEnji Cooper         err(1, "system");
146cb5fe245SEnji Cooper 
147cb5fe245SEnji Cooper     success();
148cb5fe245SEnji Cooper }
149cb5fe245SEnji Cooper 
150*c9c283bdSAlex Richardson static void
test_kevent_vnode_del(void)151cb5fe245SEnji Cooper test_kevent_vnode_del(void)
152cb5fe245SEnji Cooper {
153cb5fe245SEnji Cooper     const char *test_id = "kevent(EVFILT_VNODE, EV_DELETE)";
154cb5fe245SEnji Cooper     struct kevent kev;
155cb5fe245SEnji Cooper 
156cb5fe245SEnji Cooper     test_begin(test_id);
157cb5fe245SEnji Cooper 
158cb5fe245SEnji Cooper     EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_DELETE, 0, 0, NULL);
159cb5fe245SEnji Cooper     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
160cb5fe245SEnji Cooper         err(1, "%s", test_id);
161cb5fe245SEnji Cooper 
162cb5fe245SEnji Cooper     success();
163cb5fe245SEnji Cooper }
164cb5fe245SEnji Cooper 
165*c9c283bdSAlex Richardson static void
test_kevent_vnode_disable_and_enable(void)166cb5fe245SEnji Cooper test_kevent_vnode_disable_and_enable(void)
167cb5fe245SEnji Cooper {
168cb5fe245SEnji Cooper     const char *test_id = "kevent(EVFILT_VNODE, EV_DISABLE and EV_ENABLE)";
169cb5fe245SEnji Cooper     struct kevent kev;
170cb5fe245SEnji Cooper     int nfds;
171cb5fe245SEnji Cooper 
172cb5fe245SEnji Cooper     test_begin(test_id);
173cb5fe245SEnji Cooper 
174cb5fe245SEnji Cooper     test_no_kevents();
175cb5fe245SEnji Cooper 
176cb5fe245SEnji Cooper     /* Add the watch and immediately disable it */
177cb5fe245SEnji Cooper     EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_ATTRIB, 0, NULL);
178cb5fe245SEnji Cooper     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
179cb5fe245SEnji Cooper         err(1, "%s", test_id);
180cb5fe245SEnji Cooper     kev.flags = EV_DISABLE;
181cb5fe245SEnji Cooper     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
182cb5fe245SEnji Cooper         err(1, "%s", test_id);
183cb5fe245SEnji Cooper 
184cb5fe245SEnji Cooper     /* Confirm that the watch is disabled */
185cb5fe245SEnji Cooper     if (system("touch ./kqueue-test.tmp") < 0)
186cb5fe245SEnji Cooper         err(1, "system");
187cb5fe245SEnji Cooper     test_no_kevents();
188cb5fe245SEnji Cooper 
189cb5fe245SEnji Cooper     /* Re-enable and check again */
190cb5fe245SEnji Cooper     kev.flags = EV_ENABLE;
191cb5fe245SEnji Cooper     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
192cb5fe245SEnji Cooper         err(1, "%s", test_id);
193cb5fe245SEnji Cooper     if (system("touch ./kqueue-test.tmp") < 0)
194cb5fe245SEnji Cooper         err(1, "system");
195cb5fe245SEnji Cooper     nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL);
196cb5fe245SEnji Cooper     if (nfds < 1)
197cb5fe245SEnji Cooper         err(1, "%s", test_id);
198*c9c283bdSAlex Richardson     if (kev.ident != (uintptr_t)vnode_fd ||
199cb5fe245SEnji Cooper             kev.filter != EVFILT_VNODE ||
200cb5fe245SEnji Cooper             kev.fflags != NOTE_ATTRIB)
201cb5fe245SEnji Cooper         err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)",
202cb5fe245SEnji Cooper                 test_id, (unsigned int)kev.ident, kev.filter, kev.flags);
203cb5fe245SEnji Cooper 
204cb5fe245SEnji Cooper     success();
205cb5fe245SEnji Cooper }
206cb5fe245SEnji Cooper 
207cb5fe245SEnji Cooper #if HAVE_EV_DISPATCH
208*c9c283bdSAlex Richardson static void
test_kevent_vnode_dispatch(void)209cb5fe245SEnji Cooper test_kevent_vnode_dispatch(void)
210cb5fe245SEnji Cooper {
211cb5fe245SEnji Cooper     const char *test_id = "kevent(EVFILT_VNODE, EV_DISPATCH)";
212cb5fe245SEnji Cooper     struct kevent kev;
213cb5fe245SEnji Cooper     int nfds;
214cb5fe245SEnji Cooper 
215cb5fe245SEnji Cooper     test_begin(test_id);
216cb5fe245SEnji Cooper 
217cb5fe245SEnji Cooper     test_no_kevents();
218cb5fe245SEnji Cooper 
219cb5fe245SEnji Cooper     EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_DISPATCH, NOTE_ATTRIB, 0, NULL);
220cb5fe245SEnji Cooper     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
221cb5fe245SEnji Cooper         err(1, "%s", test_id);
222cb5fe245SEnji Cooper 
223cb5fe245SEnji Cooper     if (system("touch ./kqueue-test.tmp") < 0)
224cb5fe245SEnji Cooper         err(1, "system");
225cb5fe245SEnji Cooper 
226cb5fe245SEnji Cooper     nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL);
227cb5fe245SEnji Cooper     if (nfds < 1)
228cb5fe245SEnji Cooper         err(1, "%s", test_id);
229*c9c283bdSAlex Richardson     if (kev.ident != (uintptr_t)vnode_fd ||
230cb5fe245SEnji Cooper             kev.filter != EVFILT_VNODE ||
231cb5fe245SEnji Cooper             kev.fflags != NOTE_ATTRIB)
232cb5fe245SEnji Cooper         err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)",
233cb5fe245SEnji Cooper                 test_id, (unsigned int)kev.ident, kev.filter, kev.flags);
234cb5fe245SEnji Cooper 
235cb5fe245SEnji Cooper     /* Confirm that the watch is disabled automatically */
236cb5fe245SEnji Cooper     puts("-- checking that watch is disabled");
237cb5fe245SEnji Cooper     if (system("touch ./kqueue-test.tmp") < 0)
238cb5fe245SEnji Cooper         err(1, "system");
239cb5fe245SEnji Cooper     test_no_kevents();
240cb5fe245SEnji Cooper 
241cb5fe245SEnji Cooper     /* Delete the watch */
242cb5fe245SEnji Cooper     EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_DELETE, NOTE_ATTRIB, 0, NULL);
243cb5fe245SEnji Cooper     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
244cb5fe245SEnji Cooper         err(1, "remove watch failed: %s", test_id);
245cb5fe245SEnji Cooper 
246cb5fe245SEnji Cooper     success();
247cb5fe245SEnji Cooper }
248cb5fe245SEnji Cooper #endif 	/* HAVE_EV_DISPATCH */
249cb5fe245SEnji Cooper 
250cb5fe245SEnji Cooper void
test_evfilt_vnode(void)251*c9c283bdSAlex Richardson test_evfilt_vnode(void)
252cb5fe245SEnji Cooper {
253cb5fe245SEnji Cooper     kqfd = kqueue();
254cb5fe245SEnji Cooper     test_kevent_vnode_add();
255cb5fe245SEnji Cooper     test_kevent_vnode_del();
256cb5fe245SEnji Cooper     test_kevent_vnode_disable_and_enable();
257cb5fe245SEnji Cooper #if HAVE_EV_DISPATCH
258cb5fe245SEnji Cooper     test_kevent_vnode_dispatch();
259cb5fe245SEnji Cooper #endif
260cb5fe245SEnji Cooper     test_kevent_vnode_note_write();
261cb5fe245SEnji Cooper     test_kevent_vnode_note_attrib();
262cb5fe245SEnji Cooper     test_kevent_vnode_note_rename();
263cb5fe245SEnji Cooper     test_kevent_vnode_note_delete();
264cb5fe245SEnji Cooper     close(kqfd);
265cb5fe245SEnji Cooper }
266