/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:
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_NOCTTY,
87
 
                                   O_RDONLY */
 
86
                                   open(), O_WRONLY, O_RDONLY */
88
87
#include <sys/wait.h>           /* waitpid(), WNOHANG, WIFEXITED(),
89
88
                                   WEXITSTATUS() */
90
89
#include <limits.h>             /* PIPE_BUF, NAME_MAX, INT_MAX */
432
431
    case EACCES:
433
432
    case ENAMETOOLONG:
434
433
    case ENOENT:
435
 
    case ENOTDIR:
436
434
      return EX_OSFILE;
437
435
    default:
438
436
      return EX_OSERR;
1019
1017
    return false;
1020
1018
  }
1021
1019
 
1022
 
  if(inotify_add_watch(fd, dir, IN_CLOSE_WRITE | IN_MOVED_TO
1023
 
                       | IN_MOVED_FROM| IN_DELETE | IN_EXCL_UNLINK
1024
 
                       | IN_ONLYDIR)
 
1020
  if(inotify_add_watch(fd, dir, IN_CLOSE_WRITE
 
1021
                       | IN_MOVED_TO | IN_DELETE)
1025
1022
     == -1){
1026
1023
    error(0, errno, "Failed to create inotify watch on %s", dir);
1027
1024
    return false;
1074
1071
  /* "sufficient to read at least one event." - inotify(7) */
1075
1072
  const size_t ievent_size = (sizeof(struct inotify_event)
1076
1073
                              + NAME_MAX + 1);
1077
 
  struct {
1078
 
    struct inotify_event event;
1079
 
    char name_buffer[NAME_MAX + 1];
1080
 
  } ievent_buffer;
1081
 
  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);
1082
1077
 
1083
1078
  const ssize_t read_length = read(fd, ievent, ievent_size);
1084
1079
  if(read_length == 0){ /* EOF */
1122
1117
             immediately */
1123
1118
          queue->next_run = 1;
1124
1119
        }
1125
 
      } else if(ievent->mask & (IN_MOVED_FROM | IN_DELETE)){
 
1120
      } else if(ievent->mask & IN_DELETE){
1126
1121
        if(not string_set_add(cancelled_filenames,
1127
1122
                              question_filename)){
1128
1123
          error(0, errno, "Could not add question %s to"
2225
2220
 
2226
2221
  {
2227
2222
    __attribute__((cleanup(cleanup_close)))
2228
 
      const int devnull_fd = open("/dev/null",
2229
 
                                  O_WRONLY | O_CLOEXEC | O_NOCTTY);
 
2223
      const int devnull_fd = open("/dev/null", O_WRONLY | O_CLOEXEC);
2230
2224
    g_assert_cmpint(devnull_fd, >=, 0);
2231
2225
    __attribute__((cleanup(cleanup_close)))
2232
2226
      const int real_stderr_fd = dup(STDERR_FILENO);
2256
2250
    {
2257
2251
      __attribute__((cleanup(cleanup_close)))
2258
2252
        const int devnull_fd = open("/dev/null",
2259
 
                                    O_WRONLY | O_CLOEXEC | O_NOCTTY);
 
2253
                                    O_WRONLY | O_CLOEXEC);
2260
2254
      g_assert_cmpint(devnull_fd, >=, 0);
2261
2255
      __attribute__((cleanup(cleanup_close)))
2262
2256
        const int real_stderr_fd = dup(STDERR_FILENO);
2907
2901
 
2908
2902
  __attribute__((cleanup(cleanup_close)))
2909
2903
    const int devnull_fd = open("/dev/null",
2910
 
                                O_WRONLY | O_CLOEXEC | O_NOCTTY);
 
2904
                                O_WRONLY | O_CLOEXEC);
2911
2905
  g_assert_cmpint(devnull_fd, >=, 0);
2912
2906
  __attribute__((cleanup(cleanup_close)))
2913
2907
    const int real_stderr_fd = dup(STDERR_FILENO);
2978
2972
 
2979
2973
  __attribute__((cleanup(cleanup_close)))
2980
2974
    const int devnull_fd = open("/dev/null",
2981
 
                                O_WRONLY | O_CLOEXEC, O_NOCTTY);
 
2975
                                O_WRONLY | O_CLOEXEC);
2982
2976
  g_assert_cmpint(devnull_fd, >=, 0);
2983
2977
  __attribute__((cleanup(cleanup_close)))
2984
2978
    const int real_stderr_fd = dup(STDERR_FILENO);
3022
3016
    buffer password = {};
3023
3017
 
3024
3018
  /* Reading /proc/self/mem from offset 0 will always give EIO */
3025
 
  const int fd = open("/proc/self/mem",
3026
 
                      O_RDONLY | O_CLOEXEC | O_NOCTTY);
 
3019
  const int fd = open("/proc/self/mem", O_RDONLY | O_CLOEXEC);
3027
3020
 
3028
3021
  bool password_is_read = false;
3029
3022
  bool quit_now = false;
3457
3450
  g_assert_cmpuint((unsigned int)queue->length, ==, 0);
3458
3451
}
3459
3452
 
3460
 
static void test_add_inotify_dir_watch_nondir(__attribute__((unused))
3461
 
                                              test_fixture *fixture,
3462
 
                                            __attribute__((unused))
3463
 
                                              gconstpointer
3464
 
                                              user_data){
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;
3474
 
 
3475
 
  bool quit_now = false;
3476
 
  buffer password = {};
3477
 
  bool mandos_client_exited = false;
3478
 
  bool password_is_read = false;
3479
 
 
3480
 
  const char not_a_directory[] = "/dev/tty";
3481
 
 
3482
 
  FILE *real_stderr = stderr;
3483
 
  FILE *devnull = fopen("/dev/null", "we");
3484
 
  g_assert_nonnull(devnull);
3485
 
  stderr = devnull;
3486
 
  g_assert_false(add_inotify_dir_watch(queue, epoll_fd, &quit_now,
3487
 
                                       &password, not_a_directory,
3488
 
                                       &cancelled_filenames,
3489
 
                                       &current_time,
3490
 
                                       &mandos_client_exited,
3491
 
                                       &password_is_read));
3492
 
  stderr = real_stderr;
3493
 
  g_assert_cmpint(fclose(devnull), ==, 0);
3494
 
 
3495
 
  g_assert_cmpuint((unsigned int)queue->length, ==, 0);
3496
 
}
3497
 
 
3498
3453
static void test_add_inotify_dir_watch_EAGAIN(__attribute__((unused))
3499
3454
                                              test_fixture *fixture,
3500
3455
                                              __attribute__((unused))
3715
3670
}
3716
3671
 
3717
3672
static
3718
 
void test_add_inotify_dir_watch_IN_MOVED_FROM(__attribute__((unused))
3719
 
                                              test_fixture *fixture,
3720
 
                                              __attribute__((unused))
3721
 
                                              gconstpointer
3722
 
                                              user_data){
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;
3732
 
 
3733
 
  bool quit_now = false;
3734
 
  buffer password = {};
3735
 
  bool mandos_client_exited = false;
3736
 
  bool password_is_read = false;
3737
 
 
3738
 
  __attribute__((cleanup(cleanup_string)))
3739
 
    char *tempdir = make_temporary_directory();
3740
 
  g_assert_nonnull(tempdir);
3741
 
 
3742
 
  __attribute__((cleanup(cleanup_string)))
3743
 
    char *tempfilename = make_temporary_file_in_directory(tempdir);
3744
 
  g_assert_nonnull(tempfilename);
3745
 
 
3746
 
  __attribute__((cleanup(cleanup_string)))
3747
 
    char *targetdir = make_temporary_directory();
3748
 
  g_assert_nonnull(targetdir);
3749
 
 
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);
3755
 
 
3756
 
  g_assert_true(add_inotify_dir_watch(queue, epoll_fd, &quit_now,
3757
 
                                      &password, tempdir,
3758
 
                                      &cancelled_filenames,
3759
 
                                      &current_time,
3760
 
                                      &mandos_client_exited,
3761
 
                                      &password_is_read));
3762
 
 
3763
 
  g_assert_cmpint(rename(tempfilename, targetfilename), ==, 0);
3764
 
 
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);
3769
 
 
3770
 
  /* "sufficient to read at least one event." - inotify(7) */
