/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-07-29 16:35:53 UTC
  • Revision ID: teddy@recompile.se-20190729163553-1i442i2cbx64c537
Make tests and man page examples match

Make the tests test_manual_page_example[1-5] match exactly what is
written in the manual page, and add comments to manual page as
reminders to keep tests and manual page examples in sync.

* mandos-ctl (Test_commands_from_options.test_manual_page_example_1):
  Remove "--verbose" option, since the manual does not have it as the
  first example, and change assertion to match.
* mandos-ctl.xml (EXAMPLE): Add comments to all examples documenting
  which test function they correspond to.  Also remove unnecessary
  quotes from option arguments in fourth example, and clarify language
  slightly in fifth example.

Show diffs side-by-side

added added

removed removed

Lines of Context:
431
431
    case EACCES:
432
432
    case ENAMETOOLONG:
433
433
    case ENOENT:
434
 
    case ENOTDIR:
435
434
      return EX_OSFILE;
436
435
    default:
437
436
      return EX_OSERR;
1018
1017
    return false;
1019
1018
  }
1020
1019
 
1021
 
  if(inotify_add_watch(fd, dir, IN_CLOSE_WRITE | IN_MOVED_TO
1022
 
                       | IN_MOVED_FROM| IN_DELETE | IN_EXCL_UNLINK
1023
 
                       | IN_ONLYDIR)
 
1020
  if(inotify_add_watch(fd, dir, IN_CLOSE_WRITE
 
1021
                       | IN_MOVED_TO | IN_DELETE)
1024
1022
     == -1){
1025
1023
    error(0, errno, "Failed to create inotify watch on %s", dir);
1026
1024
    return false;
1073
1071
  /* "sufficient to read at least one event." - inotify(7) */
1074
1072
  const size_t ievent_size = (sizeof(struct inotify_event)
1075
1073
                              + NAME_MAX + 1);
1076
 
  struct {
1077
 
    struct inotify_event event;
1078
 
    char name_buffer[NAME_MAX + 1];
1079
 
  } ievent_buffer;
1080
 
  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 *)
 
1076
                                  ievent_buffer);
1081
1077
 
1082
1078
  const ssize_t read_length = read(fd, ievent, ievent_size);
1083
1079
  if(read_length == 0){ /* EOF */
1121
1117
             immediately */
1122
1118
          queue->next_run = 1;
1123
1119
        }
