master
c 996 lines 30.3 KB
Raw
1 /*++
2
3 Copyright (c) Microsoft. All rights reserved.
4
5 Module Name:
6
7 inotify.c
8
9 Abstract:
10
11 This file contains extensive inotify unit tests.
12
13 --*/
14
15 #include "lxtcommon.h"
16 #include "unittests.h"
17 #include "lxtfs.h"
18 #include <poll.h>
19 #include <dirent.h>
20 #include <sys/epoll.h>
21 #include <sys/time.h>
22 #include <sys/types.h>
23 #include <sys/stat.h>
24 #include <sys/inotify.h>
25 #include <sys/mount.h>
26 #include <unistd.h>
27 #include <fcntl.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <limits.h>
31 #include <errno.h>
32
33 #define LXT_NAME "INOTIFY"
34
35 #define INOTIFY_TEST_BASE_DIR_LXFS "/data/inotify_test/"
36 #define INOTIFY_TEST_PROCFS_MAX_QUEUED_EVENTS_FILE "/proc/sys/fs/inotify/max_queued_events"
37
38 int TestInotifyComprehensive1Common(char* BaseDir);
39
40 int TestInotifyComprehensive2Common(char* BaseDir);
41
42 LXT_VARIATION_HANDLER TestInotifyNonBlockRead;
43 LXT_VARIATION_HANDLER TestInotifyEventQueueOverflow;
44 LXT_VARIATION_HANDLER TestInotifyEpollLxfs;
45 LXT_VARIATION_HANDLER TestInotifyBasicLxfs;
46 LXT_VARIATION_HANDLER TestInotifyComprehensive1Lxfs;
47 LXT_VARIATION_HANDLER TestInotifyComprehensive2Lxfs;
48 LXT_VARIATION_HANDLER TestInotifyPosixUnlinkRenameLxfs;
49 LXT_VARIATION_HANDLER TestInotifyUnmountBindLxfs;
50 LXT_VARIATION_HANDLER TestInotifyFtruncateLxfs;
51 LXT_VARIATION_HANDLER TestInotifyPseudoPlugin;
52
53 //
54 // Global constants
55 //
56
57 static const LXT_VARIATION g_LxtVariations[] = {
58 {"Test non-blocking read of inotify descriptor", TestInotifyNonBlockRead},
59 {"Test overflow of inotify event queue", TestInotifyEventQueueOverflow},
60 {"Test inotify with epoll - lxfs", TestInotifyEpollLxfs},
61 {"Test inotify watching basic paths - lxfs", TestInotifyBasicLxfs},
62 {"Comprehensive inotify tests 1 - lxfs", TestInotifyComprehensive1Lxfs},
63 {"Comprehensive inotify tests 2 - lxfs", TestInotifyComprehensive2Lxfs},
64 {"Test inotify with POSIX unlink/rename - lxfs", TestInotifyPosixUnlinkRenameLxfs},
65 {"Test unmounting of a bind mount - lxfs", TestInotifyUnmountBindLxfs},
66 {"Test ftruncate - lxfs", TestInotifyFtruncateLxfs},
67 {"Test inotify pseudo plugin", TestInotifyPseudoPlugin}};
68
69 int InotifyTestEntry(int Argc, char* Argv[])
70
71 /*++
72 --*/
73
74 {
75
76 LXT_ARGS Args;
77 int Result;
78
79 LxtCheckResult(LxtInitialize(Argc, Argv, &Args, LXT_NAME));
80 LxtCheckResult(LxtRunVariations(&Args, g_LxtVariations, LXT_COUNT_OF(g_LxtVariations)));
81
82 ErrorExit:
83 LxtUninitialize();
84 return !LXT_SUCCESS(Result);
85 }
86
87 int TestInotifyNonBlockRead(PLXT_ARGS Args)
88
89 {
90
91 int Id;
92 char Buf[10];
93 int Result;
94
95 //
96 // There is nothing to read here, but should not block.
97 //
98
99 LxtCheckErrno(Id = inotify_init1(IN_NONBLOCK));
100 LxtCheckErrnoFailure(Result = read(Id, Buf, 1), EAGAIN);
101 LxtCheckErrnoZeroSuccess(close(Id));
102
103 Result = LXT_RESULT_SUCCESS;
104
105 ErrorExit:
106 return Result;
107 }
108
109 int TestInotifyEventQueueOverflow(PLXT_ARGS Args)
110
111 {
112
113 int Id;
114 int Fd;
115 int ProcFd;
116 char Buf[11];
117 int Result;
118 int OriginalMaxQueuedEvents;
119 char InotifyBuf[500];
120 struct inotify_event* Events[INOTIFY_TEST_EVENTS_BUF_SIZE];
121 int NumEvents;
122 char TestFile1[PATH_MAX];
123 char TestFile2[PATH_MAX];
124 char TestFile1Hlink[PATH_MAX];
125 char TestFile1Slink[PATH_MAX];
126
127 //
128 // Initialize and also do cleanup if the files have not been removed.
129 //
130
131 sprintf(TestFile1, "%s%s", INOTIFY_TEST_BASE_DIR_LXFS, INOTIFY_TEST_FILE1_NAME_ONLY);
132
133 sprintf(TestFile2, "%s%s", INOTIFY_TEST_BASE_DIR_LXFS, INOTIFY_TEST_FILE2_NAME_ONLY);
134
135 sprintf(TestFile1Hlink, "%s%s", INOTIFY_TEST_BASE_DIR_LXFS, INOTIFY_TEST_FILE1_HLINK_NAME_ONLY);
136
137 sprintf(TestFile1Slink, "%s%s", INOTIFY_TEST_BASE_DIR_LXFS, INOTIFY_TEST_FILE1_SLINK_NAME_ONLY);
138
139 unlink(TestFile1);
140 unlink(TestFile2);
141 unlink(TestFile1Hlink);
142 unlink(TestFile1Slink);
143 rmdir(INOTIFY_TEST_BASE_DIR_LXFS);
144 LxtCheckErrnoZeroSuccess(mkdir(INOTIFY_TEST_BASE_DIR_LXFS, 0777));
145 LxtCheckErrno(Fd = creat(TestFile1, 0777));
146 LxtCheckErrnoZeroSuccess(close(Fd));
147
148 //
149 // Read the procFS value /proc/sys/fs/inotify/max_queued_events.
150 //
151
152 LxtCheckErrno(ProcFd = open(INOTIFY_TEST_PROCFS_MAX_QUEUED_EVENTS_FILE, O_RDWR));
153
154 LxtCheckErrno(Result = read(ProcFd, Buf, sizeof(Buf)));
155 OriginalMaxQueuedEvents = atoi(Buf);
156 LxtCheckNotEqual(OriginalMaxQueuedEvents, 0, "%d");
157
158 //
159 // Change the value to -1, verify failed.
160 //
161
162 sprintf(Buf, "-1");
163 LxtCheckErrnoFailure(Result = write(ProcFd, Buf, strlen(Buf)), EINVAL);
164
165 //
166 // Change the value to INT_MAX + 1 (2^31), verify failed.
167 //
168
169 sprintf(Buf, "2147483648");
170 LxtCheckErrnoFailure(Result = write(ProcFd, Buf, strlen(Buf)), EINVAL);
171
172 //
173 // Change the value to INT_MAX (2^31 - 1), verify succeeded.
174 //
175
176 sprintf(Buf, "2147483647");
177 LxtCheckErrno(Result = write(ProcFd, Buf, strlen(Buf)));
178 LxtCheckEqual(atoi(Buf), INT_MAX, "%d");
179
180 //
181 // Change the value to 2, and then read it back to verify.
182 //
183
184 sprintf(Buf, "2");
185 LxtCheckErrno(Result = write(ProcFd, Buf, strlen(Buf)));
186 LxtCheckErrno(Result = read(ProcFd, Buf, sizeof(Buf)));
187 LxtCheckEqual(atoi(Buf), 2, "%d");
188
189 //
190 // Generate 2 inotify events, verify that there is no overflow.
191 //
192
193 LxtCheckErrno(Id = inotify_init());
194 LxtCheckErrno(Result = inotify_add_watch(Id, TestFile1, IN_ALL_EVENTS));
195 LxtCheckErrno(Fd = open(TestFile1, O_RDWR));
196 LxtCheckErrnoZeroSuccess(close(Fd));
197 LxtCheckErrno(LxtFsInotifyReadAndProcess(Id, InotifyBuf, sizeof(InotifyBuf), Events, INOTIFY_TEST_EVENTS_BUF_SIZE, &NumEvents, FALSE));
198
199 LxtCheckEqual(NumEvents, 2, "%d");
200 LxtCheckEqual(Events[0]->mask, IN_OPEN, "%d");
201 LxtCheckEqual(Events[1]->mask, IN_CLOSE_WRITE, "%d");
202
203 //
204 // Generate 3 inotify events, verify that there is an overflow.
205 //
206
207 LxtCheckErrno(Fd = open(TestFile1, O_RDWR));
208 LxtCheckErrnoZeroSuccess(fchmod(Fd, 0666));
209 LxtCheckErrnoZeroSuccess(fchmod(Fd, 0777));
210 LxtCheckErrnoZeroSuccess(close(Fd));
211 LxtCheckErrno(LxtFsInotifyReadAndProcess(Id, InotifyBuf, sizeof(InotifyBuf), Events, INOTIFY_TEST_EVENTS_BUF_SIZE, &NumEvents, FALSE));
212
213 LxtCheckEqual(NumEvents, 3, "%d");
214 LxtCheckEqual(Events[0]->mask, IN_OPEN, "%d");
215 LxtCheckEqual(Events[1]->mask, IN_ATTRIB, "%d");
216 LxtCheckEqual(Events[2]->mask, IN_Q_OVERFLOW, "%d");
217 LxtCheckEqual(Events[2]->wd, -1, "%d");
218 LxtCheckEqual(Events[2]->cookie, 0, "%d");
219 LxtCheckEqual(Events[1]->len, 0, "%d");
220
221 //
222 // Restore the max_queued_events value to the original value read
223 // in the beginning, and verify.
224 //
225
226 sprintf(Buf, "%d", OriginalMaxQueuedEvents);
227 LxtCheckErrno(Result = write(ProcFd, Buf, strlen(Buf)));
228 LxtCheckErrno(Result = read(ProcFd, Buf, sizeof(Buf)));
229 LxtCheckEqual(atoi(Buf), OriginalMaxQueuedEvents, "%d");
230
231 Result = LXT_RESULT_SUCCESS;
232
233 ErrorExit:
234 close(Id);
235 close(Fd);
236 close(ProcFd);
237 unlink(TestFile1);
238 unlink(TestFile2);
239 unlink(TestFile1Hlink);
240 unlink(TestFile1Slink);
241 rmdir(INOTIFY_TEST_BASE_DIR_LXFS);
242 return Result;
243 }
244
245 int TestInotifyEpollLxfs(PLXT_ARGS Args)
246
247 {
248
249 return LxtFsInotifyEpollCommon(INOTIFY_TEST_BASE_DIR_LXFS);
250 }
251
252 int TestInotifyBasicLxfs(PLXT_ARGS Args)
253
254 {
255
256 int Id;
257 int Result;
258 int Wd[10];
259
260 //
261 // Test watching basic Lxfs paths.
262 //
263
264 LxtCheckErrno(Id = inotify_init());
265 LxtCheckErrno(Wd[0] = inotify_add_watch(Id, "/", IN_ALL_EVENTS));
266 LxtCheckErrno(Wd[1] = inotify_add_watch(Id, "/mnt", IN_ALL_EVENTS));
267 LxtCheckErrno(Wd[2] = inotify_add_watch(Id, "/mnt/", IN_ALL_EVENTS));
268 LxtCheckErrno(Wd[3] = inotify_add_watch(Id, "/proc", IN_ALL_EVENTS));
269 LxtCheckErrno(Wd[4] = inotify_add_watch(Id, "/sys", IN_ALL_EVENTS));
270 Result = LXT_RESULT_SUCCESS;
271
272 ErrorExit:
273 close(Id);
274 return Result;
275 }
276
277 int TestInotifyComprehensive1Lxfs(PLXT_ARGS Args)
278
279 {
280
281 return TestInotifyComprehensive1Common(INOTIFY_TEST_BASE_DIR_LXFS);
282 }
283
284 int TestInotifyComprehensive1Common(char* BaseDir)
285
286 /*++
287 --*/
288
289 {
290
291 int Fd;
292 int Id1;
293 int Id2;
294 int Wd[10];
295 char Buf[10];
296 char InotifyBuf[500];
297 struct inotify_event* Events[INOTIFY_TEST_EVENTS_BUF_SIZE];
298 int NumEvents;
299 int Bytes;
300 int Result;
301 int Index;
302 int AttribEvent;
303 int CreateEvent;
304 char TestFile1[PATH_MAX];
305 char TestFile2[PATH_MAX];
306 char TestFile1Hlink[PATH_MAX];
307 char TestFile1Slink[PATH_MAX];
308
309 //
310 // Initialize and also do cleanup if the files have not been removed.
311 //
312
313 sprintf(TestFile1, "%s%s", BaseDir, INOTIFY_TEST_FILE1_NAME_ONLY);
314 sprintf(TestFile2, "%s%s", BaseDir, INOTIFY_TEST_FILE2_NAME_ONLY);
315 sprintf(TestFile1Hlink, "%s%s", BaseDir, INOTIFY_TEST_FILE1_HLINK_NAME_ONLY);
316 sprintf(TestFile1Slink, "%s%s", BaseDir, INOTIFY_TEST_FILE1_SLINK_NAME_ONLY);
317 unlink(TestFile1);
318 unlink(TestFile2);
319 unlink(TestFile1Hlink);
320 unlink(TestFile1Slink);
321 rmdir(BaseDir);
322 LxtCheckErrnoZeroSuccess(mkdir(BaseDir, 0777));
323 LxtCheckErrno(Fd = creat(TestFile1, 0777));
324 LxtCheckErrnoZeroSuccess(close(Fd));
325
326 //
327 // Setup inotify.
328 //
329
330 LxtCheckErrno(Id1 = inotify_init());
331 LxtCheckErrno(Id2 = inotify_init());
332 LxtCheckErrno(Wd[0] = inotify_add_watch(Id1, TestFile1, IN_ALL_EVENTS));
333
334 //
335 // Check that "output params" can also be specified as input.
336 //
337
338 LxtCheckErrno(Wd[1] = inotify_add_watch(Id1, BaseDir, IN_ALL_EVENTS | IN_IGNORED | IN_ISDIR | IN_Q_OVERFLOW | IN_UNMOUNT));
339
340 LxtCheckEqual(Wd[0], 1, "%d");
341 LxtCheckEqual(Wd[1], 2, "%d");
342
343 //
344 // Test IN_OPEN, IN_ATTRIB, IN_MODIFY, IN_ACCESS, IN_CLOSE_WRITE.
345 //
346
347 LxtCheckErrno(Fd = open(TestFile1, O_RDWR));
348 LxtCheckErrnoZeroSuccess(fchmod(Fd, 0666));
349 LxtCheckErrno(Bytes = write(Fd, Buf, 10));
350 LxtCheckEqual(Bytes, 10, "%d");
351 LxtCheckErrno(Bytes = write(Fd, Buf, 10));
352 LxtCheckEqual(Bytes, 10, "%d");
353 LxtCheckErrnoZeroSuccess(lseek(Fd, 0, SEEK_SET));
354 LxtCheckErrno(Bytes = read(Fd, Buf, 10));
355 LxtCheckEqual(Bytes, 10, "%d");
356 LxtCheckErrno(Bytes = read(Fd, Buf, 10));
357 LxtCheckEqual(Bytes, 10, "%d");
358 LxtCheckErrnoZeroSuccess(fchmod(Fd, 0777));
359 LxtCheckErrnoZeroSuccess(close(Fd));
360
361 //
362 // Verify.
363 //
364
365 LxtCheckErrno(LxtFsInotifyReadAndProcess(Id1, InotifyBuf, sizeof(InotifyBuf), Events, INOTIFY_TEST_EVENTS_BUF_SIZE, &NumEvents, FALSE));
366
367 LxtCheckEqual(NumEvents, 16, "%d");
368 for (Index = 0; Index < 2; Index++)
369 {
370 LxtCheckEqual(Events[0 + Index]->mask, IN_OPEN, "%d");
371 LxtCheckEqual(Events[2 + Index]->mask, IN_ATTRIB, "%d");
372 LxtCheckEqual(Events[4 + Index]->mask, IN_MODIFY, "%d");
373 LxtCheckEqual(Events[6 + Index]->mask, IN_MODIFY, "%d");
374 LxtCheckEqual(Events[8 + Index]->mask, IN_ACCESS, "%d");
375 LxtCheckEqual(Events[10 + Index]->mask, IN_ACCESS, "%d");
376 LxtCheckEqual(Events[12 + Index]->mask, IN_ATTRIB, "%d");
377 LxtCheckEqual(Events[14 + Index]->mask, IN_CLOSE_WRITE, "%d");
378 }
379
380 for (Index = 0; Index < NumEvents; Index++)
381 {
382 LxtCheckEqual(Events[Index]->cookie, 0, "%d");
383 if ((Index % 2) == 0)
384 {
385
386 //
387 // The parent directory.
388 //
389
390 LxtCheckEqual(Events[Index]->wd, 2, "%d");
391 LxtCheckTrue(strcmp(Events[Index]->name, INOTIFY_TEST_FILE1_NAME_ONLY) == 0);
392 LxtCheckNotEqual(Events[Index]->len, 0, "%d");
393 }
394 else
395 {
396
397 //
398 // The file (child).
399 //
400
401 LxtCheckEqual(Events[Index]->wd, 1, "%d");
402 LxtCheckEqual(Events[Index]->len, 0, "%d");
403 }
404 }
405
406 //
407 // Test IN_CLOSE_NOWRITE.
408 //
409
410 LxtCheckErrno(Fd = open(TestFile1, O_RDONLY));
411 LxtCheckErrno(Bytes = read(Fd, Buf, 10));
412 LxtCheckEqual(Bytes, 10, "%d");
413 LxtCheckErrno(Bytes = read(Fd, Buf, 10));
414 LxtCheckEqual(Bytes, 10, "%d");
415 LxtCheckErrnoZeroSuccess(close(Fd));
416
417 //
418 // Verify.
419 //
420
421 LxtCheckErrno(LxtFsInotifyReadAndProcess(Id1, InotifyBuf, sizeof(InotifyBuf), Events, INOTIFY_TEST_EVENTS_BUF_SIZE, &NumEvents, FALSE));
422
423 LxtCheckEqual(NumEvents, 8, "%d");
424
425 //
426 // Test that opening an existing file with O_TRUNC generates IN_MODIFY,
427 // even if the open is for read-only access.
428 //
429
430 LxtCheckErrno(Fd = open(TestFile1, O_RDONLY | O_TRUNC));
431 LxtCheckErrnoZeroSuccess(close(Fd));
432
433 //
434 // Verify.
435 //
436
437 LxtCheckErrno(LxtFsInotifyReadAndProcess(Id1, InotifyBuf, sizeof(InotifyBuf), Events, INOTIFY_TEST_EVENTS_BUF_SIZE, &NumEvents, FALSE));
438
439 LxtCheckEqual(NumEvents, 6, "%d");
440 LxtCheckEqual(Events[0]->mask, IN_MODIFY, "%d");
441 LxtCheckEqual(Events[1]->mask, IN_MODIFY, "%d");
442 LxtCheckEqual(Events[2]->mask, IN_OPEN, "%d");
443 LxtCheckEqual(Events[3]->mask, IN_OPEN, "%d");
444 LxtCheckEqual(Events[4]->mask, IN_CLOSE_NOWRITE, "%d");
445 LxtCheckEqual(Events[5]->mask, IN_CLOSE_NOWRITE, "%d");
446
447 //
448 // Test that opening an existing file with only O_PATH generates IN_OPEN.
449 //
450
451 LxtCheckErrno(Fd = open(TestFile1, O_PATH));
452 LxtCheckErrnoZeroSuccess(close(Fd));
453
454 //
455 // Verify.
456 //
457
458 LxtCheckErrno(LxtFsInotifyReadAndProcess(Id1, InotifyBuf, sizeof(InotifyBuf), Events, INOTIFY_TEST_EVENTS_BUF_SIZE, &NumEvents, FALSE));
459
460 LxtCheckEqual(NumEvents, 4, "%d");
461 LxtCheckEqual(Events[0]->mask, IN_OPEN, "%d");
462 LxtCheckEqual(Events[1]->mask, IN_OPEN, "%d");
463 LxtCheckEqual(Events[2]->mask, IN_CLOSE_NOWRITE, "%d");
464 LxtCheckEqual(Events[3]->mask, IN_CLOSE_NOWRITE, "%d");
465
466 //
467 // Test IN_MOVED_FROM, IN_MOVED_TO, IN_MOVE_SELF
468 // (rename with no overwrite).
469 //
470
471 LxtCheckErrnoZeroSuccess(rename(TestFile1, TestFile2));
472 LxtCheckErrnoZeroSuccess(rename(TestFile2, TestFile1));
473
474 //
475 // Verify.
476 //
477
478 LxtCheckErrno(LxtFsInotifyReadAndProcess(Id1, InotifyBuf, sizeof(InotifyBuf), Events, INOTIFY_TEST_EVENTS_BUF_SIZE, &NumEvents, FALSE));
479
480 LxtCheckEqual(NumEvents, 6, "%d");
481 LxtCheckEqual(Events[0]->mask, IN_MOVED_FROM, "%d");
482 LxtCheckEqual(Events[1]->mask, IN_MOVED_TO, "%d");
483 LxtCheckEqual(Events[2]->mask, IN_MOVE_SELF, "%d");
484 LxtCheckEqual(Events[0]->cookie, Events[1]->cookie, "%d");
485 LxtCheckTrue(strcmp(Events[0]->name, INOTIFY_TEST_FILE1_NAME_ONLY) == 0);
486 LxtCheckTrue(strcmp(Events[1]->name, INOTIFY_TEST_FILE2_NAME_ONLY) == 0);
487
488 //
489 // Test IN_DELETE and IN_DELETE_SELF.
490 //
491
492 LxtCheckErrnoZeroSuccess(unlink(TestFile1));
493
494 //
495 // Verify.
496 //
497
498 LxtCheckErrno(LxtFsInotifyReadAndProcess(Id1, InotifyBuf, sizeof(InotifyBuf), Events, INOTIFY_TEST_EVENTS_BUF_SIZE, &NumEvents, FALSE));
499
500 LxtCheckEqual(NumEvents, 4, "%d");
501 LxtCheckEqual(Events[0]->mask, IN_ATTRIB, "%d");
502 LxtCheckEqual(Events[1]->mask, IN_DELETE_SELF, "%d");
503 LxtCheckEqual(Events[2]->mask, IN_IGNORED, "%d");
504 LxtCheckEqual(Events[3]->mask, IN_DELETE, "%d");
505 LxtCheckEqual(Events[0]->wd, 1, "%d");
506 LxtCheckEqual(Events[1]->wd, 1, "%d");
507 LxtCheckEqual(Events[2]->wd, 1, "%d");
508 LxtCheckEqual(Events[3]->wd, 2, "%d");
509 //
510 // Test IN_CREATE, and that inotify_rm_watch() generates IN_IGNORED.
511 //
512
513 LxtCheckErrno(Fd = creat(TestFile1, 0777));
514 LxtCheckErrnoZeroSuccess(close(Fd));
515 LxtCheckErrno(Wd[0] = inotify_add_watch(Id1, TestFile1, IN_ALL_EVENTS));
516 LxtCheckErrnoZeroSuccess(inotify_rm_watch(Id1, Wd[0]));
517 LxtCheckErrnoZeroSuccess(inotify_rm_watch(Id1, Wd[1]));
518
519 //
520 // Verify.
521 //
522
523 LxtCheckErrno(LxtFsInotifyReadAndProcess(Id1, InotifyBuf, sizeof(InotifyBuf), Events, INOTIFY_TEST_EVENTS_BUF_SIZE, &NumEvents, FALSE));
524
525 LxtCheckEqual(NumEvents, 5, "%d");
526 LxtCheckEqual(Events[0]->mask, IN_CREATE, "%d");
527 LxtCheckEqual(Events[1]->mask, IN_OPEN, "%d");
528 LxtCheckEqual(Events[2]->mask, IN_CLOSE_WRITE, "%d");
529 LxtCheckEqual(Events[3]->mask, IN_IGNORED, "%d");
530 LxtCheckEqual(Events[4]->mask, IN_IGNORED, "%d");
531 LxtCheckEqual(Events[0]->wd, 2, "%d");
532 LxtCheckEqual(Events[1]->wd, 2, "%d");
533 LxtCheckEqual(Events[2]->wd, 2, "%d");
534 LxtCheckEqual(Events[3]->wd, 3, "%d");
535 LxtCheckEqual(Events[4]->wd, 2, "%d");
536
537 //
538 // Test that IN_ONESHOT generates only one event and then IN_IGNORED.
539 //
540
541 LxtCheckErrno(Wd[0] = inotify_add_watch(Id1, TestFile1, IN_ALL_EVENTS | IN_ONESHOT));
542 LxtCheckErrno(Fd = open(TestFile1, O_RDONLY));
543 LxtCheckErrnoZeroSuccess(close(Fd));
544
545 //
546 // Verify.
547 //
548
549 LxtCheckErrno(LxtFsInotifyReadAndProcess(Id1, InotifyBuf, sizeof(InotifyBuf), Events, INOTIFY_TEST_EVENTS_BUF_SIZE, &NumEvents, FALSE));
550
551 LxtCheckEqual(NumEvents, 2, "%d");
552 LxtCheckEqual(Events[0]->mask, IN_OPEN, "%d");
553 LxtCheckEqual(Events[1]->mask, IN_IGNORED, "%d");
554
555 //
556 // Test IN_ONLYDIR on file, should fail.
557 //
558
559 LxtCheckErrnoFailure(Wd[1] = inotify_add_watch(Id1, TestFile1, IN_ALL_EVENTS | IN_ONLYDIR), ENOTDIR);
560
561 //
562 // Test operations on directories.
563 //
564
565 LxtCheckErrno(Wd[1] = inotify_add_watch(Id1, BaseDir, IN_ALL_EVENTS | IN_ONLYDIR));
566
567 LxtCheckErrno(Fd = open(BaseDir, O_RDONLY));
568 LxtCheckErrnoZeroSuccess(fchmod(Fd, 0666));
569 LxtCheckErrnoZeroSuccess(fchmod(Fd, 0777));
570 LxtCheckErrnoZeroSuccess(close(Fd));
571
572 //
573 // Verify.
574 //
575
576 LxtCheckErrno(LxtFsInotifyReadAndProcess(Id1, InotifyBuf, sizeof(InotifyBuf), Events, INOTIFY_TEST_EVENTS_BUF_SIZE, &NumEvents, FALSE));
577
578 LxtCheckEqual(NumEvents, 3, "%d");
579 LxtCheckEqual(Events[0]->mask, IN_OPEN | IN_ISDIR, "%d");
580 LxtCheckEqual(Events[1]->mask, IN_ATTRIB | IN_ISDIR, "%d");
581 LxtCheckEqual(Events[2]->mask, IN_CLOSE_NOWRITE | IN_ISDIR, "%d");
582
583 //
584 // Test creating a symbolic link.
585 //
586
587 LxtCheckErrno(Wd[0] = inotify_add_watch(Id1, TestFile1, IN_ALL_EVENTS));
588 LxtCheckErrnoZeroSuccess(symlink(TestFile1, TestFile1Slink));
589
590 //
591 // Verify.
592 //
593
594 LxtCheckErrno(LxtFsInotifyReadAndProcess(Id1, InotifyBuf, sizeof(InotifyBuf), Events, INOTIFY_TEST_EVENTS_BUF_SIZE, &NumEvents, FALSE));
595
596 LxtCheckEqual(NumEvents, 1, "%d");
597 LxtCheckEqual(Events[0]->mask, IN_CREATE, "%d");
598 LxtCheckEqual(Events[0]->wd, 5, "%d");
599 LxtCheckTrue(strcmp(Events[0]->name, INOTIFY_TEST_FILE1_SLINK_NAME_ONLY) == 0);
600
601 //
602 // Test creating a hard link.
603 //
604
605 LxtCheckErrnoZeroSuccess(link(TestFile1, TestFile1Hlink));
606
607 //
608 // Verify. Note that Ubuntu generates 2 events, whereas WSL generates 4 events.
609 // This is due to WSL performing unnecessary file opens, which will be fixed
610 // in the future. Also, the ordering of the events differs between Ubuntu and WSL.
611 //
612
613 LxtCheckErrno(LxtFsInotifyReadAndProcess(Id1, InotifyBuf, sizeof(InotifyBuf), Events, INOTIFY_TEST_EVENTS_BUF_SIZE, &NumEvents, FALSE));
614
615 LxtCheckTrue((NumEvents == 2) || (NumEvents == 4));
616 if (Events[0]->mask == IN_ATTRIB)
617 {
618 AttribEvent = 0;
619 CreateEvent = 1;
620 }
621 else
622 {
623 AttribEvent = 1;
624 CreateEvent = 0;
625 }
626
627 LxtCheckEqual(Events[AttribEvent]->mask, IN_ATTRIB, "%d");
628 LxtCheckEqual(Events[AttribEvent]->wd, 6, "%d");
629 LxtCheckEqual(Events[CreateEvent]->mask, IN_CREATE, "%d");
630 LxtCheckEqual(Events[CreateEvent]->wd, 5, "%d");
631 LxtCheckTrue(strcmp(Events[CreateEvent]->name, INOTIFY_TEST_FILE1_HLINK_NAME_ONLY) == 0);
632
633 Result = LXT_RESULT_SUCCESS;
634
635 ErrorExit:
636 close(Id1);
637 close(Id2);
638 close(Fd);
639 unlink(TestFile1);
640 unlink(TestFile2);
641 unlink(TestFile1Hlink);
642 unlink(TestFile1Slink);
643 rmdir(BaseDir);
644 return Result;
645 }
646
647 int TestInotifyComprehensive2Lxfs(PLXT_ARGS Args)
648
649 {
650
651 return TestInotifyComprehensive2Common(INOTIFY_TEST_BASE_DIR_LXFS);
652 }
653
654 int TestInotifyComprehensive2Common(char* BaseDir)
655
656 /*++
657 --*/
658
659 {
660
661 int Fd;
662 int Id1;
663 int Id2;
664 int Wd[10];
665 char Buf[10];
666 char InotifyBuf[500];
667 struct inotify_event* Events[INOTIFY_TEST_EVENTS_BUF_SIZE];
668 int NumEvents;
669 int Bytes;
670 int Result;
671 char TestFile1[PATH_MAX];
672 char TestFile2[PATH_MAX];
673 char TestFile1Hlink[PATH_MAX];
674 char TestFile1Slink[PATH_MAX];
675
676 //
677 // Initialize and also do cleanup if the files have not been removed.
678 //
679
680 sprintf(TestFile1, "%s%s", BaseDir, INOTIFY_TEST_FILE1_NAME_ONLY);
681 sprintf(TestFile2, "%s%s", BaseDir, INOTIFY_TEST_FILE2_NAME_ONLY);
682 sprintf(TestFile1Hlink, "%s%s", BaseDir, INOTIFY_TEST_FILE1_HLINK_NAME_ONLY);
683 sprintf(TestFile1Slink, "%s%s", BaseDir, INOTIFY_TEST_FILE1_SLINK_NAME_ONLY);
684 unlink(TestFile1);
685 unlink(TestFile2);
686 unlink(TestFile1Hlink);
687 unlink(TestFile1Slink);
688 rmdir(BaseDir);
689 LxtCheckErrnoZeroSuccess(mkdir(BaseDir, 0777));
690 LxtCheckErrno(Fd = creat(TestFile1, 0777));
691 LxtCheckErrnoZeroSuccess(close(Fd));
692
693 //
694 // Setup inotify.
695 //
696
697 LxtCheckErrno(Id1 = inotify_init());
698 LxtCheckErrno(Id2 = inotify_init());
699
700 //
701 // Test IN_EXCL_UNLINK on both the directory and the file to be unlinked.
702 // Also test deleting a file that has open handles to it.
703 //
704
705 LxtCheckErrno(
706 Wd[0] = // wd: 1
707 inotify_add_watch(Id1, TestFile1, IN_ALL_EVENTS | IN_EXCL_UNLINK));
708
709 LxtCheckErrno(
710 Wd[1] = // wd: 2
711 inotify_add_watch(Id1, BaseDir, IN_ALL_EVENTS | IN_EXCL_UNLINK));
712
713 LxtCheckErrno(Fd = open(TestFile1, O_RDWR));
714 unlink(TestFile1);
715 LxtCheckErrno(Bytes = write(Fd, Buf, 10));
716 LxtCheckErrnoZeroSuccess(close(Fd));
717
718 //
719 // Verify. Note that the write and close on the unlinked file did not
720 // generate any events on either the directory or the file since the
721 // IN_EXCL_UNLINK flag was set on both.
722 //
723
724 LxtCheckErrno(LxtFsInotifyReadAndProcess(Id1, InotifyBuf, sizeof(InotifyBuf), Events, INOTIFY_TEST_EVENTS_BUF_SIZE, &NumEvents, FALSE));
725
726 LxtCheckEqual(NumEvents, 6, "%d");
727 LxtCheckEqual(Wd[0], 1, "%d");
728 LxtCheckEqual(Wd[1], 2, "%d");
729 LxtCheckEqual(Events[0]->mask, IN_OPEN, "%d");
730 LxtCheckEqual(Events[1]->mask, IN_OPEN, "%d");
731 LxtCheckEqual(Events[2]->mask, IN_ATTRIB, "%d");
732 LxtCheckEqual(Events[3]->mask, IN_DELETE, "%d");
733 LxtCheckEqual(Events[4]->mask, IN_DELETE_SELF, "%d");
734 LxtCheckEqual(Events[5]->mask, IN_IGNORED, "%d");
735 LxtCheckEqual(Events[0]->wd, 2, "%d");
736 LxtCheckEqual(Events[1]->wd, 1, "%d");
737 LxtCheckEqual(Events[2]->wd, 1, "%d");
738 LxtCheckEqual(Events[3]->wd, 2, "%d");
739 LxtCheckEqual(Events[4]->wd, 1, "%d");
740 LxtCheckEqual(Events[5]->wd, 1, "%d");
741
742 //
743 // Test IN_EXCL_UNLINK on the directory only.
744 //
745
746 LxtCheckErrno(Fd = creat(TestFile1, 0777));
747 LxtCheckErrnoZeroSuccess(close(Fd));
748 LxtCheckErrnoZeroSuccess(close(Id1));
749 LxtCheckErrno(Id1 = inotify_init());
750 LxtCheckErrno(
751 Wd[0] = // wd: 1
752 inotify_add_watch(Id1, TestFile1, IN_ALL_EVENTS));
753
754 LxtCheckErrno(
755 Wd[1] = // wd: 2
756 inotify_add_watch(Id1, BaseDir, IN_ALL_EVENTS | IN_EXCL_UNLINK));
757
758 LxtCheckErrno(Fd = open(TestFile1, O_RDWR));
759 unlink(TestFile1);
760 LxtCheckErrno(Bytes = write(Fd, Buf, 10));
761 LxtCheckErrnoZeroSuccess(close(Fd));
762
763 //
764 // Verify. Note that the file events are still generated even though it was
765 // unlinked, because the file does not have the IN_EXCL_UNLINK flag set.
766 //
767
768 LxtCheckErrno(LxtFsInotifyReadAndProcess(Id1, InotifyBuf, sizeof(InotifyBuf), Events, INOTIFY_TEST_EVENTS_BUF_SIZE, &NumEvents, FALSE));
769
770 LxtCheckEqual(NumEvents, 8, "%d");
771 LxtCheckEqual(Wd[0], 1, "%d");
772 LxtCheckEqual(Wd[1], 2, "%d");
773 LxtCheckEqual(Events[0]->mask, IN_OPEN, "%d");
774 LxtCheckEqual(Events[1]->mask, IN_OPEN, "%d");
775 LxtCheckEqual(Events[2]->mask, IN_ATTRIB, "%d");
776 LxtCheckEqual(Events[3]->mask, IN_DELETE, "%d");
777 LxtCheckEqual(Events[4]->mask, IN_MODIFY, "%d");
778 LxtCheckEqual(Events[5]->mask, IN_CLOSE_WRITE, "%d");
779 LxtCheckEqual(Events[6]->mask, IN_DELETE_SELF, "%d");
780 LxtCheckEqual(Events[7]->mask, IN_IGNORED, "%d");
781 LxtCheckEqual(Events[0]->wd, 2, "%d");
782 LxtCheckEqual(Events[1]->wd, 1, "%d");
783 LxtCheckEqual(Events[2]->wd, 1, "%d");
784 LxtCheckEqual(Events[3]->wd, 2, "%d");
785 LxtCheckEqual(Events[4]->wd, 1, "%d");
786 LxtCheckEqual(Events[5]->wd, 1, "%d");
787 LxtCheckEqual(Events[6]->wd, 1, "%d");
788 LxtCheckEqual(Events[7]->wd, 1, "%d");
789
790 //
791 // Test IN_EXCL_UNLINK on the unlinked file only.
792 //
793
794 LxtCheckErrno(Fd = creat(TestFile1, 0777));
795 LxtCheckErrnoZeroSuccess(close(Fd));
796 LxtCheckErrnoZeroSuccess(close(Id1));
797 LxtCheckErrno(Id1 = inotify_init());
798 LxtCheckErrno(
799 Wd[0] = // wd: 1
800 inotify_add_watch(Id1, TestFile1, IN_ALL_EVENTS | IN_EXCL_UNLINK));
801
802 LxtCheckErrno(
803 Wd[1] = // wd: 2
804 inotify_add_watch(Id1, BaseDir, IN_ALL_EVENTS));
805
806 LxtCheckErrno(Fd = open(TestFile1, O_RDWR));
807 unlink(TestFile1);
808 LxtCheckErrno(Bytes = write(Fd, Buf, 10));
809 LxtCheckErrnoZeroSuccess(close(Fd));
810
811 //
812 // Verify. Note that the directory still receives the events from the unlinked
813 // child, because the directory does not have the IN_EXCL_UNLINK flag set.
814 //
815
816 LxtCheckErrno(LxtFsInotifyReadAndProcess(Id1, InotifyBuf, sizeof(InotifyBuf), Events, INOTIFY_TEST_EVENTS_BUF_SIZE, &NumEvents, FALSE));
817
818 LxtCheckEqual(NumEvents, 8, "%d");
819 LxtCheckEqual(Wd[0], 1, "%d");
820 LxtCheckEqual(Wd[1], 2, "%d");
821 LxtCheckEqual(Events[0]->mask, IN_OPEN, "%d");
822 LxtCheckEqual(Events[1]->mask, IN_OPEN, "%d");
823 LxtCheckEqual(Events[2]->mask, IN_ATTRIB, "%d");
824 LxtCheckEqual(Events[3]->mask, IN_DELETE, "%d");
825 LxtCheckEqual(Events[4]->mask, IN_MODIFY, "%d");
826 LxtCheckEqual(Events[5]->mask, IN_CLOSE_WRITE, "%d");
827 LxtCheckEqual(Events[6]->mask, IN_DELETE_SELF, "%d");
828 LxtCheckEqual(Events[7]->mask, IN_IGNORED, "%d");
829 LxtCheckEqual(Events[0]->wd, 2, "%d");
830 LxtCheckEqual(Events[1]->wd, 1, "%d");
831 LxtCheckEqual(Events[2]->wd, 1, "%d");
832 LxtCheckEqual(Events[3]->wd, 2, "%d");
833 LxtCheckEqual(Events[4]->wd, 2, "%d");
834 LxtCheckEqual(Events[5]->wd, 2, "%d");
835 LxtCheckEqual(Events[6]->wd, 1, "%d");
836 LxtCheckEqual(Events[7]->wd, 1, "%d");
837
838 //
839 // Test watching the same file twice.
840 //
841
842 LxtCheckErrno(Fd = creat(TestFile1, 0777));
843 LxtCheckErrnoZeroSuccess(close(Fd));
844 LxtCheckErrnoZeroSuccess(close(Id1));
845 LxtCheckErrno(Id1 = inotify_init());
846 LxtCheckErrno(
847 Wd[0] = // wd: 1
848 inotify_add_watch(Id1, TestFile1, IN_OPEN));
849
850 LxtCheckErrno(
851 Wd[1] = // wd: 1
852 inotify_add_watch(Id1, TestFile1, IN_CLOSE));
853
854 LxtCheckErrno(Fd = open(TestFile1, O_WRONLY));
855 LxtCheckErrnoZeroSuccess(close(Fd));
856
857 //
858 // Verify that IN_CLOSE_WRITE is received, and that IN_OPEN is not received.
859 //
860
861 LxtCheckErrno(LxtFsInotifyReadAndProcess(Id1, InotifyBuf, sizeof(InotifyBuf), Events, INOTIFY_TEST_EVENTS_BUF_SIZE, &NumEvents, FALSE));
862
863 LxtCheckEqual(NumEvents, 1, "%d");
864 LxtCheckEqual(Events[0]->mask, IN_CLOSE_WRITE, "%d");
865 LxtCheckEqual(Events[0]->wd, 1, "%d");
866 LxtCheckEqual(Wd[0], Wd[1], "%d");
867
868 //
869 // Test watching the same file twice, but with IN_MASK_ADD.
870 //
871
872 LxtCheckErrno(Fd = creat(TestFile1, 0777));
873 LxtCheckErrnoZeroSuccess(close(Fd));
874 LxtCheckErrnoZeroSuccess(close(Id1));
875 LxtCheckErrno(Id1 = inotify_init());
876 LxtCheckErrno(
877 Wd[0] = // wd: 1
878 inotify_add_watch(Id1, TestFile1, IN_OPEN));
879
880 LxtCheckErrno(
881 Wd[1] = // wd: 1
882 inotify_add_watch(Id1, TestFile1, IN_CLOSE | IN_MASK_ADD));
883
884 LxtCheckErrno(Fd = open(TestFile1, O_RDONLY));
885 LxtCheckErrnoZeroSuccess(close(Fd));
886
887 //
888 // Verify that both IN_OPEN and IN_CLOSE_NOWRITE are received.
889 //
890
891 LxtCheckErrno(LxtFsInotifyReadAndProcess(Id1, InotifyBuf, sizeof(InotifyBuf), Events, INOTIFY_TEST_EVENTS_BUF_SIZE, &NumEvents, FALSE));
892
893 LxtCheckEqual(NumEvents, 2, "%d");
894 LxtCheckEqual(Events[0]->mask, IN_OPEN, "%d");
895 LxtCheckEqual(Events[1]->mask, IN_CLOSE_NOWRITE, "%d");
896 LxtCheckEqual(Events[0]->wd, 1, "%d");
897 LxtCheckEqual(Events[1]->wd, 1, "%d");
898 LxtCheckEqual(Wd[0], Wd[1], "%d");
899
900 Result = LXT_RESULT_SUCCESS;
901
902 ErrorExit:
903 close(Id1);
904 close(Id2);
905 close(Fd);
906 unlink(TestFile1);
907 rmdir(BaseDir);
908 return Result;
909 }
910
911 int TestInotifyPosixUnlinkRenameLxfs(PLXT_ARGS Args)
912
913 {
914
915 return LxtFsInotifyPosixUnlinkRenameCommon(INOTIFY_TEST_BASE_DIR_LXFS);
916 }
917
918 int TestInotifyUnmountBindLxfs(PLXT_ARGS Args)
919
920 {
921
922 return LxtFsInotifyUnmountBindCommon(INOTIFY_TEST_BASE_DIR_LXFS);
923 }
924
925 int TestInotifyFtruncateLxfs(PLXT_ARGS Args)
926
927 {
928
929 int ChildPid;
930 int Fd;
931 struct pollfd PollFd;
932 int Result;
933 char TestFile1[PATH_MAX];
934
935 ChildPid = -1;
936 Fd = -1;
937
938 //
939 // Initialize and also do cleanup if the files have not been removed.
940 //
941
942 sprintf(TestFile1, "%s%s", INOTIFY_TEST_BASE_DIR_LXFS, INOTIFY_TEST_FILE1_NAME_ONLY);
943
944 unlink(TestFile1);
945 rmdir(INOTIFY_TEST_BASE_DIR_LXFS);
946 LxtCheckErrnoZeroSuccess(mkdir(INOTIFY_TEST_BASE_DIR_LXFS, 0777));
947 LxtCheckErrno(Fd = creat(TestFile1, 0777));
948 LxtCheckErrno(ftruncate(Fd, 1024));
949 LxtCheckErrno(ChildPid = fork());
950 if (ChildPid == 0)
951 {
952 sleep(2);
953 LxtCheckErrno(ftruncate(Fd, 1024));
954 fsync(Fd);
955 goto ErrorExit;
956 }
957
958 int Id = inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
959 LxtCheckErrno(inotify_add_watch(Id, TestFile1, IN_ALL_EVENTS));
960 PollFd.fd = Id;
961 PollFd.events = POLLIN;
962 LxtCheckErrno(ppoll(&PollFd, 1, NULL, NULL));
963 Result = LXT_RESULT_SUCCESS;
964
965 ErrorExit:
966 if (Fd != -1)
967 {
968 LxtClose(Fd);
969 }
970
971 if (ChildPid == 0)
972 {
973 _exit(Result);
974 }
975
976 return Result;
977 }
978
979 int TestInotifyPseudoPlugin(PLXT_ARGS Args)
980
981 {
982
983 int Id;
984 int Result;
985
986 LxtCheckErrno(Id = inotify_init());
987 LxtCheckErrno(inotify_add_watch(Id, "/proc/self/ns/pid", IN_ALL_EVENTS));
988
989 ErrorExit:
990 if (Id != -1)
991 {
992 LxtClose(Id);
993 }
994
995 return Result;
996 }