3771
 
  const size_t ievent_size = (sizeof(struct inotify_event)
3772
 
                              + NAME_MAX + 1);
3773
 
  struct inotify_event *ievent = malloc(ievent_size);
3774
 
  g_assert_nonnull(ievent);
3775
 
 
3776
 
  ssize_t read_size = read(added_read_task->fd, ievent, ievent_size);
3777
 
 
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));
3781
 
 
3782
 
  free(ievent);
3783
 
 
3784
 
  g_assert_cmpint(unlink(targetfilename), ==, 0);
3785
 
  g_assert_cmpint(rmdir(targetdir), ==, 0);
3786
 
  g_assert_cmpint(rmdir(tempdir), ==, 0);
3787
 
}
3788
 
 
3789
 
static
3790
3673
void test_add_inotify_dir_watch_IN_DELETE(__attribute__((unused))
3791
3674
                                          test_fixture *fixture,
3792
3675
                                          __attribute__((unused))
3850
3733
  g_assert_cmpint(rmdir(tempdir), ==, 0);
3851
3734
}
3852
3735
 
3853
 
static
3854
 
void test_add_inotify_dir_watch_IN_EXCL_UNLINK(__attribute__((unused))
3855
 
                                               test_fixture *fixture,
3856
 
                                               __attribute__((unused))
3857
 
                                               gconstpointer
3858
 
                                               user_data){
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;
3868
 
 
3869
 
  bool quit_now = false;
3870
 
  buffer password = {};
3871
 
  bool mandos_client_exited = false;
3872
 
  bool password_is_read = false;
3873
 
 
3874
 
  __attribute__((cleanup(cleanup_string)))
3875
 
    char *tempdir = make_temporary_directory();
3876
 
  g_assert_nonnull(tempdir);
3877
 
 
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
3882
 
                         | O_NOFOLLOW);