1124
 
      } else if(ievent->mask & (IN_MOVED_FROM | IN_DELETE)){
 
1120
      } else if(ievent->mask & IN_DELETE){
1125
1121
        if(not string_set_add(cancelled_filenames,
1126
1122
                              question_filename)){
1127
1123
          error(0, errno, "Could not add question %s to"
3454
3450
  g_assert_cmpuint((unsigned int)queue->length, ==, 0);
3455
3451
}
3456
3452
 
3457
 
static void test_add_inotify_dir_watch_nondir(__attribute__((unused))
3458
 
                                              test_fixture *fixture,
3459
 
                                            __attribute__((unused))
3460
 
                                              gconstpointer
3461
 
                                              user_data){
3462
 
  __attribute__((cleanup(cleanup_close)))
3463
 
    const int epoll_fd = epoll_create1(EPOLL_CLOEXEC);
3464
 
  g_assert_cmpint(epoll_fd, >=, 0);
3465
 
  __attribute__((cleanup(cleanup_queue)))
3466
 
    task_queue *queue = create_queue();
3467
 
  g_assert_nonnull(queue);
3468
 
  __attribute__((cleanup(string_set_clear)))
3469
 
    string_set cancelled_filenames = {};
3470
 
  const mono_microsecs current_time = 0;
3471
 
 
3472
 
  bool quit_now = false;
3473
 
  buffer password = {};
3474
 
  bool mandos_client_exited = false;
3475
 
  bool password_is_read = false;
3476
 
 
3477
 
  const char not_a_directory[] = "/dev/tty";
3478
 
 
3479
 
  FILE *real_stderr = stderr;
3480
 
  FILE *devnull = fopen("/dev/null", "we");
3481
 
  g_assert_nonnull(devnull);
3482
 
  stderr = devnull;
3483
 
  g_assert_false(add_inotify_dir_watch(queue, epoll_fd, &quit_now,
3484
 
                                       &password, not_a_directory,
3485
 
                                       &cancelled_filenames,
3486
 
                                       &current_time,
3487
 
                                       &mandos_client_exited,
3488
 
                                       &password_is_read));
3489
 
  stderr = real_stderr;
3490
 
  g_assert_cmpint(fclose(devnull), ==, 0);
3491
 
 
3492
 
  g_assert_cmpuint((unsigned int)queue->length, ==, 0);
3493
 
}
3494
 
 
3495
3453
static void test_add_inotify_dir_watch_EAGAIN(__attribute__((unused))
3496
3454
                                              test_fixture *fixture,
3497
3455
                                              __attribute__((unused))
3712
3670
}
3713
3671
 
3714
3672
static
3715
 
void test_add_inotify_dir_watch_IN_MOVED_FROM(__attribute__((unused))
3716
 
                                              test_fixture *fixture,
3717
 
                                              __attribute__((unused))
3718
 
                                              gconstpointer
3719
 
                                              user_data){
3720
 
  __attribute__((cleanup(cleanup_close)))
3721
 
    const int epoll_fd = epoll_create1(EPOLL_CLOEXEC);
3722
 
  g_assert_cmpint(epoll_fd, >=, 0);
3723
 
  __attribute__((cleanup(cleanup_queue)))
3724
 
    task_queue *queue = create_queue();
3725
 
  g_assert_nonnull(queue);
3726
 
  __attribute__((cleanup(string_set_clear)))
3727
 
    string_set cancelled_filenames = {};
3728
 
  const mono_microsecs current_time = 0;
3729
 
 
3730
 
  bool quit_now = false;
3731
 
  buffer password = {};
3732
 
  bool mandos_client_exited = false;
3733
 
  bool password_is_read = false;
3734
 
 
3735
 
  __attribute__((cleanup(cleanup_string)))
3736
 
    char *tempdir = make_temporary_directory();
3737
 
  g_assert_nonnull(tempdir);
3738
 
 
3739
 
  __attribute__((cleanup(cleanup_string)))
3740
 
    char *tempfilename = make_temporary_file_in_directory(tempdir);
3741
 
  g_assert_nonnull(tempfilename);
3742
 
 
3743
 
  __attribute__((cleanup(cleanup_string)))
3744
 
    char *targetdir = make_temporary_directory();
3745
 
  g_assert_nonnull(targetdir);
3746
 
 
3747
 
  __attribute__((cleanup(cleanup_string)))
3748
 
    char *targetfilename = NULL;
3749
 
  g_assert_cmpint(asprintf(&targetfilename, "%s/%s", targetdir,
3750
 
                           basename(tempfilename)), >, 0);
3751
 
  g_assert_nonnull(targetfilename);
3752
 
 
3753
 
  g_assert_true(add_inotify_dir_watch(queue, epoll_fd, &quit_now,
3754
 
                                      &password, tempdir,
3755
 
                                      &cancelled_filenames,
3756
 
                                      &current_time,
3757
 
                                      &mandos_client_exited,
3758
 
                                      &password_is_read));
3759
 
 
3760
 
  g_assert_cmpint(rename(tempfilename, targetfilename), ==, 0);
3761
 
 
3762
 
  const task_context *const added_read_task
3763
 
    = find_matching_task(queue,
3764
 
                         (task_context){ .func=read_inotify_event });
3765
 
  g_assert_nonnull(added_read_task);
3766
 
 
3767
 
  /* "sufficient to read at least one event." - inotify(7) */
3768
 
  const size_t ievent_size = (sizeof(struct inotify_event)
3769
 
                              + NAME_MAX + 1);
3770
 
  struct inotify_event *ievent = malloc(ievent_size);
3771
 
  g_assert_nonnull(ievent);
3772
 
 
3773
 
  ssize_t read_size = read(added_read_task->fd, ievent, ievent_size);
3774
 
 
3775
 
  g_assert_cmpint((int)read_size, >, 0);
3776
 
  g_assert_true(ievent->mask & IN_MOVED_FROM);
3777
 
  g_assert_cmpstr(ievent->name, ==, basename(tempfilename));
3778
 
 
3779
 
  free(ievent);
3780
 
 
3781
 
  g_assert_cmpint(unlink(targetfilename), ==, 0);
3782
 
  g_assert_cmpint(rmdir(targetdir), ==, 0);
3783
 
  g_assert_cmpint(rmdir(tempdir), ==, 0);
3784
 
}
3785
 
 
3786
 
static
3787
3673
void test_add_inotify_dir_watch_IN_DELETE(__attribute__((unused))
3788
3674
                                          test_fixture *fixture,
3789
3675
                                          __attribute__((unused))
3847
3733
  g_assert_cmpint(rmdir(tempdir), ==, 0);
3848
3734
}
3849
3735
 
3850
 
static
3851
 
void test_add_inotify_dir_watch_IN_EXCL_UNLINK(__attribute__((unused))
3852
 
                                               test_fixture *fixture,
3853
 
                                               __attribute__((unused))
3854
 
                                               gconstpointer
3855
 
                                               user_data){
3856
 
  __attribute__((cleanup(cleanup_close)))
3857
 
    const int epoll_fd = epoll_create1(EPOLL_CLOEXEC);
3858
 
  g_assert_cmpint(epoll_fd, >=, 0);
3859
 
  __attribute__((cleanup(cleanup_queue)))
3860
 
    task_queue *queue = create_queue();
3861
 
  g_assert_nonnull(queue);
3862
 
  __attribute__((cleanup(string_set_clear)))
3863
 
    string_set cancelled_filenames = {};
3864
 
  const mono_microsecs current_time = 0;
3865
 
 
3866
 
  bool quit_now = false;
3867
 
  buffer password = {};
3868
 
  bool mandos_client_exited = false;
3869
 
  bool password_is_read = false;
3870
 
 
3871
 
  __attribute__((cleanup(cleanup_string)))
3872
 
    char *tempdir = make_temporary_directory();
3873
 
  g_assert_nonnull(tempdir);
3874
 
 
3875
 
  __attribute__((cleanup(cleanup_string)))
3876
 
    char *tempfile = make_temporary_file_in_directory(tempdir);
3877
 
  g_assert_nonnull(tempfile);
3878
 
  int tempfile_fd = open(tempfile, O_WRONLY | O_CLOEXEC | O_NOCTTY
3879
 
                         | O_NOFOLLOW);
3880
 
  g_assert_cmpint(tempfile_fd, >, 2);
3881
 
 
3882
 
  g_assert_true(add_inotify_dir_watch(queue, epoll_fd, &quit_now,
3883
 
                                      &password, tempdir,
3884
 
                                      &cancelled_filenames,
3885
 
                                      &current_time,
3886
 
                                      &mandos_client_exited,
3887
 
                                      &password_is_read));
3888
 
  g_assert_cmpint(unlink(tempfile), ==, 0);
3889
 
 
3890
 
  g_assert_cmpuint((unsigned int)queue->length, >, 0);
3891
 
 
3892
 
  const task_context *const added_read_task
3893
 
    = find_matching_task(queue,
3894
 
                         (task_context){ .func=read_inotify_event });
3895
 
  g_assert_nonnull(added_read_task);
3896
 
 
3897
 
  g_assert_cmpint(added_read_task->fd, >, 2);
3898
 
  g_assert_true(fd_has_cloexec_and_nonblock(added_read_task->fd));
3899
 
 
3900
 
  /* "sufficient to read at least one event." - inotify(7) */
3901
 
  const size_t ievent_size = (sizeof(struct inotify_event)
3902
 
                              + NAME_MAX + 1);
3903
 
  struct inotify_event *ievent = malloc(ievent_size);
3904
 
  g_assert_nonnull(ievent);
3905
 
 
3906
 
  ssize_t read_size = 0;
3907
 
  read_size = read(added_read_task->fd, ievent, ievent_size);
3908
 
 
3909
 
  g_assert_cmpint((int)read_size, >, 0);
3910
 
  g_assert_true(ievent->mask & IN_DELETE);
3911
 
  g_assert_cmpstr(ievent->name, ==, basename(tempfile));
3912
 
 
3913
 
  g_assert_cmpint(close(tempfile_fd), ==, 0);
3914
 
 
3915
 
  /* IN_EXCL_UNLINK should make the closing of the previously unlinked
3916
 
     file not appear as an ievent, so we should not see it now. */
3917
 
  read_size = read(added_read_task->fd, ievent, ievent_size);
3918
 
  g_assert_cmpint((int)read_size, ==, -1);
3919
 
  g_assert_true(errno == EAGAIN);
3920
 
 
3921
 
  free(ievent);
3922
 
 
3923
 
  g_assert_cmpint(rmdir(tempdir), ==, 0);
3924
 
}
3925
 
 
3926
3736
static void test_read_inotify_event_readerror(__attribute__((unused))
3927
3737
                                              test_fixture *fixture,
3928
3738
                                              __attribute__((unused))
4119
3929
  const size_t ievent_max_size = (sizeof(struct inotify_event)
4120
3930
                                  + NAME_MAX + 1);
4121
3931
  g_assert_cmpint(ievent_max_size, <=, PIPE_BUF);
4122
 
  struct {
4123
 
    struct inotify_event event;
4124
 
    char name_buffer[NAME_MAX + 1];
4125
 
  } ievent_buffer;
4126
 
  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 *)
 
3934
                                  ievent_buffer);
4127
3935
 
4128
3936
  const char dummy_file_name[] = "ask.dummy_file_name";
4129
3937
  ievent->mask = IN_CLOSE_WRITE;
4131
3939
  memcpy(ievent->name, dummy_file_name, sizeof(dummy_file_name));
4132
3940
  const size_t ievent_size = (sizeof(struct inotify_event)
4133
3941
                              + sizeof(dummy_file_name));
4134
 
  g_assert_cmpint(write(pipefds[1], (char *)ievent, ievent_size),
 
3942
  g_assert_cmpint(write(pipefds[1], ievent_buffer, ievent_size),
4135
3943
                  ==, ievent_size);
4136
3944
  g_assert_cmpint(close(pipefds[1]), ==, 0);
4137
3945
 
4214
4022
  const size_t ievent_max_size = (sizeof(struct inotify_event)
4215
4023
                                  + NAME_MAX + 1);
4216
4024
  g_assert_cmpint(ievent_max_size, <=, PIPE_BUF);
4217
 
  struct {
4218
 
    struct inotify_event event;
4219
 
    char name_buffer[NAME_MAX + 1];
4220
 
  } ievent_buffer;
4221
 
  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 *)
 
4027
                                  ievent_buffer);
