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);
3675
3747
void test_add_inotify_dir_watch_IN_DELETE(__attribute__((unused))
3676
3748
test_fixture *fixture,
3677
3749
__attribute__((unused))
3735
3807
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);
3738
3886
static void test_read_inotify_event_readerror(__attribute__((unused))
3739
3887
test_fixture *fixture,
3740
3888
__attribute__((unused))
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,
4107
4340
static void test_read_inotify_event_IN_DELETE(__attribute__((unused))
4108
4341
test_fixture *fixture,
4109
4342
__attribute__((unused))
4342
4575
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));
4346
4664
void test_read_inotify_event_IN_DELETE_badname(__attribute__((unused))
4347
4665
test_fixture *fixture,
7593
7911
test_add_inotify_dir_watch_IN_CLOSE_WRITE);
7594
7912
test_add_st("/task-creators/add_inotify_dir_watch/IN_MOVED_TO",
7595
7913
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);
7596
7918
test_add_st("/task-creators/add_inotify_dir_watch/IN_DELETE",
7597
7919
test_add_inotify_dir_watch_IN_DELETE);
7598
7920
test_add_st("/task/read_inotify_event/readerror",
7607
7929
test_read_inotify_event_IN_CLOSE_WRITE);
7608
7930
test_add_st("/task/read_inotify_event/IN_MOVED_TO",
7609
7931
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);
7610
7934
test_add_st("/task/read_inotify_event/IN_DELETE",
7611
7935
test_read_inotify_event_IN_DELETE);
7612
7936
test_add_st("/task/read_inotify_event/IN_CLOSE_WRITE/badname",
7613
7937
test_read_inotify_event_IN_CLOSE_WRITE_badname);
7614
7938
test_add_st("/task/read_inotify_event/IN_MOVED_TO/badname",
7615
7939
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);
7616
7942
test_add_st("/task/read_inotify_event/IN_DELETE/badname",
7617
7943
test_read_inotify_event_IN_DELETE_badname);
7618
7944
test_add_st("/task/open_and_parse_question/ENOENT",