3883
 
  g_assert_cmpint(tempfile_fd, >, 2);
3884
 
 
3885
 
  g_assert_true(add_inotify_dir_watch(queue, epoll_fd, &quit_now,
3886
 
                                      &password, tempdir,
3887
 
                                      &cancelled_filenames,
3888
 
                                      &current_time,
3889
 
                                      &mandos_client_exited,
3890
 
                                      &password_is_read));
3891
 
  g_assert_cmpint(unlink(tempfile), ==, 0);
3892
 
 
3893
 
  g_assert_cmpuint((unsigned int)queue->length, >, 0);
3894
 
 
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);
3899
 
 
3900
 
  g_assert_cmpint(added_read_task->fd, >, 2);
3901
 
  g_assert_true(fd_has_cloexec_and_nonblock(added_read_task->fd));
3902
 
 
3903
 
  /* "sufficient to read at least one event." - inotify(7) */
3904
 
  const size_t ievent_size = (sizeof(struct inotify_event)
3905
 
                              + NAME_MAX + 1);
3906
 
  struct inotify_event *ievent = malloc(ievent_size);
3907
 
  g_assert_nonnull(ievent);
3908
 
 
3909
 
  ssize_t read_size = 0;
3910
 
  read_size = read(added_read_task->fd, ievent, ievent_size);
3911
 
 
3912
 
  g_assert_cmpint((int)read_size, >, 0);
3913
 
  g_assert_true(ievent->mask & IN_DELETE);
3914
 
  g_assert_cmpstr(ievent->name, ==, basename(tempfile));
3915
 
 
3916
 
  g_assert_cmpint(close(tempfile_fd), ==, 0);
3917
 
 
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);
3923
 
 
3924
 
  free(ievent);
3925
 
 
3926
 
  g_assert_cmpint(rmdir(tempdir), ==, 0);