4222
4028
 
4223
4029
  const char dummy_file_name[] = "ask.dummy_file_name";
4224
4030
  ievent->mask = IN_MOVED_TO;
4226
4032
  memcpy(ievent->name, dummy_file_name, sizeof(dummy_file_name));
4227
4033
  const size_t ievent_size = (sizeof(struct inotify_event)
4228
4034
                              + sizeof(dummy_file_name));
4229
 
  g_assert_cmpint(write(pipefds[1], (char *)ievent, ievent_size),
 
4035
  g_assert_cmpint(write(pipefds[1], ievent_buffer, ievent_size),
4230
4036
                  ==, ievent_size);
4231
4037
  g_assert_cmpint(close(pipefds[1]), ==, 0);
4232
4038
 
4292
4098
      }));
4293
4099
}
4294
4100
 
4295
 
static
4296
 
void test_read_inotify_event_IN_MOVED_FROM(__attribute__((unused))
4297
 
                                           test_fixture *fixture,
4298
 
                                           __attribute__((unused))
4299
 
                                           gconstpointer user_data){
4300
 
  __attribute__((cleanup(cleanup_close)))
4301
 
    const int epoll_fd = epoll_create1(EPOLL_CLOEXEC);
4302
 
  g_assert_cmpint(epoll_fd, >=, 0);
4303
 
  __attribute__((cleanup(string_set_clear)))
4304
 
    string_set cancelled_filenames = {};
4305
 
  const mono_microsecs current_time = 0;
4306
 
 
4307
 
  int pipefds[2];
4308
 
  g_assert_cmpint(pipe2(pipefds, O_CLOEXEC | O_NONBLOCK), ==, 0);
4309
 
 
4310
 
  /* "sufficient to read at least one event." - inotify(7) */
4311
 
  const size_t ievent_max_size = (sizeof(struct inotify_event)
4312
 
                                  + NAME_MAX + 1);
4313
 
  g_assert_cmpint(ievent_max_size, <=, PIPE_BUF);
4314
 
  struct {
4315
 
    struct inotify_event event;
4316
 
    char name_buffer[NAME_MAX + 1];
4317
 
  } ievent_buffer;
4318
 
  struct inotify_event *const ievent = &ievent_buffer.event;
4319
 
 
4320
 
  const char dummy_file_name[] = "ask.dummy_file_name";
4321
 
  ievent->mask = IN_MOVED_FROM;
4322
 
  ievent->len = sizeof(dummy_file_name);
4323
 
  memcpy(ievent->name, dummy_file_name, sizeof(dummy_file_name));
4324
 
  const size_t ievent_size = (sizeof(struct inotify_event)
4325
 
                              + sizeof(dummy_file_name));
4326
 
  g_assert_cmpint(write(pipefds[1], (char *)ievent, ievent_size),
4327
 
                  ==, ievent_size);
4328
 
  g_assert_cmpint(close(pipefds[1]), ==, 0);
4329
 
 
4330
 
  bool quit_now = false;
4331
 
  buffer password = {};
4332
 
  bool mandos_client_exited = false;
4333
 
  bool password_is_read = false;
4334
 
  __attribute__((cleanup(cleanup_queue)))
4335
 
    task_queue *queue = create_queue();
4336
 
  g_assert_nonnull(queue);
4337
 
 
4338
 
  task_context task = {
4339
 
    .func=read_inotify_event,
4340
 
    .epoll_fd=epoll_fd,
4341
 
    .fd=pipefds[0],
4342
 
    .quit_now=&quit_now,
4343
 
    .password=&password,
4344
 
    .filename=strdup("/nonexistent"),
4345
 
    .cancelled_filenames=&cancelled_filenames,
4346
 
    .current_time=&current_time,
4347
 
    .mandos_client_exited=&mandos_client_exited,
4348
 
    .password_is_read=&password_is_read,
4349
 
  };
4350
 
  task.func(task, queue);
4351
 
  g_assert_false(quit_now);
4352
 
  g_assert_true(queue->next_run == 0);
4353
 
  g_assert_cmpuint((unsigned int)queue->length, ==, 1);
4354
 
 
4355
 
  g_assert_nonnull(find_matching_task(queue, (task_context){
4356
 
        .func=read_inotify_event,
4357
 
        .epoll_fd=epoll_fd,
4358
 
        .fd=pipefds[0],
4359
 
        .quit_now=&quit_now,
4360
 
        .password=&password,
4361
 
        .filename=task.filename,
4362
 
        .cancelled_filenames=&cancelled_filenames,
4363
 
        .current_time=&current_time,
4364
 
        .mandos_client_exited=&mandos_client_exited,
4365
 
        .password_is_read=&password_is_read,
4366
 
      }));
4367
 
 
4368
 
  g_assert_true(epoll_set_contains(epoll_fd, pipefds[0],
4369
 
                                   EPOLLIN | EPOLLRDHUP));
4370
 
 
4371
 
  __attribute__((cleanup(cleanup_string)))
4372
 
    char *filename = NULL;
4373
 
  g_assert_cmpint(asprintf(&filename, "%s/%s", task.filename,
4374
 
                           dummy_file_name), >, 0);
4375
 
  g_assert_nonnull(filename);
4376
 
  g_assert_true(string_set_contains(*task.cancelled_filenames,
4377
 
                                    filename));
4378
 
}
4379
 
 
4380
4101
static void test_read_inotify_event_IN_DELETE(__attribute__((unused))
4381
4102
                                              test_fixture *fixture,
4382
4103
                                              __attribute__((unused))
4396
4117
  const size_t ievent_max_size = (sizeof(struct inotify_event)
4397
4118
                                  + NAME_MAX + 1);
4398
4119
  g_assert_cmpint(ievent_max_size, <=, PIPE_BUF);
4399
 
  struct {
4400
 
    struct inotify_event event;
4401
 
    char name_buffer[NAME_MAX + 1];
4402
 
  } ievent_buffer;
4403
 
  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 *)
 
