1071
1071
/* "sufficient to read at least one event." - inotify(7) */
1072
1072
const size_t ievent_size = (sizeof(struct inotify_event)
1073
1073
+ NAME_MAX + 1);
1075
struct inotify_event event;
1076
char name_buffer[NAME_MAX + 1];
1078
struct inotify_event *const ievent = &ievent_buffer.event;
1074
char ievent_buffer[sizeof(struct inotify_event) + NAME_MAX + 1];
1075
struct inotify_event *ievent = ((struct inotify_event *)
1080
1078
const ssize_t read_length = read(fd, ievent, ievent_size);
1081
1079
if(read_length == 0){ /* EOF */
3675
void test_add_inotify_dir_watch_IN_MOVED_FROM(__attribute__((unused))
3676
test_fixture *fixture,
3677
__attribute__((unused))
3680
__attribute__((cleanup(cleanup_close)))
3681
const int epoll_fd = epoll_create1(EPOLL_CLOEXEC);
3682
g_assert_cmpint(epoll_fd, >=, 0);
3683
__attribute__((cleanup(cleanup_queue)))
3684
task_queue *queue = create_queue();
3685
g_assert_nonnull(queue);
3686
__attribute__((cleanup(string_set_clear)))
3687
string_set cancelled_filenames = {};
3688
const mono_microsecs current_time = 0;
3690
bool quit_now = false;
3691
buffer password = {};
3692
bool mandos_client_exited = false;
3693
bool password_is_read = false;
3695
__attribute__((cleanup(cleanup_string)))
3696
char *tempdir = make_temporary_directory();
3697
g_assert_nonnull(tempdir);
3699
__attribute__((cleanup(cleanup_string)))
3700
char *tempfilename = make_temporary_file_in_directory(tempdir);
3701
g_assert_nonnull(tempfilename);
3703
__attribute__((cleanup(cleanup_string)))
3704
char *targetdir = make_temporary_directory();
3705
g_assert_nonnull(targetdir);
3707
__attribute__((cleanup(cleanup_string)))
3708
char *targetfilename = NULL;
3709
g_assert_cmpint(asprintf(&targetfilename, "%s/%s", targetdir,
3710
basename(tempfilename)), >, 0);
3711
g_assert_nonnull(targetfilename);
3713
g_assert_true(add_inotify_dir_watch(queue, epoll_fd, &quit_now,
3715
&cancelled_filenames,
3717
&mandos_client_exited,
3718
&password_is_read));
3720
g_assert_cmpint(rename(tempfilename, targetfilename), ==, 0);
3722
const task_context *const added_read_task
3723
= find_matching_task(queue,
3724
(task_context){ .func=read_inotify_event });
3725
g_assert_nonnull(added_read_task);
3727
/* "sufficient to read at least one event." - inotify(7) */
3728
const size_t ievent_size = (sizeof(struct inotify_event)
3730
struct inotify_event *ievent = malloc(ievent_size);
3731
g_assert_nonnull(ievent);
3733
ssize_t read_size = read(added_read_task->fd, ievent, ievent_size);
3735
g_assert_cmpint((int)read_size, >, 0);
3736
g_assert_true(ievent->mask & IN_MOVED_FROM);
3737
g_assert_cmpstr(ievent->name, ==, basename(tempfilename));
3741
g_assert_cmpint(unlink(targetfilename), ==, 0);
3742
g_assert_cmpint(rmdir(targetdir), ==, 0);
3743
g_assert_cmpint(rmdir(tempdir), ==, 0);
3747
3673
void test_add_inotify_dir_watch_IN_DELETE(__attribute__((unused))
3748
3674
test_fixture *fixture,
3749
3675
__attribute__((unused))
3807
3733
g_assert_cmpint(rmdir(tempdir), ==, 0);
3811
void test_add_inotify_dir_watch_IN_EXCL_UNLINK(__attribute__((unused))
3812
test_fixture *fixture,
3813
__attribute__((unused))
3816
__attribute__((cleanup(cleanup_close)))
3817
const int epoll_fd = epoll_create1(EPOLL_CLOEXEC);
3818
g_assert_cmpint(epoll_fd, >=, 0);
3819
__attribute__((cleanup(cleanup_queue)))
3820
task_queue *queue = create_queue();
3821
g_assert_nonnull(queue);
3822
__attribute__((cleanup(string_set_clear)))
3823
string_set cancelled_filenames = {};
3824
const mono_microsecs current_time = 0;
3826
bool quit_now = false;
3827
buffer password = {};
3828
bool mandos_client_exited = false;
3829
bool password_is_read = false;
3831
__attribute__((cleanup(cleanup_string)))
3832
char *tempdir = make_temporary_directory();
3833
g_assert_nonnull(tempdir);
3835
__attribute__((cleanup(cleanup_string)))
3836
char *tempfile = make_temporary_file_in_directory(tempdir);
3837
g_assert_nonnull(tempfile);
3838
int tempfile_fd = open(tempfile, O_WRONLY | O_CLOEXEC | O_NOCTTY
3840
g_assert_cmpint(tempfile_fd, >, 2);
3842
g_assert_true(add_inotify_dir_watch(queue, epoll_fd, &quit_now,
3844
&cancelled_filenames,
3846
&mandos_client_exited,
3847
&password_is_read));
3848
g_assert_cmpint(unlink(tempfile), ==, 0);
3850
g_assert_cmpuint((unsigned int)queue->length, >, 0);
3852
const task_context *const added_read_task
3853
= find_matching_task(queue,
3854
(task_context){ .func=read_inotify_event });
3855
g_assert_nonnull(added_read_task);
3857
g_assert_cmpint(added_read_task->fd, >, 2);
3858
g_assert_true(fd_has_cloexec_and_nonblock(added_read_task->fd));
3860
/* "sufficient to read at least one event." - inotify(7) */
3861
const size_t ievent_size = (sizeof(struct inotify_event)
3863
struct inotify_event *ievent = malloc(ievent_size);
3864
g_assert_nonnull(ievent);
3866
ssize_t read_size = 0;
3867
read_size = read(added_read_task->fd, ievent, ievent_size);
3869
g_assert_cmpint((int)read_size, >, 0);
3870
g_assert_true(ievent->mask & IN_DELETE);
3871
g_assert_cmpstr(ievent->name, ==, basename(tempfile));
3873
g_assert_cmpint(close(tempfile_fd), ==, 0);
3875
/* IN_EXCL_UNLINK should make the closing of the previously unlinked
3876
file not appear as an ievent, so we should not see it now. */
3877
read_size = read(added_read_task->fd, ievent, ievent_size);
3878
g_assert_cmpint((int)read_size, ==, -1);
3879
g_assert_true(errno == EAGAIN);
3883
g_assert_cmpint(rmdir(tempdir), ==, 0);
3886
3736
static void test_read_inotify_event_readerror(__attribute__((unused))
3887
3737
test_fixture *fixture,
3888
3738
__attribute__((unused))
4079
3929
const size_t ievent_max_size = (sizeof(struct inotify_event)
4080
3930
+ NAME_MAX + 1);
4081
3931
g_assert_cmpint(ievent_max_size, <=, PIPE_BUF);
4083
struct inotify_event event;
4084
char name_buffer[NAME_MAX + 1];
4086
struct inotify_event *const ievent = &ievent_buffer.event;
3932
char ievent_buffer[sizeof(struct inotify_event) + NAME_MAX + 1];
3933
struct inotify_event *ievent = ((struct inotify_event *)
4088
3936
const char dummy_file_name[] = "ask.dummy_file_name";
4089
3937
ievent->mask = IN_CLOSE_WRITE;
4091
3939
memcpy(ievent->name, dummy_file_name, sizeof(dummy_file_name));
4092
3940
const size_t ievent_size = (sizeof(struct inotify_event)
4093
3941
+ sizeof(dummy_file_name));
4094
g_assert_cmpint(write(pipefds[1], (char *)ievent, ievent_size),
3942
g_assert_cmpint(write(pipefds[1], ievent_buffer, ievent_size),
4095
3943
==, ievent_size);
4096
3944
g_assert_cmpint(close(pipefds[1]), ==, 0);
4174
4022
const size_t ievent_max_size = (sizeof(struct inotify_event)
4175
4023
+ NAME_MAX + 1);
4176
4024
g_assert_cmpint(ievent_max_size, <=, PIPE_BUF);
4178
struct inotify_event event;
4179
char name_buffer[NAME_MAX + 1];
4181
struct inotify_event *const ievent = &ievent_buffer.event;
4025
char ievent_buffer[sizeof(struct inotify_event) + NAME_MAX + 1];
4026
struct inotify_event *ievent = ((struct inotify_event *)
4183
4029
const char dummy_file_name[] = "ask.dummy_file_name";
4184
4030
ievent->mask = IN_MOVED_TO;
4186
4032
memcpy(ievent->name, dummy_file_name, sizeof(dummy_file_name));
4187
4033
const size_t ievent_size = (sizeof(struct inotify_event)
4188
4034
+ sizeof(dummy_file_name));
4189
g_assert_cmpint(write(pipefds[1], (char *)ievent, ievent_size),
4035
g_assert_cmpint(write(pipefds[1], ievent_buffer, ievent_size),
4190
4036
==, ievent_size);
4191
4037
g_assert_cmpint(close(pipefds[1]), ==, 0);
4256
void test_read_inotify_event_IN_MOVED_FROM(__attribute__((unused))
4257
test_fixture *fixture,
4258
__attribute__((unused))
4259
gconstpointer user_data){
4260
__attribute__((cleanup(cleanup_close)))
4261
const int epoll_fd = epoll_create1(EPOLL_CLOEXEC);
4262
g_assert_cmpint(epoll_fd, >=, 0);
4263
__attribute__((cleanup(string_set_clear)))
4264
string_set cancelled_filenames = {};
4265
const mono_microsecs current_time = 0;
4268
g_assert_cmpint(pipe2(pipefds, O_CLOEXEC | O_NONBLOCK), ==, 0);
4270
/* "sufficient to read at least one event." - inotify(7) */
4271
const size_t ievent_max_size = (sizeof(struct inotify_event)
4273
g_assert_cmpint(ievent_max_size, <=, PIPE_BUF);
4275
struct inotify_event event;
4276
char name_buffer[NAME_MAX + 1];
4278
struct inotify_event *const ievent = &ievent_buffer.event;
4280
const char dummy_file_name[] = "ask.dummy_file_name";
4281
ievent->mask = IN_MOVED_FROM;
4282
ievent->len = sizeof(dummy_file_name);
4283
memcpy(ievent->name, dummy_file_name, sizeof(dummy_file_name));
4284
const size_t ievent_size = (sizeof(struct inotify_event)
4285
+ sizeof(dummy_file_name));
4286
g_assert_cmpint(write(pipefds[1], (char *)ievent, ievent_size),
4288
g_assert_cmpint(close(pipefds[1]), ==, 0);
4290
bool quit_now = false;
4291
buffer password = {};
4292
bool mandos_client_exited = false;
4293
bool password_is_read = false;
4294
__attribute__((cleanup(cleanup_queue)))
4295
task_queue *queue = create_queue();
4296
g_assert_nonnull(queue);
4298
task_context task = {
4299
.func=read_inotify_event,
4302
.quit_now=&quit_now,
4303
.password=&password,
4304
.filename=strdup("/nonexistent"),
4305
.cancelled_filenames=&cancelled_filenames,
4306
.current_time=¤t_time,
4307
.mandos_client_exited=&mandos_client_exited,
4308
.password_is_read=&password_is_read,
4310
task.func(task, queue);
4311
g_assert_false(quit_now);
4312
g_assert_true(queue->next_run == 0);
4313
g_assert_cmpuint((unsigned int)queue->length, ==, 1);
4315
g_assert_nonnull(find_matching_task(queue, (task_context){
4316
.func=read_inotify_event,
4319
.quit_now=&quit_now,
4320
.password=&password,
4321
.filename=task.filename,
4322
.cancelled_filenames=&cancelled_filenames,
4323
.current_time=¤t_time,
4324
.mandos_client_exited=&mandos_client_exited,
4325
.password_is_read=&password_is_read,
4328
g_assert_true(epoll_set_contains(epoll_fd, pipefds[0],
4329
EPOLLIN | EPOLLRDHUP));
4331
__attribute__((cleanup(cleanup_string)))
4332
char *filename = NULL;
4333
g_assert_cmpint(asprintf(&filename, "%s/%s", task.filename,
4334
dummy_file_name), >, 0);
4335
g_assert_nonnull(filename);
4336
g_assert_true(string_set_contains(*task.cancelled_filenames,
4340
4101
static void test_read_inotify_event_IN_DELETE(__attribute__((unused))
4341
4102
test_fixture *fixture,
4342
4103
__attribute__((unused))
4356
4117
const size_t ievent_max_size = (sizeof(struct inotify_event)
4357
4118
+ NAME_MAX + 1);
4358
4119
g_assert_cmpint(ievent_max_size, <=, PIPE_BUF);
4360
struct inotify_event event;
4361
char name_buffer[NAME_MAX + 1];
4363
struct inotify_event *const ievent = &ievent_buffer.event;
4120
char ievent_buffer[sizeof(struct inotify_event) + NAME_MAX + 1];
4121
struct inotify_event *ievent = ((struct inotify_event *)
4365
4124
const char dummy_file_name[] = "ask.dummy_file_name";
4366
4125
ievent->mask = IN_DELETE;
4368
4127
memcpy(ievent->name, dummy_file_name, sizeof(dummy_file_name));
4369
4128
const size_t ievent_size = (sizeof(struct inotify_event)
4370
4129
+ sizeof(dummy_file_name));
4371
g_assert_cmpint(write(pipefds[1], (char *)ievent, ievent_size),
4130
g_assert_cmpint(write(pipefds[1], ievent_buffer, ievent_size),
4372
4131
==, ievent_size);
4373
4132
g_assert_cmpint(close(pipefds[1]), ==, 0);
4440
4199
const size_t ievent_max_size = (sizeof(struct inotify_event)
4441
4200
+ NAME_MAX + 1);
4442
4201
g_assert_cmpint(ievent_max_size, <=, PIPE_BUF);
4444
struct inotify_event event;
4445
char name_buffer[NAME_MAX + 1];
4447
struct inotify_event *const ievent = &ievent_buffer.event;
4202
char ievent_buffer[sizeof(struct inotify_event) + NAME_MAX + 1];
4203
struct inotify_event *ievent = ((struct inotify_event *)
4449
4206
const char dummy_file_name[] = "ignored.dummy_file_name";
4450
4207
ievent->mask = IN_CLOSE_WRITE;
4452
4209
memcpy(ievent->name, dummy_file_name, sizeof(dummy_file_name));
4453
4210
const size_t ievent_size = (sizeof(struct inotify_event)
4454
4211
+ sizeof(dummy_file_name));
4455
g_assert_cmpint(write(pipefds[1], (char *)ievent, ievent_size),
4212
g_assert_cmpint(write(pipefds[1], ievent_buffer, ievent_size),
4456
4213
==, ievent_size);
4457
4214
g_assert_cmpint(close(pipefds[1]), ==, 0);
4516
4273
const size_t ievent_max_size = (sizeof(struct inotify_event)
4517
4274
+ NAME_MAX + 1);
4518
4275
g_assert_cmpint(ievent_max_size, <=, PIPE_BUF);
4520
struct inotify_event event;
4521
char name_buffer[NAME_MAX + 1];
4523
struct inotify_event *const ievent = &ievent_buffer.event;
4276
char ievent_buffer[sizeof(struct inotify_event) + NAME_MAX + 1];
4277
struct inotify_event *ievent = ((struct inotify_event *)
4525
4280
const char dummy_file_name[] = "ignored.dummy_file_name";
4526
4281
ievent->mask = IN_MOVED_TO;
4528
4283
memcpy(ievent->name, dummy_file_name, sizeof(dummy_file_name));
4529
4284
const size_t ievent_size = (sizeof(struct inotify_event)
4530
4285
+ sizeof(dummy_file_name));
4531
g_assert_cmpint(write(pipefds[1], (char *)ievent, ievent_size),
4286
g_assert_cmpint(write(pipefds[1], ievent_buffer, ievent_size),
4532
4287
==, ievent_size);
4533
4288
g_assert_cmpint(close(pipefds[1]), ==, 0);
4575
4330
EPOLLIN | EPOLLRDHUP));
4579
test_read_inotify_event_IN_MOVED_FROM_badname(__attribute__((unused))
4580
test_fixture *fixture,
4581
__attribute__((unused))
4584
__attribute__((cleanup(cleanup_close)))
4585
const int epoll_fd = epoll_create1(EPOLL_CLOEXEC);
4586
g_assert_cmpint(epoll_fd, >=, 0);
4587
__attribute__((cleanup(string_set_clear)))
4588
string_set cancelled_filenames = {};
4589
const mono_microsecs current_time = 0;
4592
g_assert_cmpint(pipe2(pipefds, O_CLOEXEC | O_NONBLOCK), ==, 0);
4594
/* "sufficient to read at least one event." - inotify(7) */
4595
const size_t ievent_max_size = (sizeof(struct inotify_event)
4597
g_assert_cmpint(ievent_max_size, <=, PIPE_BUF);
4599
struct inotify_event event;
4600
char name_buffer[NAME_MAX + 1];
4602
struct inotify_event *const ievent = &ievent_buffer.event;
4604
const char dummy_file_name[] = "ignored.dummy_file_name";
4605
ievent->mask = IN_MOVED_FROM;
4606
ievent->len = sizeof(dummy_file_name);
4607
memcpy(ievent->name, dummy_file_name, sizeof(dummy_file_name));
4608
const size_t ievent_size = (sizeof(struct inotify_event)
4609
+ sizeof(dummy_file_name));
4610
g_assert_cmpint(write(pipefds[1], (char *)ievent, ievent_size),
4612
g_assert_cmpint(close(pipefds[1]), ==, 0);
4614
bool quit_now = false;
4615
buffer password = {};
4616
bool mandos_client_exited = false;
4617
bool password_is_read = false;
4618
__attribute__((cleanup(cleanup_queue)))
4619
task_queue *queue = create_queue();
4620
g_assert_nonnull(queue);
4622
task_context task = {
4623
.func=read_inotify_event,
4626
.quit_now=&quit_now,
4627
.password=&password,
4628
.filename=strdup("/nonexistent"),
4629
.cancelled_filenames=&cancelled_filenames,
4630
.current_time=¤t_time,
4631
.mandos_client_exited=&mandos_client_exited,
4632
.password_is_read=&password_is_read,
4634
task.func(task, queue);
4635
g_assert_false(quit_now);
4636
g_assert_true(queue->next_run == 0);
4637
g_assert_cmpuint((unsigned int)queue->length, ==, 1);
4639
g_assert_nonnull(find_matching_task(queue, (task_context){
4640
.func=read_inotify_event,
4643
.quit_now=&quit_now,
4644
.password=&password,
4645
.filename=task.filename,
4646
.cancelled_filenames=&cancelled_filenames,
4647
.current_time=¤t_time,
4648
.mandos_client_exited=&mandos_client_exited,
4649
.password_is_read=&password_is_read,
4652
g_assert_true(epoll_set_contains(epoll_fd, pipefds[0],
4653
EPOLLIN | EPOLLRDHUP));
4655
__attribute__((cleanup(cleanup_string)))
4656
char *filename = NULL;
4657
g_assert_cmpint(asprintf(&filename, "%s/%s", task.filename,
4658
dummy_file_name), >, 0);
4659
g_assert_nonnull(filename);
4660
g_assert_false(string_set_contains(cancelled_filenames, filename));
4664
4334
void test_read_inotify_event_IN_DELETE_badname(__attribute__((unused))
4665
4335
test_fixture *fixture,
4680
4350
const size_t ievent_max_size = (sizeof(struct inotify_event)
4681
4351
+ NAME_MAX + 1);
4682
4352
g_assert_cmpint(ievent_max_size, <=, PIPE_BUF);
4684
struct inotify_event event;
4685
char name_buffer[NAME_MAX + 1];
4687
struct inotify_event *const ievent = &ievent_buffer.event;
4353
char ievent_buffer[sizeof(struct inotify_event) + NAME_MAX + 1];
4354
struct inotify_event *ievent = ((struct inotify_event *)
4689
4357
const char dummy_file_name[] = "ignored.dummy_file_name";
4690
4358
ievent->mask = IN_DELETE;
4692
4360
memcpy(ievent->name, dummy_file_name, sizeof(dummy_file_name));
4693
4361
const size_t ievent_size = (sizeof(struct inotify_event)
4694
4362
+ sizeof(dummy_file_name));
4695
g_assert_cmpint(write(pipefds[1], (char *)ievent, ievent_size),
4363
g_assert_cmpint(write(pipefds[1], ievent_buffer, ievent_size),
4696
4364
==, ievent_size);
4697
4365
g_assert_cmpint(close(pipefds[1]), ==, 0);
7911
7579
test_add_inotify_dir_watch_IN_CLOSE_WRITE);
7912
7580
test_add_st("/task-creators/add_inotify_dir_watch/IN_MOVED_TO",
7913
7581
test_add_inotify_dir_watch_IN_MOVED_TO);
7914
test_add_st("/task-creators/add_inotify_dir_watch/IN_MOVED_FROM",
7915
test_add_inotify_dir_watch_IN_MOVED_FROM);
7916
test_add_st("/task-creators/add_inotify_dir_watch/IN_EXCL_UNLINK",
7917
test_add_inotify_dir_watch_IN_EXCL_UNLINK);
7918
7582
test_add_st("/task-creators/add_inotify_dir_watch/IN_DELETE",
7919
7583
test_add_inotify_dir_watch_IN_DELETE);
7920
7584
test_add_st("/task/read_inotify_event/readerror",
7929
7593
test_read_inotify_event_IN_CLOSE_WRITE);
7930
7594
test_add_st("/task/read_inotify_event/IN_MOVED_TO",
7931
7595
test_read_inotify_event_IN_MOVED_TO);
7932
test_add_st("/task/read_inotify_event/IN_MOVED_FROM",
7933
test_read_inotify_event_IN_MOVED_FROM);
7934
7596
test_add_st("/task/read_inotify_event/IN_DELETE",
7935
7597
test_read_inotify_event_IN_DELETE);
7936
7598
test_add_st("/task/read_inotify_event/IN_CLOSE_WRITE/badname",
7937
7599
test_read_inotify_event_IN_CLOSE_WRITE_badname);
7938
7600
test_add_st("/task/read_inotify_event/IN_MOVED_TO/badname",
7939
7601
test_read_inotify_event_IN_MOVED_TO_badname);
7940
test_add_st("/task/read_inotify_event/IN_MOVED_FROM/badname",
7941
test_read_inotify_event_IN_MOVED_FROM_badname);
7942
7602
test_add_st("/task/read_inotify_event/IN_DELETE/badname",
7943
7603
test_read_inotify_event_IN_DELETE_badname);
7944
7604
test_add_st("/task/open_and_parse_question/ENOENT",