3927
 
}
3928
 
 
3929
3736
static void test_read_inotify_event_readerror(__attribute__((unused))
3930
3737
                                              test_fixture *fixture,
3931
3738
                                              __attribute__((unused))
3937
3744
  const mono_microsecs current_time = 0;
3938
3745
 
3939
3746
  /* Reading /proc/self/mem from offset 0 will always result in EIO */
3940
 
  const int fd = open("/proc/self/mem",
3941
 
                      O_RDONLY | O_CLOEXEC | O_NOCTTY);
 
3747
  const int fd = open("/proc/self/mem", O_RDONLY | O_CLOEXEC);
3942
3748
 
3943
3749
  bool quit_now = false;
3944
3750
  __attribute__((cleanup(cleanup_queue)))
4123
3929
  const size_t ievent_max_size = (sizeof(struct inotify_event)
4124
3930
                                  + NAME_MAX + 1);
4125
3931
  g_assert_cmpint(ievent_max_size, <=, PIPE_BUF);
4126
 
  struct {
4127
 
    struct inotify_event event;
4128
 
    char name_buffer[NAME_MAX + 1];
4129
 
  } ievent_buffer;
4130
 
  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);
4131
3935
 
4132
3936
  const char dummy_file_name[] = "ask.dummy_file_name";
4133
3937
  ievent->mask = IN_CLOSE_WRITE;
4135
3939
  memcpy(ievent->name, dummy_file_name, sizeof(dummy_file_name));
4136
3940
  const size_t ievent_size = (sizeof(struct inotify_event)
4137
3941
                              + sizeof(dummy_file_name));
4138
 
  g_assert_cmpint(write(pipefds[1], (char *)ievent, ievent_size),
 
3942
  g_assert_cmpint(write(pipefds[1], ievent_buffer, ievent_size),
4139
3943
                  ==, ievent_size);
4140
3944
  g_assert_cmpint(close(pipefds[1]), ==, 0);
4141
3945
 
4218
4022
  const size_t ievent_max_size = (sizeof(struct inotify_event)
4219
4023
                                  + NAME_MAX + 1);
4220
4024
  g_assert_cmpint(ievent_max_size, <=, PIPE_BUF);
4221
 
  struct {
4222
 
    struct inotify_event event;
4223
 
    char name_buffer[NAME_MAX + 1];
4224
 
  } ievent_buffer;
4225
 
  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);
4226
4028
 
4227
4029
  const char dummy_file_name[] = "ask.dummy_file_name";
4228
4030
  ievent->mask = IN_MOVED_TO;
4230
4032
  memcpy(ievent->name, dummy_file_name, sizeof(dummy_file_name));
4231
4033
  const size_t ievent_size = (sizeof(struct inotify_event)
4232
4034
                              + sizeof(dummy_file_name));
4233
 
  g_assert_cmpint(write(pipefds[1], (char *)ievent, ievent_size),
 
4035
  g_assert_cmpint(write(pipefds[1], ievent_buffer, ievent_size),
4234
4036
                  ==, ievent_size);
4235
4037
  g_assert_cmpint(close(pipefds[1]), ==, 0);
4236
4038
 
4296
4098
      }));
4297
4099
}
4298
4100
 
4299
 
static
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;
4310
 
 
4311
 
  int pipefds[2];
4312
 
  g_assert_cmpint(pipe2(pipefds, O_CLOEXEC | O_NONBLOCK), ==, 0);
4313
 
 
4314
 
  /* "sufficient to read at least one event." - inotify(7) */
4315
 
  const size_t ievent_max_size = (sizeof(struct inotify_event)
4316
 
                                  + NAME_MAX + 1);
4317
 
  g_assert_cmpint(ievent_max_size, <=, PIPE_BUF);
4318
 
  struct {
4319
 
    struct inotify_event event;
4320
 
    char name_buffer[NAME_MAX + 1];
4321
 
  } ievent_buffer;
4322
 
  struct inotify_event *const ievent = &ievent_buffer.event;
4323
 
 
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),
4331
 
                  ==, ievent_size);
4332
 
  g_assert_cmpint(close(pipefds[1]), ==, 0);