4122
                                  ievent_buffer);
4404
4123
 
4405
4124
  const char dummy_file_name[] = "ask.dummy_file_name";
4406
4125
  ievent->mask = IN_DELETE;
4408
4127
  memcpy(ievent->name, dummy_file_name, sizeof(dummy_file_name));
4409
4128
  const size_t ievent_size = (sizeof(struct inotify_event)
4410
4129
                              + sizeof(dummy_file_name));
4411
 
  g_assert_cmpint(write(pipefds[1], (char *)ievent, ievent_size),
 
4130
  g_assert_cmpint(write(pipefds[1], ievent_buffer, ievent_size),
4412
4131
                  ==, ievent_size);
4413
4132
  g_assert_cmpint(close(pipefds[1]), ==, 0);
4414
4133
 
4480
4199
  const size_t ievent_max_size = (sizeof(struct inotify_event)
4481
4200
                                  + NAME_MAX + 1);
4482
4201
  g_assert_cmpint(ievent_max_size, <=, PIPE_BUF);
4483
 
  struct {
4484
 
    struct inotify_event event;
4485
 
    char name_buffer[NAME_MAX + 1];
4486
 
  } ievent_buffer;
4487
 
  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 *)
 
4204
                                  ievent_buffer);
4488
4205
 
4489
4206
  const char dummy_file_name[] = "ignored.dummy_file_name";
