/mandos/trunk

To get this branch, use:
bzr branch http://bzr.recompile.se/loggerhead/mandos/trunk

« back to all changes in this revision

Viewing changes to dracut-module/password-agent.c

  • Committer: Teddy Hogeborn
  • Date: 2019-08-03 11:39:38 UTC
  • Revision ID: teddy@recompile.se-20190803113938-httj8rqsnct08txx
dracut-module/password-agent.c: Bug fix: Ignore deleted files

If a question file ("ask.*") is opened, deleted, and then closed, we
still get an IN_CLOSE_WRITE ievent after the IN_DELETE ievent.  We
should pass the IN_EXCL_UNLINK flag to inotify_add_watch() to avoid
this.

* dracut-module/password-agent.c (add_inotify_dir_watch): Add
  "IN_EXCL_UNLINK" flag to inotify_add_watch().
  (test_add_inotify_dir_watch_IN_EXCL_UNLINK): New test.
  (run_tests): Add new test.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1017
1017
    return false;
1018
1018
  }
1019
1019
 
1020
 
  if(inotify_add_watch(fd, dir, IN_CLOSE_WRITE
1021
 
                       | IN_MOVED_TO | IN_DELETE)
 
1020
  if(inotify_add_watch(fd, dir, IN_CLOSE_WRITE | IN_MOVED_TO
 
1021
                       | IN_MOVED_FROM| IN_DELETE | IN_EXCL_UNLINK)
1022
1022
     == -1){
1023
1023
    error(0, errno, "Failed to create inotify watch on %s", dir);
1024
1024
    return false;
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);
1074
 
  char ievent_buffer[sizeof(struct inotify_event) + NAME_MAX + 1];
1075
 
  struct inotify_event *ievent = ((struct inotify_event *)
1076
 
                                  ievent_buffer);
 
1074
  struct {
 
1075
    struct inotify_event event;
 
1076
    char name_buffer[NAME_MAX + 1];
 
1077
  } ievent_buffer;
 
1078
  struct inotify_event *const ievent = &ievent_buffer.event;
1077
1079
 
1078
1080
  const ssize_t read_length = read(fd, ievent, ievent_size);
1079
1081
  if(read_length == 0){ /* EOF */
1117
1119
             immediately */
1118
1120
          queue->next_run = 1;
1119
1121
        }
1120
 
      } else if(ievent->mask & IN_DELETE){
 
1122
      } else if(ievent->mask & (IN_MOVED_FROM | IN_DELETE)){
1121
1123
        if(not string_set_add(cancelled_filenames,
1122
1124
                              question_filename)){
1123
1125
          error(0, errno, "Could not add question %s to"
3670
3672
}
3671
3673
 
3672
3674
static
 
3675
void test_add_inotify_dir_watch_IN_MOVED_FROM(__attribute__((unused))
 
3676
                                              test_fixture *fixture,
 
3677
                                              __attribute__((unused))
 
3678
                                              gconstpointer
 
3679
                                              user_data){
 
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;
 
3689
 
 
3690
  bool quit_now = false;
 
3691
  buffer password = {};
 
3692
  bool mandos_client_exited = false;
 
3693
  bool password_is_read = false;
 
3694
 
 
3695
  __attribute__((cleanup(cleanup_string)))
 
3696
    char *tempdir = make_temporary_directory();
 
3697
  g_assert_nonnull(tempdir);
 
3698
 
 
3699
  __attribute__((cleanup(cleanup_string)))
 
3700
    char *tempfilename = make_temporary_file_in_directory(tempdir);
 
3701
  g_assert_nonnull(tempfilename);
 
3702
 
 
3703
  __attribute__((cleanup(cleanup_string)))
 
3704
    char *targetdir = make_temporary_directory();
 
3705
  g_assert_nonnull(targetdir);
 
3706
 
 
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);
 
3712
 
 
3713
  g_assert_true(add_inotify_dir_watch(queue, epoll_fd, &quit_now,
 
3714
                                      &password, tempdir,
 
3715
                                      &cancelled_filenames,
 
3716
                                      &current_time,
 
3717
                                      &mandos_client_exited,
 
3718
                                      &password_is_read));
 
3719
 
 
3720
  g_assert_cmpint(rename(tempfilename, targetfilename), ==, 0);
 
3721
 
 
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);
 
3726
 
 
3727
  /* "sufficient to read at least one event." - inotify(7) */
 
3728
  const size_t ievent_size = (sizeof(struct inotify_event)
 
3729
                              + NAME_MAX + 1);
 
3730
  struct inotify_event *ievent = malloc(ievent_size);
 
3731
  g_assert_nonnull(ievent);
 
3732
 
 
3733
  ssize_t read_size = read(added_read_task->fd, ievent, ievent_size);
 
3734
 
 
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));
 