4333
 
 
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);
4341
 
 
4342
 
  task_context task = {
4343
 
    .func=read_inotify_event,
4344
 
    .epoll_fd=epoll_fd,
4345
 
    .fd=pipefds[0],
4346
 
    .quit_now=&quit_now,
4347
 
    .password=&password,
4348
 
    .filename=strdup("/nonexistent"),
4349
 
    .cancelled_filenames=&cancelled_filenames,
4350
 
    .current_time=&current_time,
4351
 
    .mandos_client_exited=&mandos_client_exited,
4352
 
    .password_is_read=&password_is_read,
4353
 
  };
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);
4358
 
 
4359
 
  g_assert_nonnull(find_matching_task(queue, (task_context){
4360
 
        .func=read_inotify_event,
4361
 
        .epoll_fd=epoll_fd,
4362
 
        .fd=pipefds[0],
4363
 
        .quit_now=&quit_now,
4364
 
        .password=&password,
4365
 
        .filename=task.filename,
4366
 
        .cancelled_filenames=&cancelled_filenames,
4367
 
        .current_time=&current_time,
4368
 
        .mandos_client_exited=&mandos_client_exited,
4369
 
        .password_is_read=&password_is_read,
4370
 
      }));
4371
 
 
4372
 
  g_assert_true(epoll_set_contains(epoll_fd, pipefds[0],
4373
 
                                   EPOLLIN | EPOLLRDHUP));
4374
 
 
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,
4381
 
                                    filename));
4382
 
}
4383
 
 
4384
4101
static void test_read_inotify_event_IN_DELETE(__attribute__((unused))
4385
4102
                                              test_fixture *fixture,
4386
4103
                                              __attribute__((unused))
4400
4117
  const size_t ievent_max_size = (sizeof(struct inotify_event)
4401
4118
                                  + NAME_MAX + 1);
4402
4119
  g_assert_cmpint(ievent_max_size, <=, PIPE_BUF);
4403
 
  struct {
4404
 
    struct inotify_event event;
4405
 
    char name_buffer[NAME_MAX + 1];
4406
 
  } ievent_buffer;
4407
 
  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);
4408
4123
 
4409
4124
  const char dummy_file_name[] = "ask.dummy_file_name";
4410
4125
  ievent->mask = IN_DELETE;
4412
4127
  memcpy(ievent->name, dummy_file_name, sizeof(dummy_file_name));
4413
4128
  const size_t ievent_size = (sizeof(struct inotify_event)
4414
4129
                              + sizeof(dummy_file_name));
4415
 
  g_assert_cmpint(write(pipefds[1], (char *)ievent, ievent_size),
 
4130
  g_assert_cmpint(write(pipefds[1], ievent_buffer, ievent_size),
4416
4131
                  ==, ievent_size);
4417
4132
  g_assert_cmpint(close(pipefds[1]), ==, 0);
4418
4133
 
4484
4199
  const size_t ievent_max_size = (sizeof(struct inotify_event)
4485
4200
                                  + NAME_MAX + 1);
4486
4201
  g_assert_cmpint(ievent_max_size, <=, PIPE_BUF);
4487
 
  struct {
4488
 
    struct inotify_event event;
4489
 
    char name_buffer[NAME_MAX + 1];
4490
 
  } ievent_buffer;
4491
 
  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);
4492
4205
 
4493
4206
  const char dummy_file_name[] = "ignored.dummy_file_name";
4494
4207
  ievent->mask = IN_CLOSE_WRITE;
4496
4209
  memcpy(ievent->name, dummy_file_name, sizeof(dummy_file_name));
4497
4210
  const size_t ievent_size = (sizeof(struct inotify_event)
4498
4211
                              + sizeof(dummy_file_name));
4499
 
  g_assert_cmpint(write(pipefds[1], (char *)ievent, ievent_size),
 
4212
  g_assert_cmpint(write(pipefds[1], ievent_buffer, ievent_size),
4500
4213
                  ==, ievent_size);
4501
4214
  g_assert_cmpint(close(pipefds[1]), ==, 0);
4502
4215
 
4560
4273
  const size_t ievent_max_size = (sizeof(struct inotify_event)
4561
4274
                                  + NAME_MAX + 1);
4562
4275
  g_assert_cmpint(ievent_max_size, <=, PIPE_BUF);
4563
 
  struct {
4564
 
    struct inotify_event event;
4565
 
    char name_buffer[NAME_MAX + 1];
4566
 
  } ievent_buffer;
4567
 
  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);
4568
4279
 
4569
4280
  const char dummy_file_name[] = "ignored.dummy_file_name";
4570
4281
  ievent->mask = IN_MOVED_TO;
4572
4283
  memcpy(ievent->name, dummy_file_name, sizeof(dummy_file_name));