4490
4207
  ievent->mask = IN_CLOSE_WRITE;
4492
4209
  memcpy(ievent->name, dummy_file_name, sizeof(dummy_file_name));
4493
4210
  const size_t ievent_size = (sizeof(struct inotify_event)
4494
4211
                              + sizeof(dummy_file_name));
4495
 
  g_assert_cmpint(write(pipefds[1], (char *)ievent, ievent_size),
 
4212
  g_assert_cmpint(write(pipefds[1], ievent_buffer, ievent_size),
4496
4213
                  ==, ievent_size);
4497
4214
  g_assert_cmpint(close(pipefds[1]), ==, 0);
4498
4215
 
4556
4273
  const size_t ievent_max_size = (sizeof(struct inotify_event)
4557
4274
                                  + NAME_MAX + 1);
4558
4275
  g_assert_cmpint(ievent_max_size, <=, PIPE_BUF);
4559
 
  struct {
4560
 
    struct inotify_event event;
4561
 
    char name_buffer[NAME_MAX + 1];
4562
 
  } ievent_buffer;
4563
 
  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 *)
 
4278
                                  ievent_buffer);
4564
4279
 
4565
4280
  const char dummy_file_name[] = "ignored.dummy_file_name";
4566
4281
  ievent->mask = IN_MOVED_TO;