3738
 
 
3739
  free(ievent);
 
3740
 
 
3741
  g_assert_cmpint(unlink(targetfilename), ==, 0);
 
3742
  g_assert_cmpint(rmdir(targetdir), ==, 0);
 
3743
  g_assert_cmpint(rmdir(tempdir), ==, 0);
 
3744
}
 
3745
 
 
3746
static
3673
3747
void test_add_inotify_dir_watch_IN_DELETE(__attribute__((unused))
3674
3748
                                          test_fixture *fixture,
3675
3749
                                          __attribute__((unused))
3733
3807
  g_assert_cmpint(rmdir(tempdir), ==, 0);
3734
3808
}
3735
3809
 
 
3810
static
 
3811
void test_add_inotify_dir_watch_IN_EXCL_UNLINK(__attribute__((unused))
 
3812
                                               test_fixture *fixture,
 
3813
                                               __attribute__((unused))
 
3814
                                               gconstpointer
 
3815
                                               user_data){
 
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;
 
3825
 
 
3826
  bool quit_now = false;
 
3827
  buffer password = {};
 
3828
  bool mandos_client_exited = false;
 
3829
  bool password_is_read = false;
 
3830
 
 
3831
  __attribute__((cleanup(cleanup_string)))
 
3832
    char *tempdir = make_temporary_directory();
 
3833
  g_assert_nonnull(tempdir);
 
3834
 
 
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
 
3839
                         | O_NOFOLLOW);
 
3840
  g_assert_cmpint(tempfile_fd, >, 2);
 
3841
 
 
3842
  g_assert_true(add_inotify_dir_watch(queue, epoll_fd, &quit_now,
 
3843
                                      &password, tempdir,
 
3844
                                      &cancelled_filenames,
 
3845
                                      &current_time,
 
3846
                                      &mandos_client_exited,
 
3847
                                      &password_is_read));
 
3848
  g_assert_cmpint(unlink(tempfile), ==, 0);
 
3849
 
 
3850
  g_assert_cmpuint((unsigned int)queue->length, >, 0);
 
3851
 
 
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);
 
3856
 
 
3857
  g_assert_cmpint(added_read_task->fd, >, 2);
 
3858
  g_assert_true(fd_has_cloexec_and_nonblock(added_read_task->fd));
 
3859
 
 
3860
  /* "sufficient to read at least one event." - inotify(7) */
 
3861
  const size_t ievent_size = (sizeof(struct inotify_event)
 
3862
                              + NAME_MAX + 1);
 
3863
  struct inotify_event *ievent = malloc(ievent_size);
 
3864
  g_assert_nonnull(ievent);
 
3865
 
 
3866
  ssize_t read_size = 0;
 
3867
  read_size = read(added_read_task->fd, ievent, ievent_size);
 
3868
 
 
3869
  g_assert_cmpint((int)read_size, >, 0);
 
3870
  g_assert_true(ievent->mask & IN_DELETE);
 
3871
  g_assert_cmpstr(ievent->name, ==, basename(tempfile));
 
3872
 
 
3873
  g_assert_cmpint(close(tempfile_fd), ==, 0);
 
3874
 
 
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);
 
3880
 
 
3881
  free(ievent);
 
3882
 
 
3883
  g_assert_cmpint(rmdir(tempdir), ==, 0);
 
3884
}
 
3885
 
3736
3886
static void test_read_inotify_event_readerror(__attribute__((unused))
3737
3887
                                              test_fixture *fixture,
3738
3888
                                              __attribute__((unused))
3929
4079
  const size_t ievent_max_size = (sizeof(struct inotify_event)
3930
4080
                                  + NAME_MAX + 1);
3931
4081
  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 *)
3934
 
                                  ievent_buffer);
 
4082
  struct {
 
4083
    struct inotify_event event;
 
4084
    char name_buffer[NAME_MAX + 1];
 
4085
  } ievent_buffer;
 
4086
  struct inotify_event *const ievent = &ievent_buffer.event;
3935
4087
 
3936
4088
  const char dummy_file_name[] = "ask.dummy_file_name";
3937
4089
  ievent->mask = IN_CLOSE_WRITE;
3939
4091
  memcpy(ievent->name, dummy_file_name, sizeof(dummy_file_name));