4573
4284
  const size_t ievent_size = (sizeof(struct inotify_event)
4574
4285
                              + sizeof(dummy_file_name));
4575
 
  g_assert_cmpint(write(pipefds[1], (char *)ievent, ievent_size),
 
4286
  g_assert_cmpint(write(pipefds[1], ievent_buffer, ievent_size),
4576
4287
                  ==, ievent_size);
4577
4288
  g_assert_cmpint(close(pipefds[1]), ==, 0);
4578
4289
 
4619
4330
                                   EPOLLIN | EPOLLRDHUP));
4620
4331
}
4621
4332
 
4622
 
static void
4623
 
test_read_inotify_event_IN_MOVED_FROM_badname(__attribute__((unused))
4624
 
                                              test_fixture *fixture,
4625
 
                                              __attribute__((unused))
4626
 
                                              gconstpointer
4627
 
                                              user_data){
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;
4634
 
 
4635
 
  int pipefds[2];
4636
 
  g_assert_cmpint(pipe2(pipefds, O_CLOEXEC | O_NONBLOCK), ==, 0);
4637
 
 
4638
 
  /* "sufficient to read at least one event." - inotify(7) */
4639
 
  const size_t ievent_max_size = (sizeof(struct inotify_event)
4640
 
                                  + NAME_MAX + 1);
4641
 
  g_assert_cmpint(ievent_max_size, <=, PIPE_BUF);
4642
 
  struct {
4643
 
    struct inotify_event event;
4644
 
    char name_buffer[NAME_MAX + 1];
4645
 
  } ievent_buffer;
4646
 
  struct inotify_event *const ievent = &ievent_buffer.event;
4647
 
 
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),
4655
 
                  ==, ievent_size);
4656
 
  g_assert_cmpint(close(pipefds[1]), ==, 0);
4657
 
 
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);
4665
 
 
4666
 
  task_context task = {
4667
 
    .func=read_inotify_event,
4668
 
    .epoll_fd=epoll_fd,
4669
 
    .fd=pipefds[0],
4670
 
    .quit_now=&quit_now,
4671
 
    .password=&password,
4672
 
    .filename=strdup("/nonexistent"),
4673
 
    .cancelled_filenames=&cancelled_filenames,
4674
 
    .current_time=&current_time,
4675
 
    .mandos_client_exited=&mandos_client_exited,
4676
 
    .password_is_read=&password_is_read,
4677
 
  };
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);
4682
 
 
4683
 
  g_assert_nonnull(find_matching_task(queue, (task_context){
4684
 
        .func=read_inotify_event,
4685
 
        .epoll_fd=epoll_fd,
4686
 
        .fd=pipefds[0],
4687
 
        .quit_now=&quit_now,
4688
 
        .password=&password,
4689
 
        .filename=task.filename,
4690
 
        .cancelled_filenames=&cancelled_filenames,
4691
 
        .current_time=&current_time,
4692
 
        .mandos_client_exited=&mandos_client_exited,
4693
 
        .password_is_read=&password_is_read,
4694
 
      }));
4695
 
 
4696
 
  g_assert_true(epoll_set_contains(epoll_fd, pipefds[0],
4697
 
                                   EPOLLIN | EPOLLRDHUP));
4698
 
 
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));
4705
 
}
4706
 
 
4707
4333
static
4708
4334
void test_read_inotify_event_IN_DELETE_badname(__attribute__((unused))
4709
4335
                                               test_fixture *fixture,
4724
4350
  const size_t ievent_max_size = (sizeof(struct inotify_event)
4725
4351
                                  + NAME_MAX + 1);
4726
4352
  g_assert_cmpint(ievent_max_size, <=, PIPE_BUF);
4727
 
  struct {
4728
 
    struct inotify_event event;
4729
 
    char name_buffer[NAME_MAX + 1];
4730
 
  } ievent_buffer;
4731
 
  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);
4732
4356
 
4733
4357
  const char dummy_file_name[] = "ignored.dummy_file_name";
4734
4358
  ievent->mask = IN_DELETE;
4736
4360
  memcpy(ievent->name, dummy_file_name, sizeof(dummy_file_name));