4568
4283
  memcpy(ievent->name, dummy_file_name, sizeof(dummy_file_name));
4569
4284
  const size_t ievent_size = (sizeof(struct inotify_event)
4570
4285
                              + sizeof(dummy_file_name));
4571
 
  g_assert_cmpint(write(pipefds[1], (char *)ievent, ievent_size),
 
4286
  g_assert_cmpint(write(pipefds[1], ievent_buffer, ievent_size),
4572
4287
                  ==, ievent_size);
4573
4288
  g_assert_cmpint(close(pipefds[1]), ==, 0);
4574
4289
 
4615
4330
                                   EPOLLIN | EPOLLRDHUP));
4616
4331
}
4617
4332
 
4618
 
static void
4619
 
test_read_inotify_event_IN_MOVED_FROM_badname(__attribute__((unused))
4620
 
                                              test_fixture *fixture,
4621
 
                                              __attribute__((unused))
4622
 
                                              gconstpointer
4623
 
                                              user_data){
4624
 
  __attribute__((cleanup(cleanup_close)))
4625
 
    const int epoll_fd = epoll_create1(EPOLL_CLOEXEC);
4626
 
  g_assert_cmpint(epoll_fd, >=, 0);
4627
 
  __attribute__((cleanup(string_set_clear)))
4628
 
    string_set cancelled_filenames = {};
4629
 
  const mono_microsecs current_time = 0;
4630
 
 
4631
 
  int pipefds[2];
4632
 
  g_assert_cmpint(pipe2(pipefds, O_CLOEXEC | O_NONBLOCK), ==, 0);
4633
 
 
4634
 
  /* "sufficient to read at least one event." - inotify(7) */
4635
 
  const size_t ievent_max_size = (sizeof(struct inotify_event)
4636
 
                                  + NAME_MAX + 1);
4637
 
  g_assert_cmpint(ievent_max_size, <=, PIPE_BUF);
4638
 
  struct {
4639
 
    struct inotify_event event;
4640
 
    char name_buffer[NAME_MAX + 1];
4641
 
  } ievent_buffer;
4642
 
  struct inotify_event *const ievent = &ievent_buffer.event;
4643
 
 
4644
 
  const char dummy_file_name[] = "ignored.dummy_file_name";
4645
 
  ievent->mask = IN_MOVED_FROM;
4646
 
  ievent->len = sizeof(dummy_file_name);
4647
 
  memcpy(ievent->name, dummy_file_name, sizeof(dummy_file_name));
4648
 
  const size_t ievent_size = (sizeof(struct inotify_event)
4649
 
                              + sizeof(dummy_file_name));
4650
 
  g_assert_cmpint(write(pipefds[1], (char *)ievent, ievent_size),
4651
 
                  ==, ievent_size);
4652
 
  g_assert_cmpint(close(pipefds[1]), ==, 0);
4653
 
 
4654
 
  bool quit_now = false;
4655
 
  buffer password = {};
4656
 
  bool mandos_client_exited = false;
4657
 
  bool password_is_read = false;
4658
 
  __attribute__((cleanup(cleanup_queue)))
4659
 
    task_queue *queue = create_queue();
4660
 
  g_assert_nonnull(queue);
4661
 
 
4662
 
  task_context task = {
4663
 
    .func=read_inotify_event,
4664
 
    .epoll_fd=epoll_fd,
4665
 
    .fd=pipefds[0],
4666
 
    .quit_now=&quit_now,
4667
 
    .password=&password,
4668
 
    .filename=strdup("/nonexistent"),
4669
 
    .cancelled_filenames=&cancelled_filenames,
4670
 
    .current_time=&current_time,
4671
 
    .mandos_client_exited=&mandos_client_exited,
4672
 
    .password_is_read=&password_is_read,
4673
 
  };
4674
 
  task.func(task, queue);
4675
 
  g_assert_false(quit_now);
4676
 
  g_assert_true(queue->next_run == 0);
4677
 
  g_assert_cmpuint((unsigned int)queue->length, ==, 1);
4678
 
 
4679
 
  g_assert_nonnull(find_matching_task(queue, (task_context){
4680
 
        .func=read_inotify_event,
4681
 
        .epoll_fd=epoll_fd,
4682
 
        .fd=pipefds[0],
4683
 
        .quit_now=&quit_now,
4684
 
        .password=&password,
4685
 
        .filename=task.filename,
4686
 
        .cancelled_filenames=&cancelled_filenames,
4687
 
        .current_time=&current_time,
4688
 
        .mandos_client_exited=&mandos_client_exited,
4689
 
        .password_is_read=&password_is_read,
4690
 
      }));
4691
 
 
4692
 
  g_assert_true(epoll_set_contains(epoll_fd, pipefds[0],
4693
 
                                   EPOLLIN | EPOLLRDHUP));
4694
 
 
4695
 
  __attribute__((cleanup(cleanup_string)))
4696
 
    char *filename = NULL;
4697
 
  g_assert_cmpint(asprintf(&filename, "%s/%s", task.filename,
4698
 
                           dummy_file_name), >, 0);
4699
 
  g_assert_nonnull(filename);
4700
 
  g_assert_false(string_set_contains(cancelled_filenames, filename));
4701
 
}
4702
 
 
4703
4333
static
4704
4334
void test_read_inotify_event_IN_DELETE_badname(__attribute__((unused))
4705
4335
                                               test_fixture *fixture,
4720
4350
  const size_t ievent_max_size = (sizeof(struct inotify_event)
4721
4351
                                  + NAME_MAX + 1);
4722
4352
  g_assert_cmpint(ievent_max_size, <=, PIPE_BUF);
4723
 
  struct {
4724
 
    struct inotify_event event;
4725
 
    char name_buffer[NAME_MAX + 1];
4726
 
  } ievent_buffer;
4727
 
  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 *)
 