3940
4092
  const size_t ievent_size = (sizeof(struct inotify_event)
3941
4093
                              + sizeof(dummy_file_name));
3942
 
  g_assert_cmpint(write(pipefds[1], ievent_buffer, ievent_size),
 
4094
  g_assert_cmpint(write(pipefds[1], (char *)ievent, ievent_size),
3943
4095
                  ==, ievent_size);
3944
4096
  g_assert_cmpint(close(pipefds[1]), ==, 0);
3945
4097
 
4022
4174
  const size_t ievent_max_size = (sizeof(struct inotify_event)
4023
4175
                                  + NAME_MAX + 1);
4024
4176
  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 *)
4027
 
                                  ievent_buffer);
 
4177
  struct {
 
4178
    struct inotify_event event;
 
4179
    char name_buffer[NAME_MAX + 1];
 
4180
  } ievent_buffer;
 
4181
  struct inotify_event *const ievent = &ievent_buffer.event;
4028
4182
 
4029
4183
  const char dummy_file_name[] = "ask.dummy_file_name";
4030
4184
  ievent->mask = IN_MOVED_TO;
4032
4186
  memcpy(ievent->name, dummy_file_name, sizeof(dummy_file_name));
4033
4187
  const size_t ievent_size = (sizeof(struct inotify_event)
4034
4188
                              + sizeof(dummy_file_name));
4035
 
  g_assert_cmpint(write(pipefds[1], ievent_buffer, ievent_size),
 
4189
  g_assert_cmpint(write(pipefds[1], (char *)ievent, ievent_size),
4036
4190
                  ==, ievent_size);
4037
4191
  g_assert_cmpint(close(pipefds[1]), ==, 0);
4038
4192
 
4098
4252
      }));
4099
4253
}
4100
4254
 
 
4255
static
 
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;
 
4266
 
 
4267
  int pipefds[2];
 
4268
  g_assert_cmpint(pipe2(pipefds, O_CLOEXEC | O_NONBLOCK), ==, 0);
 
4269
 
 
4270
  /* "sufficient to read at least one event." - inotify(7) */
 
4271
  const size_t ievent_max_size = (sizeof(struct inotify_event)
 
4272
                                  + NAME_MAX + 1);
 
4273
  g_assert_cmpint(ievent_max_size, <=, PIPE_BUF);
 
4274
  struct {
 
4275
    struct inotify_event event;
 
4276
    char name_buffer[NAME_MAX + 1];
 
4277
  } ievent_buffer;
 
4278
  struct inotify_event *const ievent = &ievent_buffer.event;
 
4279
 
 
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),
 
4287
                  ==, ievent_size);
 
4288
  g_assert_cmpint(close(pipefds[1]), ==, 0);
 
4289
 
 
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);
 
4297
 
 
4298
  task_context task = {
 
4299
    .func=read_inotify_event,
 
4300
    .epoll_fd=epoll_fd,
 
4301
    .fd=pipefds[0],
 
4302
    .quit_now=&quit_now,
 
4303
    .password=&password,
 
4304
    .filename=strdup("/nonexistent"),
 
4305
    .cancelled_filenames=&cancelled_filenames,
 
4306
    .current_time=&current_time,
 
4307
    .mandos_client_exited=&mandos_client_exited,
 
4308
    .password_is_read=&password_is_read,
 
4309
  };
 
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);
 
4314
 
 
4315
  g_assert_nonnull(find_matching_task(queue, (task_context){
 
4316
        .func=read_inotify_event,
 
4317
        .epoll_fd=epoll_fd,
 
4318
        .fd=pipefds[0],
 
4319
        .quit_now=&quit_now,
 
4320
        .password=&password,
 
4321
        .filename=task.filename,
 
4322
        .cancelled_filenames=&cancelled_filenames,
 
4323
        .current_time=&current_time,
 
4324
        .mandos_client_exited=&mandos_client_exited,
 
4325
        .password_is_read=&password_is_read,
 
4326
      }));
 
4327
 
 
4328
  g_assert_true(epoll_set_contains(epoll_fd, pipefds[0],
 
4329
                                   EPOLLIN | EPOLLRDHUP));
 
4330
 
 
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,
 
4337
                                    filename));
 
4338
}
 
4339
 
4101
4340
static void test_read_inotify_event_IN_DELETE(__attribute__((unused))
4102
4341
                                              test_fixture *fixture,
4103
4342
                                              __attribute__((unused))
4117
4356
  const size_t ievent_max_size = (sizeof(struct inotify_event)
4118
4357
                                  + NAME_MAX + 1);
4119
4358
  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 *)