4737
4361
  const size_t ievent_size = (sizeof(struct inotify_event)
4738
4362
                              + sizeof(dummy_file_name));
4739
 
  g_assert_cmpint(write(pipefds[1], (char *)ievent, ievent_size),
 
4363
  g_assert_cmpint(write(pipefds[1], ievent_buffer, ievent_size),
4740
4364
                  ==, ievent_size);
4741
4365
  g_assert_cmpint(close(pipefds[1]), ==, 0);
4742
4366
 
5629
5253
                                            __attribute__((unused))
5630
5254
                                            gconstpointer user_data){
5631
5255
  __attribute__((cleanup(cleanup_close)))
5632
 
    const int epoll_fd = open("/dev/null",
5633
 
                              O_WRONLY | O_CLOEXEC | O_NOCTTY);
 
5256
    const int epoll_fd = open("/dev/null", O_WRONLY | O_CLOEXEC);
5634
5257
  __attribute__((cleanup(cleanup_string)))
5635
5258
    char *const question_filename = strdup("/nonexistent/question");
5636
5259
  g_assert_nonnull(question_filename);
6040
5663
                                            __attribute__((unused))
6041
5664
                                            gconstpointer user_data){
6042
5665
  __attribute__((cleanup(cleanup_close)))
6043
 
    const int epoll_fd = open("/dev/null",
6044
 
                              O_WRONLY | O_CLOEXEC | O_NOCTTY);
 
5666
    const int epoll_fd = open("/dev/null", O_WRONLY | O_CLOEXEC);
6045
5667
  __attribute__((cleanup(cleanup_string)))
6046
5668
    char *const question_filename = strdup("/nonexistent/question");
6047
5669
  g_assert_nonnull(question_filename);
6310
5932
                                              const char *const
6311
5933
                                              dirname){
6312
5934
  __attribute__((cleanup(cleanup_close)))
6313
 
    const int devnull_fd = open("/dev/null",
6314
 
                                O_WRONLY | O_CLOEXEC | O_NOCTTY);
 
5935
    const int devnull_fd = open("/dev/null", O_WRONLY | O_CLOEXEC);
6315
5936
  g_assert_cmpint(devnull_fd, >=, 0);
6316
5937
  __attribute__((cleanup(cleanup_close)))
6317
5938
    const int real_stderr_fd = dup(STDERR_FILENO);
7952
7573
              test_add_inotify_dir_watch);
7953
7574
  test_add_st("/task-creators/add_inotify_dir_watch/fail",
7954
7575
              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);
7957
7576
  test_add_st("/task-creators/add_inotify_dir_watch/EAGAIN",
7958
7577
              test_add_inotify_dir_watch_EAGAIN);
7959
7578
  test_add_st("/task-creators/add_inotify_dir_watch/IN_CLOSE_WRITE",
7960
7579
              test_add_inotify_dir_watch_IN_CLOSE_WRITE);
7961
7580
  test_add_st("/task-creators/add_inotify_dir_watch/IN_MOVED_TO",
7962
7581
              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);
7967
7582
  test_add_st("/task-creators/add_inotify_dir_watch/IN_DELETE",
7968
7583
              test_add_inotify_dir_watch_IN_DELETE);
7969
7584
  test_add_st("/task/read_inotify_event/readerror",
7978
7593
              test_read_inotify_event_IN_CLOSE_WRITE);
7979
7594
  test_add_st("/task/read_inotify_event/IN_MOVED_TO",
7980
7595
              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);
7983
7596
  test_add_st("/task/read_inotify_event/IN_DELETE",
7984
7597
              test_read_inotify_event_IN_DELETE);
7985
7598
  test_add_st("/task/read_inotify_event/IN_CLOSE_WRITE/badname",
7986
7599
              test_read_inotify_event_IN_CLOSE_WRITE_badname);
7987
7600
  test_add_st("/task/read_inotify_event/IN_MOVED_TO/badname",
7988
7601
              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);
7991
7602
  test_add_st("/task/read_inotify_event/IN_DELETE/badname",
7992
7603
              test_read_inotify_event_IN_DELETE_badname);
7993
7604
  test_add_st("/task/open_and_parse_question/ENOENT",