4355
                                  ievent_buffer);
4728
4356
 
4729
4357
  const char dummy_file_name[] = "ignored.dummy_file_name";
4730
4358
  ievent->mask = IN_DELETE;
4732
4360
  memcpy(ievent->name, dummy_file_name, sizeof(dummy_file_name));
4733
4361
  const size_t ievent_size = (sizeof(struct inotify_event)
4734
4362
                              + sizeof(dummy_file_name));
4735
 
  g_assert_cmpint(write(pipefds[1], (char *)ievent, ievent_size),
 
4363
  g_assert_cmpint(write(pipefds[1], ievent_buffer, ievent_size),
4736
4364
                  ==, ievent_size);
4737
4365
  g_assert_cmpint(close(pipefds[1]), ==, 0);
4738
4366
 
7945
7573
              test_add_inotify_dir_watch);
7946
7574
  test_add_st("/task-creators/add_inotify_dir_watch/fail",
7947
7575
              test_add_inotify_dir_watch_fail);
7948
 
  test_add_st("/task-creators/add_inotify_dir_watch/not-a-directory",
7949
 
              test_add_inotify_dir_watch_nondir);
7950
7576
  test_add_st("/task-creators/add_inotify_dir_watch/EAGAIN",
7951
7577
              test_add_inotify_dir_watch_EAGAIN);