4122
 
                                  ievent_buffer);
 
4359
  struct {
 
4360
    struct inotify_event event;
 
4361
    char name_buffer[NAME_MAX + 1];
 
4362
  } ievent_buffer;
 
4363
  struct inotify_event *const ievent = &ievent_buffer.event;
4123
4364
 
4124
4365
  const char dummy_file_name[] = "ask.dummy_file_name";
4125
4366
  ievent->mask = IN_DELETE;
4127
4368
  memcpy(ievent->name, dummy_file_name, sizeof(dummy_file_name));
4128
4369
  const size_t ievent_size = (sizeof(struct inotify_event)
4129
4370
                              + sizeof(dummy_file_name));
4130
 
  g_assert_cmpint(write(pipefds[1], ievent_buffer, ievent_size),
 
4371
  g_assert_cmpint(write(pipefds[1], (char *)ievent, ievent_size),
4131
4372
                  ==, ievent_size);
4132
4373
  g_assert_cmpint(close(pipefds[1]), ==, 0);
4133
4374
 
4199
4440
  const size_t ievent_max_size = (sizeof(struct inotify_event)
4200
4441
                                  + NAME_MAX + 1);
4201
4442
  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 *)
4204
 
                                  ievent_buffer);
 
4443
  struct {
 
4444
    struct inotify_event event;
 
4445
    char name_buffer[NAME_MAX + 1];
 
4446
  } ievent_buffer;
 
4447
  struct inotify_event *const ievent = &ievent_buffer.event;
4205
4448
 
4206
4449
  const char dummy_file_name[] = "ignored.dummy_file_name";
4207
4450
  ievent->mask = IN_CLOSE_WRITE;
4209
4452
  memcpy(ievent->name, dummy_file_name, sizeof(dummy_file_name));
4210
4453
  const size_t ievent_size = (sizeof(struct inotify_event)
4211
4454
                              + sizeof(dummy_file_name));
4212
 
  g_assert_cmpint(write(pipefds[1], ievent_buffer, ievent_size),
 
4455
  g_assert_cmpint(write(pipefds[1], (char *)ievent, ievent_size),
4213
4456
                  ==, ievent_size);
4214
4457
  g_assert_cmpint(close(pipefds[1]), ==, 0);
4215
4458
 
4273
4516
  const size_t ievent_max_size = (sizeof(struct inotify_event)
4274
4517
                                  + NAME_MAX + 1);
4275
4518
  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 *)
4278
 
                                  ievent_buffer);
 
4519
  struct {
 
4520
    struct inotify_event event;
 
4521
    char name_buffer[NAME_MAX + 1];
 
4522
  } ievent_buffer;
 
4523
  struct inotify_event *const ievent = &ievent_buffer.event;
4279
4524
 
4280
4525
  const char dummy_file_name[] = "ignored.dummy_file_name";
4281
4526
  ievent->mask = IN_MOVED_TO;
4283
4528
  memcpy(ievent->name, dummy_file_name, sizeof(dummy_file_name));
4284
4529
  const size_t ievent_size = (sizeof(struct inotify_event)
4285
4530
                              + sizeof(dummy_file_name));
4286
 
  g_assert_cmpint(write(pipefds[1], ievent_buffer, ievent_size),
 
4531
  g_assert_cmpint(write(pipefds[1], (char *)ievent, ievent_size),
4287
4532
                  ==, ievent_size);
4288
4533
  g_assert_cmpint(close(pipefds[1]), ==, 0);
4289
4534
 
4330
4575
                                   EPOLLIN | EPOLLRDHUP));
4331
4576
}
4332
4577
 
 
4578
static void
 
4579
test_read_inotify_event_IN_MOVED_FROM_badname(__attribute__((unused))
 
4580
                                              test_fixture *fixture,
 
4581
                                              __attribute__((unused))
 
4582
                                              gconstpointer
 
4583
                                              user_data){
 
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;
 
4590
 
 
4591
  int pipefds[2];
 
4592
  g_assert_cmpint(pipe2(pipefds, O_CLOEXEC | O_NONBLOCK), ==, 0);
 
4593
 
 
4594
  /* "sufficient to read at least one event." - inotify(7) */
 
4595
  const size_t ievent_max_size = (sizeof(struct inotify_event)
 
4596
                                  + NAME_MAX + 1);
 
4597
  g_assert_cmpint(ievent_max_size, <=, PIPE_BUF);
 
4598
  struct {
 
4599
    struct inotify_event event;
 
4600
    char name_buffer[NAME_MAX + 1];
 
4601
  } ievent_buffer;
 
4602
  struct inotify_event *const ievent = &ievent_buffer.event;
 
4603
 
 
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),
 
