83
83
#include <sys/mman.h> /* munlock(), mlock() */
84
84
#include <fcntl.h> /* O_CLOEXEC, O_NONBLOCK, fcntl(),
85
85
F_GETFD, F_GETFL, FD_CLOEXEC,
86
open(), O_WRONLY, O_RDONLY */
86
open(), O_WRONLY, O_NOCTTY,
87
88
#include <sys/wait.h> /* waitpid(), WNOHANG, WIFEXITED(),
89
90
#include <limits.h> /* PIPE_BUF, NAME_MAX, INT_MAX */
1071
1074
/* "sufficient to read at least one event." - inotify(7) */
1072
1075
const size_t ievent_size = (sizeof(struct inotify_event)
1073
1076
+ NAME_MAX + 1);
1074
char ievent_buffer[sizeof(struct inotify_event) + NAME_MAX + 1];
1075
struct inotify_event *ievent = ((struct inotify_event *)
1078
struct inotify_event event;
1079
char name_buffer[NAME_MAX + 1];
1081
struct inotify_event *const ievent = &ievent_buffer.event;
1078
1083
const ssize_t read_length = read(fd, ievent, ievent_size);
1079
1084
if(read_length == 0){ /* EOF */
3450
3457
g_assert_cmpuint((unsigned int)queue->length, ==, 0);
3460
static void test_add_inotify_dir_watch_nondir(__attribute__((unused))
3461
test_fixture *fixture,
3462
__attribute__((unused))
3465
__attribute__((cleanup(cleanup_close)))
3466
const int epoll_fd = epoll_create1(EPOLL_CLOEXEC);
3467
g_assert_cmpint(epoll_fd, >=, 0);
3468
__attribute__((cleanup(cleanup_queue)))
3469
task_queue *queue = create_queue();
3470
g_assert_nonnull(queue);
3471
__attribute__((cleanup(string_set_clear)))
3472
string_set cancelled_filenames = {};
3473
const mono_microsecs current_time = 0;
3475
bool quit_now = false;
3476
buffer password = {};
3477
bool mandos_client_exited = false;
3478
bool password_is_read = false;
3480
const char not_a_directory[] = "/dev/tty";
3482
FILE *real_stderr = stderr;
3483
FILE *devnull = fopen("/dev/null", "we");
3484
g_assert_nonnull(devnull);
3486
g_assert_false(add_inotify_dir_watch(queue, epoll_fd, &quit_now,
3487
&password, not_a_directory,
3488
&cancelled_filenames,
3490
&mandos_client_exited,
3491
&password_is_read));
3492
stderr = real_stderr;
3493
g_assert_cmpint(fclose(devnull), ==, 0);
3495
g_assert_cmpuint((unsigned int)queue->length, ==, 0);
3453
3498
static void test_add_inotify_dir_watch_EAGAIN(__attribute__((unused))
3454
3499
test_fixture *fixture,
3455
3500
__attribute__((unused))
3718
void test_add_inotify_dir_watch_IN_MOVED_FROM(__attribute__((unused))
3719
test_fixture *fixture,
3720
__attribute__((unused))
3723
__attribute__((cleanup(cleanup_close)))
3724
const int epoll_fd = epoll_create1(EPOLL_CLOEXEC);
3725
g_assert_cmpint(epoll_fd, >=, 0);
3726
__attribute__((cleanup(cleanup_queue)))
3727
task_queue *queue = create_queue();
3728
g_assert_nonnull(queue);
3729
__attribute__((cleanup(string_set_clear)))
3730
string_set cancelled_filenames = {};
3731
const mono_microsecs current_time = 0;
3733
bool quit_now = false;
3734
buffer password = {};
3735
bool mandos_client_exited = false;
3736
bool password_is_read = false;
3738
__attribute__((cleanup(cleanup_string)))
3739
char *tempdir = make_temporary_directory();
3740
g_assert_nonnull(tempdir);
3742
__attribute__((cleanup(cleanup_string)))
3743
char *tempfilename = make_temporary_file_in_directory(tempdir);
3744
g_assert_nonnull(tempfilename);
3746
__attribute__((cleanup(cleanup_string)))
3747
char *targetdir = make_temporary_directory();
3748
g_assert_nonnull(targetdir);
3750
__attribute__((cleanup(cleanup_string)))
3751
char *targetfilename = NULL;
3752
g_assert_cmpint(asprintf(&targetfilename, "%s/%s", targetdir,
3753
basename(tempfilename)), >, 0);
3754
g_assert_nonnull(targetfilename);
3756
g_assert_true(add_inotify_dir_watch(queue, epoll_fd, &quit_now,
3758
&cancelled_filenames,
3760
&mandos_client_exited,
3761
&password_is_read));
3763
g_assert_cmpint(rename(tempfilename, targetfilename), ==, 0);
3765
const task_context *const added_read_task
3766
= find_matching_task(queue,
3767
(task_context){ .func=read_inotify_event });
3768
g_assert_nonnull(added_read_task);
3770
/* "sufficient to read at least one event." - inotify(7) */
3771
const size_t ievent_size = (sizeof(struct inotify_event)
3773
struct inotify_event *ievent = malloc(ievent_size);
3774
g_assert_nonnull(ievent);
3776
ssize_t read_size = read(added_read_task->fd, ievent, ievent_size);
3778
g_assert_cmpint((int)read_size, >, 0);
3779
g_assert_true(ievent->mask & IN_MOVED_FROM);
3780
g_assert_cmpstr(ievent->name, ==, basename(tempfilename));
3784
g_assert_cmpint(unlink(targetfilename), ==, 0);
3785
g_assert_cmpint(rmdir(targetdir), ==, 0);
3786
g_assert_cmpint(rmdir(tempdir), ==, 0);
3673
3790
void test_add_inotify_dir_watch_IN_DELETE(__attribute__((unused))
3674
3791
test_fixture *fixture,
3675
3792
__attribute__((unused))
3733
3850
g_assert_cmpint(rmdir(tempdir), ==, 0);
3854
void test_add_inotify_dir_watch_IN_EXCL_UNLINK(__attribute__((unused))
3855
test_fixture *fixture,
3856
__attribute__((unused))
3859
__attribute__((cleanup(cleanup_close)))
3860
const int epoll_fd = epoll_create1(EPOLL_CLOEXEC);
3861
g_assert_cmpint(epoll_fd, >=, 0);
3862
__attribute__((cleanup(cleanup_queue)))
3863
task_queue *queue = create_queue();
3864
g_assert_nonnull(queue);
3865
__attribute__((cleanup(string_set_clear)))
3866
string_set cancelled_filenames = {};
3867
const mono_microsecs current_time = 0;
3869
bool quit_now = false;
3870
buffer password = {};
3871
bool mandos_client_exited = false;
3872
bool password_is_read = false;
3874
__attribute__((cleanup(cleanup_string)))
3875
char *tempdir = make_temporary_directory();
3876
g_assert_nonnull(tempdir);
3878
__attribute__((cleanup(cleanup_string)))
3879
char *tempfile = make_temporary_file_in_directory(tempdir);
3880
g_assert_nonnull(tempfile);
3881
int tempfile_fd = open(tempfile, O_WRONLY | O_CLOEXEC | O_NOCTTY
3883
g_assert_cmpint(tempfile_fd, >, 2);
3885
g_assert_true(add_inotify_dir_watch(queue, epoll_fd, &quit_now,
3887
&cancelled_filenames,
3889
&mandos_client_exited,
3890
&password_is_read));
3891
g_assert_cmpint(unlink(tempfile), ==, 0);
3893
g_assert_cmpuint((unsigned int)queue->length, >, 0);
3895
const task_context *const added_read_task
3896
= find_matching_task(queue,
3897
(task_context){ .func=read_inotify_event });
3898
g_assert_nonnull(added_read_task);
3900
g_assert_cmpint(added_read_task->fd, >, 2);
3901
g_assert_true(fd_has_cloexec_and_nonblock(added_read_task->fd));
3903
/* "sufficient to read at least one event." - inotify(7) */
3904
const size_t ievent_size = (sizeof(struct inotify_event)
3906
struct inotify_event *ievent = malloc(ievent_size);
3907
g_assert_nonnull(ievent);
3909
ssize_t read_size = 0;
3910
read_size = read(added_read_task->fd, ievent, ievent_size);
3912
g_assert_cmpint((int)read_size, >, 0);
3913
g_assert_true(ievent->mask & IN_DELETE);
3914
g_assert_cmpstr(ievent->name, ==, basename(tempfile));
3916
g_assert_cmpint(close(tempfile_fd), ==, 0);
3918
/* IN_EXCL_UNLINK should make the closing of the previously unlinked
3919
file not appear as an ievent, so we should not see it now. */
3920
read_size = read(added_read_task->fd, ievent, ievent_size);
3921
g_assert_cmpint((int)read_size, ==, -1);
3922
g_assert_true(errno == EAGAIN);
3926
g_assert_cmpint(rmdir(tempdir), ==, 0);
3736
3929
static void test_read_inotify_event_readerror(__attribute__((unused))
3737
3930
test_fixture *fixture,
3738
3931
__attribute__((unused))
3929
4123
const size_t ievent_max_size = (sizeof(struct inotify_event)
3930
4124
+ NAME_MAX + 1);
3931
4125
g_assert_cmpint(ievent_max_size, <=, PIPE_BUF);
3932
char ievent_buffer[sizeof(struct inotify_event) + NAME_MAX + 1];
3933
struct inotify_event *ievent = ((struct inotify_event *)
4127
struct inotify_event event;
4128
char name_buffer[NAME_MAX + 1];
4130
struct inotify_event *const ievent = &ievent_buffer.event;
3936
4132
const char dummy_file_name[] = "ask.dummy_file_name";
3937
4133
ievent->mask = IN_CLOSE_WRITE;
3939
4135
memcpy(ievent->name, dummy_file_name, sizeof(dummy_file_name));
3940
4136
const size_t ievent_size = (sizeof(struct inotify_event)
3941
4137
+ sizeof(dummy_file_name));
3942
g_assert_cmpint(write(pipefds[1], ievent_buffer, ievent_size),
4138
g_assert_cmpint(write(pipefds[1], (char *)ievent, ievent_size),
3943
4139
==, ievent_size);
3944
4140
g_assert_cmpint(close(pipefds[1]), ==, 0);
4022
4218
const size_t ievent_max_size = (sizeof(struct inotify_event)
4023
4219
+ NAME_MAX + 1);
4024
4220
g_assert_cmpint(ievent_max_size, <=, PIPE_BUF);
4025
char ievent_buffer[sizeof(struct inotify_event) + NAME_MAX + 1];
4026
struct inotify_event *ievent = ((struct inotify_event *)
4222
struct inotify_event event;
4223
char name_buffer[NAME_MAX + 1];
4225
struct inotify_event *const ievent = &ievent_buffer.event;
4029
4227
const char dummy_file_name[] = "ask.dummy_file_name";
4030
4228
ievent->mask = IN_MOVED_TO;
4032
4230
memcpy(ievent->name, dummy_file_name, sizeof(dummy_file_name));
4033
4231
const size_t ievent_size = (sizeof(struct inotify_event)
4034
4232
+ sizeof(dummy_file_name));
4035
g_assert_cmpint(write(pipefds[1], ievent_buffer, ievent_size),
4233
g_assert_cmpint(write(pipefds[1], (char *)ievent, ievent_size),
4036
4234
==, ievent_size);
4037
4235
g_assert_cmpint(close(pipefds[1]), ==, 0);
4300
void test_read_inotify_event_IN_MOVED_FROM(__attribute__((unused))
4301
test_fixture *fixture,
4302
__attribute__((unused))
4303
gconstpointer user_data){
4304
__attribute__((cleanup(cleanup_close)))
4305
const int epoll_fd = epoll_create1(EPOLL_CLOEXEC);
4306
g_assert_cmpint(epoll_fd, >=, 0);
4307
__attribute__((cleanup(string_set_clear)))
4308
string_set cancelled_filenames = {};
4309
const mono_microsecs current_time = 0;
4312
g_assert_cmpint(pipe2(pipefds, O_CLOEXEC | O_NONBLOCK), ==, 0);
4314
/* "sufficient to read at least one event." - inotify(7) */
4315
const size_t ievent_max_size = (sizeof(struct inotify_event)
4317
g_assert_cmpint(ievent_max_size, <=, PIPE_BUF);
4319
struct inotify_event event;
4320
char name_buffer[NAME_MAX + 1];
4322
struct inotify_event *const ievent = &ievent_buffer.event;
4324
const char dummy_file_name[] = "ask.dummy_file_name";
4325
ievent->mask = IN_MOVED_FROM;
4326
ievent->len = sizeof(dummy_file_name);
4327
memcpy(ievent->name, dummy_file_name, sizeof(dummy_file_name));
4328
const size_t ievent_size = (sizeof(struct inotify_event)
4329
+ sizeof(dummy_file_name));
4330
g_assert_cmpint(write(pipefds[1], (char *)ievent, ievent_size),
4332
g_assert_cmpint(close(pipefds[1]), ==, 0);
4334
bool quit_now = false;
4335
buffer password = {};
4336
bool mandos_client_exited = false;
4337
bool password_is_read = false;
4338
__attribute__((cleanup(cleanup_queue)))
4339
task_queue *queue = create_queue();
4340
g_assert_nonnull(queue);
4342
task_context task = {
4343
.func=read_inotify_event,
4346
.quit_now=&quit_now,
4347
.password=&password,
4348
.filename=strdup("/nonexistent"),
4349
.cancelled_filenames=&cancelled_filenames,
4350
.current_time=¤t_time,
4351
.mandos_client_exited=&mandos_client_exited,
4352
.password_is_read=&password_is_read,
4354
task.func(task, queue);
4355
g_assert_false(quit_now);
4356
g_assert_true(queue->next_run == 0);
4357
g_assert_cmpuint((unsigned int)queue->length, ==, 1);
4359
g_assert_nonnull(find_matching_task(queue, (task_context){
4360
.func=read_inotify_event,
4363
.quit_now=&quit_now,
4364
.password=&password,
4365
.filename=task.filename,
4366
.cancelled_filenames=&cancelled_filenames,
4367
.current_time=¤t_time,
4368
.mandos_client_exited=&mandos_client_exited,
4369
.password_is_read=&password_is_read,
4372
g_assert_true(epoll_set_contains(epoll_fd, pipefds[0],
4373
EPOLLIN | EPOLLRDHUP));
4375
__attribute__((cleanup(cleanup_string)))
4376
char *filename = NULL;
4377
g_assert_cmpint(asprintf(&filename, "%s/%s", task.filename,
4378
dummy_file_name), >, 0);
4379
g_assert_nonnull(filename);
4380
g_assert_true(string_set_contains(*task.cancelled_filenames,
4101
4384
static void test_read_inotify_event_IN_DELETE(__attribute__((unused))
4102
4385
test_fixture *fixture,
4103
4386
__attribute__((unused))
4117
4400
const size_t ievent_max_size = (sizeof(struct inotify_event)
4118
4401
+ NAME_MAX + 1);
4119
4402
g_assert_cmpint(ievent_max_size, <=, PIPE_BUF);
4120
char ievent_buffer[sizeof(struct inotify_event) + NAME_MAX + 1];
4121
struct inotify_event *ievent = ((struct inotify_event *)
4404
struct inotify_event event;
4405
char name_buffer[NAME_MAX + 1];
4407
struct inotify_event *const ievent = &ievent_buffer.event;
4124
4409
const char dummy_file_name[] = "ask.dummy_file_name";
4125
4410
ievent->mask = IN_DELETE;
4127
4412
memcpy(ievent->name, dummy_file_name, sizeof(dummy_file_name));
4128
4413
const size_t ievent_size = (sizeof(struct inotify_event)
4129
4414
+ sizeof(dummy_file_name));
4130
g_assert_cmpint(write(pipefds[1], ievent_buffer, ievent_size),
4415
g_assert_cmpint(write(pipefds[1], (char *)ievent, ievent_size),
4131
4416
==, ievent_size);
4132
4417
g_assert_cmpint(close(pipefds[1]), ==, 0);
4199
4484
const size_t ievent_max_size = (sizeof(struct inotify_event)
4200
4485
+ NAME_MAX + 1);
4201
4486
g_assert_cmpint(ievent_max_size, <=, PIPE_BUF);
4202
char ievent_buffer[sizeof(struct inotify_event) + NAME_MAX + 1];
4203
struct inotify_event *ievent = ((struct inotify_event *)
4488
struct inotify_event event;
4489
char name_buffer[NAME_MAX + 1];
4491
struct inotify_event *const ievent = &ievent_buffer.event;
4206
4493
const char dummy_file_name[] = "ignored.dummy_file_name";
4207
4494
ievent->mask = IN_CLOSE_WRITE;
4209
4496
memcpy(ievent->name, dummy_file_name, sizeof(dummy_file_name));
4210
4497
const size_t ievent_size = (sizeof(struct inotify_event)
4211
4498
+ sizeof(dummy_file_name));
4212
g_assert_cmpint(write(pipefds[1], ievent_buffer, ievent_size),
4499
g_assert_cmpint(write(pipefds[1], (char *)ievent, ievent_size),
4213
4500
==, ievent_size);
4214
4501
g_assert_cmpint(close(pipefds[1]), ==, 0);
4273
4560
const size_t ievent_max_size = (sizeof(struct inotify_event)
4274
4561
+ NAME_MAX + 1);
4275
4562
g_assert_cmpint(ievent_max_size, <=, PIPE_BUF);
4276
char ievent_buffer[sizeof(struct inotify_event) + NAME_MAX + 1];
4277
struct inotify_event *ievent = ((struct inotify_event *)
4564
struct inotify_event event;
4565
char name_buffer[NAME_MAX + 1];
4567
struct inotify_event *const ievent = &ievent_buffer.event;
4280
4569
const char dummy_file_name[] = "ignored.dummy_file_name";
4281
4570
ievent->mask = IN_MOVED_TO;
4283
4572
memcpy(ievent->name, dummy_file_name, sizeof(dummy_file_name));
4284
4573
const size_t ievent_size = (sizeof(struct inotify_event)
4285
4574
+ sizeof(dummy_file_name));
4286
g_assert_cmpint(write(pipefds[1], ievent_buffer, ievent_size),
4575
g_assert_cmpint(write(pipefds[1], (char *)ievent, ievent_size),
4287
4576
==, ievent_size);
4288
4577
g_assert_cmpint(close(pipefds[1]), ==, 0);
4330
4619
EPOLLIN | EPOLLRDHUP));
4623
test_read_inotify_event_IN_MOVED_FROM_badname(__attribute__((unused))
4624
test_fixture *fixture,
4625
__attribute__((unused))
4628
__attribute__((cleanup(cleanup_close)))
4629
const int epoll_fd = epoll_create1(EPOLL_CLOEXEC);
4630
g_assert_cmpint(epoll_fd, >=, 0);
4631
__attribute__((cleanup(string_set_clear)))
4632
string_set cancelled_filenames = {};
4633
const mono_microsecs current_time = 0;
4636
g_assert_cmpint(pipe2(pipefds, O_CLOEXEC | O_NONBLOCK), ==, 0);
4638
/* "sufficient to read at least one event." - inotify(7) */
4639
const size_t ievent_max_size = (sizeof(struct inotify_event)
4641
g_assert_cmpint(ievent_max_size, <=, PIPE_BUF);
4643
struct inotify_event event;
4644
char name_buffer[NAME_MAX + 1];
4646
struct inotify_event *const ievent = &ievent_buffer.event;
4648
const char dummy_file_name[] = "ignored.dummy_file_name";
4649
ievent->mask = IN_MOVED_FROM;
4650
ievent->len = sizeof(dummy_file_name);
4651
memcpy(ievent->name, dummy_file_name, sizeof(dummy_file_name));
4652
const size_t ievent_size = (sizeof(struct inotify_event)
4653
+ sizeof(dummy_file_name));
4654
g_assert_cmpint(write(pipefds[1], (char *)ievent, ievent_size),
4656
g_assert_cmpint(close(pipefds[1]), ==, 0);
4658
bool quit_now = false;
4659
buffer password = {};
4660
bool mandos_client_exited = false;
4661
bool password_is_read = false;
4662
__attribute__((cleanup(cleanup_queue)))
4663
task_queue *queue = create_queue();
4664
g_assert_nonnull(queue);
4666
task_context task = {
4667
.func=read_inotify_event,
4670
.quit_now=&quit_now,
4671
.password=&password,
4672
.filename=strdup("/nonexistent"),
4673
.cancelled_filenames=&cancelled_filenames,
4674
.current_time=¤t_time,
4675
.mandos_client_exited=&mandos_client_exited,
4676
.password_is_read=&password_is_read,
4678
task.func(task, queue);
4679
g_assert_false(quit_now);
4680
g_assert_true(queue->next_run == 0);
4681
g_assert_cmpuint((unsigned int)queue->length, ==, 1);
4683
g_assert_nonnull(find_matching_task(queue, (task_context){
4684
.func=read_inotify_event,
4687
.quit_now=&quit_now,
4688
.password=&password,
4689
.filename=task.filename,
4690
.cancelled_filenames=&cancelled_filenames,
4691
.current_time=¤t_time,
4692
.mandos_client_exited=&mandos_client_exited,
4693
.password_is_read=&password_is_read,
4696
g_assert_true(epoll_set_contains(epoll_fd, pipefds[0],
4697
EPOLLIN | EPOLLRDHUP));
4699
__attribute__((cleanup(cleanup_string)))
4700
char *filename = NULL;
4701
g_assert_cmpint(asprintf(&filename, "%s/%s", task.filename,
4702
dummy_file_name), >, 0);
4703
g_assert_nonnull(filename);
4704
g_assert_false(string_set_contains(cancelled_filenames, filename));
4334
4708
void test_read_inotify_event_IN_DELETE_badname(__attribute__((unused))
4335
4709
test_fixture *fixture,
4350
4724
const size_t ievent_max_size = (sizeof(struct inotify_event)
4351
4725
+ NAME_MAX + 1);
4352
4726
g_assert_cmpint(ievent_max_size, <=, PIPE_BUF);
4353
char ievent_buffer[sizeof(struct inotify_event) + NAME_MAX + 1];
4354
struct inotify_event *ievent = ((struct inotify_event *)
4728
struct inotify_event event;
4729
char name_buffer[NAME_MAX + 1];
4731
struct inotify_event *const ievent = &ievent_buffer.event;
4357
4733
const char dummy_file_name[] = "ignored.dummy_file_name";
4358
4734
ievent->mask = IN_DELETE;
4360
4736
memcpy(ievent->name, dummy_file_name, sizeof(dummy_file_name));
4361
4737
const size_t ievent_size = (sizeof(struct inotify_event)
4362
4738
+ sizeof(dummy_file_name));
4363
g_assert_cmpint(write(pipefds[1], ievent_buffer, ievent_size),
4739
g_assert_cmpint(write(pipefds[1], (char *)ievent, ievent_size),
4364
4740
==, ievent_size);
4365
4741
g_assert_cmpint(close(pipefds[1]), ==, 0);
7573
7952
test_add_inotify_dir_watch);
7574
7953
test_add_st("/task-creators/add_inotify_dir_watch/fail",
7575
7954
test_add_inotify_dir_watch_fail);
7955
test_add_st("/task-creators/add_inotify_dir_watch/not-a-directory",
7956
test_add_inotify_dir_watch_nondir);
7576
7957
test_add_st("/task-creators/add_inotify_dir_watch/EAGAIN",
7577
7958
test_add_inotify_dir_watch_EAGAIN);
7578
7959
test_add_st("/task-creators/add_inotify_dir_watch/IN_CLOSE_WRITE",
7579
7960
test_add_inotify_dir_watch_IN_CLOSE_WRITE);
7580
7961
test_add_st("/task-creators/add_inotify_dir_watch/IN_MOVED_TO",
7581
7962
test_add_inotify_dir_watch_IN_MOVED_TO);
7963
test_add_st("/task-creators/add_inotify_dir_watch/IN_MOVED_FROM",
7964
test_add_inotify_dir_watch_IN_MOVED_FROM);
7965
test_add_st("/task-creators/add_inotify_dir_watch/IN_EXCL_UNLINK",
7966
test_add_inotify_dir_watch_IN_EXCL_UNLINK);
7582
7967
test_add_st("/task-creators/add_inotify_dir_watch/IN_DELETE",
7583
7968
test_add_inotify_dir_watch_IN_DELETE);
7584
7969
test_add_st("/task/read_inotify_event/readerror",
7593
7978
test_read_inotify_event_IN_CLOSE_WRITE);
7594
7979
test_add_st("/task/read_inotify_event/IN_MOVED_TO",
7595
7980
test_read_inotify_event_IN_MOVED_TO);
7981
test_add_st("/task/read_inotify_event/IN_MOVED_FROM",
7982
test_read_inotify_event_IN_MOVED_FROM);
7596
7983
test_add_st("/task/read_inotify_event/IN_DELETE",
7597
7984
test_read_inotify_event_IN_DELETE);
7598
7985
test_add_st("/task/read_inotify_event/IN_CLOSE_WRITE/badname",
7599
7986
test_read_inotify_event_IN_CLOSE_WRITE_badname);
7600
7987
test_add_st("/task/read_inotify_event/IN_MOVED_TO/badname",
7601
7988
test_read_inotify_event_IN_MOVED_TO_badname);
7989
test_add_st("/task/read_inotify_event/IN_MOVED_FROM/badname",
7990
test_read_inotify_event_IN_MOVED_FROM_badname);
7602
7991
test_add_st("/task/read_inotify_event/IN_DELETE/badname",
7603
7992
test_read_inotify_event_IN_DELETE_badname);
7604
7993
test_add_st("/task/open_and_parse_question/ENOENT",