7952
7578
  test_add_st("/task-creators/add_inotify_dir_watch/IN_CLOSE_WRITE",
7953
7579
              test_add_inotify_dir_watch_IN_CLOSE_WRITE);
7954
7580
  test_add_st("/task-creators/add_inotify_dir_watch/IN_MOVED_TO",
7955
7581
              test_add_inotify_dir_watch_IN_MOVED_TO);
7956
 
  test_add_st("/task-creators/add_inotify_dir_watch/IN_MOVED_FROM",
7957
 
              test_add_inotify_dir_watch_IN_MOVED_FROM);
7958
 
  test_add_st("/task-creators/add_inotify_dir_watch/IN_EXCL_UNLINK",
7959
 
              test_add_inotify_dir_watch_IN_EXCL_UNLINK);
7960
7582
  test_add_st("/task-creators/add_inotify_dir_watch/IN_DELETE",
7961
7583
              test_add_inotify_dir_watch_IN_DELETE);
7962
7584
  test_add_st("/task/read_inotify_event/readerror",
7971
7593
              test_read_inotify_event_IN_CLOSE_WRITE);
7972
7594
  test_add_st("/task/read_inotify_event/IN_MOVED_TO",
7973
7595
              test_read_inotify_event_IN_MOVED_TO);
7974
 
  test_add_st("/task/read_inotify_event/IN_MOVED_FROM",
7975
 
              test_read_inotify_event_IN_MOVED_FROM);
7976
7596
  test_add_st("/task/read_inotify_event/IN_DELETE",
7977
7597
              test_read_inotify_event_IN_DELETE);
7978
7598
  test_add_st("/task/read_inotify_event/IN_CLOSE_WRITE/badname",
7979
7599
              test_read_inotify_event_IN_CLOSE_WRITE_badname);
7980
7600
  test_add_st("/task/read_inotify_event/IN_MOVED_TO/badname",
7981
7601
              test_read_inotify_event_IN_MOVED_TO_badname);
7982
 
  test_add_st("/task/read_inotify_event/IN_MOVED_FROM/badname",
7983
 
              test_read_inotify_event_IN_MOVED_FROM_badname);
7984
7602
  test_add_st("/task/read_inotify_event/IN_DELETE/badname",
7985
7603
              test_read_inotify_event_IN_DELETE_badname);
7986
7604
  test_add_st("/task/open_and_parse_question/ENOENT",