4611
                  ==, ievent_size);
 
4612
  g_assert_cmpint(close(pipefds[1]), ==, 0);
 
4613
 
 
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);
 
4621
 
 
4622
  task_context task = {
 
4623
    .func=read_inotify_event,
 
4624
    .epoll_fd=epoll_fd,
 
4625
    .fd=pipefds[0],
 
4626
    .quit_now=&quit_now,
 
4627
    .password=&password,
 
4628
    .filename=strdup("/nonexistent"),
 
4629
    .cancelled_filenames=&cancelled_filenames,
 
4630
    .current_time=&current_time,
 
4631
    .mandos_client_exited=&mandos_client_exited,
 
4632
    .password_is_read=&password_is_read,
 
4633
  };
 
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);
 
4638
 
 
4639
  g_assert_nonnull(find_matching_task(queue, (task_context){
 
4640
        .func=read_inotify_event,
 
4641
        .epoll_fd=epoll_fd,
 
4642
        .fd=pipefds[0],
 
4643
        .quit_now=&quit_now,
 
4644
        .password=&password,
 
4645
        .filename=task.filename,
 
4646
        .cancelled_filenames=&cancelled_filenames,
 
4647
        .current_time=&current_time,
 
4648
        .mandos_client_exited=&mandos_client_exited,
 
4649
        .password_is_read=&password_is_read,
 
4650
      }));
 
4651
 
 
4652
  g_assert_true(epoll_set_contains(epoll_fd, pipefds[0],
 
4653
                                   EPOLLIN | EPOLLRDHUP));
 
4654
 
 
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));
 
4661
}
 
4662
 
4333
4663
static
4334
4664
void test_read_inotify_event_IN_DELETE_badname(__attribute__((unused))
4335
4665
                                               test_fixture *fixture,
4350
4680
  const size_t ievent_max_size = (sizeof(struct inotify_event)
4351
4681
                                  + NAME_MAX + 1);
4352
4682
  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 *)
4355
 
                                  ievent_buffer);
 
4683
  struct {
 
4684
    struct inotify_event event;
 
4685
    char name_buffer[NAME_MAX + 1];
 
4686
  } ievent_buffer;
 
4687
  struct inotify_event *const ievent = &ievent_buffer.event;
4356
4688
 
4357
4689
  const char dummy_file_name[] = "ignored.dummy_file_name";
4358
4690
  ievent->mask = IN_DELETE;
4360
4692
  memcpy(ievent->name, dummy_file_name, sizeof(dummy_file_name));
4361
4693
  const size_t ievent_size = (sizeof(struct inotify_event)
4362
4694
                              + sizeof(dummy_file_name));
4363
 
  g_assert_cmpint(write(pipefds[1], ievent_buffer, ievent_size),
 
4695
  g_assert_cmpint(write(pipefds[1], (char *)ievent, ievent_size),
4364
4696
                  ==, ievent_size);
4365
4697
  g_assert_cmpint(close(pipefds[1]), ==, 0);
4366
4698
 
7579
7911
              test_add_inotify_dir_watch_IN_CLOSE_WRITE);
7580
7912
  test_add_st("/task-creators/add_inotify_dir_watch/IN_MOVED_TO",
7581
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);
7582
7918
  test_add_st("/task-creators/add_inotify_dir_watch/IN_DELETE",
7583
7919
              test_add_inotify_dir_watch_IN_DELETE);
7584
7920
  test_add_st("/task/read_inotify_event/readerror",
7593
7929
              test_read_inotify_event_IN_CLOSE_WRITE);
7594
7930
  test_add_st("/task/read_inotify_event/IN_MOVED_TO",
7595
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);
7596
7934
  test_add_st("/task/read_inotify_event/IN_DELETE",
7597
7935
              test_read_inotify_event_IN_DELETE);
7598
7936
  test_add_st("/task/read_inotify_event/IN_CLOSE_WRITE/badname",
7599
7937
              test_read_inotify_event_IN_CLOSE_WRITE_badname);
7600
7938
  test_add_st("/task/read_inotify_event/IN_MOVED_TO/badname",
7601
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);
7602
7942
  test_add_st("/task/read_inotify_event/IN_DELETE/badname",
7603
7943
              test_read_inotify_event_IN_DELETE_badname);
7604
7944
  test_add_st("/task/open_and_parse_question/ENOENT",