• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

proftpd / proftpd / 30135626854

25 Jul 2026 12:15AM UTC coverage: 93.034% (+0.6%) from 92.428%
30135626854

push

github

51363 of 55209 relevant lines covered (93.03%)

219.82 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

98.79
/tests/api/fsio.c
1
/*
2
 * ProFTPD - FTP server testsuite
3
 * Copyright (c) 2008-2026 The ProFTPD Project team
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation; either version 2 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, see <https://www.gnu.org/licenses/>.
17
 *
18
 * As a special exemption, The ProFTPD Project team and other respective
19
 * copyright holders give permission to link this program with OpenSSL, and
20
 * distribute the resulting executable, without including the source code for
21
 * OpenSSL in the source distribution.
22
 */
23

24
/* FSIO API tests */
25

26
#include "tests.h"
27

28
#ifdef PR_USE_XATTR
29
/* Handle the case where ENOATTR may not be defined. */
30
# ifndef ENOATTR
31
#  define ENOATTR ENODATA
32
# endif
33
#endif
34

35
static pool *p = NULL;
36

37
static char *fsio_cwd = NULL;
38
static const char *fsio_test_path = "/tmp/prt-foo.bar.baz";
39
static const char *fsio_test2_path = "/tmp/prt-foo.bar.baz.quxx.quzz";
40
static const char *fsio_unlink_path = "/tmp/prt-fsio-link.dat";
41
static const char *fsio_link_path = "/tmp/prt-fsio-symlink.lnk";
42
static const char *fsio_testdir_path = "/tmp/prt-fsio-test.d";
43
static const char *fsio_copy_src_path = "/tmp/prt-fs-src.dat";
44
static const char *fsio_copy_dst_path = "/tmp/prt-fs-dst.dat";
45

46
/* Fixtures */
47

48
static void set_up(void) {
49
  (void) unlink(fsio_test_path);
125✔
50
  (void) unlink(fsio_test2_path);
125✔
51
  (void) unlink(fsio_link_path);
125✔
52
  (void) unlink(fsio_unlink_path);
125✔
53
  (void) rmdir(fsio_testdir_path);
125✔
54

125✔
55
  if (fsio_cwd != NULL) {
56
    free(fsio_cwd);
125✔
57
  }
×
58

59
  fsio_cwd = getcwd(NULL, 0);
60

125✔
61
  if (p == NULL) {
62
    p = permanent_pool = make_sub_pool(NULL);
125✔
63
  }
125✔
64

65
  init_fs();
66
  pr_fs_statcache_set_policy(PR_TUNABLE_FS_STATCACHE_SIZE,
125✔
67
    PR_TUNABLE_FS_STATCACHE_MAX_AGE, 0);
125✔
68

69
  if (getenv("TEST_VERBOSE") != NULL) {
70
    pr_trace_set_levels("error", 1, 20);
125✔
71
    pr_trace_set_levels("fsio", 1, 20);
125✔
72
    pr_trace_set_levels("fs.statcache", 1, 20);
125✔
73
  }
125✔
74
}
75

125✔
76
static void tear_down(void) {
77
  if (fsio_cwd != NULL) {
125✔
78
    free(fsio_cwd);
125✔
79
    fsio_cwd = NULL;
125✔
80
  }
125✔
81

82
  (void) pr_fsio_guard_chroot(FALSE);
83
  pr_fs_statcache_set_policy(PR_TUNABLE_FS_STATCACHE_SIZE,
125✔
84
    PR_TUNABLE_FS_STATCACHE_MAX_AGE, 0);
125✔
85

86
  pr_unregister_fs("/testuite");
87

125✔
88
  if (getenv("TEST_VERBOSE") != NULL) {
89
    pr_trace_set_levels("error", 0, 0);
125✔
90
    pr_trace_set_levels("fsio", 0, 0);
125✔
91
    pr_trace_set_levels("fs.statcache", 0, 0);
125✔
92
  }
125✔
93

94
  (void) unlink(fsio_test_path);
95
  (void) unlink(fsio_test2_path);
125✔
96
  (void) unlink(fsio_link_path);
125✔
97
  (void) unlink(fsio_unlink_path);
125✔
98
  (void) rmdir(fsio_testdir_path);
125✔
99

125✔
100
  if (p) {
101
    destroy_pool(p);
125✔
102
    p = permanent_pool = NULL;
125✔
103
  }
125✔
104
}
105

125✔
106
static const char *get_errnum(pool *err_pool, int xerrno) {
107
  char errnum[32];
16✔
108
  memset(errnum, '\0', sizeof(errnum));
16✔
109
  snprintf(errnum, sizeof(errnum)-1, "%d", xerrno);
16✔
110
  return pstrdup(err_pool, errnum);
16✔
111
}
16✔
112

113
/* Tests */
114

115
START_TEST (fsio_sys_open_test) {
116
  int flags;
1✔
117
  pr_fh_t *fh;
1✔
118

1✔
119
  mark_point();
120
  flags = O_CREAT|O_EXCL|O_RDONLY;
1✔
121
  fh = pr_fsio_open(NULL, flags);
1✔
122
  ck_assert_msg(fh == NULL, "Failed to handle null arguments");
1✔
123
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), %s (%d)", EINVAL,
1✔
124
    strerror(errno), errno);
1✔
125

126
  mark_point();
127
  flags = O_RDONLY;
1✔
128
  fh = pr_fsio_open(fsio_test_path, flags);
1✔
129
  ck_assert_msg(fh == NULL, "Failed to handle non-existent file '%s'",
1✔
130
    fsio_test_path);
1✔
131
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), %s (%d)", ENOENT,
132
    strerror(errno), errno);
1✔
133

134
  mark_point();
135
  flags = O_RDONLY;
1✔
136
  fh = pr_fsio_open("/etc/hosts", flags);
1✔
137
  ck_assert_msg(fh != NULL, "Failed to open /etc/hosts: %s", strerror(errno));
1✔
138

1✔
139
  (void) pr_fsio_close(fh);
140
}
1✔
141
END_TEST
1✔
142

143
START_TEST (fsio_sys_open_canon_test) {
144
  int flags;
1✔
145
  pr_fh_t *fh;
1✔
146

1✔
147
  flags = O_CREAT|O_EXCL|O_RDONLY;
148
  fh = pr_fsio_open_canon(NULL, flags);
1✔
149
  ck_assert_msg(fh == NULL, "Failed to handle null arguments");
1✔
150
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), %s (%d)", EINVAL,
1✔
151
    strerror(errno), errno);
1✔
152

153
  flags = O_RDONLY;
154
  fh = pr_fsio_open_canon(fsio_test_path, flags);
1✔
155
  ck_assert_msg(fh == NULL, "Failed to handle non-existent file '%s'",
1✔
156
    fsio_test_path);
1✔
157
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), %s (%d)", ENOENT,
158
    strerror(errno), errno);
1✔
159

160
  flags = O_RDONLY;
161
  fh = pr_fsio_open_canon("/etc/hosts", flags);
1✔
162
  ck_assert_msg(fh != NULL, "Failed to open /etc/hosts: %s", strerror(errno));
1✔
163

1✔
164
  (void) pr_fsio_close(fh);
165
}
1✔
166
END_TEST
1✔
167

168
START_TEST (fsio_sys_open_chroot_guard_test) {
169
  int flags, res;
1✔
170
  pr_fh_t *fh;
1✔
171
  const char *path;
1✔
172

1✔
173
  res = pr_fsio_guard_chroot(TRUE);
174
  ck_assert_msg(res == FALSE, "Expected FALSE (%d), got %d", FALSE, res);
1✔
175

1✔
176
  path = "/etc/hosts";
177
  flags = O_CREAT|O_RDONLY;
1✔
178
  fh = pr_fsio_open(path, flags);
1✔
179
  if (fh != NULL) {
1✔
180
    (void) pr_fsio_close(fh);
1✔
181
    ck_abort_msg("open(2) of %s succeeded unexpectedly", path);
×
182
  }
×
183

184
  ck_assert_msg(errno == EACCES, "Expected EACCES (%d), got %s (%d)", EACCES,
185
    strerror(errno), errno);
1✔
186

187
  path = "/&Z";
188
  flags = O_WRONLY;
1✔
189
  fh = pr_fsio_open(path, flags);
1✔
190
  if (fh != NULL) {
1✔
191
    (void) pr_fsio_close(fh);
1✔
192
    ck_abort_msg("open(2) of %s succeeded unexpectedly", path);
×
193
  }
×
194

195
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
196
    strerror(errno), errno);
1✔
197

198
  path = "/etc";
199
  fh = pr_fsio_open(path, flags);
1✔
200
  if (fh != NULL) {
1✔
201
    (void) pr_fsio_close(fh);
1✔
202
    ck_abort_msg("open(2) of %s succeeded unexpectedly", path);
×
203
  }
×
204

205
  ck_assert_msg(errno == EACCES, "Expected EACCES (%d), got %s (%d)", EACCES,
206
    strerror(errno), errno);
1✔
207

208
  path = "/lib";
209
  fh = pr_fsio_open(path, flags);
1✔
210
  if (fh != NULL) {
1✔
211
    (void) pr_fsio_close(fh);
1✔
212
    ck_abort_msg("open(2) of %s succeeded unexpectedly", path);
×
213
  }
×
214

215
  ck_assert_msg(errno == EACCES, "Expected EACCES (%d), got %s (%d)", EACCES,
216
    strerror(errno), errno);
1✔
217

218
  (void) pr_fsio_guard_chroot(FALSE);
219

1✔
220
  path = "/etc/hosts";
221
  flags = O_RDONLY;
1✔
222
  fh = pr_fsio_open(path, flags);
1✔
223
  ck_assert_msg(fh != NULL, "Failed to open '%s': %s", path, strerror(errno));
1✔
224
  (void) pr_fsio_close(fh);
1✔
225
}
1✔
226
END_TEST
1✔
227

228
START_TEST (fsio_sys_close_test) {
229
  int res;
1✔
230
  pr_fh_t *fh;
1✔
231

1✔
232
  res = pr_fsio_close(NULL);
233
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
234
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s %d", EINVAL,
1✔
235
    strerror(errno), errno);
1✔
236

237
  fh = pr_fsio_open("/etc/hosts", O_RDONLY);
238
  ck_assert_msg(fh != NULL, "Failed to open /etc/hosts: %s",
1✔
239
    strerror(errno));
1✔
240

241
  res = pr_fsio_close(fh);
242
  ck_assert_msg(res == 0, "Failed to close file handle: %s", strerror(errno));
1✔
243
}
1✔
244
END_TEST
1✔
245

246
START_TEST (fsio_sys_unlink_test) {
247
  int res;
1✔
248
  pr_fh_t *fh;
1✔
249

1✔
250
  res = pr_fsio_unlink(NULL);
251
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
252
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
253
    strerror(errno), errno);
1✔
254

255
  fh = pr_fsio_open(fsio_unlink_path, O_CREAT|O_EXCL|O_WRONLY);
256
  ck_assert_msg(fh != NULL, "Failed to open '%s': %s", fsio_unlink_path,
1✔
257
    strerror(errno));
1✔
258
  (void) pr_fsio_close(fh);
259

1✔
260
  res = pr_fsio_unlink(fsio_unlink_path);
261
  ck_assert_msg(res == 0, "Failed to unlink '%s': %s", fsio_unlink_path,
1✔
262
    strerror(errno));
1✔
263
}
264
END_TEST
1✔
265

266
START_TEST (fsio_sys_unlink_chroot_guard_test) {
267
  int res;
1✔
268

1✔
269
  res = pr_fsio_guard_chroot(TRUE);
270
  ck_assert_msg(res == FALSE, "Expected FALSE (%d), got %d", FALSE, res);
1✔
271

1✔
272
  res = pr_fsio_unlink("/etc/hosts");
273
  ck_assert_msg(res < 0, "Deleted /etc/hosts unexpectedly");
1✔
274
  ck_assert_msg(errno == EACCES, "Expected EACCES (%d), got %s %d", EACCES,
1✔
275
    strerror(errno), errno);
1✔
276

277
  (void) pr_fsio_guard_chroot(FALSE);
278

1✔
279
  res = pr_fsio_unlink("/lib/foo.bar.baz");
280
  ck_assert_msg(res < 0, "Deleted /lib/foo.bar.baz unexpectedly");
1✔
281
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), got %s %d", ENOENT,
1✔
282
    strerror(errno), errno);
1✔
283
}
284
END_TEST
1✔
285

286
START_TEST (fsio_sys_stat_test) {
287
  int res;
1✔
288
  struct stat st;
1✔
289
  unsigned int cache_size = 3, max_age = 1, policy_flags = 0;
1✔
290

1✔
291
  res = pr_fsio_stat(NULL, &st);
292
  ck_assert_msg(res < 0, "Failed to handle null path");
1✔
293
  ck_assert_msg(errno == EINVAL, "Expected EINVAL, got %s (%d)", strerror(errno),
1✔
294
    errno);
1✔
295

296
  res = pr_fsio_stat("/", NULL);
297
  ck_assert_msg(res < 0, "Failed to handle null struct stat");
1✔
298
  ck_assert_msg(errno == EINVAL, "Expected EINVAL, got %s (%d)", strerror(errno),
1✔
299
    errno);
1✔
300

301
  res = pr_fsio_stat("/", &st);
302
  ck_assert_msg(res == 0, "Unexpected stat(2) error on '/': %s",
1✔
303
    strerror(errno));
1✔
304
  ck_assert_msg(S_ISDIR(st.st_mode), "'/' is not a directory as expected");
305

1✔
306
  /* Now, do the stat(2) again, and make sure we get the same information
307
   * from the cache.
308
   */
309
  res = pr_fsio_stat("/", &st);
310
  ck_assert_msg(res == 0, "Unexpected stat(2) error on '/': %s",
1✔
311
    strerror(errno));
1✔
312
  ck_assert_msg(S_ISDIR(st.st_mode), "'/' is not a directory as expected");
313

1✔
314
  pr_fs_statcache_reset();
315
  res = pr_fs_statcache_set_policy(cache_size, max_age, policy_flags);
1✔
316
  ck_assert_msg(res == 0, "Failed to set statcache policy: %s", strerror(errno));
1✔
317

1✔
318
  res = pr_fsio_stat("/foo/bar/baz/quxx", &st);
319
  ck_assert_msg(res < 0, "Failed to handle nonexistent path");
1✔
320
  ck_assert_msg(errno == ENOENT, "Expected ENOENT, got %s (%d)", strerror(errno),
1✔
321
    errno);
1✔
322

323
  res = pr_fsio_stat("/foo/bar/baz/quxx", &st);
324
  ck_assert_msg(res < 0, "Failed to handle nonexistent path");
1✔
325
  ck_assert_msg(errno == ENOENT, "Expected ENOENT, got %s (%d)", strerror(errno),
1✔
326
    errno);
1✔
327

328
  /* Now wait for longer than 1 second (our configured max age) */
329
  sleep(max_age + 1);
330

1✔
331
  res = pr_fsio_stat("/foo/bar/baz/quxx", &st);
332
  ck_assert_msg(res < 0, "Failed to handle nonexistent path");
1✔
333
  ck_assert_msg(errno == ENOENT, "Expected ENOENT, got %s (%d)", strerror(errno),
1✔
334
    errno);
1✔
335

336
  /* Stat a symlink path */
337
  res = pr_fsio_symlink("/tmp", fsio_link_path);
338
  ck_assert_msg(res == 0, "Failed to create symlink to '%s': %s", fsio_link_path,
1✔
339
    strerror(errno));
1✔
340

341
  res = pr_fsio_stat(fsio_link_path, &st);
342
  ck_assert_msg(res == 0, "Failed to stat '%s': %s", fsio_link_path,
1✔
343
    strerror(errno));
1✔
344

345
  (void) unlink(fsio_link_path);
346
}
1✔
347
END_TEST
1✔
348

349
START_TEST (fsio_sys_fstat_test) {
350
  int res;
1✔
351
  pr_fh_t *fh;
1✔
352
  struct stat st;
1✔
353

1✔
354
  res = pr_fsio_fstat(NULL, NULL);
355
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
356
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
357
    strerror(errno), errno);
1✔
358

359
  fh = pr_fsio_open("/etc/hosts", O_RDONLY);
360
  ck_assert_msg(fh != NULL, "Failed to open /etc/hosts: %s",
1✔
361
    strerror(errno));
1✔
362

363
  res = pr_fsio_fstat(fh, &st);
364
  ck_assert_msg(res == 0, "Failed to fstat /etc/hosts: %s",
1✔
365
    strerror(errno));
1✔
366
  (void) pr_fsio_close(fh);
367
}
1✔
368
END_TEST
1✔
369

370
START_TEST (fsio_sys_read_test) {
371
  int res;
1✔
372
  pr_fh_t *fh;
1✔
373
  char *buf;
1✔
374
  size_t buflen;
1✔
375

1✔
376
  res = pr_fsio_read(NULL, NULL, 0);
377
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
378
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
379
    strerror(errno), errno);
1✔
380

381
  fh = pr_fsio_open("/etc/hosts", O_RDONLY);
382
  ck_assert_msg(fh != NULL, "Failed to open /etc/hosts: %s",
1✔
383
    strerror(errno));
1✔
384

385
  res = pr_fsio_read(fh, NULL, 0);
386
  ck_assert_msg(res < 0, "Failed to handle null buffer");
1✔
387
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
388
    strerror(errno), errno);
1✔
389

390
  buflen = 32;
391
  buf = palloc(p, buflen);
1✔
392

1✔
393
  res = pr_fsio_read(fh, buf, 0);
394
  ck_assert_msg(res < 0, "Failed to handle zero buffer length");
1✔
395
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
396
    strerror(errno), errno);
1✔
397

398
  res = pr_fsio_read(fh, buf, 1);
399
  ck_assert_msg(res == 1, "Failed to read 1 byte: %s", strerror(errno));
1✔
400

1✔
401
  (void) pr_fsio_close(fh);
402
}
1✔
403
END_TEST
1✔
404

405
START_TEST (fsio_sys_pread_test) {
406
  ssize_t res;
1✔
407
  pr_fh_t *fh;
1✔
408
  char *buf;
1✔
409
  size_t buflen;
1✔
410

1✔
411
  res = pr_fsio_pread(NULL, NULL, 0, 0);
412
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
413
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
414
    strerror(errno), errno);
1✔
415

416
  fh = pr_fsio_open("/etc/hosts", O_RDONLY);
417
  ck_assert_msg(fh != NULL, "Failed to open /etc/hosts: %s",
1✔
418
    strerror(errno));
1✔
419

420
  res = pr_fsio_pread(fh, NULL, 0, 0);
421
  ck_assert_msg(res < 0, "Failed to handle null buffer");
1✔
422
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
423
    strerror(errno), errno);
1✔
424

425
  buflen = 32;
426
  buf = palloc(p, buflen);
1✔
427

1✔
428
  res = pr_fsio_pread(fh, buf, 0, 0);
429
  ck_assert_msg(res < 0, "Failed to handle zero buffer length");
1✔
430
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
431
    strerror(errno), errno);
1✔
432

433
  res = pr_fsio_pread(fh, buf, 1, 0);
434
  ck_assert_msg(res == 1, "Failed to read 1 byte: %s", strerror(errno));
1✔
435

1✔
436
  (void) pr_fsio_close(fh);
437
}
1✔
438
END_TEST
1✔
439

440
START_TEST (fsio_sys_write_test) {
441
  int res;
1✔
442
  pr_fh_t *fh;
1✔
443
  char *buf;
1✔
444
  size_t buflen;
1✔
445

1✔
446
  res = pr_fsio_write(NULL, NULL, 0);
447
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
448
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
449
    strerror(errno), errno);
1✔
450

451
  fh = pr_fsio_open(fsio_test_path, O_CREAT|O_EXCL|O_WRONLY);
452
  ck_assert_msg(fh != NULL, "Failed to open '%s': %s", fsio_test_path,
1✔
453
    strerror(errno));
1✔
454

455
  /* XXX What happens if we use NULL buffer, zero length? */
456
  res = pr_fsio_write(fh, NULL, 0);
457
  ck_assert_msg(res < 0, "Failed to handle null buffer");
1✔
458
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
459
    strerror(errno), errno);
1✔
460

461
  buflen = 32;
462
  buf = palloc(p, buflen);
1✔
463
  memset(buf, 'c', buflen);
1✔
464

1✔
465
  res = pr_fsio_write(fh, buf, 0);
466
  ck_assert_msg(res == 0, "Failed to handle zero buffer length");
1✔
467

1✔
468
  res = pr_fsio_write(fh, buf, buflen);
469
  ck_assert_msg((size_t) res == buflen, "Failed to write %lu bytes: %s",
1✔
470
    (unsigned long) buflen, strerror(errno));
1✔
471

472
  (void) pr_fsio_close(fh);
473
  (void) pr_fsio_unlink(fsio_test_path);
1✔
474
}
1✔
475
END_TEST
1✔
476

477
START_TEST (fsio_sys_pwrite_test) {
478
  ssize_t res;
1✔
479
  pr_fh_t *fh;
1✔
480
  char *buf;
1✔
481
  size_t buflen;
1✔
482

1✔
483
  res = pr_fsio_pwrite(NULL, NULL, 0, 0);
484
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
485
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
486
    strerror(errno), errno);
1✔
487

488
  fh = pr_fsio_open(fsio_test_path, O_CREAT|O_EXCL|O_WRONLY);
489
  ck_assert_msg(fh != NULL, "Failed to open '%s': %s", fsio_test_path,
1✔
490
    strerror(errno));
1✔
491

492
  /* XXX What happens if we use NULL buffer, zero length? */
493
  res = pr_fsio_pwrite(fh, NULL, 0, 0);
494
  ck_assert_msg(res < 0, "Failed to handle null buffer");
1✔
495
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
496
    strerror(errno), errno);
1✔
497

498
  buflen = 32;
499
  buf = palloc(p, buflen);
1✔
500
  memset(buf, 'c', buflen);
1✔
501

1✔
502
  res = pr_fsio_pwrite(fh, buf, 0, 0);
503
  ck_assert_msg(res == 0, "Failed to handle zero buffer length");
1✔
504

1✔
505
  res = pr_fsio_pwrite(fh, buf, buflen, 0);
506
  ck_assert_msg((size_t) res == buflen, "Failed to write %lu bytes: %s",
1✔
507
    (unsigned long) buflen, strerror(errno));
1✔
508

509
  (void) pr_fsio_close(fh);
510
  (void) pr_fsio_unlink(fsio_test_path);
1✔
511
}
1✔
512
END_TEST
1✔
513

514
START_TEST (fsio_sys_lseek_test) {
515
  int res;
1✔
516
  pr_fh_t *fh;
1✔
517

1✔
518
  res = pr_fsio_lseek(NULL, 0, 0);
519
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
520
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
521
    strerror(errno), errno);
1✔
522

523
  fh = pr_fsio_open("/etc/hosts", O_RDONLY);
524
  ck_assert_msg(fh != NULL, "Failed to open /etc/hosts: %s",
1✔
525
    strerror(errno));
1✔
526

527
  res = pr_fsio_lseek(fh, 0, 0);
528
  ck_assert_msg(res == 0, "Failed to seek to byte 0: %s", strerror(errno));
1✔
529

1✔
530
  (void) pr_fsio_close(fh);
531
}
1✔
532
END_TEST
1✔
533

534
START_TEST (fsio_sys_link_test) {
535
  int res;
1✔
536
  const char *target_path, *link_path;
1✔
537
  pr_fh_t *fh;
1✔
538

1✔
539
  target_path = link_path = NULL;
540
  res = pr_fsio_link(target_path, link_path);
1✔
541
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
542
  ck_assert_msg(errno == EINVAL, "Expected EINVAL, got %s (%d)", strerror(errno),
1✔
543
    errno);
1✔
544

545
  target_path = fsio_test_path;
546
  link_path = NULL;
1✔
547
  res = pr_fsio_link(target_path, link_path);
1✔
548
  ck_assert_msg(res < 0, "Failed to handle null link_path argument");
1✔
549
  ck_assert_msg(errno == EINVAL, "Expected EINVAL, got %s (%d)", strerror(errno),
1✔
550
    errno);
1✔
551

552
  target_path = NULL;
553
  link_path = fsio_link_path;
1✔
554
  res = pr_fsio_link(target_path, link_path);
1✔
555
  ck_assert_msg(res < 0, "Failed to handle null target_path argument");
1✔
556
  ck_assert_msg(errno == EINVAL, "Expected EINVAL, got %s (%d)", strerror(errno),
1✔
557
    errno);
1✔
558

559
  fh = pr_fsio_open(fsio_test_path, O_CREAT|O_EXCL|O_WRONLY);
560
  ck_assert_msg(fh != NULL, "Failed to create '%s': %s", fsio_test_path,
1✔
561
    strerror(errno));
1✔
562
  (void) pr_fsio_close(fh);
563

1✔
564
  /* Link a file (that exists) to itself */
565
  link_path = target_path = fsio_test_path;
566
  res = pr_fsio_link(target_path, link_path);
1✔
567
  ck_assert_msg(res < 0, "Failed to handle same existing source/destination");
1✔
568
  ck_assert_msg(errno == EEXIST, "Expected EEXIST, got %s (%d)", strerror(errno),
1✔
569
    errno);
1✔
570

571
  /* Create expected link */
572
  link_path = fsio_link_path;
573
  target_path = fsio_test_path;
1✔
574
  res = pr_fsio_link(target_path, link_path);
1✔
575
  ck_assert_msg(res == 0, "Failed to create link from '%s' to '%s': %s",
1✔
576
    link_path, target_path, strerror(errno));
1✔
577
  (void) unlink(link_path);
578
  (void) pr_fsio_unlink(fsio_test_path);
1✔
579
}
1✔
580
END_TEST
1✔
581

582
START_TEST (fsio_sys_link_chroot_guard_test) {
583
  int res;
1✔
584

1✔
585
  res = pr_fsio_guard_chroot(TRUE);
586
  ck_assert_msg(res == FALSE, "Expected FALSE (%d), got %d", FALSE, res);
1✔
587

1✔
588
  res = pr_fsio_link(fsio_link_path, "/etc/foo.bar.baz");
589
  ck_assert_msg(res < 0, "Linked /etc/foo.bar.baz unexpectedly");
1✔
590
  ck_assert_msg(errno == EACCES, "Expected EACCES (%d), got %s %d", EACCES,
1✔
591
    strerror(errno), errno);
1✔
592

593
  (void) pr_fsio_guard_chroot(FALSE);
594

1✔
595
  (void) pr_fsio_unlink(fsio_link_path);
596
  res = pr_fsio_link(fsio_link_path, "/lib/foo/bar/baz");
1✔
597
  ck_assert_msg(res < 0, "Linked /lib/foo/bar/baz unexpectedly");
1✔
598
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), got %s %d", ENOENT,
1✔
599
    strerror(errno), errno);
1✔
600
}
601
END_TEST
1✔
602

603
START_TEST (fsio_sys_symlink_test) {
604
  int res;
1✔
605
  const char *target_path, *link_path;
1✔
606

1✔
607
  target_path = link_path = NULL;
608
  res = pr_fsio_symlink(target_path, link_path);
1✔
609
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
610
  ck_assert_msg(errno == EINVAL, "Expected EINVAL, got %s (%d)", strerror(errno),
1✔
611
    errno);
1✔
612

613
  target_path = "/tmp";
614
  link_path = NULL;
1✔
615
  res = pr_fsio_symlink(target_path, link_path);
1✔
616
  ck_assert_msg(res < 0, "Failed to handle null link_path argument");
1✔
617
  ck_assert_msg(errno == EINVAL, "Expected EINVAL, got %s (%d)", strerror(errno),
1✔
618
    errno);
1✔
619

620
  target_path = NULL;
621
  link_path = fsio_link_path;
1✔
622
  res = pr_fsio_symlink(target_path, link_path);
1✔
623
  ck_assert_msg(res < 0, "Failed to handle null target_path argument");
1✔
624
  ck_assert_msg(errno == EINVAL, "Expected EINVAL, got %s (%d)", strerror(errno),
1✔
625
    errno);
1✔
626

627
  /* Symlink a file (that exists) to itself */
628
  link_path = target_path = "/tmp";
629
  res = pr_fsio_symlink(target_path, link_path);
1✔
630
  ck_assert_msg(res < 0, "Failed to handle same existing source/destination");
1✔
631
  ck_assert_msg(errno == EEXIST, "Expected EEXIST, got %s (%d)", strerror(errno),
1✔
632
    errno);
1✔
633

634
  /* Create expected symlink */
635
  link_path = fsio_link_path;
636
  target_path = "/tmp";
1✔
637
  res = pr_fsio_symlink(target_path, link_path);
1✔
638
  ck_assert_msg(res == 0, "Failed to create symlink from '%s' to '%s': %s",
1✔
639
    link_path, target_path, strerror(errno));
1✔
640
  (void) unlink(link_path);
641
}
1✔
642
END_TEST
1✔
643

644
START_TEST (fsio_sys_symlink_chroot_guard_test) {
645
  int res;
1✔
646

1✔
647
  res = pr_fsio_guard_chroot(TRUE);
648
  ck_assert_msg(res == FALSE, "Expected FALSE (%d), got %d", FALSE, res);
1✔
649

1✔
650
  res = pr_fsio_symlink(fsio_link_path, "/etc/foo.bar.baz");
651
  ck_assert_msg(res < 0, "Symlinked /etc/foo.bar.baz unexpectedly");
1✔
652
  ck_assert_msg(errno == EACCES, "Expected EACCES (%d), got %s %d", EACCES,
1✔
653
    strerror(errno), errno);
1✔
654

655
  (void) pr_fsio_guard_chroot(FALSE);
656
  (void) pr_fsio_unlink(fsio_link_path);
1✔
657

1✔
658
  res = pr_fsio_symlink(fsio_link_path, "/lib/foo/bar/baz");
659
  ck_assert_msg(res < 0, "Symlinked /lib/foo/bar/baz unexpectedly");
1✔
660
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), got %s %d", ENOENT,
1✔
661
    strerror(errno), errno);
1✔
662
}
663
END_TEST
1✔
664

665
START_TEST (fsio_sys_readlink_test) {
666
  int res;
1✔
667
  char buf[PR_TUNABLE_BUFFER_SIZE];
1✔
668
  const char *link_path, *target_path, *path;
1✔
669

1✔
670
  res = pr_fsio_readlink(NULL, NULL, 0);
671
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
672
  ck_assert_msg(errno == EINVAL, "Expected EINVAL, got %s (%d)", strerror(errno),
1✔
673
    errno);
1✔
674

675
  /* Read a non-symlink file */
676
  path = "/";
677
  res = pr_fsio_readlink(path, buf, sizeof(buf)-1);
1✔
678
  ck_assert_msg(res < 0, "Failed to handle non-symlink path");
1✔
679
  ck_assert_msg(errno == EINVAL, "Expected EINVAL, got %s (%d)", strerror(errno),
1✔
680
    errno);
1✔
681

682
  /* Read a symlink file */
683
  target_path = "/tmp";
684
  link_path = fsio_link_path;
1✔
685
  res = pr_fsio_symlink(target_path, link_path);
1✔
686
  ck_assert_msg(res == 0, "Failed to create symlink from '%s' to '%s': %s",
1✔
687
    link_path, target_path, strerror(errno));
1✔
688

689
  memset(buf, '\0', sizeof(buf));
690
  res = pr_fsio_readlink(link_path, buf, sizeof(buf)-1);
1✔
691
  ck_assert_msg(res > 0, "Failed to read symlink '%s': %s", link_path,
1✔
692
    strerror(errno));
1✔
693
  buf[res] = '\0';
694
  ck_assert_msg(strcmp(buf, target_path) == 0, "Expected '%s', got '%s'",
1✔
695
    target_path, buf);
1✔
696

697
  /* Read a symlink file using a zero-length buffer */
698
  res = pr_fsio_readlink(link_path, buf, 0);
699
  ck_assert_msg(res <= 0, "Expected length <= 0, got %d", res);
1✔
700

1✔
701
  (void) unlink(link_path);
702
}
1✔
703
END_TEST
1✔
704

705
START_TEST (fsio_sys_lstat_test) {
706
  int res;
1✔
707
  struct stat st;
1✔
708
  unsigned int cache_size = 3, max_age = 1, policy_flags = 0;
1✔
709

1✔
710
  res = pr_fsio_lstat(NULL, &st);
711
  ck_assert_msg(res < 0, "Failed to handle null path");
1✔
712
  ck_assert_msg(errno == EINVAL, "Expected EINVAL, got %s (%d)", strerror(errno),
1✔
713
    errno);
1✔
714

715
  res = pr_fsio_lstat("/", NULL);
716
  ck_assert_msg(res < 0, "Failed to handle null struct stat");
1✔
717
  ck_assert_msg(errno == EINVAL, "Expected EINVAL, got %s (%d)", strerror(errno),
1✔
718
    errno);
1✔
719

720
  res = pr_fsio_lstat("/", &st);
721
  ck_assert_msg(res == 0, "Unexpected lstat(2) error on '/': %s",
1✔
722
    strerror(errno));
1✔
723
  ck_assert_msg(S_ISDIR(st.st_mode), "'/' is not a directory as expected");
724

1✔
725
  /* Now, do the lstat(2) again, and make sure we get the same information
726
   * from the cache.
727
   */
728
  res = pr_fsio_lstat("/", &st);
729
  ck_assert_msg(res == 0, "Unexpected lstat(2) error on '/': %s",
1✔
730
    strerror(errno));
1✔
731
  ck_assert_msg(S_ISDIR(st.st_mode), "'/' is not a directory as expected");
732

1✔
733
  pr_fs_statcache_reset();
734
  res = pr_fs_statcache_set_policy(cache_size, max_age, policy_flags);
1✔
735
  ck_assert_msg(res == 0, "Failed to set statcache policy: %s", strerror(errno));
1✔
736

1✔
737
  res = pr_fsio_lstat("/foo/bar/baz/quxx", &st);
738
  ck_assert_msg(res < 0, "Failed to handle nonexistent path");
1✔
739
  ck_assert_msg(errno == ENOENT, "Expected ENOENT, got %s (%d)", strerror(errno),
1✔
740
    errno);
1✔
741

742
  res = pr_fsio_lstat("/foo/bar/baz/quxx", &st);
743
  ck_assert_msg(res < 0, "Failed to handle nonexistent path");
1✔
744
  ck_assert_msg(errno == ENOENT, "Expected ENOENT, got %s (%d)", strerror(errno),
1✔
745
    errno);
1✔
746

747
  /* Now wait for longer than 1 second (our configured max age) */
748
  sleep(max_age + 1);
749

1✔
750
  res = pr_fsio_lstat("/foo/bar/baz/quxx", &st);
751
  ck_assert_msg(res < 0, "Failed to handle nonexistent path");
1✔
752
  ck_assert_msg(errno == ENOENT, "Expected ENOENT, got %s (%d)", strerror(errno),
1✔
753
    errno);
1✔
754

755
  /* lstat a symlink path */
756
  res = pr_fsio_symlink("/tmp", fsio_link_path);
757
  ck_assert_msg(res == 0, "Failed to create symlink to '%s': %s", fsio_link_path,
1✔
758
    strerror(errno));
1✔
759

760
  res = pr_fsio_lstat(fsio_link_path, &st);
761
  ck_assert_msg(res == 0, "Failed to lstat '%s': %s", fsio_link_path,
1✔
762
    strerror(errno));
1✔
763

764
  (void) unlink(fsio_link_path);
765
}
1✔
766
END_TEST
1✔
767

768
START_TEST (fsio_sys_access_dir_test) {
769
  int res;
1✔
770
  uid_t uid = getuid();
1✔
771
  gid_t gid = getgid();
1✔
772
  mode_t perms;
1✔
773
  array_header *suppl_gids;
1✔
774

1✔
775
  res = pr_fsio_access(NULL, X_OK, uid, gid, NULL);
776
  ck_assert_msg(res < 0, "Failed to handle null path");
1✔
777
  ck_assert_msg(errno == EINVAL, "Expected EINVAL, got %s (%d)", strerror(errno),
1✔
778
    errno);
1✔
779

780
  res = pr_fsio_access("/baz/bar/foo", X_OK, uid, gid, NULL);
781
  ck_assert_msg(res < 0, "Failed to handle nonexistent path");
1✔
782
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
1✔
783
    strerror(errno), errno);
1✔
784

785
  /* Make the directory to check; we want it to have perms 771.*/
786
  perms = (mode_t) 0771;
787
  res = mkdir(fsio_testdir_path, perms);
1✔
788
  ck_assert_msg(res >= 0, "Unable to create directory '%s': %s", fsio_testdir_path,
1✔
789
    strerror(errno));
1✔
790

791
  /* Use chmod(2) to ensure that the directory has the perms we want,
792
   * regardless of any umask settings.
793
   */
794
  res = chmod(fsio_testdir_path, perms);
795
  ck_assert_msg(res >= 0, "Unable to set perms %04o on directory '%s': %s", perms,
1✔
796
    fsio_testdir_path, strerror(errno));
1✔
797

798
  /* First, check that we ourselves can access our own directory. */
799

800
  pr_fs_clear_cache2(fsio_testdir_path);
801
  res = pr_fsio_access(fsio_testdir_path, F_OK, uid, gid, NULL);
1✔
802
  ck_assert_msg(res == 0, "Failed to check for file access on directory: %s",
1✔
803
    strerror(errno));
1✔
804

805
  pr_fs_clear_cache2(fsio_testdir_path);
806
  res = pr_fsio_access(fsio_testdir_path, R_OK, uid, gid, NULL);
1✔
807
  ck_assert_msg(res == 0, "Failed to check for read access on directory: %s",
1✔
808
    strerror(errno));
1✔
809

810
  pr_fs_clear_cache2(fsio_testdir_path);
811
  res = pr_fsio_access(fsio_testdir_path, W_OK, uid, gid, NULL);
1✔
812
  ck_assert_msg(res == 0, "Failed to check for write access on directory: %s",
1✔
813
    strerror(errno));
1✔
814

815
  pr_fs_clear_cache2(fsio_testdir_path);
816
  res = pr_fsio_access(fsio_testdir_path, X_OK, uid, gid, NULL);
1✔
817
  ck_assert_msg(res == 0, "Failed to check for execute access on directory: %s",
1✔
818
    strerror(errno));
1✔
819

820
  suppl_gids = make_array(p, 1, sizeof(gid_t));
821
  *((gid_t *) push_array(suppl_gids)) = gid;
1✔
822

1✔
823
  pr_fs_clear_cache2(fsio_testdir_path);
824
  res = pr_fsio_access(fsio_testdir_path, X_OK, uid, gid, suppl_gids);
1✔
825
  ck_assert_msg(res == 0, "Failed to check for execute access on directory: %s",
1✔
826
    strerror(errno));
1✔
827

828
  pr_fs_clear_cache2(fsio_testdir_path);
829
  res = pr_fsio_access(fsio_testdir_path, R_OK, uid, gid, suppl_gids);
1✔
830
  ck_assert_msg(res == 0, "Failed to check for read access on directory: %s",
1✔
831
    strerror(errno));
1✔
832

833
  pr_fs_clear_cache2(fsio_testdir_path);
834
  res = pr_fsio_access(fsio_testdir_path, W_OK, uid, gid, suppl_gids);
1✔
835
  ck_assert_msg(res == 0, "Failed to check for write access on directory: %s",
1✔
836
    strerror(errno));
1✔
837

838
  if (getenv("CI") == NULL) {
839
    uid_t other_uid;
1✔
840
    gid_t other_gid;
×
841

×
842
    /* Deliberately use IDs other than the current ones. */
843
    other_uid = uid - 1;
844
    other_gid = gid - 1;
×
845

×
846
    /* Next, check that others can access the directory. */
847
    pr_fs_clear_cache2(fsio_testdir_path);
848
    res = pr_fsio_access(fsio_testdir_path, F_OK, other_uid, other_gid,
×
849
      NULL);
×
850
    ck_assert_msg(res == 0,
851
      "Failed to check for other file access on directory: %s",
×
852
      strerror(errno));
853

854
    pr_fs_clear_cache2(fsio_testdir_path);
855
    res = pr_fsio_access(fsio_testdir_path, R_OK, other_uid, other_gid,
×
856
      NULL);
×
857
    ck_assert_msg(res < 0,
858
      "other read access on directory succeeded unexpectedly");
×
859
    ck_assert_msg(errno == EACCES, "Expected EACCES, got %s (%d)",
860
      strerror(errno), errno);
×
861

862
    pr_fs_clear_cache2(fsio_testdir_path);
863
    res = pr_fsio_access(fsio_testdir_path, W_OK, other_uid, other_gid,
×
864
      NULL);
×
865
    ck_assert_msg(res < 0,
866
      "other write access on directory succeeded unexpectedly");
×
867
    ck_assert_msg(errno == EACCES, "Expected EACCES, got %s (%d)",
868
      strerror(errno), errno);
×
869

870
    pr_fs_clear_cache2(fsio_testdir_path);
871
    res = pr_fsio_access(fsio_testdir_path, X_OK, other_uid, other_gid,
×
872
      NULL);
×
873
    ck_assert_msg(res == 0, "Failed to check for execute access on directory: %s",
874
      strerror(errno));
×
875
  }
876

877
  (void) rmdir(fsio_testdir_path);
878
}
1✔
879
END_TEST
1✔
880

881
START_TEST (fsio_sys_access_file_test) {
882
  int fd, res;
1✔
883
  uid_t uid = getuid();
1✔
884
  gid_t gid = getgid();
1✔
885
  mode_t perms = 0665;
1✔
886
  array_header *suppl_gids;
1✔
887

1✔
888
  /* Make the file to check; we want it to have perms 664.*/
889
  fd = open(fsio_test_path, O_CREAT|O_EXCL|O_WRONLY, S_IRUSR|S_IWUSR);
890
  ck_assert_msg(fd >= 0, "Unable to create file '%s': %s", fsio_test_path,
1✔
891
    strerror(errno));
1✔
892

893
  /* Use chmod(2) to ensure that the file has the perms we want,
894
   * regardless of any umask settings.
895
   */
896
  res = chmod(fsio_test_path, perms);
897
  ck_assert_msg(res >= 0, "Unable to set perms %04o on file '%s': %s", perms,
1✔
898
    fsio_test_path, strerror(errno));
1✔
899

900
  /* First, check that we ourselves can access our own file. */
901

902
  pr_fs_clear_cache2(fsio_test_path);
903
  res = pr_fsio_access(fsio_test_path, F_OK, uid, gid, NULL);
1✔
904
  ck_assert_msg(res == 0, "Failed to check for file access on '%s': %s",
1✔
905
    fsio_test_path, strerror(errno));
1✔
906

907
  pr_fs_clear_cache2(fsio_test_path);
908
  res = pr_fsio_access(fsio_test_path, R_OK, uid, gid, NULL);
1✔
909
  ck_assert_msg(res == 0, "Failed to check for read access on '%s': %s",
1✔
910
    fsio_test_path, strerror(errno));
1✔
911

912
  pr_fs_clear_cache2(fsio_test_path);
913
  res = pr_fsio_access(fsio_test_path, W_OK, uid, gid, NULL);
1✔
914
  ck_assert_msg(res == 0, "Failed to check for write access on '%s': %s",
1✔
915
    fsio_test_path, strerror(errno));
1✔
916

917
  pr_fs_clear_cache2(fsio_test_path);
918
  res = pr_fsio_access(fsio_test_path, X_OK, uid, gid, NULL);
1✔
919
  ck_assert_msg(res == 0, "Failed to check for execute access on '%s': %s",
1✔
920
    fsio_test_path, strerror(errno));
1✔
921

922
  suppl_gids = make_array(p, 1, sizeof(gid_t));
923
  *((gid_t *) push_array(suppl_gids)) = gid;
1✔
924

1✔
925
  pr_fs_clear_cache2(fsio_test_path);
926
  res = pr_fsio_access(fsio_test_path, X_OK, uid, gid, suppl_gids);
1✔
927
  ck_assert_msg(res == 0, "Failed to check for execute access on '%s': %s",
1✔
928
    fsio_test_path, strerror(errno));
1✔
929

930
  pr_fs_clear_cache2(fsio_test_path);
931
  res = pr_fsio_access(fsio_test_path, R_OK, uid, gid, suppl_gids);
1✔
932
  ck_assert_msg(res == 0, "Failed to check for read access on '%s': %s",
1✔
933
    fsio_test_path, strerror(errno));
1✔
934

935
  pr_fs_clear_cache2(fsio_test_path);
936
  res = pr_fsio_access(fsio_test_path, W_OK, uid, gid, suppl_gids);
1✔
937
  ck_assert_msg(res == 0, "Failed to check for write access on '%s': %s",
1✔
938
    fsio_test_path, strerror(errno));
1✔
939

940
  (void) unlink(fsio_test_path);
941
}
1✔
942
END_TEST
1✔
943

944
START_TEST (fsio_sys_faccess_test) {
945
  int res;
1✔
946
  uid_t uid = getuid();
1✔
947
  gid_t gid = getgid();
1✔
948
  mode_t perms = 0664;
1✔
949
  pr_fh_t *fh;
1✔
950

1✔
951
  res = pr_fsio_faccess(NULL, F_OK, uid, gid, NULL);
952
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
953
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
954
    strerror(errno), errno);
1✔
955

956
  fh = pr_fsio_open(fsio_test_path, O_CREAT|O_EXCL|O_WRONLY);
957
  ck_assert_msg(fh != NULL, "Unable to create file '%s': %s", fsio_test_path,
1✔
958
    strerror(errno));
1✔
959

960
  /* Use chmod(2) to ensure that the file has the perms we want,
961
   * regardless of any umask settings.
962
   */
963
  res = chmod(fsio_test_path, perms);
964
  ck_assert_msg(res >= 0, "Unable to set perms %04o on file '%s': %s", perms,
1✔
965
    fsio_test_path, strerror(errno));
1✔
966

967
  /* First, check that we ourselves can access our own file. */
968

969
  pr_fs_clear_cache2(fsio_test_path);
970
  res = pr_fsio_faccess(fh, F_OK, uid, gid, NULL);
1✔
971
  ck_assert_msg(res == 0, "Failed to check for file access on '%s': %s",
1✔
972
    fsio_test_path, strerror(errno));
1✔
973

974
  pr_fs_clear_cache2(fsio_test_path);
975
  res = pr_fsio_faccess(fh, R_OK, uid, gid, NULL);
1✔
976
  ck_assert_msg(res == 0, "Failed to check for read access on '%s': %s",
1✔
977
    fsio_test_path, strerror(errno));
1✔
978

979
  pr_fs_clear_cache2(fsio_test_path);
980
  res = pr_fsio_faccess(fh, W_OK, uid, gid, NULL);
1✔
981
  ck_assert_msg(res == 0, "Failed to check for write access on '%s': %s",
1✔
982
    fsio_test_path, strerror(errno));
1✔
983

984
  pr_fs_clear_cache2(fsio_test_path);
985
  res = pr_fsio_faccess(fh, X_OK, uid, gid, NULL);
1✔
986
  ck_assert_msg(res < 0,
1✔
987
    "Check for execute access on '%s' succeeded unexpectedly", fsio_test_path);
1✔
988

989
  (void) pr_fsio_close(fh);
990
  (void) pr_fsio_unlink(fsio_test_path);
1✔
991
}
1✔
992
END_TEST
1✔
993

994
START_TEST (fsio_sys_truncate_test) {
995
  int res;
1✔
996
  off_t len = 0;
1✔
997
  pr_fh_t *fh;
1✔
998

1✔
999
  res = pr_fsio_truncate(NULL, 0);
1000
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
1001
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
1002
    strerror(errno), errno);
1✔
1003

1004
  res = pr_fsio_truncate(fsio_test_path, 0);
1005
  ck_assert_msg(res < 0, "Truncated '%s' unexpectedly", fsio_test_path);
1✔
1006
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
1✔
1007
    strerror(errno), errno);
1✔
1008

1009
  fh = pr_fsio_open(fsio_test_path, O_CREAT|O_EXCL|O_WRONLY);
1010
  ck_assert_msg(fh != NULL, "Failed to create '%s': %s", fsio_test_path,
1✔
1011
    strerror(errno));
1✔
1012

1013
  res = pr_fsio_truncate(fsio_test_path, len);
1014
  ck_assert_msg(res == 0, "Failed to truncate '%s': %s", fsio_test_path,
1✔
1015
    strerror(errno));
1✔
1016

1017
  (void) pr_fsio_close(fh);
1018
  (void) pr_fsio_unlink(fsio_test_path);
1✔
1019
}
1✔
1020
END_TEST
1✔
1021

1022
START_TEST (fsio_sys_truncate_chroot_guard_test) {
1023
  int res;
1✔
1024

1✔
1025
  res = pr_fsio_guard_chroot(TRUE);
1026
  ck_assert_msg(res == FALSE, "Expected FALSE (%d), got %d", FALSE, res);
1✔
1027

1✔
1028
  res = pr_fsio_truncate("/etc/foo.bar.baz", 0);
1029
  ck_assert_msg(res < 0, "Truncated /etc/foo.bar.baz unexpectedly");
1✔
1030
  ck_assert_msg(errno == EACCES, "Expected EACCES (%d), got %s %d", EACCES,
1✔
1031
    strerror(errno), errno);
1✔
1032

1033
  (void) pr_fsio_guard_chroot(FALSE);
1034

1✔
1035
  res = pr_fsio_truncate("/lib/foo/bar/baz", 0);
1036
  ck_assert_msg(res < 0, "Truncated /lib/foo/bar/baz unexpectedly");
1✔
1037
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), got %s %d", ENOENT,
1✔
1038
    strerror(errno), errno);
1✔
1039
}
1040
END_TEST
1✔
1041

1042
START_TEST (fsio_sys_ftruncate_test) {
1043
  int res;
1✔
1044
  off_t len = 0;
1✔
1045
  pr_fh_t *fh;
1✔
1046
  pr_buffer_t *buf;
1✔
1047

1✔
1048
  res = pr_fsio_ftruncate(NULL, 0);
1049
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
1050
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
1051
    strerror(errno), errno);
1✔
1052

1053
  fh = pr_fsio_open(fsio_test_path, O_CREAT|O_EXCL|O_WRONLY);
1054
  ck_assert_msg(fh != NULL, "Failed to create '%s': %s", fsio_test_path,
1✔
1055
    strerror(errno));
1✔
1056

1057
  mark_point();
1058
  res = pr_fsio_ftruncate(fh, len);
1✔
1059
  ck_assert_msg(res == 0, "Failed to truncate '%s': %s", fsio_test_path,
1✔
1060
    strerror(errno));
1✔
1061

1062
  /* Attach a read buffer to the handle, make sure it is cleared. */
1063
  buf = pcalloc(fh->fh_pool, sizeof(pr_buffer_t));
1064
  buf->buflen = 100;
1✔
1065
  buf->remaining = 1;
1✔
1066

1✔
1067
  fh->fh_buf = buf;
1068

1✔
1069
  mark_point();
1070
  res = pr_fsio_ftruncate(fh, len);
1✔
1071
  ck_assert_msg(res == 0, "Failed to truncate '%s': %s", fsio_test_path,
1✔
1072
    strerror(errno));
1✔
1073
  ck_assert_msg(buf->remaining == buf->buflen,
1074
    "Expected %lu, got %lu", (unsigned long) buf->buflen,
1✔
1075
    (unsigned long) buf->remaining);
1076

1077
  (void) pr_fsio_close(fh);
1078
  (void) pr_fsio_unlink(fsio_test_path);
1✔
1079
}
1✔
1080
END_TEST
1✔
1081

1082
START_TEST (fsio_sys_chmod_test) {
1083
  int res;
1✔
1084
  mode_t mode = 0644;
1✔
1085
  pr_fh_t *fh;
1✔
1086

1✔
1087
  res = pr_fsio_chmod(NULL, mode);
1088
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
1089
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
1090
    strerror(errno), errno);
1✔
1091

1092
  res = pr_fsio_chmod(fsio_test_path, 0);
1093
  ck_assert_msg(res < 0, "Changed perms of '%s' unexpectedly", fsio_test_path);
1✔
1094
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
1✔
1095
    strerror(errno), errno);
1✔
1096

1097
  fh = pr_fsio_open(fsio_test_path, O_CREAT|O_EXCL|O_WRONLY);
1098
  ck_assert_msg(fh != NULL, "Failed to create '%s': %s", fsio_test_path,
1✔
1099
    strerror(errno));
1✔
1100

1101
  res = pr_fsio_chmod(fsio_test_path, mode);
1102
  ck_assert_msg(res == 0, "Failed to set perms of '%s': %s", fsio_test_path,
1✔
1103
    strerror(errno));
1✔
1104

1105
  (void) pr_fsio_close(fh);
1106
  (void) pr_fsio_unlink(fsio_test_path);
1✔
1107
}
1✔
1108
END_TEST
1✔
1109

1110
START_TEST (fsio_sys_chmod_chroot_guard_test) {
1111
  int res;
1✔
1112
  mode_t mode = 0644;
1✔
1113

1✔
1114
  res = pr_fsio_guard_chroot(TRUE);
1115
  ck_assert_msg(res == FALSE, "Expected FALSE (%d), got %d", FALSE, res);
1✔
1116

1✔
1117
  res = pr_fsio_chmod("/etc/foo.bar.baz", mode);
1118
  ck_assert_msg(res < 0, "Set mode on /etc/foo.bar.baz unexpectedly");
1✔
1119
  ck_assert_msg(errno == EACCES, "Expected EACCES (%d), got %s %d", EACCES,
1✔
1120
    strerror(errno), errno);
1✔
1121

1122
  (void) pr_fsio_guard_chroot(FALSE);
1123

1✔
1124
  res = pr_fsio_chmod("/lib/foo/bar/baz", mode);
1125
  ck_assert_msg(res < 0, "Set mode on /lib/foo/bar/baz unexpectedly");
1✔
1126
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), got %s %d", ENOENT,
1✔
1127
    strerror(errno), errno);
1✔
1128
}
1129
END_TEST
1✔
1130

1131
START_TEST (fsio_sys_fchmod_test) {
1132
  int res;
1✔
1133
  mode_t mode = 0644;
1✔
1134
  pr_fh_t *fh;
1✔
1135

1✔
1136
  res = pr_fsio_fchmod(NULL, mode);
1137
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
1138
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
1139
    strerror(errno), errno);
1✔
1140

1141
  fh = pr_fsio_open(fsio_test_path, O_CREAT|O_EXCL|O_WRONLY);
1142
  ck_assert_msg(fh != NULL, "Failed to create '%s': %s", fsio_test_path,
1✔
1143
    strerror(errno));
1✔
1144

1145
  res = pr_fsio_fchmod(fh, mode);
1146
  ck_assert_msg(res == 0, "Failed to set perms of '%s': %s", fsio_test_path,
1✔
1147
    strerror(errno));
1✔
1148

1149
  (void) pr_fsio_close(fh);
1150
  (void) pr_fsio_unlink(fsio_test_path);
1✔
1151
}
1✔
1152
END_TEST
1✔
1153

1154
START_TEST (fsio_sys_chown_test) {
1155
  int res;
1✔
1156
  uid_t uid = getuid();
1✔
1157
  gid_t gid = getgid();
1✔
1158
  pr_fh_t *fh;
1✔
1159

1✔
1160
  res = pr_fsio_chown(NULL, uid, gid);
1161
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
1162
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
1163
    strerror(errno), errno);
1✔
1164

1165
  res = pr_fsio_chown(fsio_test_path, uid, gid);
1166
  ck_assert_msg(res < 0, "Changed ownership of '%s' unexpectedly",
1✔
1167
    fsio_test_path);
1✔
1168
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
1169
    strerror(errno), errno);
1✔
1170

1171
  fh = pr_fsio_open(fsio_test_path, O_CREAT|O_EXCL|O_WRONLY);
1172
  ck_assert_msg(fh != NULL, "Failed to create '%s': %s", fsio_test_path,
1✔
1173
    strerror(errno));
1✔
1174

1175
  res = pr_fsio_chown(fsio_test_path, uid, gid);
1176
  ck_assert_msg(res == 0, "Failed to set ownership of '%s': %s", fsio_test_path,
1✔
1177
    strerror(errno));
1✔
1178

1179
  (void) pr_fsio_close(fh);
1180
  (void) pr_fsio_unlink(fsio_test_path);
1✔
1181
}
1✔
1182
END_TEST
1✔
1183

1184
START_TEST (fsio_sys_chown_chroot_guard_test) {
1185
  int res;
1✔
1186
  uid_t uid = getuid();
1✔
1187
  gid_t gid = getgid();
1✔
1188

1✔
1189
  res = pr_fsio_guard_chroot(TRUE);
1190
  ck_assert_msg(res == FALSE, "Expected FALSE (%d), got %d", FALSE, res);
1✔
1191

1✔
1192
  res = pr_fsio_chown("/etc/foo.bar.baz", uid, gid);
1193
  ck_assert_msg(res < 0, "Set ownership on /etc/foo.bar.baz unexpectedly");
1✔
1194
  ck_assert_msg(errno == EACCES, "Expected EACCES (%d), got %s %d", EACCES,
1✔
1195
    strerror(errno), errno);
1✔
1196

1197
  (void) pr_fsio_guard_chroot(FALSE);
1198

1✔
1199
  res = pr_fsio_chown("/lib/foo/bar/baz", uid, gid);
1200
  ck_assert_msg(res < 0, "Set ownership on /lib/foo/bar/baz unexpectedly");
1✔
1201
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), got %s %d", ENOENT,
1✔
1202
    strerror(errno), errno);
1✔
1203
}
1204
END_TEST
1✔
1205

1206
START_TEST (fsio_sys_fchown_test) {
1207
  int res;
1✔
1208
  uid_t uid = getuid();
1✔
1209
  gid_t gid = getgid();
1✔
1210
  pr_fh_t *fh;
1✔
1211

1✔
1212
  res = pr_fsio_fchown(NULL, uid, gid);
1213
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
1214
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
1215
    strerror(errno), errno);
1✔
1216

1217
  fh = pr_fsio_open(fsio_test_path, O_CREAT|O_EXCL|O_WRONLY);
1218
  ck_assert_msg(fh != NULL, "Failed to create '%s': %s", fsio_test_path,
1✔
1219
    strerror(errno));
1✔
1220

1221
  res = pr_fsio_fchown(fh, uid, gid);
1222
  ck_assert_msg(res == 0, "Failed to set ownership of '%s': %s", fsio_test_path,
1✔
1223
    strerror(errno));
1✔
1224

1225
  (void) pr_fsio_close(fh);
1226
  (void) pr_fsio_unlink(fsio_test_path);
1✔
1227
}
1✔
1228
END_TEST
1✔
1229

1230
START_TEST (fsio_sys_lchown_test) {
1231
  int res;
1✔
1232
  uid_t uid = getuid();
1✔
1233
  gid_t gid = getgid();
1✔
1234
  pr_fh_t *fh;
1✔
1235

1✔
1236
  res = pr_fsio_lchown(NULL, uid, gid);
1237
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
1238
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
1239
    strerror(errno), errno);
1✔
1240

1241
  res = pr_fsio_lchown(fsio_test_path, uid, gid);
1242
  ck_assert_msg(res < 0, "Changed ownership of '%s' unexpectedly",
1✔
1243
    fsio_test_path);
1✔
1244
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
1245
    strerror(errno), errno);
1✔
1246

1247
  fh = pr_fsio_open(fsio_test_path, O_CREAT|O_EXCL|O_WRONLY);
1248
  ck_assert_msg(fh != NULL, "Failed to create '%s': %s", fsio_test_path,
1✔
1249
    strerror(errno));
1✔
1250

1251
  res = pr_fsio_lchown(fsio_test_path, uid, gid);
1252
  ck_assert_msg(res == 0, "Failed to set ownership of '%s': %s", fsio_test_path,
1✔
1253
    strerror(errno));
1✔
1254

1255
  (void) pr_fsio_close(fh);
1256
  (void) pr_fsio_unlink(fsio_test_path);
1✔
1257
}
1✔
1258
END_TEST
1✔
1259

1260
START_TEST (fsio_sys_lchown_chroot_guard_test) {
1261
  int res;
1✔
1262
  uid_t uid = getuid();
1✔
1263
  gid_t gid = getgid();
1✔
1264

1✔
1265
  res = pr_fsio_guard_chroot(TRUE);
1266
  ck_assert_msg(res == FALSE, "Expected FALSE (%d), got %d", FALSE, res);
1✔
1267

1✔
1268
  res = pr_fsio_lchown("/etc/foo.bar.baz", uid, gid);
1269
  ck_assert_msg(res < 0, "Set ownership on /etc/foo.bar.baz unexpectedly");
1✔
1270
  ck_assert_msg(errno == EACCES, "Expected EACCES (%d), got %s %d", EACCES,
1✔
1271
    strerror(errno), errno);
1✔
1272

1273
  (void) pr_fsio_guard_chroot(FALSE);
1274

1✔
1275
  res = pr_fsio_lchown("/lib/foo/bar/baz", uid, gid);
1276
  ck_assert_msg(res < 0, "Set ownership on /lib/foo/bar/baz unexpectedly");
1✔
1277
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), got %s %d", ENOENT,
1✔
1278
    strerror(errno), errno);
1✔
1279
}
1280
END_TEST
1✔
1281

1282
START_TEST (fsio_sys_rename_test) {
1283
  int res;
1✔
1284
  pr_fh_t *fh;
1✔
1285

1✔
1286
  res = pr_fsio_rename(NULL, NULL);
1287
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
1288
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
1289
    strerror(errno), errno);
1✔
1290

1291
  res = pr_fsio_rename(fsio_test_path, NULL);
1292
  ck_assert_msg(res < 0, "Failed to handle null dst argument");
1✔
1293
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
1294
    strerror(errno), errno);
1✔
1295

1296
  res = pr_fsio_rename(fsio_test_path, fsio_test2_path);
1297
  ck_assert_msg(res < 0, "Failed to handle non-existent files");
1✔
1298
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
1✔
1299
    strerror(errno), errno);
1✔
1300

1301
  fh = pr_fsio_open(fsio_test_path, O_CREAT|O_EXCL|O_WRONLY);
1302
  ck_assert_msg(fh != NULL, "Failed to create '%s': %s", fsio_test_path,
1✔
1303
    strerror(errno));
1✔
1304
  (void) pr_fsio_close(fh);
1305

1✔
1306
  res = pr_fsio_rename(fsio_test_path, fsio_test2_path);
1307
  ck_assert_msg(res == 0, "Failed to rename '%s' to '%s': %s", fsio_test_path,
1✔
1308
    fsio_test2_path, strerror(errno));
1✔
1309

1310
  (void) pr_fsio_unlink(fsio_test_path);
1311
  (void) pr_fsio_unlink(fsio_test2_path);
1✔
1312
}
1✔
1313
END_TEST
1✔
1314

1315
START_TEST (fsio_sys_rename_chroot_guard_test) {
1316
  int res;
1✔
1317
  pr_fh_t *fh;
1✔
1318

1✔
1319
  res = pr_fsio_guard_chroot(TRUE);
1320
  ck_assert_msg(res == FALSE, "Expected FALSE (%d), got %d", FALSE, res);
1✔
1321

1✔
1322
  fh = pr_fsio_open(fsio_test_path, O_CREAT|O_EXCL|O_WRONLY);
1323
  ck_assert_msg(fh != NULL, "Failed to create '%s': %s", fsio_test_path,
1✔
1324
    strerror(errno));
1✔
1325
  (void) pr_fsio_close(fh);
1326

1✔
1327
  res = pr_fsio_rename(fsio_test_path, "/etc/foo.bar.baz");
1328
  ck_assert_msg(res < 0, "Renamed '%s' unexpectedly", fsio_test_path);
1✔
1329
  ck_assert_msg(errno == EACCES, "Expected EACCES (%d), got %s (%d)", EACCES,
1✔
1330
    strerror(errno), errno);
1✔
1331

1332
  res = pr_fsio_rename("/etc/foo.bar.baz", fsio_test_path);
1333
  ck_assert_msg(res < 0, "Renamed '/etc/foo.bar.baz' unexpectedly");
1✔
1334
  ck_assert_msg(errno == EACCES, "Expected EACCES (%d), got %s (%d)", EACCES,
1✔
1335
    strerror(errno), errno);
1✔
1336

1337
  (void) pr_fsio_guard_chroot(FALSE);
1338

1✔
1339
  res = pr_fsio_rename("/etc/foo/bar/baz", "/lib/quxx/quzz");
1340
  ck_assert_msg(res < 0, "Renamed '/etc/foo/bar/baz' unexpectedly");
1✔
1341
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
1✔
1342
    strerror(errno), errno);
1✔
1343

1344
  (void) pr_fsio_unlink(fsio_test_path);
1345
}
1✔
1346
END_TEST
1✔
1347

1348
START_TEST (fsio_sys_utimes_test) {
1349
  int res;
1✔
1350
  struct timeval tvs[3];
1✔
1351
  pr_fh_t *fh;
1✔
1352

1✔
1353
  memset(tvs, 0, sizeof(tvs));
1354

1✔
1355
  res = pr_fsio_utimes(NULL, NULL);
1356
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
1357
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
1358
    strerror(errno), errno);
1✔
1359

1360
  res = pr_fsio_utimes(fsio_test_path, (struct timeval *) &tvs);
1361
  ck_assert_msg(res < 0, "Changed times of '%s' unexpectedly", fsio_test_path);
1✔
1362
  ck_assert_msg(errno == ENOENT || errno == EINVAL,
1✔
1363
    "Expected ENOENT (%d) or EINVAL (%d), got %s (%d)", ENOENT, EINVAL,
1✔
1364
    strerror(errno), errno);
1365

1366
  fh = pr_fsio_open(fsio_test_path, O_CREAT|O_EXCL|O_WRONLY);
1367
  ck_assert_msg(fh != NULL, "Failed to create '%s': %s", fsio_test_path,
1✔
1368
    strerror(errno));
1✔
1369

1370
  memset(&tvs, 0, sizeof(tvs));
1371
  res = pr_fsio_utimes(fsio_test_path, (struct timeval *) &tvs);
1✔
1372
  ck_assert_msg(res == 0, "Failed to set times of '%s': %s", fsio_test_path,
1✔
1373
    strerror(errno));
1✔
1374

1375
  (void) pr_fsio_close(fh);
1376
  (void) pr_fsio_unlink(fsio_test_path);
1✔
1377
}
1✔
1378
END_TEST
1✔
1379

1380
START_TEST (fsio_sys_utimes_chroot_guard_test) {
1381
  int res;
1✔
1382
  struct timeval tvs[3];
1✔
1383

1✔
1384
  memset(tvs, 0, sizeof(tvs));
1385

1✔
1386
  res = pr_fsio_guard_chroot(TRUE);
1387
  ck_assert_msg(res == FALSE, "Expected FALSE (%d), got %d", FALSE, res);
1✔
1388

1✔
1389
  res = pr_fsio_utimes("/etc/foo.bar.baz", (struct timeval *) &tvs);
1390
  ck_assert_msg(res < 0, "Set times on /etc/foo.bar.baz unexpectedly");
1✔
1391
  ck_assert_msg(errno == EACCES, "Expected EACCES (%d), got %s %d", EACCES,
1✔
1392
    strerror(errno), errno);
1✔
1393

1394
  (void) pr_fsio_guard_chroot(FALSE);
1395

1✔
1396
  res = pr_fsio_utimes("/lib/foo/bar/baz", (struct timeval *) &tvs);
1397
  ck_assert_msg(res < 0, "Set times on /lib/foo/bar/baz unexpectedly");
1✔
1398
  ck_assert_msg(errno == ENOENT || errno == EINVAL,
1✔
1399
    "Expected ENOENT (%d) or EINVAL (%d), got %s %d", ENOENT, EINVAL,
1✔
1400
    strerror(errno), errno);
1401
}
1402
END_TEST
1✔
1403

1404
START_TEST (fsio_sys_futimes_test) {
1405
  int res;
1✔
1406
  struct timeval tvs[3];
1✔
1407
  pr_fh_t *fh;
1✔
1408

1✔
1409
  memset(tvs, 0, sizeof(tvs));
1410

1✔
1411
  res = pr_fsio_futimes(NULL, NULL);
1412
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
1413
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
1414
    strerror(errno), errno);
1✔
1415

1416
  fh = pr_fsio_open(fsio_test_path, O_CREAT|O_EXCL|O_WRONLY);
1417
  ck_assert_msg(fh != NULL, "Failed to create '%s': %s", fsio_test_path,
1✔
1418
    strerror(errno));
1✔
1419

1420
  memset(&tvs, 0, sizeof(tvs));
1421
  res = pr_fsio_futimes(fh, (struct timeval *) &tvs);
1✔
1422
  ck_assert_msg(res == 0, "Failed to set times of '%s': %s", fsio_test_path,
1✔
1423
    strerror(errno));
1✔
1424

1425
  (void) pr_fsio_close(fh);
1426
  (void) pr_fsio_unlink(fsio_test_path);
1✔
1427
}
1✔
1428
END_TEST
1✔
1429

1430
START_TEST (fsio_sys_fsync_test) {
1431
  int res;
1✔
1432
  pr_fh_t *fh;
1✔
1433

1✔
1434
  res = pr_fsio_fsync(NULL);
1435
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
1436
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
1437
    strerror(errno), errno);
1✔
1438

1439
  fh = pr_fsio_open(fsio_test_path, O_CREAT|O_EXCL|O_WRONLY);
1440
  ck_assert_msg(fh != NULL, "Failed to open '%s': %s", fsio_test_path,
1✔
1441
    strerror(errno));
1✔
1442

1443
  res = pr_fsio_fsync(fh);
1444
#ifdef HAVE_FSYNC
1✔
1445
  ck_assert_msg(res == 0, "fsync of '%s' failed: %s", fsio_test_path,
1446
    strerror(errno));
1✔
1447
#else
1448
  ck_assert_msg(res < 0, "fsync of '%s' succeeded unexpectedly", fsio_test_path);
1449
  ck_assert_msg(errno == ENOSYS, "Expected ENOSYS (%d), got %s (%d)", ENOSYS,
1450
    strerror(errno), errno);
1451
#endif /* HAVE_FSYNC */
1452

1453
  (void) pr_fsio_close(fh);
1454
  (void) pr_fsio_unlink(fsio_test_path);
1✔
1455
}
1✔
1456
END_TEST
1✔
1457

1458
START_TEST (fsio_sys_realpath_test) {
1459
  const char *res;
1✔
1460

1✔
1461
  mark_point();
1462
  res = pr_fsio_realpath(NULL, NULL);
1✔
1463
  ck_assert_msg(res == NULL, "Failed to handle null pool");
1✔
1464
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
1465
    strerror(errno), errno);
1✔
1466

1467
  mark_point();
1468
  res = pr_fsio_realpath(p, NULL);
1✔
1469
  ck_assert_msg(res == NULL, "Failed to handle null path");
1✔
1470
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
1471
    strerror(errno), errno);
1✔
1472

1473
  mark_point();
1474
  res = pr_fsio_realpath(p, "/tmp");
1✔
1475
  ck_assert_msg(res != NULL, "Failed to resolve path '/tmp': %s",
1✔
1476
    strerror(errno));
1✔
1477
}
1478
END_TEST
1✔
1479

1480
START_TEST (fsio_sys_getxattr_test) {
1481
  ssize_t res;
1✔
1482
  const char *path, *name;
1✔
1483
  unsigned long fsio_opts;
1✔
1484

1✔
1485
  res = pr_fsio_getxattr(NULL, NULL, NULL, NULL, 0);
1486
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
1487
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
1488
    strerror(errno), errno);
1✔
1489

1490
  res = pr_fsio_getxattr(p, NULL, NULL, NULL, 0);
1491
  ck_assert_msg(res < 0, "Failed to handle null path");
1✔
1492
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
1493
    strerror(errno), errno);
1✔
1494

1495
  path = fsio_test_path;
1496
  res = pr_fsio_getxattr(p, path, NULL, NULL, 0);
1✔
1497
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
1498
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
1499
    strerror(errno), errno);
1✔
1500

1501
  name = "foo.bar";
1502

1✔
1503
  fsio_opts = pr_fsio_set_options(PR_FSIO_OPT_IGNORE_XATTR);
1504
  res = pr_fsio_getxattr(p, path, name, NULL, 0);
1✔
1505
  ck_assert_msg(res < 0, "Failed to handle disabled xattr");
1✔
1506
  ck_assert_msg(errno == ENOSYS, "Expected ENOSYS (%d), got %s (%d)", ENOSYS,
1✔
1507
    strerror(errno), errno);
1✔
1508

1509
  (void) pr_fsio_set_options(fsio_opts);
1510
  res = pr_fsio_getxattr(p, path, name, NULL, 0);
1✔
1511
#ifdef PR_USE_XATTR
1✔
1512
  ck_assert_msg(res < 0, "Failed to handle nonexist attribute '%s'", name);
1513
  ck_assert_msg(errno == ENOENT || errno == ENOATTR || errno == ENOTSUP,
1✔
1514
    "Expected ENOENT (%d), ENOATTR (%d) or ENOTSUP (%d), got %s (%d)",
1✔
1515
    ENOENT, ENOATTR, ENOTSUP, strerror(errno), errno);
1516

1517
#else
1518
  ck_assert_msg(res < 0, "Failed to handle --disable-xattr");
1519
  ck_assert_msg(errno == ENOSYS, "Expected ENOSYS (%d), got %s (%d)", ENOSYS,
1520
    strerror(errno), errno);
1521
#endif /* PR_USE_XATTR */
1522
}
1523
END_TEST
1✔
1524

1525
START_TEST (fsio_sys_lgetxattr_test) {
1526
  ssize_t res;
1✔
1527
  const char *path, *name;
1✔
1528
  unsigned long fsio_opts;
1✔
1529

1✔
1530
  res = pr_fsio_lgetxattr(NULL, NULL, NULL, NULL, 0);
1531
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
1532
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
1533
    strerror(errno), errno);
1✔
1534

1535
  res = pr_fsio_lgetxattr(p, NULL, NULL, NULL, 0);
1536
  ck_assert_msg(res < 0, "Failed to handle null path");
1✔
1537
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
1538
    strerror(errno), errno);
1✔
1539

1540
  path = fsio_test_path;
1541
  res = pr_fsio_lgetxattr(p, path, NULL, NULL, 0);
1✔
1542
  ck_assert_msg(res < 0, "Failed to handle null xattr name");
1✔
1543
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
1544
    strerror(errno), errno);
1✔
1545

1546
  name = "foo.bar";
1547

1✔
1548
  fsio_opts = pr_fsio_set_options(PR_FSIO_OPT_IGNORE_XATTR);
1549
  res = pr_fsio_lgetxattr(p, path, name, NULL, 0);
1✔
1550
  ck_assert_msg(res < 0, "Failed to handle disabled xattr");
1✔
1551
  ck_assert_msg(errno == ENOSYS, "Expected ENOSYS (%d), got %s (%d)", ENOSYS,
1✔
1552
    strerror(errno), errno);
1✔
1553

1554
  pr_fsio_set_options(fsio_opts);
1555
  res = pr_fsio_lgetxattr(p, path, name, NULL, 0);
1✔
1556
#ifdef PR_USE_XATTR
1✔
1557
  ck_assert_msg(res < 0, "Failed to handle nonexist attribute '%s'", name);
1558
  ck_assert_msg(errno == ENOENT || errno == ENOATTR || errno == ENOTSUP,
1✔
1559
    "Expected ENOENT (%d), ENOATTR (%d) or ENOTSUP (%d), got %s (%d)",
1✔
1560
    ENOENT, ENOATTR, ENOTSUP, strerror(errno), errno);
1561

1562
#else
1563
  ck_assert_msg(res < 0, "Failed to handle --disable-xattr");
1564
  ck_assert_msg(errno == ENOSYS, "Expected ENOSYS (%d), got %s (%d)", ENOSYS,
1565
    strerror(errno), errno);
1566
#endif /* PR_USE_XATTR */
1567
}
1568
END_TEST
1✔
1569

1570
START_TEST (fsio_sys_fgetxattr_test) {
1571
  ssize_t res;
1✔
1572
  pr_fh_t *fh;
1✔
1573
  const char *name;
1✔
1574
  unsigned long fsio_opts;
1✔
1575

1✔
1576
  res = pr_fsio_fgetxattr(NULL, NULL, NULL, NULL, 0);
1577
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
1578
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
1579
    strerror(errno), errno);
1✔
1580

1581
  res = pr_fsio_fgetxattr(p, NULL, NULL, NULL, 0);
1582
  ck_assert_msg(res < 0, "Failed to handle null file handle");
1✔
1583
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
1584
    strerror(errno), errno);
1✔
1585

1586
  (void) unlink(fsio_test_path);
1587
  fh = pr_fsio_open(fsio_test_path, O_CREAT|O_EXCL|O_RDWR);
1✔
1588
  ck_assert_msg(fh != NULL, "Failed to open '%s': %s", fsio_test_path,
1✔
1589
    strerror(errno));
1✔
1590

1591
  res = pr_fsio_fgetxattr(p, fh, NULL, NULL, 0);
1592
  ck_assert_msg(res < 0, "Failed to handle null xattr name");
1✔
1593
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
1594
    strerror(errno), errno);
1✔
1595

1596
  name = "foo.bar";
1597

1✔
1598
  fsio_opts = pr_fsio_set_options(PR_FSIO_OPT_IGNORE_XATTR);
1599
  res = pr_fsio_fgetxattr(p, fh, name, NULL, 0);
1✔
1600
  ck_assert_msg(res < 0, "Failed to handle disabled xattr");
1✔
1601
  ck_assert_msg(errno == ENOSYS, "Expected ENOSYS (%d), got %s (%d)", ENOSYS,
1✔
1602
    strerror(errno), errno);
1✔
1603

1604
  pr_fsio_set_options(fsio_opts);
1605
  res = pr_fsio_fgetxattr(p, fh, name, NULL, 0);
1✔
1606
#ifdef PR_USE_XATTR
1✔
1607
  ck_assert_msg(res < 0, "Failed to handle nonexist attribute '%s'", name);
1608
  ck_assert_msg(errno == ENOENT || errno == ENOATTR || errno == ENOTSUP,
1✔
1609
    "Expected ENOENT (%d), ENOATTR (%d) or ENOTSUP (%d), got %s (%d)",
1✔
1610
    ENOENT, ENOATTR, ENOTSUP, strerror(errno), errno);
1611

1612
#else
1613
  ck_assert_msg(res < 0, "Failed to handle --disable-xattr");
1614
  ck_assert_msg(errno == ENOSYS, "Expected ENOSYS (%d), got %s (%d)", ENOSYS,
1615
    strerror(errno), errno);
1616
#endif /* PR_USE_XATTR */
1617

1618
  pr_fsio_close(fh);
1619
  (void) unlink(fsio_test_path);
1✔
1620
}
1✔
1621
END_TEST
1✔
1622

1623
START_TEST (fsio_sys_listxattr_test) {
1624
  int res;
1✔
1625
  const char *path;
1✔
1626
  pr_fh_t *fh = NULL;
1✔
1627
  array_header *names = NULL;
1✔
1628
  unsigned long fsio_opts;
1✔
1629

1✔
1630
  res = pr_fsio_listxattr(NULL, NULL, NULL);
1631
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
1632
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
1633
    strerror(errno), errno);
1✔
1634

1635
  res = pr_fsio_listxattr(p, NULL, NULL);
1636
  ck_assert_msg(res < 0, "Failed to handle null path");
1✔
1637
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
1638
    strerror(errno), errno);
1✔
1639

1640
  path = fsio_test_path;
1641
  res = pr_fsio_listxattr(p, path, NULL);
1✔
1642
  ck_assert_msg(res < 0, "Failed to handle null array");
1✔
1643
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
1644
    strerror(errno), errno);
1✔
1645

1646
  fsio_opts = pr_fsio_set_options(PR_FSIO_OPT_IGNORE_XATTR);
1647
  res = pr_fsio_listxattr(p, path, &names);
1✔
1648
  ck_assert_msg(res < 0, "Failed to handle disabled xattr");
1✔
1649
  ck_assert_msg(errno == ENOSYS, "Expected ENOSYS (%d), got %s (%d)", ENOSYS,
1✔
1650
    strerror(errno), errno);
1✔
1651

1652
  pr_fsio_set_options(fsio_opts);
1653
  res = pr_fsio_listxattr(p, path, &names);
1✔
1654
#ifdef PR_USE_XATTR
1✔
1655
  ck_assert_msg(res < 0, "Failed to handle nonexistent path '%s'", path);
1656
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
1✔
1657
    strerror(errno), errno);
1✔
1658

1659
  (void) unlink(fsio_test_path);
1660
  fh = pr_fsio_open(fsio_test_path, O_CREAT|O_EXCL|O_WRONLY);
1✔
1661
  ck_assert_msg(fh != NULL, "Failed to open '%s': %s", fsio_test_path,
1✔
1662
    strerror(errno));
1✔
1663
  pr_fsio_close(fh);
1664

1✔
1665
  res = pr_fsio_listxattr(p, path, &names);
1666
  ck_assert_msg(res >= 0, "Failed to list xattrs for '%s': %s", path, strerror(errno));
1✔
1667

1✔
1668
  (void) unlink(fsio_test_path);
1669
#else
1✔
1670
  (void) fh;
1671
  ck_assert_msg(res < 0, "Failed to handle --disable-xattr");
1672
  ck_assert_msg(errno == ENOSYS, "Expected ENOSYS (%d), got %s (%d)", ENOSYS,
1673
    strerror(errno), errno);
1674
#endif /* PR_USE_XATTR */
1675
}
1676
END_TEST
1✔
1677

1678
START_TEST (fsio_sys_llistxattr_test) {
1679
  int res;
1✔
1680
  const char *path;
1✔
1681
  pr_fh_t *fh = NULL;
1✔
1682
  array_header *names = NULL;
1✔
1683
  unsigned long fsio_opts;
1✔
1684

1✔
1685
  res = pr_fsio_llistxattr(NULL, NULL, NULL);
1686
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
1687
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
1688
    strerror(errno), errno);
1✔
1689

1690
  res = pr_fsio_llistxattr(p, NULL, NULL);
1691
  ck_assert_msg(res < 0, "Failed to handle null path");
1✔
1692
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
1693
    strerror(errno), errno);
1✔
1694

1695
  path = fsio_test_path;
1696
  res = pr_fsio_llistxattr(p, path, NULL);
1✔
1697
  ck_assert_msg(res < 0, "Failed to handle null array");
1✔
1698
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
1699
    strerror(errno), errno);
1✔
1700

1701
  fsio_opts = pr_fsio_set_options(PR_FSIO_OPT_IGNORE_XATTR);
1702
  res = pr_fsio_llistxattr(p, path, &names);
1✔
1703
  ck_assert_msg(res < 0, "Failed to handle disabled xattr");
1✔
1704
  ck_assert_msg(errno == ENOSYS, "Expected ENOSYS (%d), got %s (%d)", ENOSYS,
1✔
1705
    strerror(errno), errno);
1✔
1706

1707
  pr_fsio_set_options(fsio_opts);
1708
  res = pr_fsio_llistxattr(p, path, &names);
1✔
1709
#ifdef PR_USE_XATTR
1✔
1710
  ck_assert_msg(res < 0, "Failed to handle nonexistent path '%s'", path);
1711
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
1✔
1712
    strerror(errno), errno);
1✔
1713

1714
  (void) unlink(fsio_test_path);
1715
  fh = pr_fsio_open(fsio_test_path, O_CREAT|O_EXCL|O_WRONLY);
1✔
1716
  ck_assert_msg(fh != NULL, "Failed to open '%s': %s", fsio_test_path,
1✔
1717
    strerror(errno));
1✔
1718
  pr_fsio_close(fh);
1719

1✔
1720
  res = pr_fsio_listxattr(p, path, &names);
1721
  ck_assert_msg(res >= 0, "Failed to list xattrs for '%s': %s", path, strerror(errno));
1✔
1722

1✔
1723
  (void) unlink(fsio_test_path);
1724
#else
1✔
1725
  (void) fh;
1726
  ck_assert_msg(res < 0, "Failed to handle --disable-xattr");
1727
  ck_assert_msg(errno == ENOSYS, "Expected ENOSYS (%d), got %s (%d)", ENOSYS,
1728
    strerror(errno), errno);
1729
#endif /* PR_USE_XATTR */
1730
}
1731
END_TEST
1✔
1732

1733
START_TEST (fsio_sys_flistxattr_test) {
1734
  int res;
1✔
1735
  pr_fh_t *fh;
1✔
1736
  array_header *names = NULL;
1✔
1737
  unsigned long fsio_opts;
1✔
1738

1✔
1739
  res = pr_fsio_flistxattr(NULL, NULL, NULL);
1740
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
1741
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
1742
    strerror(errno), errno);
1✔
1743

1744
  res = pr_fsio_flistxattr(p, NULL, NULL);
1745
  ck_assert_msg(res < 0, "Failed to handle null file handle");
1✔
1746
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
1747
    strerror(errno), errno);
1✔
1748

1749
  (void) unlink(fsio_test_path);
1750
  fh = pr_fsio_open(fsio_test_path, O_CREAT|O_EXCL|O_RDWR);
1✔
1751
  ck_assert_msg(fh != NULL, "Failed to open '%s': %s", fsio_test_path,
1✔
1752
    strerror(errno));
1✔
1753

1754
  res = pr_fsio_flistxattr(p, fh, NULL);
1755
  ck_assert_msg(res < 0, "Failed to handle null array");
1✔
1756
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
1757
    strerror(errno), errno);
1✔
1758

1759
  fsio_opts = pr_fsio_set_options(PR_FSIO_OPT_IGNORE_XATTR);
1760
  res = pr_fsio_flistxattr(p, fh, &names);
1✔
1761
  ck_assert_msg(res < 0, "Failed to handle disabled xattr");
1✔
1762
  ck_assert_msg(errno == ENOSYS, "Expected ENOSYS (%d), got %s (%d)", ENOSYS,
1✔
1763
    strerror(errno), errno);
1✔
1764

1765
  pr_fsio_set_options(fsio_opts);
1766
  res = pr_fsio_flistxattr(p, fh, &names);
1✔
1767
#ifdef PR_USE_XATTR
1✔
1768
  ck_assert_msg(res >= 0, "Failed to list xattrs for '%s': %s", fsio_test_path,
1769
    strerror(errno));
1✔
1770

1771
#else
1772
  ck_assert_msg(res < 0, "Failed to handle --disable-xattr");
1773
  ck_assert_msg(errno == ENOSYS, "Expected ENOSYS (%d), got %s (%d)", ENOSYS,
1774
    strerror(errno), errno);
1775
#endif /* PR_USE_XATTR */
1776

1777
  pr_fsio_close(fh);
1778
  (void) unlink(fsio_test_path);
1✔
1779
}
1✔
1780
END_TEST
1✔
1781

1782
START_TEST (fsio_sys_removexattr_test) {
1783
  int res;
1✔
1784
  const char *path, *name;
1✔
1785
  unsigned long fsio_opts;
1✔
1786

1✔
1787
  res = pr_fsio_removexattr(NULL, NULL, NULL);
1788
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
1789
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
1790
    strerror(errno), errno);
1✔
1791

1792
  res = pr_fsio_removexattr(p, NULL, NULL);
1793
  ck_assert_msg(res < 0, "Failed to handle null path");
1✔
1794
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
1795
    strerror(errno), errno);
1✔
1796

1797
  path = fsio_test_path;
1798
  res = pr_fsio_removexattr(p, path, NULL);
1✔
1799
  ck_assert_msg(res < 0, "Failed to handle null attribute name");
1✔
1800
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
1801
    strerror(errno), errno);
1✔
1802

1803
  name = "foo.bar";
1804

1✔
1805
  fsio_opts = pr_fsio_set_options(PR_FSIO_OPT_IGNORE_XATTR);
1806
  res = pr_fsio_removexattr(p, path, name);
1✔
1807
  ck_assert_msg(res < 0, "Failed to handle disabled xattr");
1✔
1808
  ck_assert_msg(errno == ENOSYS, "Expected ENOSYS (%d), got %s (%d)", ENOSYS,
1✔
1809
    strerror(errno), errno);
1✔
1810

1811
  pr_fsio_set_options(fsio_opts);
1812
  res = pr_fsio_removexattr(p, path, name);
1✔
1813
#ifdef PR_USE_XATTR
1✔
1814
  ck_assert_msg(res < 0, "Failed to handle nonexistent attribute '%s'", name);
1815
  ck_assert_msg(errno == ENOENT || errno == ENOATTR || errno == ENOTSUP,
1✔
1816
    "Expected ENOENT (%d), ENOATTR (%d) or ENOTSUP (%d), got %s (%d)",
1✔
1817
    ENOENT, ENOATTR, ENOTSUP, strerror(errno), errno);
1818

1819
#else
1820
  ck_assert_msg(res < 0, "Failed to handle --disable-xattr");
1821
  ck_assert_msg(errno == ENOSYS, "Expected ENOSYS (%d), got %s (%d)", ENOSYS,
1822
    strerror(errno), errno);
1823
#endif /* PR_USE_XATTR */
1824
}
1825
END_TEST
1✔
1826

1827
START_TEST (fsio_sys_lremovexattr_test) {
1828
  int res;
1✔
1829
  const char *path, *name;
1✔
1830
  unsigned long fsio_opts;
1✔
1831

1✔
1832
  res = pr_fsio_lremovexattr(NULL, NULL, NULL);
1833
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
1834
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
1835
    strerror(errno), errno);
1✔
1836

1837
  res = pr_fsio_lremovexattr(p, NULL, NULL);
1838
  ck_assert_msg(res < 0, "Failed to handle null path");
1✔
1839
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
1840
    strerror(errno), errno);
1✔
1841

1842
  path = fsio_test_path;
1843
  res = pr_fsio_lremovexattr(p, path, NULL);
1✔
1844
  ck_assert_msg(res < 0, "Failed to handle null attribute name");
1✔
1845
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
1846
    strerror(errno), errno);
1✔
1847

1848
  name = "foo.bar";
1849

1✔
1850
  fsio_opts = pr_fsio_set_options(PR_FSIO_OPT_IGNORE_XATTR);
1851
  res = pr_fsio_lremovexattr(p, path, name);
1✔
1852
  ck_assert_msg(res < 0, "Failed to handle disabled xattr");
1✔
1853
  ck_assert_msg(errno == ENOSYS, "Expected ENOSYS (%d), got %s (%d)", ENOSYS,
1✔
1854
    strerror(errno), errno);
1✔
1855

1856
  pr_fsio_set_options(fsio_opts);
1857
  res = pr_fsio_lremovexattr(p, path, name);
1✔
1858
#ifdef PR_USE_XATTR
1✔
1859
  ck_assert_msg(res < 0, "Failed to handle nonexistent attribute '%s'", name);
1860
  ck_assert_msg(errno == ENOENT || errno == ENOATTR || errno == ENOTSUP,
1✔
1861
    "Expected ENOENT (%d), ENOATTR (%d) or ENOTSUP (%d), got %s (%d)",
1✔
1862
    ENOENT, ENOATTR, ENOTSUP, strerror(errno), errno);
1863

1864
#else
1865
  ck_assert_msg(res < 0, "Failed to handle --disable-xattr");
1866
  ck_assert_msg(errno == ENOSYS, "Expected ENOSYS (%d), got %s (%d)", ENOSYS,
1867
    strerror(errno), errno);
1868
#endif /* PR_USE_XATTR */
1869
}
1870
END_TEST
1✔
1871

1872
START_TEST (fsio_sys_fremovexattr_test) {
1873
  int res;
1✔
1874
  pr_fh_t *fh;
1✔
1875
  const char *name;
1✔
1876
  unsigned long fsio_opts;
1✔
1877

1✔
1878
  res = pr_fsio_fremovexattr(NULL, NULL, NULL);
1879
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
1880
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
1881
    strerror(errno), errno);
1✔
1882

1883
  res = pr_fsio_fremovexattr(p, NULL, NULL);
1884
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
1885
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
1886
    strerror(errno), errno);
1✔
1887

1888
  (void) unlink(fsio_test_path);
1889
  fh = pr_fsio_open(fsio_test_path, O_CREAT|O_EXCL|O_RDWR);
1✔
1890
  ck_assert_msg(fh != NULL, "Failed to open '%s': %s", fsio_test_path,
1✔
1891
    strerror(errno));
1✔
1892

1893
  res = pr_fsio_fremovexattr(p, fh, NULL);
1894
  ck_assert_msg(res < 0, "Failed to handle null attribute name");
1✔
1895
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
1896
    strerror(errno), errno);
1✔
1897

1898
  name = "foo.bar";
1899

1✔
1900
  fsio_opts = pr_fsio_set_options(PR_FSIO_OPT_IGNORE_XATTR);
1901
  res = pr_fsio_fremovexattr(p, fh, name);
1✔
1902
  ck_assert_msg(res < 0, "Failed to handle disabled xattr");
1✔
1903
  ck_assert_msg(errno == ENOSYS, "Expected ENOSYS (%d), got %s (%d)", ENOSYS,
1✔
1904
    strerror(errno), errno);
1✔
1905

1906
  pr_fsio_set_options(fsio_opts);
1907
  res = pr_fsio_fremovexattr(p, fh, name);
1✔
1908
#ifdef PR_USE_XATTR
1✔
1909
  ck_assert_msg(res < 0, "Failed to handle nonexistent attribute '%s'", name);
1910
  ck_assert_msg(errno == ENOENT || errno == ENOATTR || errno == ENOTSUP,
1✔
1911
    "Expected ENOENT (%d), ENOATTR (%d) or ENOTSUP (%d), got %s (%d)",
1✔
1912
    ENOENT, ENOATTR, ENOTSUP, strerror(errno), errno);
1913

1914
#else
1915
  ck_assert_msg(res < 0, "Failed to handle --disable-xattr");
1916
  ck_assert_msg(errno == ENOSYS, "Expected ENOSYS (%d), got %s (%d)", ENOSYS,
1917
    strerror(errno), errno);
1918
#endif /* PR_USE_XATTR */
1919

1920
  pr_fsio_close(fh);
1921
  (void) unlink(fsio_test_path);
1✔
1922
}
1✔
1923
END_TEST
1✔
1924

1925
START_TEST (fsio_sys_setxattr_test) {
1926
  int res, flags;
1✔
1927
  const char *path, *name;
1✔
1928
  pr_fh_t *fh;
1✔
1929
  unsigned long fsio_opts;
1✔
1930

1✔
1931
  res = pr_fsio_setxattr(NULL, NULL, NULL, NULL, 0, 0);
1932
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
1933
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
1934
    strerror(errno), errno);
1✔
1935

1936
  res = pr_fsio_setxattr(p, NULL, NULL, NULL, 0, 0);
1937
  ck_assert_msg(res < 0, "Failed to handle null path");
1✔
1938
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
1939
    strerror(errno), errno);
1✔
1940

1941
  path = fsio_test_path;
1942
  res = pr_fsio_setxattr(p, path, NULL, NULL, 0, 0);
1✔
1943
  ck_assert_msg(res < 0, "Failed to handle null attribute name");
1✔
1944
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
1945
    strerror(errno), errno);
1✔
1946

1947
  name = "foo.bar";
1948
  flags = PR_FSIO_XATTR_FL_CREATE;
1✔
1949

1✔
1950
  fsio_opts = pr_fsio_set_options(PR_FSIO_OPT_IGNORE_XATTR);
1951
  res = pr_fsio_setxattr(p, path, name, NULL, 0, flags);
1✔
1952
  ck_assert_msg(res < 0, "Failed to handle disabled xattr");
1✔
1953
  ck_assert_msg(errno == ENOSYS, "Expected ENOSYS (%d), got %s (%d)", ENOSYS,
1✔
1954
    strerror(errno), errno);
1✔
1955

1956
  pr_fsio_set_options(fsio_opts);
1957
  res = pr_fsio_setxattr(p, path, name, NULL, 0, flags);
1✔
1958
#ifdef PR_USE_XATTR
1✔
1959
  ck_assert_msg(res < 0, "Failed to handle nonexistent file '%s'", path);
1960
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
1✔
1961
    strerror(errno), errno);
1✔
1962

1963
  (void) unlink(fsio_test_path);
1964
  fh = pr_fsio_open(fsio_test_path, O_CREAT|O_EXCL|O_WRONLY);
1✔
1965
  ck_assert_msg(fh != NULL, "Failed to open '%s': %s", fsio_test_path,
1✔
1966
    strerror(errno));
1✔
1967
  pr_fsio_close(fh);
1968

1✔
1969
  res = pr_fsio_setxattr(p, path, name, NULL, 0, flags);
1970
  if (res < 0) {
1✔
1971
    ck_assert_msg(errno == ENOTSUP, "Expected ENOTSUP (%d), got %s (%d)", ENOTSUP,
1✔
1972
      strerror(errno), errno);
1✔
1973
  }
1974

1975
  (void) unlink(fsio_test_path);
1976
#else
1✔
1977
  (void) fh;
1978
  ck_assert_msg(res < 0, "Failed to handle --disable-xattr");
1979
  ck_assert_msg(errno == ENOSYS, "Expected ENOSYS (%d), got %s (%d)", ENOSYS,
1980
    strerror(errno), errno);
1981
#endif /* PR_USE_XATTR */
1982
}
1983
END_TEST
1✔
1984

1985
START_TEST (fsio_sys_lsetxattr_test) {
1986
  int res, flags;
1✔
1987
  const char *path, *name;
1✔
1988
  pr_fh_t *fh;
1✔
1989
  unsigned long fsio_opts;
1✔
1990

1✔
1991
  res = pr_fsio_lsetxattr(NULL, NULL, NULL, NULL, 0, 0);
1992
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
1993
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
1994
    strerror(errno), errno);
1✔
1995

1996
  res = pr_fsio_lsetxattr(p, NULL, NULL, NULL, 0, 0);
1997
  ck_assert_msg(res < 0, "Failed to handle null path");
1✔
1998
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
1999
    strerror(errno), errno);
1✔
2000

2001
  path = fsio_test_path;
2002
  res = pr_fsio_lsetxattr(p, path, NULL, NULL, 0, 0);
1✔
2003
  ck_assert_msg(res < 0, "Failed to handle null attribute name");
1✔
2004
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
2005
    strerror(errno), errno);
1✔
2006

2007
  name = "foo.bar";
2008
  flags = PR_FSIO_XATTR_FL_CREATE;
1✔
2009

1✔
2010
  fsio_opts = pr_fsio_set_options(PR_FSIO_OPT_IGNORE_XATTR);
2011
  res = pr_fsio_lsetxattr(p, path, name, NULL, 0, flags);
1✔
2012
  ck_assert_msg(res < 0, "Failed to handle disabled xattr");
1✔
2013
  ck_assert_msg(errno == ENOSYS, "Expected ENOSYS (%d), got %s (%d)", ENOSYS,
1✔
2014
    strerror(errno), errno);
1✔
2015

2016
  pr_fsio_set_options(fsio_opts);
2017
  res = pr_fsio_lsetxattr(p, path, name, NULL, 0, flags);
1✔
2018
#ifdef PR_USE_XATTR
1✔
2019
  ck_assert_msg(res < 0, "Failed to handle nonexistent file '%s'", path);
2020
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
1✔
2021
    strerror(errno), errno);
1✔
2022

2023
  (void) unlink(fsio_test_path);
2024
  fh = pr_fsio_open(fsio_test_path, O_CREAT|O_EXCL|O_WRONLY);
1✔
2025
  ck_assert_msg(fh != NULL, "Failed to open '%s': %s", fsio_test_path,
1✔
2026
    strerror(errno));
1✔
2027
  pr_fsio_close(fh);
2028

1✔
2029
  res = pr_fsio_lsetxattr(p, path, name, NULL, 0, flags);
2030
  if (res < 0) {
1✔
2031
    ck_assert_msg(errno == ENOTSUP, "Expected ENOTSUP (%d), got %s (%d)", ENOTSUP,
1✔
2032
      strerror(errno), errno);
1✔
2033
  }
2034

2035
  (void) unlink(fsio_test_path);
2036
#else
1✔
2037
  (void) fh;
2038
  ck_assert_msg(res < 0, "Failed to handle --disable-xattr");
2039
  ck_assert_msg(errno == ENOSYS, "Expected ENOSYS (%d), got %s (%d)", ENOSYS,
2040
    strerror(errno), errno);
2041
#endif /* PR_USE_XATTR */
2042
}
2043
END_TEST
1✔
2044

2045
START_TEST (fsio_sys_fsetxattr_test) {
2046
  int res, flags;
1✔
2047
  pr_fh_t *fh;
1✔
2048
  const char *name;
1✔
2049
  unsigned long fsio_opts;
1✔
2050

1✔
2051
  res = pr_fsio_fsetxattr(NULL, NULL, NULL, NULL, 0, 0);
2052
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
2053
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
2054
    strerror(errno), errno);
1✔
2055

2056
  res = pr_fsio_fsetxattr(p, NULL, NULL, NULL, 0, 0);
2057
  ck_assert_msg(res < 0, "Failed to handle null file handle");
1✔
2058
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
2059
    strerror(errno), errno);
1✔
2060

2061
  (void) unlink(fsio_test_path);
2062
  fh = pr_fsio_open(fsio_test_path, O_CREAT|O_EXCL|O_RDWR);
1✔
2063
  ck_assert_msg(fh != NULL, "Failed to open '%s': %s", fsio_test_path,
1✔
2064
    strerror(errno));
1✔
2065

2066
  res = pr_fsio_fsetxattr(p, fh, NULL, NULL, 0, 0);
2067
  ck_assert_msg(res < 0, "Failed to handle null attribute name");
1✔
2068
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
2069
    strerror(errno), errno);
1✔
2070

2071
  name = "foo.bar";
2072
  flags = PR_FSIO_XATTR_FL_CREATE;
1✔
2073

1✔
2074
  fsio_opts = pr_fsio_set_options(PR_FSIO_OPT_IGNORE_XATTR);
2075
  res = pr_fsio_fsetxattr(p, fh, name, NULL, 0, flags);
1✔
2076
  ck_assert_msg(res < 0, "Failed to handle disabled xattr");
1✔
2077
  ck_assert_msg(errno == ENOSYS, "Expected ENOSYS (%d), got %s (%d)", ENOSYS,
1✔
2078
    strerror(errno), errno);
1✔
2079

2080
  pr_fsio_set_options(fsio_opts);
2081
  res = pr_fsio_fsetxattr(p, fh, name, NULL, 0, flags);
1✔
2082
#ifdef PR_USE_XATTR
1✔
2083
  if (res < 0) {
2084
    ck_assert_msg(errno == ENOTSUP, "Expected ENOTSUP (%d), got %s (%d)", ENOTSUP,
1✔
2085
      strerror(errno), errno);
1✔
2086
  }
2087

2088
#else
2089
  ck_assert_msg(res < 0, "Failed to handle --disable-xattr");
2090
  ck_assert_msg(errno == ENOSYS, "Expected ENOSYS (%d), got %s (%d)", ENOSYS,
2091
    strerror(errno), errno);
2092
#endif /* PR_USE_XATTR */
2093

2094
  pr_fsio_close(fh);
2095
  (void) unlink(fsio_test_path);
1✔
2096
}
1✔
2097
END_TEST
1✔
2098

2099
START_TEST (fsio_sys_mkdir_test) {
2100
  int res;
1✔
2101
  mode_t mode = 0755;
1✔
2102

1✔
2103
  res = pr_fsio_mkdir(NULL, mode);
2104
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
2105
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
2106
    strerror(errno), errno);
1✔
2107

2108
  res = pr_fsio_mkdir(fsio_testdir_path, mode);
2109
  ck_assert_msg(res == 0, "Failed to create '%s': %s", fsio_testdir_path,
1✔
2110
    strerror(errno));
1✔
2111

2112
  (void) pr_fsio_rmdir(fsio_testdir_path);
2113
}
1✔
2114
END_TEST
1✔
2115

2116
START_TEST (fsio_sys_mkdir_chroot_guard_test) {
2117
  int res;
1✔
2118
  mode_t mode = 0755;
1✔
2119

1✔
2120
  res = pr_fsio_guard_chroot(TRUE);
2121
  ck_assert_msg(res == FALSE, "Expected FALSE (%d), got %d", FALSE, res);
1✔
2122

1✔
2123
  res = pr_fsio_mkdir("/etc/foo.bar.baz.d", mode);
2124
  ck_assert_msg(res < 0, "Created /etc/foo.bar.baz.d unexpectedly");
1✔
2125
  ck_assert_msg(errno == EACCES, "Expected EACCES (%d), got %s %d", EACCES,
1✔
2126
    strerror(errno), errno);
1✔
2127

2128
  (void) pr_fsio_guard_chroot(FALSE);
2129

1✔
2130
  res = pr_fsio_mkdir("/lib/foo/bar/baz.d", mode);
2131
  ck_assert_msg(res < 0, "Created /lib/foo/bar/baz.d unexpectedly");
1✔
2132
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), got %s %d", ENOENT,
1✔
2133
    strerror(errno), errno);
1✔
2134
}
2135
END_TEST
1✔
2136

2137
START_TEST (fsio_sys_rmdir_test) {
2138
  int res;
1✔
2139
  mode_t mode = 0755;
1✔
2140

1✔
2141
  res = pr_fsio_rmdir(NULL);
2142
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
2143
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
2144
    strerror(errno), errno);
1✔
2145

2146
  res = pr_fsio_rmdir(fsio_testdir_path);
2147
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
2148
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
1✔
2149
    strerror(errno), errno);
1✔
2150

2151
  res = pr_fsio_mkdir(fsio_testdir_path, mode);
2152
  ck_assert_msg(res == 0, "Failed to create '%s': %s", fsio_testdir_path,
1✔
2153
    strerror(errno));
1✔
2154

2155
  res = pr_fsio_rmdir(fsio_testdir_path);
2156
  ck_assert_msg(res == 0, "Failed to remove '%s': %s", fsio_testdir_path,
1✔
2157
    strerror(errno));
1✔
2158
}
2159
END_TEST
1✔
2160

2161
START_TEST (fsio_sys_rmdir_chroot_guard_test) {
2162
  int res;
1✔
2163

1✔
2164
  res = pr_fsio_guard_chroot(TRUE);
2165
  ck_assert_msg(res == FALSE, "Expected FALSE (%d), got %d", FALSE, res);
1✔
2166

1✔
2167
  res = pr_fsio_rmdir("/etc/foo.bar.baz.d");
2168
  ck_assert_msg(res < 0, "Removed /etc/foo.bar.baz.d unexpectedly");
1✔
2169
  ck_assert_msg(errno == EACCES, "Expected EACCES (%d), got %s %d", EACCES,
1✔
2170
    strerror(errno), errno);
1✔
2171

2172
  (void) pr_fsio_guard_chroot(FALSE);
2173

1✔
2174
  res = pr_fsio_rmdir("/lib/foo/bar/baz.d");
2175
  ck_assert_msg(res < 0, "Removed /lib/etc/foo.bar.baz.d unexpectedly");
1✔
2176
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), got %s %d", ENOENT,
1✔
2177
    strerror(errno), errno);
1✔
2178
}
2179
END_TEST
1✔
2180

2181
START_TEST (fsio_sys_chdir_test) {
2182
  int res;
1✔
2183

1✔
2184
  res = pr_fsio_chdir(NULL, FALSE);
2185
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
2186
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
2187
    strerror(errno), errno);
1✔
2188

2189
  res = pr_fsio_chdir("/etc/hosts", FALSE);
2190
  ck_assert_msg(res < 0, "Failed to handle file argument");
1✔
2191
  ck_assert_msg(errno == EINVAL || errno == ENOTDIR,
1✔
2192
    "Expected EINVAL (%d) or ENOTDIR (%d), got %s (%d)", EINVAL, ENOTDIR,
1✔
2193
    strerror(errno), errno);
2194

2195
  res = pr_fsio_chdir("/tmp", FALSE);
2196
  ck_assert_msg(res == 0, "Failed to chdir to '%s': %s", fsio_cwd,
1✔
2197
    strerror(errno));
1✔
2198

2199
  res = pr_fsio_chdir(fsio_cwd, FALSE);
2200
  ck_assert_msg(res == 0, "Failed to chdir to '%s': %s", fsio_cwd,
1✔
2201
    strerror(errno));
1✔
2202
}
2203
END_TEST
1✔
2204

2205
START_TEST (fsio_sys_chdir_canon_test) {
2206
  int res;
1✔
2207

1✔
2208
  res = pr_fsio_chdir_canon(NULL, FALSE);
2209
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
2210
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
2211
    strerror(errno), errno);
1✔
2212

2213
  res = pr_fsio_chdir_canon("/tmp", FALSE);
2214
  ck_assert_msg(res == 0, "Failed to chdir to '%s': %s", fsio_cwd,
1✔
2215
    strerror(errno));
1✔
2216

2217
  res = pr_fsio_chdir_canon(fsio_cwd, FALSE);
2218
  ck_assert_msg(res == 0, "Failed to chdir to '%s': %s", fsio_cwd,
1✔
2219
    strerror(errno));
1✔
2220
}
2221
END_TEST
1✔
2222

2223
START_TEST (fsio_sys_chroot_test) {
2224
  int res;
1✔
2225

1✔
2226
  res = pr_fsio_chroot(NULL);
2227
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
2228
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
2229
    strerror(errno), errno);
1✔
2230

2231
  if (getuid() != 0) {
2232
    res = pr_fsio_chroot("/tmp");
1✔
2233
    ck_assert_msg(res < 0, "Failed to chroot without root privs");
×
2234
    ck_assert_msg(errno == EPERM, "Expected EPERM (%d), got %s (%d)", EPERM,
×
2235
      strerror(errno), errno);
×
2236
  }
2237
}
2238
END_TEST
1✔
2239

2240
START_TEST (fsio_sys_opendir_test) {
2241
  void *res = NULL, *res2 = NULL;
1✔
2242
  const char *path;
1✔
2243

1✔
2244
  mark_point();
2245
  res = pr_fsio_opendir(NULL);
1✔
2246
  ck_assert_msg(res == NULL, "Failed to handle null arguments");
1✔
2247
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
2248
    strerror(errno), errno);
1✔
2249

2250
  mark_point();
2251
  path = "/etc/hosts";
1✔
2252
  res = pr_fsio_opendir(path);
1✔
2253
  ck_assert_msg(res == NULL, "Failed to handle file argument");
1✔
2254
  ck_assert_msg(errno == ENOTDIR, "Expected ENOTDIR (%d), got %s (%d)", ENOTDIR,
1✔
2255
    strerror(errno), errno);
1✔
2256

2257
  mark_point();
2258
  path = "/tmp/";
1✔
2259
  res = pr_fsio_opendir(path);
1✔
2260
  ck_assert_msg(res != NULL, "Failed to open '%s': %s", path, strerror(errno));
1✔
2261

1✔
2262
  mark_point();
2263
  path = "/usr/";
1✔
2264
  res2 = pr_fsio_opendir(path);
1✔
2265
  ck_assert_msg(res != NULL, "Failed to open '%s': %s", path, strerror(errno));
1✔
2266

1✔
2267
  (void) pr_fsio_closedir(res);
2268
  (void) pr_fsio_closedir(res2);
1✔
2269
}
1✔
2270
END_TEST
1✔
2271

2272
START_TEST (fsio_sys_readdir_test) {
2273
  void *dirh;
1✔
2274
  struct dirent *dent;
1✔
2275

1✔
2276
  dent = pr_fsio_readdir(NULL);
2277
  ck_assert_msg(dent == NULL, "Failed to handle null arguments");
1✔
2278
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
2279
    strerror(errno), errno);
1✔
2280

2281
  dent = pr_fsio_readdir("/etc/hosts");
2282
  ck_assert_msg(dent == NULL, "Failed to handle file argument");
1✔
2283
  ck_assert_msg(errno == ENOTDIR, "Expected ENOTDIR (%d), got %s (%d)", ENOTDIR,
1✔
2284
    strerror(errno), errno);
1✔
2285

2286
  mark_point();
2287
  dirh = pr_fsio_opendir("/tmp/");
1✔
2288
  ck_assert_msg(dirh != NULL, "Failed to open '/tmp/': %s", strerror(errno));
1✔
2289

1✔
2290
  dent = pr_fsio_readdir(dirh);
2291
  ck_assert_msg(dent != NULL, "Failed to read directory entry: %s",
1✔
2292
    strerror(errno));
1✔
2293

2294
  (void) pr_fsio_closedir(dirh);
2295
}
1✔
2296
END_TEST
1✔
2297

2298
START_TEST (fsio_sys_closedir_test) {
2299
  void *dirh;
1✔
2300
  int res;
1✔
2301

1✔
2302
  res = pr_fsio_closedir(NULL);
2303
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
2304
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
2305
    strerror(errno), errno);
1✔
2306

2307
  dirh = pr_fsio_opendir("/tmp/");
2308
  ck_assert_msg(dirh != NULL, "Failed to open '/tmp/': %s", strerror(errno));
1✔
2309

1✔
2310
  res = pr_fsio_closedir(dirh);
2311
  ck_assert_msg(res == 0, "Failed to close '/tmp/': %s", strerror(errno));
1✔
2312

1✔
2313
  /* Closing an already-closed directory descriptor should fail. */
2314
  res = pr_fsio_closedir(dirh);
2315
  ck_assert_msg(res < 0, "Failed to handle already-closed directory handle");
1✔
2316
  ck_assert_msg(errno == ENOTDIR, "Expected ENOTDIR (%d), got %s (%d)", ENOTDIR,
1✔
2317
    strerror(errno), errno);
1✔
2318
}
2319
END_TEST
1✔
2320

2321
static const char *test_chmod_explainer(pool *err_pool, int xerrno,
2322
    const char *path, mode_t mode, const char **args) {
1✔
2323
  *args = pstrdup(err_pool, "fake args");
2324
  return pstrdup(err_pool, "test mode is not real");
1✔
2325
}
1✔
2326

2327
START_TEST (fsio_sys_chmod_with_error_test) {
2328
  int res;
1✔
2329
  pr_error_t *err = NULL;
1✔
2330
  const char *errstr, *expected;
1✔
2331
  module m;
1✔
2332
  pr_error_explainer_t *explainer;
1✔
2333

1✔
2334
  mark_point();
2335
  res = pr_fsio_chmod_with_error(NULL, fsio_test_path, 0755, NULL);
1✔
2336
  ck_assert_msg(res < 0, "Failed to handle non-existent file '%s'",
1✔
2337
    fsio_test_path);
1✔
2338
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), %s (%d)", ENOENT,
2339
    strerror(errno), errno);
1✔
2340

2341
  mark_point();
2342
  res = pr_fsio_chmod_with_error(p, fsio_test_path, 0755, &err);
1✔
2343
  ck_assert_msg(res < 0, "Failed to handle non-existent file '%s'",
1✔
2344
    fsio_test_path);
1✔
2345
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), %s (%d)", ENOENT,
2346
    strerror(errno), errno);
1✔
2347
  ck_assert_msg(err == NULL, "Unexpectedly populated error");
2348

1✔
2349
  memset(&m, 0, sizeof(m));
2350
  m.name = "error";
1✔
2351

1✔
2352
  explainer = pr_error_register_explainer(p, &m, "error");
2353
  explainer->explain_chmod = test_chmod_explainer;
1✔
2354

1✔
2355
  mark_point();
2356
  res = pr_fsio_chmod_with_error(p, fsio_test_path, 0755, &err);
1✔
2357
  ck_assert_msg(res < 0, "Failed to handle non-existent file '%s'",
1✔
2358
    fsio_test_path);
1✔
2359
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), %s (%d)", ENOENT,
2360
    strerror(errno), errno);
1✔
2361
  ck_assert_msg(err != NULL, "Failed to populate error");
2362

1✔
2363
  expected = pstrcat(p,
2364
    "chmod() failed with \"No such file or directory [ENOENT (",
1✔
2365
    get_errnum(p, ENOENT), ")]\"", NULL);
2366
  errstr = pr_error_strerror(err, PR_ERROR_FORMAT_USE_MINIMAL);
2367
  ck_assert_msg(strcmp(errstr, expected) == 0, "Expected '%s', got '%s'",
1✔
2368
    expected, errstr);
1✔
2369

2370
  (void) pr_error_unregister_explainer(p, &m, NULL);
2371
  pr_error_destroy(err);
1✔
2372
}
1✔
2373
END_TEST
1✔
2374

2375
static const char *test_chown_explainer(pool *err_pool, int xerrno,
2376
    const char *path, uid_t uid, gid_t gid, const char **args) {
1✔
2377
  *args = pstrdup(err_pool, "fake args");
2378
  return pstrdup(err_pool, "test mode is not real");
1✔
2379
}
1✔
2380

2381
START_TEST (fsio_sys_chown_with_error_test) {
2382
  int res;
1✔
2383
  pr_error_t *err = NULL;
1✔
2384
  const char *errstr, *expected;
1✔
2385
  module m;
1✔
2386
  pr_error_explainer_t *explainer;
1✔
2387

1✔
2388
  mark_point();
2389
  res = pr_fsio_chown_with_error(NULL, fsio_test_path, 1, 1, NULL);
1✔
2390
  ck_assert_msg(res < 0, "Failed to handle non-existent file '%s'",
1✔
2391
    fsio_test_path);
1✔
2392
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), %s (%d)", ENOENT,
2393
    strerror(errno), errno);
1✔
2394

2395
  mark_point();
2396
  res = pr_fsio_chown_with_error(p, fsio_test_path, 1, 1, &err);
1✔
2397
  ck_assert_msg(res < 0, "Failed to handle non-existent file '%s'",
1✔
2398
    fsio_test_path);
1✔
2399
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), %s (%d)", ENOENT,
2400
    strerror(errno), errno);
1✔
2401
  ck_assert_msg(err == NULL, "Unexpectedly populated error");
2402

1✔
2403
  memset(&m, 0, sizeof(m));
2404
  m.name = "error";
1✔
2405

1✔
2406
  explainer = pr_error_register_explainer(p, &m, "error");
2407
  explainer->explain_chown = test_chown_explainer;
1✔
2408

1✔
2409
  mark_point();
2410
  res = pr_fsio_chown_with_error(p, fsio_test_path, 1, 1, &err);
1✔
2411
  ck_assert_msg(res < 0, "Failed to handle non-existent file '%s'",
1✔
2412
    fsio_test_path);
1✔
2413
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), %s (%d)", ENOENT,
2414
    strerror(errno), errno);
1✔
2415
  ck_assert_msg(err != NULL, "Failed to populate error");
2416

1✔
2417
  expected = pstrcat(p,
2418
    "chown() failed with \"No such file or directory [ENOENT (",
1✔
2419
    get_errnum(p, ENOENT), ")]\"", NULL);
2420
  errstr = pr_error_strerror(err, PR_ERROR_FORMAT_USE_MINIMAL);
2421
  ck_assert_msg(strcmp(errstr, expected) == 0, "Expected '%s', got '%s'",
1✔
2422
    expected, errstr);
1✔
2423

2424
  (void) pr_error_unregister_explainer(p, &m, NULL);
2425
  pr_error_destroy(err);
1✔
2426
}
1✔
2427
END_TEST
1✔
2428

2429
static const char *test_chroot_explainer(pool *err_pool, int xerrno,
2430
    const char *path, const char **args) {
1✔
2431
  *args = pstrdup(err_pool, "fake args");
2432
  return pstrdup(err_pool, "test mode is not real");
1✔
2433
}
1✔
2434

2435
START_TEST (fsio_sys_chroot_with_error_test) {
2436
  int res, xerrno = 0;
1✔
2437
  pr_error_t *err = NULL;
1✔
2438
  const char *errstr, *expected;
1✔
2439
  module m;
1✔
2440
  pr_error_explainer_t *explainer;
1✔
2441

1✔
2442
  mark_point();
2443
  res = pr_fsio_chroot_with_error(NULL, fsio_testdir_path, NULL);
1✔
2444
  ck_assert_msg(res < 0, "Failed to handle non-existent file '%s'",
1✔
2445
    fsio_testdir_path);
1✔
2446
  ck_assert_msg(errno == EPERM || errno == ENOENT,
2447
    "Expected EPERM (%d) or ENOENT (%d), %s (%d)", EPERM, ENOENT,
1✔
2448
    strerror(errno), errno);
2449

2450
  mark_point();
2451
  res = pr_fsio_chroot_with_error(p, fsio_testdir_path, &err);
1✔
2452
  xerrno = errno;
1✔
2453
  ck_assert_msg(res < 0, "Failed to handle non-existent file '%s'",
1✔
2454
    fsio_testdir_path);
1✔
2455
  ck_assert_msg(errno == EPERM || errno == ENOENT,
2456
    "Expected EPERM (%d) or ENOENT (%d), %s (%d)", EPERM, ENOENT,
1✔
2457
    strerror(errno), errno);
2458
  ck_assert_msg(err == NULL, "Unexpectedly populated error");
2459

1✔
2460
  memset(&m, 0, sizeof(m));
2461
  m.name = "error";
1✔
2462

1✔
2463
  explainer = pr_error_register_explainer(p, &m, "error");
2464
  explainer->explain_chroot = test_chroot_explainer;
1✔
2465

1✔
2466
  mark_point();
2467
  res = pr_fsio_chroot_with_error(p, fsio_testdir_path, &err);
1✔
2468
  xerrno = errno;
1✔
2469
  ck_assert_msg(res < 0, "Failed to handle non-existent file '%s'",
1✔
2470
    fsio_testdir_path);
1✔
2471
  ck_assert_msg(errno == EPERM || errno == ENOENT,
2472
    "Expected EPERM (%d) or ENOENT (%d), %s (%d)", EPERM, ENOENT,
1✔
2473
    strerror(errno), errno);
2474
  ck_assert_msg(err != NULL, "Failed to populate error");
2475

1✔
2476
  expected = pstrcat(p,
2477
    "chroot() failed with \"", strerror(xerrno), " [",
1✔
2478
    xerrno == ENOENT ? "ENOENT" : "EPERM", " (",
2479
    get_errnum(p, xerrno), ")]\"", NULL);
2480
  errstr = pr_error_strerror(err, PR_ERROR_FORMAT_USE_MINIMAL);
2481
  ck_assert_msg(strcmp(errstr, expected) == 0, "Expected '%s', got '%s'",
1✔
2482
    expected, errstr);
1✔
2483

2484
  (void) pr_error_unregister_explainer(p, &m, NULL);
2485
  pr_error_destroy(err);
1✔
2486
}
1✔
2487
END_TEST
1✔
2488

2489
static const char *test_close_explainer(pool *err_pool, int xerrno, int fd,
2490
    const char **args) {
1✔
2491
  *args = pstrdup(err_pool, "fake args");
2492
  return pstrdup(err_pool, "test mode is not real");
1✔
2493
}
1✔
2494

2495
START_TEST (fsio_sys_close_with_error_test) {
2496
  int res;
1✔
2497
  pr_error_t *err = NULL;
1✔
2498
  const char *errstr, *expected;
1✔
2499
  module m;
1✔
2500
  pr_error_explainer_t *explainer;
1✔
2501

1✔
2502
  mark_point();
2503
  res = pr_fsio_close_with_error(NULL, NULL, NULL);
1✔
2504
  ck_assert_msg(res < 0, "Failed to handle null fh");
1✔
2505
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), %s (%d)", EINVAL,
1✔
2506
    strerror(errno), errno);
1✔
2507

2508
  mark_point();
2509
  res = pr_fsio_close_with_error(p, NULL, &err);
1✔
2510
  ck_assert_msg(res < 0, "Failed to handle null fh");
1✔
2511
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), %s (%d)", EINVAL,
1✔
2512
    strerror(errno), errno);
1✔
2513
  ck_assert_msg(err == NULL, "Unexpectedly populated error");
2514

1✔
2515
  memset(&m, 0, sizeof(m));
2516
  m.name = "error";
1✔
2517

1✔
2518
  explainer = pr_error_register_explainer(p, &m, "error");
2519
  explainer->explain_close = test_close_explainer;
1✔
2520

1✔
2521
  mark_point();
2522
  res = pr_fsio_close_with_error(p, NULL, &err);
1✔
2523
  ck_assert_msg(res < 0, "Failed to handle null fh");
1✔
2524
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), %s (%d)", EINVAL,
1✔
2525
    strerror(errno), errno);
1✔
2526
  ck_assert_msg(err != NULL, "Failed to populate error");
2527

1✔
2528
  expected = pstrcat(p,
2529
    "close() failed with \"Invalid argument [EINVAL (",
1✔
2530
    get_errnum(p, EINVAL), ")]\"", NULL);
2531
  errstr = pr_error_strerror(err, PR_ERROR_FORMAT_USE_MINIMAL);
2532
  ck_assert_msg(strcmp(errstr, expected) == 0, "Expected '%s', got '%s'",
1✔
2533
    expected, errstr);
1✔
2534

2535
  (void) pr_error_unregister_explainer(p, &m, NULL);
2536
  pr_error_destroy(err);
1✔
2537
}
1✔
2538
END_TEST
1✔
2539

2540
static const char *test_fchmod_explainer(pool *err_pool, int xerrno, int fd,
2541
    mode_t mode, const char **args) {
1✔
2542
  *args = pstrdup(err_pool, "fake args");
2543
  return pstrdup(err_pool, "test mode is not real");
1✔
2544
}
1✔
2545

2546
START_TEST (fsio_sys_fchmod_with_error_test) {
2547
  int res;
1✔
2548
  pr_error_t *err = NULL;
1✔
2549
  const char *errstr, *expected;
1✔
2550
  module m;
1✔
2551
  pr_error_explainer_t *explainer;
1✔
2552

1✔
2553
  mark_point();
2554
  res = pr_fsio_fchmod_with_error(NULL, NULL, 0755, NULL);
1✔
2555
  ck_assert_msg(res < 0, "Failed to handle null fh");
1✔
2556
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), %s (%d)", EINVAL,
1✔
2557
    strerror(errno), errno);
1✔
2558

2559
  mark_point();
2560
  res = pr_fsio_fchmod_with_error(p, NULL, 0755, &err);
1✔
2561
  ck_assert_msg(res < 0, "Failed to handle null fh");
1✔
2562
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), %s (%d)", EINVAL,
1✔
2563
    strerror(errno), errno);
1✔
2564
  ck_assert_msg(err == NULL, "Unexpectedly populated error");
2565

1✔
2566
  memset(&m, 0, sizeof(m));
2567
  m.name = "error";
1✔
2568

1✔
2569
  explainer = pr_error_register_explainer(p, &m, "error");
2570
  explainer->explain_fchmod = test_fchmod_explainer;
1✔
2571

1✔
2572
  mark_point();
2573
  res = pr_fsio_fchmod_with_error(p, NULL, 0755, &err);
1✔
2574
  ck_assert_msg(res < 0, "Failed to handle null fh");
1✔
2575
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), %s (%d)", EINVAL,
1✔
2576
    strerror(errno), errno);
1✔
2577
  ck_assert_msg(err != NULL, "Failed to populate error");
2578

1✔
2579
  expected = pstrcat(p,
2580
    "fchmod() failed with \"Invalid argument [EINVAL (",
1✔
2581
    get_errnum(p, EINVAL), ")]\"", NULL);
2582
  errstr = pr_error_strerror(err, PR_ERROR_FORMAT_USE_MINIMAL);
2583
  ck_assert_msg(strcmp(errstr, expected) == 0, "Expected '%s', got '%s'",
1✔
2584
    expected, errstr);
1✔
2585

2586
  (void) pr_error_unregister_explainer(p, &m, NULL);
2587
  pr_error_destroy(err);
1✔
2588
}
1✔
2589
END_TEST
1✔
2590

2591
static const char *test_fchown_explainer(pool *err_pool, int xerrno, int fd,
2592
    uid_t uid, gid_t gid, const char **args) {
1✔
2593
  *args = pstrdup(err_pool, "fake args");
2594
  return pstrdup(err_pool, "test mode is not real");
1✔
2595
}
1✔
2596

2597
START_TEST (fsio_sys_fchown_with_error_test) {
2598
  int res;
1✔
2599
  pr_error_t *err = NULL;
1✔
2600
  const char *errstr, *expected;
1✔
2601
  module m;
1✔
2602
  pr_error_explainer_t *explainer;
1✔
2603

1✔
2604
  mark_point();
2605
  res = pr_fsio_fchown_with_error(NULL, NULL, 1, 1, NULL);
1✔
2606
  ck_assert_msg(res < 0, "Failed to handle null fh");
1✔
2607
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), %s (%d)", EINVAL,
1✔
2608
    strerror(errno), errno);
1✔
2609

2610
  mark_point();
2611
  res = pr_fsio_fchown_with_error(p, NULL, 1, 1, &err);
1✔
2612
  ck_assert_msg(res < 0, "Failed to handle null fh");
1✔
2613
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), %s (%d)", EINVAL,
1✔
2614
    strerror(errno), errno);
1✔
2615
  ck_assert_msg(err == NULL, "Unexpectedly populated error");
2616

1✔
2617
  memset(&m, 0, sizeof(m));
2618
  m.name = "error";
1✔
2619

1✔
2620
  explainer = pr_error_register_explainer(p, &m, "error");
2621
  explainer->explain_fchown = test_fchown_explainer;
1✔
2622

1✔
2623
  mark_point();
2624
  res = pr_fsio_fchown_with_error(p, NULL, 1, 1, &err);
1✔
2625
  ck_assert_msg(res < 0, "Failed to handle null fh");
1✔
2626
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), %s (%d)", EINVAL,
1✔
2627
    strerror(errno), errno);
1✔
2628
  ck_assert_msg(err != NULL, "Failed to populate error");
2629

1✔
2630
  expected = pstrcat(p,
2631
    "fchown() failed with \"Invalid argument [EINVAL (",
1✔
2632
    get_errnum(p, EINVAL), ")]\"", NULL);
2633
  errstr = pr_error_strerror(err, PR_ERROR_FORMAT_USE_MINIMAL);
2634
  ck_assert_msg(strcmp(errstr, expected) == 0, "Expected '%s', got '%s'",
1✔
2635
    expected, errstr);
1✔
2636

2637
  (void) pr_error_unregister_explainer(p, &m, NULL);
2638
  pr_error_destroy(err);
1✔
2639
}
1✔
2640
END_TEST
1✔
2641

2642
static const char *test_lchown_explainer(pool *err_pool, int xerrno,
2643
    const char *path, uid_t uid, gid_t gid, const char **args) {
1✔
2644
  *args = pstrdup(err_pool, "fake args");
2645
  return pstrdup(err_pool, "test mode is not real");
1✔
2646
}
1✔
2647

2648
START_TEST (fsio_sys_lchown_with_error_test) {
2649
  int res;
1✔
2650
  pr_error_t *err = NULL;
1✔
2651
  const char *errstr, *expected;
1✔
2652
  module m;
1✔
2653
  pr_error_explainer_t *explainer;
1✔
2654

1✔
2655
  mark_point();
2656
  res = pr_fsio_lchown_with_error(NULL, fsio_test_path, 1, 1, NULL);
1✔
2657
  ck_assert_msg(res < 0, "Failed to handle non-existent file '%s'",
1✔
2658
    fsio_test_path);
1✔
2659
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), %s (%d)", ENOENT,
2660
    strerror(errno), errno);
1✔
2661

2662
  mark_point();
2663
  res = pr_fsio_lchown_with_error(p, fsio_test_path, 1, 1, &err);
1✔
2664
  ck_assert_msg(res < 0, "Failed to handle non-existent file '%s'",
1✔
2665
    fsio_test_path);
1✔
2666
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), %s (%d)", ENOENT,
2667
    strerror(errno), errno);
1✔
2668
  ck_assert_msg(err == NULL, "Unexpectedly populated error");
2669

1✔
2670
  memset(&m, 0, sizeof(m));
2671
  m.name = "error";
1✔
2672

1✔
2673
  explainer = pr_error_register_explainer(p, &m, "error");
2674
  explainer->explain_lchown = test_lchown_explainer;
1✔
2675

1✔
2676
  mark_point();
2677
  res = pr_fsio_lchown_with_error(p, fsio_test_path, 1, 1, &err);
1✔
2678
  ck_assert_msg(res < 0, "Failed to handle non-existent file '%s'",
1✔
2679
    fsio_test_path);
1✔
2680
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), %s (%d)", ENOENT,
2681
    strerror(errno), errno);
1✔
2682
  ck_assert_msg(err != NULL, "Failed to populate error");
2683

1✔
2684
  expected = pstrcat(p,
2685
    "lchown() failed with \"No such file or directory [ENOENT (",
1✔
2686
    get_errnum(p, ENOENT), ")]\"", NULL);
2687
  errstr = pr_error_strerror(err, PR_ERROR_FORMAT_USE_MINIMAL);
2688
  ck_assert_msg(strcmp(errstr, expected) == 0, "Expected '%s', got '%s'",
1✔
2689
    expected, errstr);
1✔
2690

2691
  (void) pr_error_unregister_explainer(p, &m, NULL);
2692
  pr_error_destroy(err);
1✔
2693
}
1✔
2694
END_TEST
1✔
2695

2696
static const char *test_lstat_explainer(pool *err_pool, int xerrno,
2697
    const char *path, struct stat *st, const char **args) {
1✔
2698
  *args = pstrdup(err_pool, "fake args");
2699
  return pstrdup(err_pool, "test mode is not real");
1✔
2700
}
1✔
2701

2702
START_TEST (fsio_sys_lstat_with_error_test) {
2703
  int res;
1✔
2704
  struct stat st;
1✔
2705
  pr_error_t *err = NULL;
1✔
2706
  const char *errstr, *expected;
1✔
2707
  module m;
1✔
2708
  pr_error_explainer_t *explainer;
1✔
2709

1✔
2710
  mark_point();
2711
  res = pr_fsio_lstat_with_error(NULL, fsio_test_path, &st, NULL);
1✔
2712
  ck_assert_msg(res < 0, "Failed to handle non-existent file '%s'",
1✔
2713
    fsio_test_path);
1✔
2714
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), %s (%d)", ENOENT,
2715
    strerror(errno), errno);
1✔
2716

2717
  mark_point();
2718
  res = pr_fsio_lstat_with_error(p, fsio_test_path, &st, &err);
1✔
2719
  ck_assert_msg(res < 0, "Failed to handle non-existent file '%s'",
1✔
2720
    fsio_test_path);
1✔
2721
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), %s (%d)", ENOENT,
2722
    strerror(errno), errno);
1✔
2723
  ck_assert_msg(err == NULL, "Unexpectedly populated error");
2724

1✔
2725
  memset(&m, 0, sizeof(m));
2726
  m.name = "error";
1✔
2727

1✔
2728
  explainer = pr_error_register_explainer(p, &m, "error");
2729
  explainer->explain_lstat = test_lstat_explainer;
1✔
2730

1✔
2731
  mark_point();
2732
  res = pr_fsio_lstat_with_error(p, fsio_test_path, &st, &err);
1✔
2733
  ck_assert_msg(res < 0, "Failed to handle non-existent file '%s'",
1✔
2734
    fsio_test_path);
1✔
2735
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), %s (%d)", ENOENT,
2736
    strerror(errno), errno);
1✔
2737
  ck_assert_msg(err != NULL, "Failed to populate error");
2738

1✔
2739
  expected = pstrcat(p,
2740
    "lstat() failed with \"No such file or directory [ENOENT (",
1✔
2741
    get_errnum(p, ENOENT), ")]\"", NULL);
2742
  errstr = pr_error_strerror(err, PR_ERROR_FORMAT_USE_MINIMAL);
2743
  ck_assert_msg(strcmp(errstr, expected) == 0, "Expected '%s', got '%s'",
1✔
2744
    expected, errstr);
1✔
2745

2746
  (void) pr_error_unregister_explainer(p, &m, NULL);
2747
  pr_error_destroy(err);
1✔
2748
}
1✔
2749
END_TEST
1✔
2750

2751
static const char *test_mkdir_explainer(pool *err_pool, int xerrno,
2752
    const char *path, mode_t mode, const char **args) {
1✔
2753
  *args = pstrdup(err_pool, "fake args");
2754
  return pstrdup(err_pool, "test mode is not real");
1✔
2755
}
1✔
2756

2757
START_TEST (fsio_sys_mkdir_with_error_test) {
2758
  int res;
1✔
2759
  pr_error_t *err = NULL;
1✔
2760
  const char *errstr, *expected, *path;
1✔
2761
  module m;
1✔
2762
  pr_error_explainer_t *explainer;
1✔
2763

1✔
2764
  path = "/tmp/foo/bar/baz/quxx/quzz.d";
2765

1✔
2766
  mark_point();
2767
  res = pr_fsio_mkdir_with_error(NULL, path, 0755, NULL);
1✔
2768
  ck_assert_msg(res < 0, "Failed to handle non-existent file '%s'",
1✔
2769
    fsio_testdir_path);
1✔
2770
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), %s (%d)", ENOENT,
2771
    strerror(errno), errno);
1✔
2772

2773
  mark_point();
2774
  res = pr_fsio_mkdir_with_error(p, path, 0755, &err);
1✔
2775
  ck_assert_msg(res < 0, "Failed to handle non-existent file '%s'",
1✔
2776
    fsio_testdir_path);
1✔
2777
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), %s (%d)", ENOENT,
2778
    strerror(errno), errno);
1✔
2779
  ck_assert_msg(err == NULL, "Unexpectedly populated error");
2780

1✔
2781
  memset(&m, 0, sizeof(m));
2782
  m.name = "error";
1✔
2783

1✔
2784
  explainer = pr_error_register_explainer(p, &m, "error");
2785
  explainer->explain_mkdir = test_mkdir_explainer;
1✔
2786

1✔
2787
  mark_point();
2788
  res = pr_fsio_mkdir_with_error(p, path, 0755, &err);
1✔
2789
  ck_assert_msg(res < 0, "Failed to handle non-existent file '%s'",
1✔
2790
    fsio_testdir_path);
1✔
2791
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), %s (%d)", ENOENT,
2792
    strerror(errno), errno);
1✔
2793
  ck_assert_msg(err != NULL, "Failed to populate error");
2794

1✔
2795
  expected = pstrcat(p,
2796
    "mkdir() failed with \"No such file or directory [ENOENT (",
1✔
2797
    get_errnum(p, ENOENT), ")]\"", NULL);
2798
  errstr = pr_error_strerror(err, PR_ERROR_FORMAT_USE_MINIMAL);
2799
  ck_assert_msg(strcmp(errstr, expected) == 0, "Expected '%s', got '%s'",
1✔
2800
    expected, errstr);
1✔
2801

2802
  (void) pr_error_unregister_explainer(p, &m, NULL);
2803
  pr_error_destroy(err);
1✔
2804
}
1✔
2805
END_TEST
1✔
2806

2807
static const char *test_open_explainer(pool *err_pool, int xerrno,
2808
    const char *path, int flags, mode_t mode, const char **args) {
1✔
2809
  *args = pstrdup(err_pool, "fake args");
2810
  return pstrdup(err_pool, "test mode is not real");
1✔
2811
}
1✔
2812

2813
START_TEST (fsio_sys_open_with_error_test) {
2814
  pr_fh_t *fh;
1✔
2815
  pr_error_t *err = NULL;
1✔
2816
  const char *errstr, *expected;
1✔
2817
  module m;
1✔
2818
  pr_error_explainer_t *explainer;
1✔
2819

1✔
2820
  mark_point();
2821
  fh = pr_fsio_open_with_error(NULL, fsio_test_path, O_RDONLY, NULL);
1✔
2822
  ck_assert_msg(fh == NULL, "Failed to handle non-existent file '%s'",
1✔
2823
    fsio_test_path);
1✔
2824
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), %s (%d)", ENOENT,
2825
    strerror(errno), errno);
1✔
2826

2827
  mark_point();
2828
  fh = pr_fsio_open_with_error(p, fsio_test_path, O_RDONLY, &err);
1✔
2829
  ck_assert_msg(fh == NULL, "Failed to handle non-existent file '%s'",
1✔
2830
    fsio_test_path);
1✔
2831
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), %s (%d)", ENOENT,
2832
    strerror(errno), errno);
1✔
2833
  ck_assert_msg(err == NULL, "Unexpectedly populated error");
2834

1✔
2835
  memset(&m, 0, sizeof(m));
2836
  m.name = "error";
1✔
2837

1✔
2838
  explainer = pr_error_register_explainer(p, &m, "error");
2839
  explainer->explain_open = test_open_explainer;
1✔
2840

1✔
2841
  mark_point();
2842
  fh = pr_fsio_open_with_error(p, fsio_test_path, O_RDONLY, &err);
1✔
2843
  ck_assert_msg(fh == NULL, "Failed to handle non-existent file '%s'",
1✔
2844
    fsio_test_path);
1✔
2845
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), %s (%d)", ENOENT,
2846
    strerror(errno), errno);
1✔
2847
  ck_assert_msg(err != NULL, "Failed to populate error");
2848

1✔
2849
  expected = pstrcat(p,
2850
    "open() failed with \"No such file or directory [ENOENT (",
1✔
2851
    get_errnum(p, ENOENT), ")]\"", NULL);
2852
  errstr = pr_error_strerror(err, PR_ERROR_FORMAT_USE_MINIMAL);
2853
  ck_assert_msg(strcmp(errstr, expected) == 0, "Expected '%s', got '%s'",
1✔
2854
    expected, errstr);
1✔
2855

2856
  (void) pr_error_unregister_explainer(p, &m, NULL);
2857
  pr_error_destroy(err);
1✔
2858
}
1✔
2859
END_TEST
1✔
2860

2861
static const char *test_read_explainer(pool *err_pool, int xerrno, int fd,
2862
    void *buf, size_t sz, const char **args) {
1✔
2863
  *args = pstrdup(err_pool, "fake args");
2864
  return pstrdup(err_pool, "test mode is not real");
1✔
2865
}
1✔
2866

2867
START_TEST (fsio_sys_read_with_error_test) {
2868
  int res;
1✔
2869
  pr_error_t *err = NULL;
1✔
2870
  const char *errstr, *expected;
1✔
2871
  module m;
1✔
2872
  pr_error_explainer_t *explainer;
1✔
2873

1✔
2874
  mark_point();
2875
  res = pr_fsio_read_with_error(NULL, NULL, NULL, 0, NULL);
1✔
2876
  ck_assert_msg(res < 0, "Failed to handle null fh");
1✔
2877
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), %s (%d)", EINVAL,
1✔
2878
    strerror(errno), errno);
1✔
2879

2880
  mark_point();
2881
  res = pr_fsio_read_with_error(p, NULL, NULL, 0, &err);
1✔
2882
  ck_assert_msg(res < 0, "Failed to handle null fh");
1✔
2883
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), %s (%d)", EINVAL,
1✔
2884
    strerror(errno), errno);
1✔
2885
  ck_assert_msg(err == NULL, "Unexpectedly populated error");
2886

1✔
2887
  memset(&m, 0, sizeof(m));
2888
  m.name = "error";
1✔
2889

1✔
2890
  explainer = pr_error_register_explainer(p, &m, "error");
2891
  explainer->explain_read = test_read_explainer;
1✔
2892

1✔
2893
  mark_point();
2894
  res = pr_fsio_read_with_error(p, NULL, NULL, 0, &err);
1✔
2895
  ck_assert_msg(res < 0, "Failed to handle null fh");
1✔
2896
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), %s (%d)", EINVAL,
1✔
2897
    strerror(errno), errno);
1✔
2898
  ck_assert_msg(err != NULL, "Failed to populate error");
2899

1✔
2900
  expected = pstrcat(p,
2901
    "read() failed with \"Invalid argument [EINVAL (",
1✔
2902
    get_errnum(p, EINVAL), ")]\"", NULL);
2903
  errstr = pr_error_strerror(err, PR_ERROR_FORMAT_USE_MINIMAL);
2904
  ck_assert_msg(strcmp(errstr, expected) == 0, "Expected '%s', got '%s'",
1✔
2905
    expected, errstr);
1✔
2906

2907
  (void) pr_error_unregister_explainer(p, &m, NULL);
2908
  pr_error_destroy(err);
1✔
2909
}
1✔
2910
END_TEST
1✔
2911

2912
static const char *test_rename_explainer(pool *err_pool, int xerrno,
2913
    const char *from, const char *to, const char **args) {
1✔
2914
  *args = pstrdup(err_pool, "fake args");
2915
  return pstrdup(err_pool, "test mode is not real");
1✔
2916
}
1✔
2917

2918
START_TEST (fsio_sys_rename_with_error_test) {
2919
  int res;
1✔
2920
  pr_error_t *err = NULL;
1✔
2921
  const char *errstr, *expected;
1✔
2922
  module m;
1✔
2923
  pr_error_explainer_t *explainer;
1✔
2924

1✔
2925
  mark_point();
2926
  res = pr_fsio_rename_with_error(NULL, fsio_test_path, fsio_test2_path, NULL);
1✔
2927
  ck_assert_msg(res < 0, "Failed to handle non-existent file '%s'",
1✔
2928
    fsio_test_path);
1✔
2929
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), %s (%d)", ENOENT,
2930
    strerror(errno), errno);
1✔
2931

2932
  mark_point();
2933
  res = pr_fsio_rename_with_error(p, fsio_test_path, fsio_test2_path, &err);
1✔
2934
  ck_assert_msg(res < 0, "Failed to handle non-existent file '%s'",
1✔
2935
    fsio_test_path);
1✔
2936
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), %s (%d)", ENOENT,
2937
    strerror(errno), errno);
1✔
2938
  ck_assert_msg(err == NULL, "Unexpectedly populated error");
2939

1✔
2940
  memset(&m, 0, sizeof(m));
2941
  m.name = "error";
1✔
2942

1✔
2943
  explainer = pr_error_register_explainer(p, &m, "error");
2944
  explainer->explain_rename = test_rename_explainer;
1✔
2945

1✔
2946
  mark_point();
2947
  res = pr_fsio_rename_with_error(p, fsio_test_path, fsio_test2_path, &err);
1✔
2948
  ck_assert_msg(res < 0, "Failed to handle non-existent file '%s'",
1✔
2949
    fsio_test_path);
1✔
2950
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), %s (%d)", ENOENT,
2951
    strerror(errno), errno);
1✔
2952
  ck_assert_msg(err != NULL, "Failed to populate error");
2953

1✔
2954
  expected = pstrcat(p,
2955
    "rename() failed with \"No such file or directory [ENOENT (",
1✔
2956
    get_errnum(p, ENOENT), ")]\"", NULL);
2957
  errstr = pr_error_strerror(err, PR_ERROR_FORMAT_USE_MINIMAL);
2958
  ck_assert_msg(strcmp(errstr, expected) == 0, "Expected '%s', got '%s'",
1✔
2959
    expected, errstr);
1✔
2960

2961
  (void) pr_error_unregister_explainer(p, &m, NULL);
2962
  pr_error_destroy(err);
1✔
2963
}
1✔
2964
END_TEST
1✔
2965

2966
static const char *test_rmdir_explainer(pool *err_pool, int xerrno,
2967
    const char *path, const char **args) {
1✔
2968
  *args = pstrdup(err_pool, "fake args");
2969
  return pstrdup(err_pool, "test mode is not real");
1✔
2970
}
1✔
2971

2972
START_TEST (fsio_sys_rmdir_with_error_test) {
2973
  int res;
1✔
2974
  pr_error_t *err = NULL;
1✔
2975
  const char *errstr, *expected;
1✔
2976
  module m;
1✔
2977
  pr_error_explainer_t *explainer;
1✔
2978

1✔
2979
  mark_point();
2980
  res = pr_fsio_rmdir_with_error(NULL, fsio_testdir_path, NULL);
1✔
2981
  ck_assert_msg(res < 0, "Failed to handle non-existent file '%s'",
1✔
2982
    fsio_testdir_path);
1✔
2983
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), %s (%d)", ENOENT,
2984
    strerror(errno), errno);
1✔
2985
  ck_assert_msg(err == NULL, "Unexpectedly populated error");
2986

1✔
2987
  memset(&m, 0, sizeof(m));
2988
  m.name = "error";
1✔
2989

1✔
2990
  explainer = pr_error_register_explainer(p, &m, "error");
2991
  explainer->explain_rmdir = test_rmdir_explainer;
1✔
2992

1✔
2993
  mark_point();
2994
  res = pr_fsio_rmdir_with_error(p, fsio_testdir_path, &err);
1✔
2995
  ck_assert_msg(res < 0, "Failed to handle non-existent file '%s'",
1✔
2996
    fsio_testdir_path);
1✔
2997
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), %s (%d)", ENOENT,
2998
    strerror(errno), errno);
1✔
2999
  ck_assert_msg(err != NULL, "Failed to populate error");
3000

1✔
3001
  expected = pstrcat(p,
3002
    "rmdir() failed with \"No such file or directory [ENOENT (",
1✔
3003
    get_errnum(p, ENOENT), ")]\"", NULL);
3004
  errstr = pr_error_strerror(err, PR_ERROR_FORMAT_USE_MINIMAL);
3005
  ck_assert_msg(strcmp(errstr, expected) == 0, "Expected '%s', got '%s'",
1✔
3006
    expected, errstr);
1✔
3007

3008
  (void) pr_error_unregister_explainer(p, &m, NULL);
3009
  pr_error_destroy(err);
1✔
3010
}
1✔
3011
END_TEST
1✔
3012

3013
static const char *test_stat_explainer(pool *err_pool, int xerrno,
3014
    const char *path, struct stat *st, const char **args) {
1✔
3015
  *args = pstrdup(err_pool, "fake args");
3016
  return pstrdup(err_pool, "test mode is not real");
1✔
3017
}
1✔
3018

3019
START_TEST (fsio_sys_stat_with_error_test) {
3020
  int res;
1✔
3021
  struct stat st;
1✔
3022
  pr_error_t *err = NULL;
1✔
3023
  const char *errstr, *expected;
1✔
3024
  module m;
1✔
3025
  pr_error_explainer_t *explainer;
1✔
3026

1✔
3027
  mark_point();
3028
  res = pr_fsio_stat_with_error(NULL, fsio_test_path, &st, NULL);
1✔
3029
  ck_assert_msg(res < 0, "Failed to handle non-existent file '%s'",
1✔
3030
    fsio_test_path);
1✔
3031
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), %s (%d)", ENOENT,
3032
    strerror(errno), errno);
1✔
3033

3034
  mark_point();
3035
  res = pr_fsio_stat_with_error(p, fsio_test_path, &st, &err);
1✔
3036
  ck_assert_msg(res < 0, "Failed to handle non-existent file '%s'",
1✔
3037
    fsio_test_path);
1✔
3038
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), %s (%d)", ENOENT,
3039
    strerror(errno), errno);
1✔
3040
  ck_assert_msg(err == NULL, "Unexpectedly populated error");
3041

1✔
3042
  memset(&m, 0, sizeof(m));
3043
  m.name = "error";
1✔
3044

1✔
3045
  explainer = pr_error_register_explainer(p, &m, "error");
3046
  explainer->explain_stat = test_stat_explainer;
1✔
3047

1✔
3048
  mark_point();
3049
  res = pr_fsio_stat_with_error(p, fsio_test_path, &st, &err);
1✔
3050
  ck_assert_msg(res < 0, "Failed to handle non-existent file '%s'",
1✔
3051
    fsio_test_path);
1✔
3052
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), %s (%d)", ENOENT,
3053
    strerror(errno), errno);
1✔
3054
  ck_assert_msg(err != NULL, "Failed to populate error");
3055

1✔
3056
  expected = pstrcat(p,
3057
    "stat() failed with \"No such file or directory [ENOENT (",
1✔
3058
    get_errnum(p, ENOENT), ")]\"", NULL);
3059
  errstr = pr_error_strerror(err, PR_ERROR_FORMAT_USE_MINIMAL);
3060
  ck_assert_msg(strcmp(errstr, expected) == 0, "Expected '%s', got '%s'",
1✔
3061
    expected, errstr);
1✔
3062

3063
  (void) pr_error_unregister_explainer(p, &m, NULL);
3064
  pr_error_destroy(err);
1✔
3065
}
1✔
3066
END_TEST
1✔
3067

3068
static const char *test_unlink_explainer(pool *err_pool, int xerrno,
3069
    const char *path, const char **args) {
1✔
3070
  *args = pstrdup(err_pool, "fake args");
3071
  return pstrdup(err_pool, "test mode is not real");
1✔
3072
}
1✔
3073

3074
START_TEST (fsio_sys_unlink_with_error_test) {
3075
  int res;
1✔
3076
  pr_error_t *err = NULL;
1✔
3077
  const char *errstr, *expected;
1✔
3078
  module m;
1✔
3079
  pr_error_explainer_t *explainer;
1✔
3080

1✔
3081
  mark_point();
3082
  res = pr_fsio_unlink_with_error(NULL, fsio_test_path, NULL);
1✔
3083
  ck_assert_msg(res < 0, "Failed to handle non-existent file '%s'",
1✔
3084
    fsio_test_path);
1✔
3085
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), %s (%d)", ENOENT,
3086
    strerror(errno), errno);
1✔
3087

3088
  mark_point();
3089
  res = pr_fsio_unlink_with_error(p, fsio_test_path, &err);
1✔
3090
  ck_assert_msg(res < 0, "Failed to handle non-existent file '%s'",
1✔
3091
    fsio_test_path);
1✔
3092
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), %s (%d)", ENOENT,
3093
    strerror(errno), errno);
1✔
3094
  ck_assert_msg(err == NULL, "Unexpectedly populated error");
3095

1✔
3096
  memset(&m, 0, sizeof(m));
3097
  m.name = "error";
1✔
3098

1✔
3099
  explainer = pr_error_register_explainer(p, &m, "error");
3100
  explainer->explain_unlink = test_unlink_explainer;
1✔
3101

1✔
3102
  mark_point();
3103
  res = pr_fsio_unlink_with_error(p, fsio_test_path, &err);
1✔
3104
  ck_assert_msg(res < 0, "Failed to handle non-existent file '%s'",
1✔
3105
    fsio_test_path);
1✔
3106
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), %s (%d)", ENOENT,
3107
    strerror(errno), errno);
1✔
3108
  ck_assert_msg(err != NULL, "Failed to populate error");
3109

1✔
3110
  expected = pstrcat(p,
3111
    "unlink() failed with \"No such file or directory [ENOENT (",
1✔
3112
    get_errnum(p, ENOENT), ")]\"", NULL);
3113
  errstr = pr_error_strerror(err, PR_ERROR_FORMAT_USE_MINIMAL);
3114
  ck_assert_msg(strcmp(errstr, expected) == 0, "Expected '%s', got '%s'",
1✔
3115
    expected, errstr);
1✔
3116

3117
  (void) pr_error_unregister_explainer(p, &m, NULL);
3118
  pr_error_destroy(err);
1✔
3119
}
1✔
3120
END_TEST
1✔
3121

3122
static const char *test_write_explainer(pool *err_pool, int xerrno, int fd,
3123
    const void *buf, size_t sz, const char **args) {
1✔
3124
  *args = pstrdup(err_pool, "fake args");
3125
  return pstrdup(err_pool, "test mode is not real");
1✔
3126
}
1✔
3127

3128
START_TEST (fsio_sys_write_with_error_test) {
3129
  int res;
1✔
3130
  pr_error_t *err = NULL;
1✔
3131
  const char *errstr, *expected;
1✔
3132
  module m;
1✔
3133
  pr_error_explainer_t *explainer;
1✔
3134

1✔
3135
  mark_point();
3136
  res = pr_fsio_write_with_error(NULL, NULL, NULL, 0, NULL);
1✔
3137
  ck_assert_msg(res < 0, "Failed to handle null pool");
1✔
3138
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), %s (%d)", EINVAL,
1✔
3139
    strerror(errno), errno);
1✔
3140

3141
  mark_point();
3142
  res = pr_fsio_write_with_error(p, NULL, NULL, 0, &err);
1✔
3143
  ck_assert_msg(res < 0, "Failed to handle null fh");
1✔
3144
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), %s (%d)", EINVAL,
1✔
3145
    strerror(errno), errno);
1✔
3146
  ck_assert_msg(err == NULL, "Unexpectedly populated error");
3147

1✔
3148
  memset(&m, 0, sizeof(m));
3149
  m.name = "error";
1✔
3150

1✔
3151
  explainer = pr_error_register_explainer(p, &m, "error");
3152
  explainer->explain_write = test_write_explainer;
1✔
3153

1✔
3154
  mark_point();
3155
  res = pr_fsio_write_with_error(p, NULL, NULL, 0, &err);
1✔
3156
  ck_assert_msg(res < 0, "Failed to handle null fh");
1✔
3157
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), %s (%d)", EINVAL,
1✔
3158
    strerror(errno), errno);
1✔
3159
  ck_assert_msg(err != NULL, "Failed to populate error");
3160

1✔
3161
  expected = pstrcat(p,
3162
    "write() failed with \"Invalid argument [EINVAL (",
1✔
3163
    get_errnum(p, EINVAL), ")]\"", NULL);
3164
  expected = "write() failed with \"Invalid argument [EINVAL (22)]\"";
3165
  errstr = pr_error_strerror(err, PR_ERROR_FORMAT_USE_MINIMAL);
1✔
3166
  ck_assert_msg(strcmp(errstr, expected) == 0, "Expected '%s', got '%s'",
1✔
3167
    expected, errstr);
1✔
3168

3169
  (void) pr_error_unregister_explainer(p, &m, NULL);
3170
  pr_error_destroy(err);
1✔
3171
}
1✔
3172
END_TEST
1✔
3173

3174
START_TEST (fsio_statcache_clear_cache_test) {
3175
  int expected, res;
1✔
3176
  struct stat st;
1✔
3177
  char *cwd;
1✔
3178

1✔
3179
  mark_point();
3180
  pr_fs_clear_cache();
1✔
3181

1✔
3182
  res = pr_fs_clear_cache2("/testsuite");
3183
  ck_assert_msg(res == 0, "Failed to clear cache: %s", strerror(errno));
1✔
3184

1✔
3185
  res = pr_fsio_stat("/tmp", &st);
3186
  ck_assert_msg(res == 0, "Failed to stat '/tmp': %s", strerror(errno));
1✔
3187

1✔
3188
  res = pr_fs_clear_cache2("/tmp");
3189
  expected = 1;
1✔
3190
  ck_assert_msg(res == expected, "Expected %d, got %d", expected, res);
1✔
3191

1✔
3192
  res = pr_fs_clear_cache2("/testsuite");
3193
  expected = 0;
1✔
3194
  ck_assert_msg(res == expected, "Expected %d, got %d", expected, res);
1✔
3195

1✔
3196
  res = pr_fsio_stat("/tmp", &st);
3197
  ck_assert_msg(res == 0, "Failed to stat '/tmp': %s", strerror(errno));
1✔
3198

1✔
3199
  res = pr_fsio_lstat("/tmp", &st);
3200
  ck_assert_msg(res == 0, "Failed to lstat '/tmp': %s", strerror(errno));
1✔
3201

1✔
3202
  res = pr_fs_clear_cache2("/tmp");
3203
  expected = 2;
1✔
3204
  ck_assert_msg(res == expected, "Expected %d, got %d", expected, res);
1✔
3205

1✔
3206
  res = pr_fsio_stat("/tmp", &st);
3207
  ck_assert_msg(res == 0, "Failed to stat '/tmp': %s", strerror(errno));
1✔
3208

1✔
3209
  res = pr_fsio_lstat("/tmp", &st);
3210
  ck_assert_msg(res == 0, "Failed to lstat '/tmp': %s", strerror(errno));
1✔
3211

1✔
3212
  cwd = getcwd(NULL, 0);
3213
  ck_assert_msg(cwd != NULL, "Failed to get cwd: %s", strerror(errno));
1✔
3214

1✔
3215
  res = pr_fs_setcwd("/");
3216
  ck_assert_msg(res == 0, "Failed to set cwd to '/': %s", strerror(errno));
1✔
3217

1✔
3218
  res = pr_fs_clear_cache2("tmp");
3219
  expected = 2;
1✔
3220
  ck_assert_msg(res == expected, "Expected %d, got %d", expected, res);
1✔
3221

1✔
3222
  res = pr_fs_setcwd(cwd);
3223
  ck_assert_msg(res == 0, "Failed to set cwd to '%s': %s", cwd,
1✔
3224
    strerror(errno));
1✔
3225

3226
  free(cwd);
3227
}
1✔
3228
END_TEST
1✔
3229

3230
START_TEST (fsio_statcache_cache_hit_test) {
3231
  int res;
1✔
3232
  struct stat st;
1✔
3233

1✔
3234
  /* First is a cache miss...*/
3235
  res = pr_fsio_stat("/tmp", &st);
3236
  ck_assert_msg(res == 0, "Failed to stat '/tmp': %s", strerror(errno));
1✔
3237

1✔
3238
  /* This is a cache hit, hopefully. */
3239
  res = pr_fsio_stat("/tmp", &st);
3240
  ck_assert_msg(res == 0, "Failed to stat '/tmp': %s", strerror(errno));
1✔
3241

1✔
3242
  pr_fs_clear_cache();
3243
}
1✔
3244
END_TEST
1✔
3245

3246
START_TEST (fsio_statcache_negative_cache_test) {
3247
  int res;
1✔
3248
  struct stat st;
1✔
3249

1✔
3250
  /* First is a cache miss...*/
3251
  res = pr_fsio_stat("/foo.bar.baz.d", &st);
3252
  ck_assert_msg(res < 0, "Check of '/foo.bar.baz.d' succeeded unexpectedly");
1✔
3253
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
1✔
3254
    strerror(errno), errno);
1✔
3255

3256
  /* This is a cache hit, hopefully. */
3257
  res = pr_fsio_stat("/foo.bar.baz.d", &st);
3258
  ck_assert_msg(res < 0, "Check of '/foo.bar.baz.d' succeeded unexpectedly");
1✔
3259
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
1✔
3260
    strerror(errno), errno);
1✔
3261

3262
  pr_fs_clear_cache();
3263
}
1✔
3264
END_TEST
1✔
3265

3266
START_TEST (fsio_statcache_expired_test) {
3267
  unsigned int cache_size, max_age;
1✔
3268
  int res;
1✔
3269
  struct stat st;
1✔
3270

1✔
3271
  cache_size = max_age = 1;
3272
  pr_fs_statcache_set_policy(cache_size, max_age, 0);
1✔
3273

1✔
3274
  /* First is a cache miss...*/
3275
  mark_point();
3276
  res = pr_fsio_stat("/tmp", &st);
1✔
3277
  ck_assert_msg(res == 0, "Failed to stat '/tmp': %s", strerror(errno));
1✔
3278

1✔
3279
  /* Wait for that cached data to expire...*/
3280
  sleep(max_age + 1);
3281

1✔
3282
  /* This is another cache miss, hopefully. */
3283
  mark_point();
3284
  res = pr_fsio_stat("/tmp2", &st);
1✔
3285
  ck_assert_msg(res < 0, "Check of '/tmp2' succeeded unexpectedly");
1✔
3286
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
1✔
3287
    strerror(errno), errno);
1✔
3288

3289
  mark_point();
3290
  pr_fs_clear_cache();
1✔
3291
}
1✔
3292
END_TEST
1✔
3293

3294
START_TEST (fsio_statcache_dump_test) {
3295
  mark_point();
1✔
3296
  pr_fs_statcache_dump();
1✔
3297
}
1✔
3298
END_TEST
1✔
3299

3300
START_TEST (fs_create_fs_test) {
3301
  pr_fs_t *fs;
1✔
3302

1✔
3303
  fs = pr_create_fs(NULL, NULL);
3304
  ck_assert_msg(fs == NULL, "Failed to handle null arguments");
1✔
3305
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
3306
    strerror(errno), errno);
1✔
3307

3308
  fs = pr_create_fs(p, NULL);
3309
  ck_assert_msg(fs == NULL, "Failed to handle null name");
1✔
3310
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
3311
    strerror(errno), errno);
1✔
3312

3313
  fs = pr_create_fs(p, "testsuite");
3314
  ck_assert_msg(fs != NULL, "Failed to create FS: %s", strerror(errno));
1✔
3315
}
1✔
3316
END_TEST
1✔
3317

3318
START_TEST (fs_insert_fs_test) {
3319
  pr_fs_t *fs, *fs2;
1✔
3320
  int res;
1✔
3321

1✔
3322
  res = pr_insert_fs(NULL, NULL);
3323
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
3324
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
3325
    strerror(errno), errno);
1✔
3326

3327
  fs = pr_create_fs(p, "testsuite");
3328
  ck_assert_msg(fs != NULL, "Failed to create FS: %s", strerror(errno));
1✔
3329

1✔
3330
  res = pr_insert_fs(fs, NULL);
3331
  ck_assert_msg(res < 0, "Failed to handle null path");
1✔
3332
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
3333
    strerror(errno), errno);
1✔
3334

3335
  res = pr_insert_fs(fs, "/testsuite");
3336
  ck_assert_msg(res == TRUE, "Failed to insert FS: %s", strerror(errno));
1✔
3337

1✔
3338
  res = pr_insert_fs(fs, "/testsuite");
3339
  ck_assert_msg(res == FALSE, "Failed to handle duplicate paths");
1✔
3340
  ck_assert_msg(errno == EEXIST, "Expected EEXIST (%d), got %s (%d)", EEXIST,
1✔
3341
    strerror(errno), errno);
1✔
3342

3343
  fs2 = pr_create_fs(p, "testsuite2");
3344
  ck_assert_msg(fs2 != NULL, "Failed to create FS: %s", strerror(errno));
1✔
3345

1✔
3346
  res = pr_insert_fs(fs2, "/testsuite2");
3347
  ck_assert_msg(res == TRUE, "Failed to insert FS: %s", strerror(errno));
1✔
3348

1✔
3349
  fs2 = pr_create_fs(p, "testsuite3");
3350
  ck_assert_msg(fs2 != NULL, "Failed to create FS: %s", strerror(errno));
1✔
3351

1✔
3352
  /* Push this FS on top of the previously registered path; FSes can be
3353
   * stacked like this.
3354
   */
3355
  res = pr_insert_fs(fs2, "/testsuite2");
3356
  ck_assert_msg(res == TRUE, "Failed to insert FS: %s", strerror(errno));
1✔
3357

1✔
3358
  (void) pr_remove_fs("/testsuite");
3359
  (void) pr_remove_fs("/testsuite2");
1✔
3360
  (void) pr_remove_fs("/testsuite3");
1✔
3361
}
1✔
3362
END_TEST
1✔
3363

3364
START_TEST (fs_get_fs_test) {
3365
  pr_fs_t *fs, *fs2, *fs3;
1✔
3366
  int exact_match = FALSE, res;
1✔
3367

1✔
3368
  fs = pr_get_fs(NULL, NULL);
3369
  ck_assert_msg(fs == NULL, "Failed to handle null arguments");
1✔
3370

1✔
3371
  fs = pr_get_fs("/testsuite", &exact_match);
3372
  ck_assert_msg(fs != NULL, "Failed to get FS: %s", strerror(errno));
1✔
3373
  ck_assert_msg(exact_match == FALSE, "Expected FALSE, got TRUE");
1✔
3374

1✔
3375
  fs2 = pr_create_fs(p, "testsuite");
3376
  ck_assert_msg(fs2 != NULL, "Failed to create FS: %s", strerror(errno));
1✔
3377

1✔
3378
  res = pr_insert_fs(fs2, "/testsuite");
3379
  ck_assert_msg(res == TRUE, "Failed to insert FS: %s", strerror(errno));
1✔
3380

1✔
3381
  fs = pr_get_fs("/testsuite", &exact_match);
3382
  ck_assert_msg(fs != NULL, "Failed to get FS: %s", strerror(errno));
1✔
3383
  ck_assert_msg(exact_match == TRUE, "Expected TRUE, got FALSE");
1✔
3384

1✔
3385
  fs3 = pr_create_fs(p, "testsuite2");
3386
  ck_assert_msg(fs3 != NULL, "Failed to create FS: %s", strerror(errno));
1✔
3387

1✔
3388
  res = pr_insert_fs(fs3, "/testsuite2/");
3389
  ck_assert_msg(res == TRUE, "Failed to insert FS: %s", strerror(errno));
1✔
3390

1✔
3391
  exact_match = FALSE;
3392
  fs = pr_get_fs("/testsuite2/foo/bar/baz", &exact_match);
1✔
3393
  ck_assert_msg(fs != NULL, "Failed to get FS: %s", strerror(errno));
1✔
3394
  ck_assert_msg(exact_match == FALSE, "Expected FALSE, got TRUE");
1✔
3395

1✔
3396
  (void) pr_remove_fs("/testsuite2");
3397
  (void) pr_remove_fs("/testsuite");
1✔
3398
}
1✔
3399
END_TEST
1✔
3400

3401
START_TEST (fs_unmount_fs_test) {
3402
  pr_fs_t *fs, *fs2;
1✔
3403
  int res;
1✔
3404

1✔
3405
  fs = pr_unmount_fs(NULL, NULL);
3406
  ck_assert_msg(fs == NULL, "Failed to handle null arguments");
1✔
3407
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
3408
    strerror(errno), errno);
1✔
3409

3410
  fs = pr_unmount_fs("/testsuite", NULL);
3411
  ck_assert_msg(fs == NULL, "Failed to handle absent FS");
1✔
3412
  ck_assert_msg(errno == EACCES, "Expected EACCES (%d), got %s (%d)", EACCES,
1✔
3413
    strerror(errno), errno);
1✔
3414

3415
  fs2 = pr_create_fs(p, "testsuite");
3416
  ck_assert_msg(fs2 != NULL, "Failed to create FS: %s", strerror(errno));
1✔
3417

1✔
3418
  res = pr_insert_fs(fs2, "/testsuite");
3419
  ck_assert_msg(res == TRUE, "Failed to insert FS: %s", strerror(errno));
1✔
3420

1✔
3421
  fs = pr_unmount_fs("/testsuite", "foo bar");
3422
  ck_assert_msg(fs == NULL, "Failed to mismatched path AND name");
1✔
3423
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
1✔
3424
    strerror(errno), errno);
1✔
3425

3426
  fs = pr_unmount_fs("/testsuite2", NULL);
3427
  ck_assert_msg(fs == NULL, "Failed to handle nonexistent path");
1✔
3428
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
1✔
3429
    strerror(errno), errno);
1✔
3430

3431
  fs2 = pr_unmount_fs("/testsuite", NULL);
3432
  ck_assert_msg(fs2 != NULL, "Failed to unmount '/testsuite': %s",
1✔
3433
    strerror(errno));
1✔
3434

3435
  fs2 = pr_create_fs(p, "testsuite");
3436
  ck_assert_msg(fs2 != NULL, "Failed to create FS: %s", strerror(errno));
1✔
3437

1✔
3438
  res = pr_insert_fs(fs2, "/testsuite");
3439
  ck_assert_msg(res == TRUE, "Failed to insert FS: %s", strerror(errno));
1✔
3440

1✔
3441
  fs2 = pr_create_fs(p, "testsuite2");
3442
  ck_assert_msg(fs2 != NULL, "Failed to create FS: %s", strerror(errno));
1✔
3443

1✔
3444
  res = pr_insert_fs(fs2, "/testsuite");
3445
  ck_assert_msg(res == TRUE, "Failed to insert FS: %s", strerror(errno));
1✔
3446

1✔
3447
  fs2 = pr_unmount_fs("/testsuite", NULL);
3448
  ck_assert_msg(fs2 != NULL, "Failed to unmount '/testsuite': %s",
1✔
3449
    strerror(errno));
1✔
3450

3451
  fs2 = pr_unmount_fs("/testsuite", NULL);
3452
  ck_assert_msg(fs2 != NULL, "Failed to unmount '/testsuite': %s",
1✔
3453
    strerror(errno));
1✔
3454

3455
  (void) pr_remove_fs("/testsuite");
3456
  (void) pr_remove_fs("/testsuite");
1✔
3457
}
1✔
3458
END_TEST
1✔
3459

3460
START_TEST (fs_remove_fs_test) {
3461
  pr_fs_t *fs, *fs2;
1✔
3462
  int res;
1✔
3463

1✔
3464
  fs = pr_remove_fs(NULL);
3465
  ck_assert_msg(fs == NULL, "Failed to handle null arguments");
1✔
3466
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
3467
    strerror(errno), errno);
1✔
3468

3469
  fs = pr_remove_fs("/testsuite");
3470
  ck_assert_msg(fs == NULL, "Failed to handle absent FS");
1✔
3471
  ck_assert_msg(errno == EACCES, "Expected EACCES (%d), got %s (%d)", EACCES,
1✔
3472
    strerror(errno), errno);
1✔
3473

3474
  fs2 = pr_create_fs(p, "testsuite");
3475
  ck_assert_msg(fs2 != NULL, "Failed to create FS: %s", strerror(errno));
1✔
3476

1✔
3477
  res = pr_insert_fs(fs2, "/testsuite");
3478
  ck_assert_msg(res == TRUE, "Failed to insert FS: %s", strerror(errno));
1✔
3479

1✔
3480
  fs = pr_remove_fs("/testsuite2");
3481
  ck_assert_msg(fs == NULL, "Failed to handle nonexistent path");
1✔
3482
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
1✔
3483
    strerror(errno), errno);
1✔
3484

3485
  fs2 = pr_remove_fs("/testsuite");
3486
  ck_assert_msg(fs2 != NULL, "Failed to remove '/testsuite': %s",
1✔
3487
    strerror(errno));
1✔
3488
}
3489
END_TEST
1✔
3490

3491
START_TEST (fs_register_fs_test) {
3492
  pr_fs_t *fs, *fs2;
1✔
3493

1✔
3494
  fs = pr_register_fs(NULL, NULL, NULL);
3495
  ck_assert_msg(fs == NULL, "Failed to handle null arguments");
1✔
3496
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
3497
    strerror(errno), errno);
1✔
3498

3499
  fs = pr_register_fs(p, NULL, NULL);
3500
  ck_assert_msg(fs == NULL, "Failed to handle null name");
1✔
3501
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
3502
    strerror(errno), errno);
1✔
3503

3504
  fs = pr_register_fs(p, "testsuite", NULL);
3505
  ck_assert_msg(fs == NULL, "Failed to handle null path");
1✔
3506
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
3507
    strerror(errno), errno);
1✔
3508

3509
  fs = pr_register_fs(p, "testsuite", "/testsuite");
3510
  ck_assert_msg(fs != NULL, "Failed to register FS: %s", strerror(errno));
1✔
3511

1✔
3512
  fs2 = pr_register_fs2(p, "testsuite", "/testsuite", 0);
3513
  ck_assert_msg(fs2 == NULL, "Failed to handle duplicate names");
1✔
3514
  ck_assert_msg(errno == EEXIST, "Expected EEXIST (%d), got %s (%d)", EEXIST,
1✔
3515
    strerror(errno), errno);
1✔
3516

3517
  (void) pr_remove_fs("/testsuite");
3518
}
1✔
3519
END_TEST
1✔
3520

3521
START_TEST (fs_register_fs2_test) {
3522
  pr_fs_t *fs, *fs2;
1✔
3523

1✔
3524
  fs = pr_register_fs2(NULL, NULL, NULL, 0);
3525
  ck_assert_msg(fs == NULL, "Failed to handle null arguments");
1✔
3526
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
3527
    strerror(errno), errno);
1✔
3528

3529
  fs = pr_register_fs2(p, NULL, NULL, 0);
3530
  ck_assert_msg(fs == NULL, "Failed to handle null name");
1✔
3531
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
3532
    strerror(errno), errno);
1✔
3533

3534
  fs = pr_register_fs2(p, "testsuite", NULL, 0);
3535
  ck_assert_msg(fs == NULL, "Failed to handle null path");
1✔
3536
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
3537
    strerror(errno), errno);
1✔
3538

3539
  fs = pr_register_fs2(p, "testsuite", "/testsuite", 0);
3540
  ck_assert_msg(fs != NULL, "Failed to register FS: %s", strerror(errno));
1✔
3541

1✔
3542
  fs2 = pr_register_fs2(p, "testsuite", "/testsuite", 0);
3543
  ck_assert_msg(fs2 == NULL, "Failed to handle duplicate names");
1✔
3544
  ck_assert_msg(errno == EEXIST, "Expected EEXIST (%d), got %s (%d)", EEXIST,
1✔
3545
    strerror(errno), errno);
1✔
3546

3547
  (void) pr_remove_fs("/testsuite");
3548
}
1✔
3549
END_TEST
1✔
3550

3551
START_TEST (fs_unregister_fs_test) {
3552
  pr_fs_t *fs;
1✔
3553
  int res;
1✔
3554

1✔
3555
  res = pr_unregister_fs(NULL);
3556
  ck_assert_msg(res < 0, "Failed to handle null argument");
1✔
3557
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
3558
    strerror(errno), errno);
1✔
3559

3560
  res = pr_unregister_fs("/testsuite");
3561
  ck_assert_msg(res < 0, "Failed to handle nonexistent path");
1✔
3562
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
1✔
3563
    strerror(errno), errno);
1✔
3564

3565
  fs = pr_register_fs(p, "testsuite", "/testsuite");
3566
  ck_assert_msg(fs != NULL, "Failed to register FS: %s", strerror(errno));
1✔
3567

1✔
3568
  res = pr_unregister_fs("/testsuite");
3569
  ck_assert_msg(res == 0, "Failed to unregister '/testsuite': %s",
1✔
3570
    strerror(errno));
1✔
3571
}
3572
END_TEST
1✔
3573

3574
START_TEST (fs_resolve_fs_map_test) {
3575
  pr_fs_t *fs;
1✔
3576
  int res;
1✔
3577

1✔
3578
  mark_point();
3579
  pr_resolve_fs_map();
1✔
3580

1✔
3581
  fs = pr_register_fs(p, "testsuite", "/testsuite");
3582
  ck_assert_msg(fs != NULL, "Failed to register FS: %s", strerror(errno));
1✔
3583

1✔
3584
  mark_point();
3585
  pr_resolve_fs_map();
1✔
3586

1✔
3587
  res = pr_unregister_fs("/testsuite");
3588
  ck_assert_msg(res == 0, "Failed to unregister '/testsuite': %s",
1✔
3589
    strerror(errno));
1✔
3590

3591
  mark_point();
3592
  pr_resolve_fs_map();
1✔
3593
}
1✔
3594
END_TEST
1✔
3595

3596
#if defined(PR_USE_DEVEL)
3597
START_TEST (fs_dump_fs_test) {
3598
  pr_fs_t *fs, *root_fs;
1✔
3599

1✔
3600
  mark_point();
3601
  pr_fs_dump(NULL);
1✔
3602

1✔
3603
  root_fs = pr_get_fs("/", NULL);
3604
  fs = pr_register_fs(p, "testsuite", "/testsuite");
1✔
3605

1✔
3606
  mark_point();
3607
  pr_fs_dump(NULL);
1✔
3608

1✔
3609
  fs->stat = root_fs->stat;
3610
  fs->fstat = root_fs->fstat;
1✔
3611
  fs->lstat = root_fs->lstat;
1✔
3612
  fs->rename = root_fs->rename;
1✔
3613
  fs->unlink = root_fs->unlink;
1✔
3614
  fs->open = root_fs->open;
1✔
3615
  fs->close = root_fs->close;
1✔
3616
  fs->read = root_fs->read;
1✔
3617
  fs->write = root_fs->write;
1✔
3618
  fs->lseek = root_fs->lseek;
1✔
3619
  fs->link = root_fs->link;
1✔
3620
  fs->readlink = root_fs->readlink;
1✔
3621
  fs->symlink = root_fs->symlink;
1✔
3622
  fs->ftruncate = root_fs->ftruncate;
1✔
3623
  fs->truncate = root_fs->truncate;
1✔
3624
  fs->chmod = root_fs->chmod;
1✔
3625
  fs->fchmod = root_fs->fchmod;
1✔
3626
  fs->chown = root_fs->chown;
1✔
3627
  fs->fchown = root_fs->fchown;
1✔
3628
  fs->lchown = root_fs->lchown;
1✔
3629
  fs->access = root_fs->access;
1✔
3630
  fs->faccess = root_fs->faccess;
1✔
3631
  fs->utimes = root_fs->utimes;
1✔
3632
  fs->futimes = root_fs->futimes;
1✔
3633
  fs->fsync = root_fs->fsync;
1✔
3634
  fs->chdir = root_fs->chdir;
1✔
3635
  fs->chroot = root_fs->chroot;
1✔
3636
  fs->opendir = root_fs->opendir;
1✔
3637
  fs->closedir = root_fs->closedir;
1✔
3638
  fs->readdir = root_fs->readdir;
1✔
3639
  fs->mkdir = root_fs->mkdir;
1✔
3640
  fs->rmdir = root_fs->rmdir;
1✔
3641

1✔
3642
  mark_point();
3643
  pr_fs_dump(NULL);
1✔
3644

1✔
3645
  pr_unregister_fs("/testsuite");
3646
}
1✔
3647
END_TEST
1✔
3648
#endif /* PR_USE_DEVEL */
3649

3650
static int fsio_chroot_cb(pr_fs_t *fs, const char *path) {
3651
  return 0;
1✔
3652
}
1✔
3653

3654
START_TEST (fsio_custom_chroot_test) {
3655
  pr_fs_t *fs;
1✔
3656
  int res;
1✔
3657
  const char *path;
1✔
3658

1✔
3659
  fs = pr_register_fs(p, "custom", "/testsuite/");
3660
  ck_assert_msg(fs != NULL, "Failed to register custom FS: %s", strerror(errno));
1✔
3661

1✔
3662
  fs->chroot = fsio_chroot_cb;
3663

1✔
3664
  mark_point();
3665
  pr_resolve_fs_map();
1✔
3666

1✔
3667
  path = "/testsuite/foo/bar";
3668
  res = pr_fsio_chroot(path);
1✔
3669
  ck_assert_msg(res == 0, "Failed to chroot (via custom FS) to '%s': %s", path,
1✔
3670
    strerror(errno));
1✔
3671

3672
  pr_unregister_fs("/testsuite");
3673
}
1✔
3674
END_TEST
1✔
3675

3676
START_TEST (fs_clean_path_test) {
3677
  char res[PR_TUNABLE_PATH_MAX+1], *path, *expected;
1✔
3678

1✔
3679
  mark_point();
3680
  pr_fs_clean_path(NULL, NULL, 0);
1✔
3681
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
3682
    strerror(errno), errno);
1✔
3683

3684
  path = "/";
3685

1✔
3686
  mark_point();
3687
  pr_fs_clean_path(path, NULL, 0);
1✔
3688
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
3689
    strerror(errno), errno);
1✔
3690

3691
  res[sizeof(res)-1] = '\0';
3692

1✔
3693
  mark_point();
3694
  pr_fs_clean_path(path, res, 0);
1✔
3695

1✔
3696
  mark_point();
3697
  pr_fs_clean_path(path, res, sizeof(res)-1);
1✔
3698
  ck_assert_msg(strcmp(res, path) == 0, "Expected cleaned path '%s', got '%s'",
1✔
3699
    path, res);
3700

3701
  mark_point();
1✔
3702
  res[sizeof(res)-1] = '\0';
1✔
3703
  path = "/test.txt";
1✔
3704
  pr_fs_clean_path(path, res, sizeof(res)-1);
1✔
3705
  ck_assert_msg(strcmp(res, path) == 0, "Expected cleaned path '%s', got '%s'",
3706
    path, res);
3707

1✔
3708
  mark_point();
1✔
3709
  res[sizeof(res)-1] = '\0';
1✔
3710
  path = "/test.txt";
1✔
3711
  pr_fs_clean_path(path, res, sizeof(res)-1);
3712
  ck_assert_msg(strcmp(res, path) == 0, "Expected cleaned path '%s', got '%s'",
3713
    path, res);
1✔
3714

1✔
3715
  mark_point();
1✔
3716
  res[sizeof(res)-1] = '\0';
1✔
3717
  path = "/./test.txt";
1✔
3718
  pr_fs_clean_path(path, res, sizeof(res)-1);
3719
  expected = "/test.txt";
3720
  ck_assert_msg(strcmp(res, expected) == 0,
1✔
3721
    "Expected cleaned path '%s', got '%s'", expected, res);
1✔
3722

1✔
3723
  mark_point();
1✔
3724
  res[sizeof(res)-1] = '\0';
1✔
3725
  path = "test.txt";
3726
  pr_fs_clean_path(path, res, sizeof(res)-1);
1✔
3727
  expected = "/test.txt";
3728
  ck_assert_msg(strcmp(res, expected) == 0,
3729
    "Expected cleaned path '%s', got '%s'", path, res);
1✔
3730

1✔
3731
  mark_point();
1✔
3732
  res[sizeof(res)-1] = '\0';
3733
  path = "/tmp/test.d/../../test.txt";
1✔
3734
  pr_fs_clean_path(path, res, sizeof(res)-1);
1✔
3735
  expected = "/test.txt";
1✔
3736
  ck_assert_msg(strcmp(res, expected) == 0,
1✔
3737
    "Expected cleaned path '%s', got '%s'", path, res);
3738

3739
  mark_point();
1✔
3740
  res[sizeof(res)-1] = '\0';
3741
  path = "/tmp/../test.d/../.././../../../././/test.txt";
1✔
3742
  pr_fs_clean_path(path, res, sizeof(res)-1);
1✔
3743
  expected = "/test.txt";
1✔
3744
  ck_assert_msg(strcmp(res, expected) == 0,
1✔
3745
    "Expected cleaned path '%s', got '%s'", path, res);
3746
}
3747
END_TEST
1✔
3748

3749
START_TEST (fs_clean_path2_test) {
1✔
3750
  char res[PR_TUNABLE_PATH_MAX+1], *path, *expected;
1✔
3751
  int code;
1✔
3752

3753
  mark_point();
3754
  code = pr_fs_clean_path2(NULL, NULL, 0, 0);
1✔
3755
  ck_assert_msg(code < 0, "Failed to handle null path");
1✔
3756
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
3757
    strerror(errno), errno);
1✔
3758

3759
  path = "/";
1✔
3760

3761
  mark_point();
3762
  code = pr_fs_clean_path2(path, NULL, 0, 0);
1✔
3763
  ck_assert_msg(code < 0, "Failed to handle null buf");
1✔
3764
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
3765
    strerror(errno), errno);
1✔
3766

3767
  mark_point();
1✔
3768
  res[sizeof(res)-1] = '\0';
1✔
3769
  code = pr_fs_clean_path2(path, res, 0, 0);
3770
  ck_assert_msg(code == 0, "Failed to handle zero length buf: %s",
3771
    strerror(errno));
1✔
3772

1✔
3773
  mark_point();
1✔
3774
  res[sizeof(res)-1] = '\0';
1✔
3775
  path = "test.txt";
3776
  code = pr_fs_clean_path2(path, res, sizeof(res)-1, 0);
1✔
3777
  ck_assert_msg(code == 0, "Failed to clean path '%s': %s", path,
1✔
3778
    strerror(errno));
3779
  ck_assert_msg(strcmp(res, path) == 0, "Expected cleaned path '%s', got '%s'",
3780
    path, res);
1✔
3781

1✔
3782
  mark_point();
1✔
3783
  res[sizeof(res)-1] = '\0';
3784
  path = "/./test.txt";
1✔
3785
  code = pr_fs_clean_path2(path, res, sizeof(res)-1, 0);
3786
  ck_assert_msg(code == 0, "Failed to clean path '%s': %s", path,
1✔
3787
    strerror(errno));
1✔
3788
  expected = "/test.txt";
3789
  ck_assert_msg(strcmp(res, expected) == 0,
1✔
3790
    "Expected cleaned path '%s', got '%s'", expected, res);
3791

3792
  mark_point();
1✔
3793
  res[sizeof(res)-1] = '\0';
1✔
3794
  path = "test.d///test.txt";
1✔
3795
  code = pr_fs_clean_path2(path, res, sizeof(res)-1, 0);
3796
  ck_assert_msg(code == 0, "Failed to clean path '%s': %s", path,
1✔
3797
    strerror(errno));
1✔
3798
  expected = "test.d/test.txt";
1✔
3799
  ck_assert_msg(strcmp(res, expected) == 0,
3800
    "Expected cleaned path '%s', got '%s'", expected, res);
3801

1✔
3802
  mark_point();
1✔
3803
  res[sizeof(res)-1] = '\0';
1✔
3804
  path = "/test.d///test.txt";
3805
  code = pr_fs_clean_path2(path, res, sizeof(res)-1,
3806
    PR_FSIO_CLEAN_PATH_FL_MAKE_ABS_PATH);
1✔
3807
  ck_assert_msg(code == 0, "Failed to clean path '%s': %s", path,
1✔
3808
    strerror(errno));
1✔
3809
  expected = "/test.d/test.txt";
3810
  ck_assert_msg(strcmp(res, expected) == 0,
3811
    "Expected cleaned path '%s', got '%s'", expected, res);
1✔
3812

1✔
3813
  mark_point();
3814
  res[sizeof(res)-1] = '\0';
1✔
3815
  path = "/tmp/test.d/../.././../../test.txt";
3816
  code = pr_fs_clean_path2(path, res, sizeof(res)-1,
1✔
3817
    PR_FSIO_CLEAN_PATH_FL_MAKE_ABS_PATH);
1✔
3818
  ck_assert_msg(code == 0, "Failed to clean path '%s': %s", path,
1✔
3819
    strerror(errno));
3820
  expected = "/test.txt";
3821
  ck_assert_msg(strcmp(res, expected) == 0,
1✔
3822
    "Expected cleaned path '%s', got '%s'", expected, res);
1✔
3823

1✔
3824
  mark_point();
1✔
3825
  res[sizeof(res)-1] = '\0';
1✔
3826
  path = "../tmp/test.d/../.././../../test.txt";
1✔
3827
  code = pr_fs_clean_path2(path, res, sizeof(res)-1,
3828
    PR_FSIO_CLEAN_PATH_FL_MAKE_ABS_PATH);
3829
  ck_assert_msg(code == 0, "Failed to clean path '%s': %s", path,
1✔
3830
    strerror(errno));
1✔
3831
  expected = "/test.txt";
1✔
3832
  ck_assert_msg(strcmp(res, expected) == 0,
1✔
3833
    "Expected cleaned path '%s', got '%s'", expected, res);
1✔
3834

1✔
3835
  mark_point();
3836
  res[sizeof(res)-1] = '\0';
3837
  path = "./tmp/test.d/../.././../../test.txt";
1✔
3838
  code = pr_fs_clean_path2(path, res, sizeof(res)-1,
1✔
3839
    PR_FSIO_CLEAN_PATH_FL_MAKE_ABS_PATH);
1✔
3840
  ck_assert_msg(code == 0, "Failed to clean path '%s': %s", path,
1✔
3841
    strerror(errno));
1✔
3842
  expected = "/test.txt";
1✔
3843
  ck_assert_msg(strcmp(res, expected) == 0,
3844
    "Expected cleaned path '%s', got '%s'", expected, res);
3845

1✔
3846
  mark_point();
1✔
3847
  res[sizeof(res)-1] = '\0';
1✔
3848
  path = "./tmp/test.d/../.././../../test.txt/.";
1✔
3849
  code = pr_fs_clean_path2(path, res, sizeof(res)-1,
1✔
3850
    PR_FSIO_CLEAN_PATH_FL_MAKE_ABS_PATH);
1✔
3851
  ck_assert_msg(code == 0, "Failed to clean path '%s': %s", path,
3852
    strerror(errno));
3853
  expected = "/test.txt";
1✔
3854
  ck_assert_msg(strcmp(res, expected) == 0,
1✔
3855
    "Expected cleaned path '%s', got '%s'", expected, res);
1✔
3856
}
1✔
3857
END_TEST
1✔
3858

1✔
3859
START_TEST (fs_dircat_test) {
3860
  char buf[PR_TUNABLE_PATH_MAX+1], *a, *b, *ok;
3861
  int res;
1✔
3862

1✔
3863
  res = pr_fs_dircat(NULL, 0, NULL, NULL);
1✔
3864
  ck_assert_msg(res == -1, "Failed to handle null arguments");
1✔
3865
  ck_assert_msg(errno == EINVAL,
1✔
3866
    "Failed to set errno to EINVAL for null arguments");
1✔
3867

3868
  res = pr_fs_dircat(buf, 0, "foo", "bar");
1✔
3869
  ck_assert_msg(res == -1, "Failed to handle zero-length buffer");
3870
  ck_assert_msg(errno == EINVAL,
3871
    "Failed to set errno to EINVAL for zero-length buffer");
1✔
3872

1✔
3873
  res = pr_fs_dircat(buf, -1, "foo", "bar");
1✔
3874
  ck_assert_msg(res == -1, "Failed to handle negative-length buffer");
3875
  ck_assert_msg(errno == EINVAL,
3876
    "Failed to set errno to EINVAL for negative-length buffer");
3877

3878
  a = pcalloc(p, PR_TUNABLE_PATH_MAX);
1✔
3879
  memset(a, 'A', PR_TUNABLE_PATH_MAX-1);
1✔
3880

3881
  b = "foo";
3882

1✔
3883
  res = pr_fs_dircat(buf, sizeof(buf)-1, a, b);
1✔
3884
  ck_assert_msg(res == -1, "Failed to handle too-long paths");
3885
  ck_assert_msg(errno == ENAMETOOLONG,
1✔
3886
    "Failed to set errno to ENAMETOOLONG for too-long paths");
3887

3888
  a = "foo";
1✔
3889
  b = "/bar";
1✔
3890
  ok = b;
3891
  res = pr_fs_dircat(buf, sizeof(buf)-1, a, b);
1✔
3892
  ck_assert_msg(res == 0, "Failed to concatenate abs-path path second dir");
1✔
3893
  ck_assert_msg(strcmp(buf, ok) == 0,
3894
    "Expected concatenated dir '%s', got '%s'", ok, buf);
3895

1✔
3896
  a = "foo";
1✔
3897
  b = "bar";
1✔
3898
  ok = "foo/bar";
3899
  res = pr_fs_dircat(buf, sizeof(buf)-1, a, b);
1✔
3900
  ck_assert_msg(res == 0, "Failed to concatenate two normal paths");
1✔
3901
  ck_assert_msg(strcmp(buf, ok) == 0,
1✔
3902
    "Expected concatenated dir '%s', got '%s'", ok, buf);
3903

3904
  a = "foo/";
1✔
3905
  b = "bar";
1✔
3906
  ok = "foo/bar";
1✔
3907
  res = pr_fs_dircat(buf, sizeof(buf)-1, a, b);
3908
  ck_assert_msg(res == 0, "Failed to concatenate first dir with trailing slash");
3909
  ck_assert_msg(strcmp(buf, ok) == 0, "Expected concatenated dir '%s', got '%s'",
1✔
3910
    ok, buf);
1✔
3911

1✔
3912
  a = "";
3913
  b = "";
1✔
3914
  ok = "/";
3915
  res = pr_fs_dircat(buf, sizeof(buf)-1, a, b);
3916
  ck_assert_msg(res == 0, "Failed to concatenate two empty paths");
1✔
3917
  ck_assert_msg(strcmp(buf, ok) == 0, "Expected concatenated dir '%s', got '%s'",
1✔
3918
    ok, buf);
1✔
3919

1✔
3920
  a = "/foo";
3921
  b = "";
1✔
3922
  ok = "/foo/";
3923
  res = pr_fs_dircat(buf, sizeof(buf)-1, a, b);
3924
  ck_assert_msg(res == 0, "Failed to concatenate two empty paths");
1✔
3925
  ck_assert_msg(strcmp(buf, ok) == 0, "Expected concatenated dir '%s', got '%s'",
1✔
3926
    ok, buf);
1✔
3927

1✔
3928
  a = "";
3929
  b = "/bar";
1✔
3930
  ok = "/bar/";
1✔
3931
  res = pr_fs_dircat(buf, sizeof(buf)-1, a, b);
1✔
3932
  ck_assert_msg(res == 0, "Failed to concatenate two empty paths");
3933
  ck_assert_msg(strcmp(buf, ok) == 0, "Expected concatenated dir '%s', got '%s'",
3934
    ok, buf);
1✔
3935
}
1✔
3936
END_TEST
1✔
3937

1✔
3938
START_TEST (fs_setcwd_test) {
3939
  int res;
3940
  const char *wd;
1✔
3941

1✔
3942
  /* Make sure that we don't segfault if we call pr_fs_setcwd() on the
1✔
3943
   * buffer that it is already using.
1✔
3944
   */
3945
  res = pr_fs_setcwd(pr_fs_getcwd());
3946
  ck_assert_msg(res == 0, "Failed to set cwd to '%s': %s", pr_fs_getcwd(),
1✔
3947
    strerror(errno));
1✔
3948

1✔
3949
  wd = pr_fs_getcwd();
3950
  ck_assert_msg(wd != NULL, "Failed to get working directory: %s",
3951
    strerror(errno));
1✔
3952
  ck_assert_msg(strcmp(wd, fsio_cwd) == 0,
1✔
3953
    "Expected '%s', got '%s'", fsio_cwd, wd);
1✔
3954

3955
  wd = pr_fs_getvwd();
1✔
3956
  ck_assert_msg(wd != NULL, "Failed to get working directory: %s",
1✔
3957
    strerror(errno));
1✔
3958
  ck_assert_msg(strcmp(wd, "/") == 0, "Expected '/', got '%s'", wd);
3959
}
3960
END_TEST
1✔
3961

1✔
3962
START_TEST (fs_glob_test) {
3963
  glob_t pglob;
1✔
3964
  int res;
1✔
3965

1✔
3966
  res = pr_fs_glob(NULL, 0, NULL, NULL);
3967
  ck_assert_msg(res < 0, "Failed to handle null arguments");
3968
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
3969
    strerror(errno), errno);
1✔
3970

1✔
3971
  res = pr_fs_glob(NULL, 0, NULL, &pglob);
3972
  ck_assert_msg(res < 0, "Failed to handle null arguments");
3973
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
3974
    strerror(errno), errno);
1✔
3975

1✔
3976
  memset(&pglob, 0, sizeof(pglob));
3977
  res = pr_fs_glob("*", 0, NULL, &pglob);
1✔
3978
  ck_assert_msg(res == 0, "Failed to glob: glob(3) returned %d: %s", res,
3979
    strerror(errno));
1✔
3980
  ck_assert_msg(pglob.gl_pathc > 0, "Expected >0, got %lu",
1✔
3981
    (unsigned long) pglob.gl_pathc);
1✔
3982

3983
  mark_point();
1✔
3984
  pr_fs_globfree(NULL);
1✔
3985
  if (res == 0) {
1✔
3986
    pr_fs_globfree(&pglob);
3987
  }
3988
}
3989
END_TEST
2✔
3990

2✔
3991
START_TEST (fs_copy_file_test) {
2✔
3992
  int res;
3993
  char *src_path = NULL, *dst_path = NULL, *text;
1✔
3994
  pr_fh_t *fh;
1✔
3995

1✔
3996
  res = pr_fs_copy_file(NULL, NULL);
1✔
3997
  ck_assert_msg(res < 0, "Failed to handle null arguments");
3998
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
3999
    strerror(errno), errno);
1✔
4000

1✔
4001
  src_path = (char *) fsio_copy_src_path;
4002
  res = pr_fs_copy_file(src_path, NULL);
1✔
4003
  ck_assert_msg(res < 0, "Failed to handle null destination path");
1✔
4004
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
4005
    strerror(errno), errno);
1✔
4006

1✔
4007
  dst_path = (char *) fsio_copy_dst_path;
4008
  res = pr_fs_copy_file(src_path, dst_path);
1✔
4009
  ck_assert_msg(res < 0, "Failed to handle nonexistent source path");
1✔
4010
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
1✔
4011
    strerror(errno), errno);
4012

4013
  res = pr_fs_copy_file("/tmp", dst_path);
1✔
4014
  ck_assert_msg(res < 0, "Failed to handle directory source path");
1✔
4015
  ck_assert_msg(errno == EISDIR, "Expected EISDIR (%d), got %s (%d)", EISDIR,
4016
    strerror(errno), errno);
1✔
4017

4018
  (void) unlink(src_path);
1✔
4019
  fh = pr_fsio_open(src_path, O_CREAT|O_EXCL|O_WRONLY);
1✔
4020
  ck_assert_msg(fh != NULL, "Failed to open '%s': %s", src_path, strerror(errno));
1✔
4021

4022
  text = "Hello, World!\n";
1✔
4023
  res = pr_fsio_write(fh, text, strlen(text));
1✔
4024
  ck_assert_msg(res >= 0, "Failed to write '%s' to '%s': %s", text, src_path,
4025
    strerror(errno));
1✔
4026

4027
  res = pr_fsio_close(fh);
1✔
4028
  ck_assert_msg(res == 0, "Failed to close '%s': %s", src_path, strerror(errno));
4029

4030
  res = pr_fs_copy_file(src_path, "/tmp");
1✔
4031
  ck_assert_msg(res < 0, "Failed to handle directory destination path");
1✔
4032
  ck_assert_msg(errno == EISDIR, "Expected EISDIR (%d), got %s (%d)", EISDIR,
1✔
4033
    strerror(errno), errno);
4034

1✔
4035
  res = pr_fs_copy_file(src_path, "/tmp/foo/bar/baz/quxx/quzz.dat");
4036
  ck_assert_msg(res < 0, "Failed to handle nonexistent destination path");
1✔
4037
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
1✔
4038
    strerror(errno), errno);
1✔
4039

1✔
4040
  mark_point();
4041
  res = pr_fs_copy_file(src_path, src_path);
4042
  ck_assert_msg(res == 0, "Failed to copy file to itself: %s", strerror(errno));
1✔
4043

1✔
4044
  (void) unlink(dst_path);
1✔
4045

1✔
4046
  mark_point();
1✔
4047
  res = pr_fs_copy_file(src_path, dst_path);
4048
  ck_assert_msg(res == 0, "Failed to copy file: %s", strerror(errno));
4049

1✔
4050
  (void) pr_fsio_unlink(src_path);
1✔
4051
  (void) pr_fsio_unlink(dst_path);
1✔
4052
}
1✔
4053
END_TEST
4054

4055
static unsigned int copy_progress_iter = 0;
1✔
4056
static void copy_progress_cb(int nwritten) {
1✔
4057
  copy_progress_iter++;
1✔
4058
}
4059

1✔
4060
START_TEST (fs_copy_file2_test) {
4061
  int res, flags;
1✔
4062
  char *src_path, *dst_path, *text;
1✔
4063
  pr_fh_t *fh;
1✔
4064

1✔
4065
  src_path = (char *) fsio_copy_src_path;
4066
  dst_path = (char *) fsio_copy_dst_path;
1✔
4067
  flags = PR_FSIO_COPY_FILE_FL_NO_DELETE_ON_FAILURE;
4068

4069
  (void) unlink(src_path);
1✔
4070
  (void) unlink(dst_path);
1✔
4071

1✔
4072
  fh = pr_fsio_open(src_path, O_CREAT|O_EXCL|O_WRONLY);
1✔
4073
  ck_assert_msg(fh != NULL, "Failed to open '%s': %s", src_path, strerror(errno));
4074

1✔
4075
  text = "Hello, World!\n";
4076
  res = pr_fsio_write(fh, text, strlen(text));
1✔
4077
  ck_assert_msg(res >= 0, "Failed to write '%s' to '%s': %s", text, src_path,
1✔
4078
    strerror(errno));
1✔
4079

1✔
4080
  res = pr_fsio_close(fh);
4081
  ck_assert_msg(res == 0, "Failed to close '%s': %s", src_path, strerror(errno));
1✔
4082

4083
  copy_progress_iter = 0;
4084

1✔
4085
  mark_point();
4086
  res = pr_fs_copy_file2(src_path, dst_path, flags, copy_progress_cb);
1✔
4087
  ck_assert_msg(res == 0, "Failed to copy file: %s", strerror(errno));
1✔
4088

1✔
4089
  (void) pr_fsio_unlink(src_path);
1✔
4090
  (void) pr_fsio_unlink(dst_path);
4091

1✔
4092
  ck_assert_msg(copy_progress_iter > 0, "Unexpected progress callback count (%u)",
4093
    copy_progress_iter);
4094
}
1✔
4095
END_TEST
4096

1✔
4097
START_TEST (fs_interpolate_test) {
1✔
4098
  int res;
1✔
4099
  char buf[PR_TUNABLE_PATH_MAX], *path;
1✔
4100

1✔
4101
  memset(buf, '\0', sizeof(buf));
4102

4103
  mark_point();
1✔
4104
  res = pr_fs_interpolate(NULL, NULL, 0);
1✔
4105
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
4106
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
4107
    strerror(errno), errno);
1✔
4108

1✔
4109
  mark_point();
4110
  path = "/tmp";
4111
  res = pr_fs_interpolate(path, NULL, 0);
1✔
4112
  ck_assert_msg(res < 0, "Failed to handle null buffer");
1✔
4113
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
4114
    strerror(errno), errno);
1✔
4115

1✔
4116
  mark_point();
4117
  res = pr_fs_interpolate(path, buf, 0);
1✔
4118
  ck_assert_msg(res < 0, "Failed to handle zero buffer length");
4119
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
4120
    strerror(errno), errno);
1✔
4121

1✔
4122
  mark_point();
1✔
4123
  res = pr_fs_interpolate(path, buf, sizeof(buf)-1);
4124
  ck_assert_msg(res == 1, "Failed to interpolate path '%s': %s", path,
4125
    strerror(errno));
1✔
4126
  ck_assert_msg(strcmp(buf, path) == 0, "Expected '%s', got '%s'", path, buf);
1✔
4127

1✔
4128
  mark_point();
4129
  path = "~/foo/bar/baz/quzz/quzz.d";
1✔
4130
  res = pr_fs_interpolate(path, buf, sizeof(buf)-1);
1✔
4131
  ck_assert_msg(res == 1, "Failed to interpolate path '%s': %s", path,
1✔
4132
    strerror(errno));
4133
  ck_assert_msg(strcmp(buf, path+1) == 0, "Expected '%s', got '%s'",
4134
    path + 1, buf);
1✔
4135

1✔
4136
  mark_point();
1✔
4137
  path = "~";
1✔
4138
  res = pr_fs_interpolate(path, buf, sizeof(buf)-1);
4139
  ck_assert_msg(res == 1, "Failed to interpolate path '%s': %s", path,
4140
    strerror(errno));
1✔
4141
  ck_assert_msg(strcmp(buf, "/") == 0, "Expected '/', got '%s'", buf);
1✔
4142

1✔
4143
  mark_point();
1✔
4144
  session.chroot_path = "/tmp";
4145
  res = pr_fs_interpolate(path, buf, sizeof(buf)-1);
4146
  ck_assert_msg(res == 1, "Failed to interpolate path '%s': %s", path,
1✔
4147
    strerror(errno));
1✔
4148
  ck_assert_msg(strcmp(buf, session.chroot_path) == 0,
1✔
4149
    "Expected '%s', got '%s'", session.chroot_path, buf);
4150

×
4151
  session.chroot_path = NULL;
4152

×
4153
  mark_point();
×
4154
  session.user_homedir = "/foo";
4155
  res = pr_fs_interpolate(path, buf, sizeof(buf)-1);
4156
  ck_assert_msg(res == 1, "Failed to interpolate path '%s': %s", path,
4157
    strerror(errno));
1✔
4158
  ck_assert_msg(strcmp(buf, session.user_homedir) == 0,
1✔
4159
    "Expected '%s', got '%s'", session.user_homedir, buf);
1✔
4160

1✔
4161
  session.user_homedir = NULL;
4162

1✔
4163
  mark_point();
4164
  path = "~foo.bar.baz.quzz";
1✔
4165
  res = pr_fs_interpolate(path, buf, sizeof(buf)-1);
1✔
4166
  ck_assert_msg(res < 0, "Interpolated '%s' unexpectedly", path);
×
4167
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
4168
    strerror(errno), errno);
4169

4170
  mark_point();
1✔
4171
  session.user = "testsuite";
1✔
4172
  path = "~/tmp.d/test.d/foo.d/bar.d";
1✔
4173
  res = pr_fs_interpolate(path, buf, sizeof(buf)-1);
1✔
4174
  ck_assert_msg(res < 0, "Interpolated '%s' unexpectedly", path);
4175
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
×
4176
    strerror(errno), errno);
4177

×
4178
  mark_point();
×
4179
  session.user_homedir = "/cached";
4180
  path = "~/tmp.d/test.d/foo.d/bar.d";
4181
  res = pr_fs_interpolate(path, buf, sizeof(buf)-1);
4182
  ck_assert_msg(res == 1, "Failed to interpolate path '%s': %s", path,
1✔
4183
    strerror(errno));
1✔
4184
  ck_assert_msg(strcmp(buf, "/cached/tmp.d/test.d/foo.d/bar.d") == 0,
1✔
4185
    "Expected '/cached/tmp.d/test.d/foo.d/bar.d', got '%s'", buf);
1✔
4186

4187
  session.user = NULL;
4188
  session.user_homedir = NULL;
1✔
4189
}
1✔
4190
END_TEST
1✔
4191

1✔
4192
START_TEST (fs_resolve_partial_test) {
4193
  int op = FSIO_FILE_STAT, res;
4194
  char buf[PR_TUNABLE_PATH_MAX], *path;
1✔
4195

1✔
4196
  res = pr_fs_resolve_partial(NULL, NULL, 0, op);
1✔
4197
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
4198
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
4199
    strerror(errno), errno);
4200

4201
  path = "/tmp";
1✔
4202
  res = pr_fs_resolve_partial(path, NULL, 0, op);
1✔
4203
  ck_assert_msg(res < 0, "Failed to handle null buffer");
4204
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
4205
    strerror(errno), errno);
1✔
4206

1✔
4207
  memset(buf, '\0', sizeof(buf));
4208
  res = pr_fs_resolve_partial(path, buf, 0, op);
4209
  ck_assert_msg(res < 0, "Failed to handle zero buffer length");
1✔
4210
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
4211
    strerror(errno), errno);
4212

4213
  res = pr_fs_resolve_partial(path, buf, sizeof(buf)-1, op);
1✔
4214
  ck_assert_msg(res == 0, "Failed to resolve '%s': %s", path, strerror(errno));
1✔
4215
  if (strcmp(buf, path) != 0) {
1✔
4216
    /* Mac-specific hack */
4217
    const char *prefix = "/private";
1✔
4218

4219
    if (strncmp(buf, prefix, strlen(prefix)) != 0) {
1✔
4220
      ck_abort_msg("Expected '%s', got '%s'", path, buf);
1✔
4221
    }
1✔
4222
  }
4223

4224
  path = "/tmp/.////./././././.";
1✔
4225
  res = pr_fs_resolve_partial(path, buf, sizeof(buf)-1, op);
1✔
4226
  ck_assert_msg(res == 0, "Failed to resolve '%s': %s", path, strerror(errno));
1✔
4227
  if (strcmp(buf, path) != 0) {
1✔
4228
    /* Mac-specific hack */
4229
    const char *prefix = "/private";
4230

1✔
4231
    if (strncmp(buf, prefix, strlen(prefix)) != 0 &&
1✔
4232
        strcmp(buf, "/tmp/") != 0) {
1✔
4233
      ck_abort_msg("Expected '%s', got '%s'", path, buf);
4234
    }
4235
  }
1✔
4236

1✔
4237
  path = "/../../../.././..///../";
4238
  res = pr_fs_resolve_partial(path, buf, sizeof(buf)-1, op);
1✔
4239
  ck_assert_msg(res == 0, "Failed to resolve '%s': %s", path, strerror(errno));
4240
  if (strcmp(buf, "/") != 0) {
×
4241
    /* Mac-specific hack */
4242
    const char *prefix = "/private";
×
4243

×
4244
    if (strncmp(buf, prefix, strlen(prefix)) != 0) {
4245
      ck_abort_msg("Expected '%s', got '%s'", path, buf);
4246
    }
4247
  }
4248

1✔
4249
  path = "/tmp/.///../../..../";
1✔
4250
  res = pr_fs_resolve_partial(path, buf, sizeof(buf)-1, op);
4251
  ck_assert_msg(res < 0, "Resolved '%s' unexpectedly", path);
4252
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
1✔
4253
    strerror(errno), errno);
1✔
4254

4255
  path = "~foo/.///../../..../";
4256
  res = pr_fs_resolve_partial(path, buf, sizeof(buf)-1, op);
1✔
4257
  ck_assert_msg(res < 0, "Resolved '%s' unexpectedly", path);
1✔
4258
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
4259
    strerror(errno), errno);
4260

1✔
4261
  path = "../../..../";
1✔
4262
  res = pr_fs_resolve_partial(path, buf, sizeof(buf)-1, op);
4263
  ck_assert_msg(res < 0, "Resolved '%s' unexpectedly", path);
1✔
4264
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
1✔
4265
    strerror(errno), errno);
1✔
4266

4267
  /* Resolve a symlink path */
4268
  res = pr_fsio_symlink("/tmp", fsio_link_path);
1✔
4269
  ck_assert_msg(res == 0, "Failed to create symlink to '%s': %s", fsio_link_path,
1✔
4270
    strerror(errno));
4271

1✔
4272
  res = pr_fs_resolve_partial(fsio_link_path, buf, sizeof(buf)-1, op);
1✔
4273
  ck_assert_msg(res == 0, "Failed to resolve '%s': %s", fsio_link_path,
4274
    strerror(errno));
1✔
4275

1✔
4276
  (void) unlink(fsio_link_path);
1✔
4277
}
4278
END_TEST
4279

1✔
4280
START_TEST (fs_resolve_path_test) {
1✔
4281
  int op = FSIO_FILE_STAT, res;
1✔
4282
  char buf[PR_TUNABLE_PATH_MAX], *path;
1✔
4283

4284
  memset(buf, '\0', sizeof(buf));
1✔
4285

1✔
4286
  res = pr_fs_resolve_path(NULL, NULL, 0, op);
1✔
4287
  ck_assert_msg(res < 0, "Failed to handle null arguments");
4288
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
4289
    strerror(errno), errno);
1✔
4290

1✔
4291
  path = "/tmp";
1✔
4292
  res = pr_fs_resolve_path(path, NULL, 0, op);
4293
  ck_assert_msg(res < 0, "Failed to handle null buffer");
4294
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
4295
    strerror(errno), errno);
1✔
4296

1✔
4297
  res = pr_fs_resolve_path(path, buf, 0, op);
4298
  ck_assert_msg(res < 0, "Failed to handle zero buffer length");
4299
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
4300
    strerror(errno), errno);
1✔
4301

1✔
4302
  res = pr_fs_resolve_path(path, buf, sizeof(buf)-1, op);
4303
  ck_assert_msg(res == 0, "Failed to resolve path '%s': %s", path,
4304
    strerror(errno));
4305
  if (strcmp(buf, path) != 0) {
1✔
4306
    /* Mac-specific hack */
1✔
4307
    const char *prefix = "/private";
1✔
4308

1✔
4309
    if (strncmp(buf, prefix, strlen(prefix)) != 0) {
4310
      ck_abort_msg("Expected '%s', got '%s'", path, buf);
4311
    }
4312
  }
4313

1✔
4314
  /* Resolve a symlink path */
4315
  res = pr_fsio_symlink("/tmp", fsio_link_path);
4316
  ck_assert_msg(res == 0, "Failed to create symlink to '%s': %s", fsio_link_path,
1✔
4317
    strerror(errno));
1✔
4318

1✔
4319
  res = pr_fs_resolve_path(fsio_link_path, buf, sizeof(buf)-1, op);
4320
  ck_assert_msg(res == 0, "Failed to resolve '%s': %s", fsio_link_path,
1✔
4321
    strerror(errno));
1✔
4322

1✔
4323
  (void) unlink(fsio_link_path);
4324
}
4325
END_TEST
1✔
4326

1✔
4327
START_TEST (fs_use_encoding_test) {
1✔
4328
  int res;
4329

4330
  res = pr_fs_use_encoding(-1);
1✔
4331
  ck_assert_msg(res < 0, "Failed to handle invalid setting");
1✔
4332
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
4333
    strerror(errno), errno);
4334

4335
  res = pr_fs_use_encoding(TRUE);
4336
  ck_assert_msg(res == TRUE, "Expected TRUE, got %d", res);
1✔
4337

1✔
4338
  res = pr_fs_use_encoding(FALSE);
1✔
4339
  ck_assert_msg(res == TRUE, "Expected TRUE, got %d", res);
1✔
4340

1✔
4341
  res = pr_fs_use_encoding(TRUE);
4342
  ck_assert_msg(res == FALSE, "Expected FALSE, got %d", res);
4343
}
1✔
4344
END_TEST
1✔
4345

1✔
4346
START_TEST (fs_decode_path2_test) {
4347
  int flags = 0;
1✔
4348
  char junk[32], *res;
1✔
4349
  const char *path;
1✔
4350

1✔
4351
  res = pr_fs_decode_path(NULL, NULL);
4352
  ck_assert_msg(res == NULL, "Failed to handle null arguments");
4353
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
4354
    strerror(errno), errno);
1✔
4355

1✔
4356
  res = pr_fs_decode_path(p, NULL);
1✔
4357
  ck_assert_msg(res == NULL, "Failed to handle null path");
4358
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
4359
    strerror(errno), errno);
1✔
4360

4361
  path = "/tmp";
1✔
4362
  res = pr_fs_decode_path2(p, path, flags);
1✔
4363
  ck_assert_msg(res != NULL, "Failed to decode path '%s': %s", path,
1✔
4364
    strerror(errno));
1✔
4365

4366
  path = "/tmp";
4367
  res = pr_fs_decode_path2(p, path, flags);
1✔
4368
  ck_assert_msg(res != NULL, "Failed to decode path '%s': %s", path,
4369
    strerror(errno));
1✔
4370

1✔
4371
  /* Test a path that cannot be decoded, using junk data from the stack */
1✔
4372
  junk[sizeof(junk)-1] = '\0';
4373
  path = junk;
1✔
4374
  res = pr_fs_decode_path2(p, path, flags);
1✔
4375
  ck_assert_msg(res != NULL, "Failed to decode path: %s", strerror(errno));
4376

4377
  /* XXX Use the FSIO_DECODE_FL_TELL_ERRORS flags, AND set the encode
4378
   * policy to use PR_ENCODE_POLICY_FL_REQUIRE_VALID_ENCODING.
4379
   */
4380
}
1✔
4381
END_TEST
4382

1✔
4383
START_TEST (fs_encode_path_test) {
4384
  char junk[32], *res;
1✔
4385
  const char *path;
1✔
4386

1✔
4387
  res = pr_fs_encode_path(NULL, NULL);
4388
  ck_assert_msg(res == NULL, "Failed to handle null arguments");
1✔
4389
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
4390
    strerror(errno), errno);
1✔
4391

4392
  res = pr_fs_encode_path(p, NULL);
1✔
4393
  ck_assert_msg(res == NULL, "Failed to handle null path");
4394
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
4395
    strerror(errno), errno);
1✔
4396

1✔
4397
  path = "/tmp";
4398
  res = pr_fs_encode_path(p, path);
1✔
4399
  ck_assert_msg(res != NULL, "Failed to encode path '%s': %s", path,
1✔
4400
    strerror(errno));
1✔
4401

4402
  /* Test a path that cannot be encoded, using junk data from the stack */
1✔
4403
  junk[sizeof(junk)-1] = '\0';
4404
  path = junk;
1✔
4405
  res = pr_fs_encode_path(p, path);
1✔
4406
  ck_assert_msg(res != NULL, "Failed to encode path: %s", strerror(errno));
1✔
4407
}
4408
END_TEST
1✔
4409

1✔
4410
START_TEST (fs_split_path_test) {
1✔
4411
  array_header *res;
1✔
4412
  const char *path, *elt;
1✔
4413

1✔
4414
  mark_point();
1✔
4415
  res = pr_fs_split_path(NULL, NULL);
1✔
4416
  ck_assert_msg(res == NULL, "Failed to handle null pool");
1✔
4417
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
4418
    strerror(errno), errno);
1✔
4419

4420
  mark_point();
1✔
4421
  res = pr_fs_split_path(p, NULL);
1✔
4422
  ck_assert_msg(res == NULL, "Failed to handle null path");
1✔
4423
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
4424
    strerror(errno), errno);
1✔
4425

1✔
4426
  path = "";
1✔
4427

1✔
4428
  mark_point();
1✔
4429
  res = pr_fs_split_path(p, path);
1✔
4430
  ck_assert_msg(res == NULL, "Failed to handle empty path");
1✔
4431
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
4432
    strerror(errno), errno);
1✔
4433

4434
  path = ".";
1✔
4435

4436
  mark_point();
1✔
4437
  res = pr_fs_split_path(p, path);
1✔
4438
  ck_assert_msg(res != NULL, "Failed to split path '%s': %s", path,
1✔
4439
    strerror(errno));
4440
  ck_assert_msg(res->nelts == 1, "Expected 1, got %u", res->nelts);
1✔
4441
  elt = ((char **) res->elts)[0];
1✔
4442

1✔
4443
  /* Note: pr_fs_split_path() cleans the path into an absolute path.  And
1✔
4444
   * the default "cwd" test setting is "/", so yes, this is surprising but
1✔
4445
   * expected.  Subject to change in the future.
1✔
4446
   */
1✔
4447
  ck_assert_msg(strcmp(elt, "/") == 0, "Expected '/', got '%s'", elt);
1✔
4448

1✔
4449
  path = "/";
4450

1✔
4451
  mark_point();
4452
  res = pr_fs_split_path(p, path);
1✔
4453
  ck_assert_msg(res != NULL, "Failed to split path '%s': %s", path,
1✔
4454
    strerror(errno));
1✔
4455
  ck_assert_msg(res->nelts == 1, "Expected 1, got %u", res->nelts);
4456
  elt = ((char **) res->elts)[0];
1✔
4457
  ck_assert_msg(strcmp(elt, "/") == 0, "Expected '/', got '%s'", elt);
1✔
4458

1✔
4459
  path = "///";
1✔
4460

1✔
4461
  mark_point();
1✔
4462
  res = pr_fs_split_path(p, path);
1✔
4463
  ck_assert_msg(res != NULL, "Failed to split path '%s': %s", path,
1✔
4464
    strerror(errno));
4465
  ck_assert_msg(res->nelts == 1, "Expected 1, got %u", res->nelts);
4466
  elt = ((char **) res->elts)[0];
1✔
4467
  ck_assert_msg(strcmp(elt, "/") == 0, "Expected '/', got '%s'", elt);
1✔
4468

1✔
4469
  path = "/foo/bar/baz/";
4470

1✔
4471
  mark_point();
1✔
4472
  res = pr_fs_split_path(p, path);
1✔
4473
  ck_assert_msg(res != NULL, "Failed to split path '%s': %s", path,
1✔
4474
    strerror(errno));
4475
  ck_assert_msg(res->nelts == 4, "Expected 4, got %u", res->nelts);
4476
  elt = ((char **) res->elts)[0];
1✔
4477
  ck_assert_msg(strcmp(elt, "/") == 0, "Expected '/', got '%s'", elt);
1✔
4478
  elt = ((char **) res->elts)[1];
1✔
4479
  ck_assert_msg(strcmp(elt, "foo") == 0, "Expected 'foo', got '%s'", elt);
1✔
4480
  elt = ((char **) res->elts)[2];
4481
  ck_assert_msg(strcmp(elt, "bar") == 0, "Expected 'bar', got '%s'", elt);
4482
  elt = ((char **) res->elts)[3];
1✔
4483
  ck_assert_msg(strcmp(elt, "baz") == 0, "Expected 'baz', got '%s'", elt);
4484

1✔
4485
  path = "/foo//bar//baz//";
1✔
4486

1✔
4487
  mark_point();
1✔
4488
  res = pr_fs_split_path(p, path);
4489
  ck_assert_msg(res != NULL, "Failed to split path '%s': %s", path,
4490
    strerror(errno));
1✔
4491
  ck_assert_msg(res->nelts == 4, "Expected 4, got %u", res->nelts);
4492
  elt = ((char **) res->elts)[0];
1✔
4493
  ck_assert_msg(strcmp(elt, "/") == 0, "Expected '/', got '%s'", elt);
1✔
4494
  elt = ((char **) res->elts)[1];
1✔
4495
  ck_assert_msg(strcmp(elt, "foo") == 0, "Expected 'foo', got '%s'", elt);
1✔
4496
  elt = ((char **) res->elts)[2];
4497
  ck_assert_msg(strcmp(elt, "bar") == 0, "Expected 'bar', got '%s'", elt);
4498
  elt = ((char **) res->elts)[3];
1✔
4499
  ck_assert_msg(strcmp(elt, "baz") == 0, "Expected 'baz', got '%s'", elt);
1✔
4500

1✔
4501
  path = "/foo/bar/baz";
1✔
4502

4503
  mark_point();
4504
  res = pr_fs_split_path(p, path);
1✔
4505
  ck_assert_msg(res != NULL, "Failed to split path '%s': %s", path,
1✔
4506
    strerror(errno));
1✔
4507
  ck_assert_msg(res->nelts == 4, "Expected 4, got %u", res->nelts);
1✔
4508
  elt = ((char **) res->elts)[0];
4509
  ck_assert_msg(strcmp(elt, "/") == 0, "Expected '/', got '%s'", elt);
1✔
4510
  elt = ((char **) res->elts)[1];
1✔
4511
  ck_assert_msg(strcmp(elt, "foo") == 0, "Expected 'foo', got '%s'", elt);
1✔
4512
  elt = ((char **) res->elts)[2];
4513
  ck_assert_msg(strcmp(elt, "bar") == 0, "Expected 'bar', got '%s'", elt);
1✔
4514
  elt = ((char **) res->elts)[3];
1✔
4515
  ck_assert_msg(strcmp(elt, "baz") == 0, "Expected 'baz', got '%s'", elt);
1✔
4516

1✔
4517
  path = "foo/bar/baz";
4518

4519
  mark_point();
1✔
4520
  res = pr_fs_split_path(p, path);
1✔
4521
  ck_assert_msg(res != NULL, "Failed to split path '%s': %s", path,
1✔
4522
    strerror(errno));
1✔
4523
  ck_assert_msg(res->nelts == 3, "Expected 3, got %u", res->nelts);
4524
  elt = ((char **) res->elts)[0];
4525
  ck_assert_msg(strcmp(elt, "foo") == 0, "Expected 'foo', got '%s'", elt);
1✔
4526
  elt = ((char **) res->elts)[1];
1✔
4527
  ck_assert_msg(strcmp(elt, "bar") == 0, "Expected 'bar', got '%s'", elt);
4528
  elt = ((char **) res->elts)[2];
1✔
4529
  ck_assert_msg(strcmp(elt, "baz") == 0, "Expected 'baz', got '%s'", elt);
1✔
4530
}
1✔
4531
END_TEST
4532

1✔
4533
START_TEST (fs_join_path_test) {
1✔
4534
  char *path;
1✔
4535
  array_header *components;
4536

1✔
4537
  mark_point();
4538
  path = pr_fs_join_path(NULL, NULL, 0);
4539
  ck_assert_msg(path == NULL, "Failed to handle null pool");
1✔
4540
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
4541
    strerror(errno), errno);
1✔
4542

4543
  mark_point();
1✔
4544
  path = pr_fs_join_path(p, NULL, 0);
1✔
4545
  ck_assert_msg(path == NULL, "Failed to handle null components");
4546
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
4547
    strerror(errno), errno);
1✔
4548

1✔
4549
  components = make_array(p, 0, sizeof(char **));
4550

1✔
4551
  mark_point();
1✔
4552
  path = pr_fs_join_path(p, components, 0);
1✔
4553
  ck_assert_msg(path == NULL, "Failed to handle empty components");
1✔
4554
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
4555
    strerror(errno), errno);
1✔
4556

1✔
4557
  *((char **) push_array(components)) = pstrdup(p, "/");
1✔
4558

1✔
4559
  mark_point();
4560
  path = pr_fs_join_path(p, components, 0);
1✔
4561
  ck_assert_msg(path == NULL, "Failed to handle empty count");
1✔
4562
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
4563
    strerror(errno), errno);
1✔
4564

1✔
4565
  mark_point();
4566
  path = pr_fs_join_path(p, components, 3);
1✔
4567
  ck_assert_msg(path == NULL, "Failed to handle invalid count");
1✔
4568
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
4569
    strerror(errno), errno);
1✔
4570

1✔
4571
  mark_point();
4572
  path = pr_fs_join_path(p, components, 1);
4573
  ck_assert_msg(path != NULL, "Failed to join path: %s", strerror(errno));
1✔
4574
  ck_assert_msg(strcmp(path, "/") == 0, "Expected '/', got '%s'", path);
1✔
4575

1✔
4576
  *((char **) push_array(components)) = pstrdup(p, "foo");
1✔
4577
  *((char **) push_array(components)) = pstrdup(p, "bar");
1✔
4578
  *((char **) push_array(components)) = pstrdup(p, "baz");
1✔
4579

4580
  mark_point();
4581
  path = pr_fs_join_path(p, components, 4);
4582
  ck_assert_msg(path != NULL, "Failed to join path: %s", strerror(errno));
4583
  ck_assert_msg(strcmp(path, "/foo/bar/baz") == 0,
4584
    "Expected '/foo/bar/baz', got '%s'", path);
4585

4586
  mark_point();
4587
  path = pr_fs_join_path(p, components, 3);
4588
  ck_assert_msg(path != NULL, "Failed to join path: %s", strerror(errno));
4589
  ck_assert_msg(strcmp(path, "/foo/bar") == 0, "Expected '/foo/bar', got '%s'",
4590
    path);
4591

4592
  mark_point();
4593
  components = make_array(p, 0, sizeof(char **));
1✔
4594

1✔
4595
  *((char **) push_array(components)) = pstrdup(p, "foo");
4596
  *((char **) push_array(components)) = pstrdup(p, "bar");
1✔
4597
  *((char **) push_array(components)) = pstrdup(p, "baz");
1✔
4598

1✔
4599
  path = pr_fs_join_path(p, components, components->nelts);
1✔
4600
  ck_assert_msg(path != NULL, "Failed to join path: %s", strerror(errno));
4601
  ck_assert_msg(strcmp(path, "foo/bar/baz") == 0,
4602
    "Expected 'foo/bar/baz', got '%s'", path);
4603
}
1✔
4604
END_TEST
1✔
4605

1✔
4606
START_TEST (fs_virtual_path_test) {
4607
  const char *path;
1✔
4608
  char buf[PR_TUNABLE_PATH_MAX];
1✔
4609

1✔
4610
  mark_point();
4611
  pr_fs_virtual_path(NULL, NULL, 0);
1✔
4612

1✔
4613
  mark_point();
4614
  path = "/tmp";
4615
  pr_fs_virtual_path(path, NULL, 0);
1✔
4616

1✔
4617
  mark_point();
4618
  memset(buf, '\0', sizeof(buf));
1✔
4619
  pr_fs_virtual_path(path, buf, 0);
1✔
4620
  ck_assert_msg(*buf == '\0', "Expected empty buffer, got '%s'", buf);
1✔
4621

4622
  mark_point();
4623
  memset(buf, '\0', sizeof(buf));
1✔
4624
  pr_fs_virtual_path(path, buf, sizeof(buf)-1);
1✔
4625
  ck_assert_msg(strcmp(buf, path) == 0, "Expected '%s', got '%s'", path, buf);
1✔
4626

1✔
4627
  mark_point();
4628
  memset(buf, '\0', sizeof(buf));
4629
  path = "tmp";
4630
  pr_fs_virtual_path(path, buf, sizeof(buf)-1);
1✔
4631
  ck_assert_msg(strcmp(buf, "/tmp") == 0, "Expected '/tmp', got '%s'", buf);
1✔
4632

1✔
4633
  mark_point();
1✔
4634
  memset(buf, '\0', sizeof(buf));
4635
  path = "/tmp/././";
4636
  pr_fs_virtual_path(path, buf, sizeof(buf)-1);
1✔
4637
  ck_assert_msg(strcmp(buf, "/tmp") == 0 || strcmp(buf, "/tmp/") == 0,
1✔
4638
    "Expected '/tmp', got '%s'", buf);
1✔
4639

1✔
4640
  mark_point();
1✔
4641
  memset(buf, '\0', sizeof(buf));
1✔
4642
  path = "tmp/../../";
4643
  pr_fs_virtual_path(path, buf, sizeof(buf)-1);
4644
  ck_assert_msg(strcmp(buf, "/") == 0, "Expected '/', got '%s'", buf);
1✔
4645
}
1✔
4646
END_TEST
1✔
4647

4648
#if 0
1✔
4649
/* This test is commented out, since libcheck is very unhappy when we
1✔
4650
 * close its logging fds out from underneath it.  Thus we keep this
1✔
4651
 * test here, for any future tinkering, just not enabled by default.
4652
 */
4653
START_TEST (fs_close_extra_fds_test) {
1✔
4654
  mark_point();
1✔
4655
  pr_fs_close_extra_fds();
1✔
4656
}
4657
END_TEST
1✔
4658
#endif
4659

4660
START_TEST (fs_get_usable_fd_test) {
1✔
4661
  int fd, res;
1✔
4662

1✔
4663
  fd = -1;
1✔
4664
  res = pr_fs_get_usable_fd(fd);
4665
  ck_assert_msg(res < 0, "Failed to handle bad fd");
1✔
4666
  ck_assert_msg(errno == EBADF || errno == EINVAL,
1✔
4667
    "Expected EBADF (%d) or EINVAL (%d), got %s (%d)", EBADF, EINVAL,
1✔
4668
    strerror(errno), errno);
4669

4670
  fd = STDERR_FILENO + 1;
1✔
4671
  res = pr_fs_get_usable_fd(fd);
1✔
4672
  ck_assert_msg(res == fd, "Expected %d, got %d", fd, res);
1✔
4673

1✔
4674
  fd = STDERR_FILENO - 1;
4675
  res = pr_fs_get_usable_fd(fd);
4676
  ck_assert_msg(res > STDERR_FILENO, "Failed to get usable fd for %d: %s", fd,
1✔
4677
    strerror(errno));
1✔
4678
  (void) close(res);
4679
}
1✔
4680
END_TEST
4681

4682
START_TEST (fs_get_usable_fd2_test) {
1✔
4683
  int fd, res;
1✔
4684

1✔
4685
  res = pr_fs_get_usable_fd2(NULL);
4686
  ck_assert_msg(res < 0, "Failed to handle null argument");
1✔
4687
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
4688
    strerror(errno), errno);
1✔
4689

1✔
4690
  fd = -1;
4691
  res = pr_fs_get_usable_fd2(&fd);
4692
  ck_assert_msg(res < 0, "Failed to handle bad fd");
1✔
4693
  ck_assert_msg(errno == EBADF || errno == EINVAL,
1✔
4694
    "Expected EBADF (%d) or EINVAL (%d), got %s (%d)", EBADF, EINVAL,
1✔
4695
    strerror(errno), errno);
1✔
4696

1✔
4697
  fd = STDERR_FILENO + 1;
1✔
4698
  res = pr_fs_get_usable_fd2(&fd);
4699
  ck_assert_msg(res == 0, "Failed to handle fd: %s", strerror(errno));
4700
  ck_assert_msg(fd == (STDERR_FILENO + 1), "Expected %d, got %d",
1✔
4701
    STDERR_FILENO + 1, fd);
1✔
4702

1✔
4703
  fd = STDERR_FILENO - 1;
1✔
4704
  res = pr_fs_get_usable_fd2(&fd);
1✔
4705
  ck_assert_msg(res == 0, "Failed to handle fd: %s", strerror(errno));
4706
  ck_assert_msg(fd > STDERR_FILENO, "Expected >%d, got %d", STDERR_FILENO, fd);
1✔
4707
  (void) close(fd);
4708
}
4709
END_TEST
1✔
4710

1✔
4711
START_TEST (fs_getsize_test) {
1✔
4712
  off_t res;
4713
  char *path;
4714

4715
  res = pr_fs_getsize(NULL);
4716
  ck_assert_msg(res == (off_t) -1, "Failed to handle null argument");
4717
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
4718
    strerror(errno), errno);
1✔
4719

4720
  path = "/tmp";
1✔
4721
  res = pr_fs_getsize(path);
1✔
4722
  ck_assert_msg(res != (off_t) -1, "Failed to get fs size for '%s': %s", path,
4723
    strerror(errno));
1✔
4724
}
1✔
4725
END_TEST
4726

1✔
4727
START_TEST (fs_getsize2_test) {
1✔
4728
  int res;
4729
  char *path;
1✔
4730
  off_t sz = 0;
1✔
4731

4732
  res = pr_fs_getsize2(NULL, NULL);
1✔
4733
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
4734
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
4735
    strerror(errno), errno);
4736

4737
  path = "/tmp";
1✔
4738
  res = pr_fs_getsize2(path, NULL);
1✔
4739
  ck_assert_msg(res < 0, "Failed to handle null size argument");
1✔
4740
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
4741
    strerror(errno), errno);
1✔
4742

1✔
4743
  res = pr_fs_getsize2(path, &sz);
4744
  ck_assert_msg(res == 0, "Failed to get fs size for '%s': %s", path,
1✔
4745
    strerror(errno));
1✔
4746
}
1✔
4747
END_TEST
1✔
4748

4749
START_TEST (fs_fgetsize_test) {
4750
  int fd = -1, res;
1✔
4751
  off_t fs_sz = 0;
4752

1✔
4753
  mark_point();
1✔
4754
  res = pr_fs_fgetsize(fd, &fs_sz);
1✔
4755
  ck_assert_msg(res < 0, "Failed to handle bad file descriptor");
4756
  ck_assert_msg(errno == EBADF, "Expected EBADF (%d), got %s (%d)", EBADF,
4757
    strerror(errno), errno);
1✔
4758

1✔
4759
  mark_point();
1✔
4760
  fd = 0;
4761
  fs_sz = 0;
1✔
4762
  res = pr_fs_fgetsize(fd, NULL);
1✔
4763
  ck_assert_msg(res < 0, "Failed to handle null size argument");
1✔
4764
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
4765
    strerror(errno), errno);
4766

4767
  mark_point();
1✔
4768
  fd = 0;
1✔
4769
  fs_sz = 0;
1✔
4770
  res = pr_fs_fgetsize(fd, &fs_sz);
1✔
4771
  ck_assert_msg(res == 0, "Failed to get fs size for fd %d: %s", fd,
4772
    strerror(errno));
4773
}
1✔
4774
END_TEST
1✔
4775

1✔
4776
START_TEST (fs_fadvise_test) {
1✔
4777
  int advice, fd = -1;
4778
  off_t off = 0, len = 0;
4779

1✔
4780
  /* We make these function calls to exercise the code paths, even
4781
   * though there's no good way to verify the behavior changed.
1✔
4782
   */
1✔
4783

1✔
4784
  advice = PR_FS_FADVISE_NORMAL;
4785
  pr_fs_fadvise(fd, off, len, advice);
4786

1✔
4787
  advice = PR_FS_FADVISE_RANDOM;
1✔
4788
  pr_fs_fadvise(fd, off, len, advice);
1✔
4789

4790
  advice = PR_FS_FADVISE_SEQUENTIAL;
4791
  pr_fs_fadvise(fd, off, len, advice);
1✔
4792

1✔
4793
  advice = PR_FS_FADVISE_WILLNEED;
1✔
4794
  pr_fs_fadvise(fd, off, len, advice);
4795

4796
  advice = PR_FS_FADVISE_DONTNEED;
4797
  pr_fs_fadvise(fd, off, len, advice);
1✔
4798

4799
  advice = PR_FS_FADVISE_NOREUSE;
1✔
4800
  pr_fs_fadvise(fd, off, len, advice);
4801
}
1✔
4802
END_TEST
1✔
4803

1✔
4804
START_TEST (fs_have_access_test) {
1✔
4805
  int res;
4806
  struct stat st;
4807
  uid_t uid;
1✔
4808
  gid_t gid;
1✔
4809
  array_header *suppl_gids;
1✔
4810

1✔
4811
  mark_point();
4812
  res = pr_fs_have_access(NULL, R_OK, 0, 0, NULL);
4813
  ck_assert_msg(res < 0, "Failed to handle null stat");
1✔
4814
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
4815
    strerror(errno), errno);
1✔
4816

1✔
4817
  memset(&st, 0, sizeof(struct stat));
4818

4819
  mark_point();
1✔
4820
  res = pr_fs_have_access(&st, R_OK, 0, 0, NULL);
4821
  ck_assert_msg(res == 0, "Failed to handle root access: %s", strerror(errno));
1✔
4822

1✔
4823
  /* Use cases: no matching UID or GID; R_OK, W_OK, X_OK. */
1✔
4824
  memset(&st, 0, sizeof(struct stat));
4825
  uid = 1;
4826
  gid = 1;
1✔
4827

1✔
4828
  mark_point();
1✔
4829
  res = pr_fs_have_access(&st, R_OK, uid, gid, NULL);
4830
  ck_assert_msg(res < 0, "Failed to handle missing other R_OK access");
4831
  ck_assert_msg(errno == EACCES, "Expected EACCES (%d), got %s (%d)", EACCES,
1✔
4832
    strerror(errno), errno);
1✔
4833

1✔
4834
  mark_point();
4835
  res = pr_fs_have_access(&st, W_OK, uid, gid, NULL);
4836
  ck_assert_msg(res < 0, "Failed to handle missing other W_OK access");
4837
  ck_assert_msg(errno == EACCES, "Expected EACCES (%d), got %s (%d)", EACCES,
1✔
4838
    strerror(errno), errno);
4839

1✔
4840
  mark_point();
4841
  res = pr_fs_have_access(&st, X_OK, uid, gid, NULL);
1✔
4842
  ck_assert_msg(res < 0, "Failed to handle missing other X_OK access");
1✔
4843
  ck_assert_msg(errno == EACCES, "Expected EACCES (%d), got %s (%d)", EACCES,
1✔
4844
    strerror(errno), errno);
1✔
4845

4846
  st.st_mode = S_IFMT|S_IROTH|S_IWOTH|S_IXOTH;
4847

1✔
4848
  mark_point();
1✔
4849
  res = pr_fs_have_access(&st, R_OK, uid, gid, NULL);
1✔
4850
  ck_assert_msg(res == 0, "Failed to handle other R_OK access: %s",
1✔
4851
    strerror(errno));
4852

4853
  mark_point();
1✔
4854
  res = pr_fs_have_access(&st, W_OK, uid, gid, NULL);
1✔
4855
  ck_assert_msg(res == 0, "Failed to handle other W_OK access: %s",
1✔
4856
    strerror(errno));
1✔
4857

4858
  mark_point();
4859
  res = pr_fs_have_access(&st, X_OK, uid, gid, NULL);
1✔
4860
  ck_assert_msg(res == 0, "Failed to handle other X_OK access: %s",
4861
    strerror(errno));
1✔
4862

1✔
4863
  /* Use cases: matching UID, not GID; R_OK, W_OK, X_OK. */
1✔
4864
  memset(&st, 0, sizeof(struct stat));
4865

4866
  st.st_uid = uid;
1✔
4867

1✔
4868
  mark_point();
1✔
4869
  res = pr_fs_have_access(&st, R_OK, uid, gid, NULL);
4870
  ck_assert_msg(res < 0, "Failed to handle missing user R_OK access");
4871
  ck_assert_msg(errno == EACCES, "Expected EACCES (%d), got %s (%d)", EACCES,
1✔
4872
    strerror(errno), errno);
1✔
4873

1✔
4874
  mark_point();
4875
  res = pr_fs_have_access(&st, W_OK, uid, gid, NULL);
4876
  ck_assert_msg(res < 0, "Failed to handle missing user W_OK access");
4877
  ck_assert_msg(errno == EACCES, "Expected EACCES (%d), got %s (%d)", EACCES,
1✔
4878
    strerror(errno), errno);
4879

1✔
4880
  mark_point();
1✔
4881
  res = pr_fs_have_access(&st, X_OK, uid, gid, NULL);
1✔
4882
  ck_assert_msg(res < 0, "Failed to handle missing user X_OK access");
1✔
4883
  ck_assert_msg(errno == EACCES, "Expected EACCES (%d), got %s (%d)", EACCES,
4884
    strerror(errno), errno);
1✔
4885

1✔
4886
  st.st_mode = S_IFMT|S_IRUSR|S_IWUSR|S_IXUSR;
1✔
4887

1✔
4888
  mark_point();
4889
  res = pr_fs_have_access(&st, R_OK, uid, gid, NULL);
4890
  ck_assert_msg(res == 0, "Failed to handle user R_OK access: %s",
1✔
4891
    strerror(errno));
1✔
4892

1✔
4893
  mark_point();
1✔
4894
  res = pr_fs_have_access(&st, W_OK, uid, gid, NULL);
4895
  ck_assert_msg(res == 0, "Failed to handle user W_OK access: %s",
4896
    strerror(errno));
1✔
4897

1✔
4898
  mark_point();
1✔
4899
  res = pr_fs_have_access(&st, X_OK, uid, gid, NULL);
1✔
4900
  ck_assert_msg(res == 0, "Failed to handle user X_OK access: %s",
4901
    strerror(errno));
4902

1✔
4903
  /* Use cases: matching GID, not UID; R_OK, W_OK, X_OK. */
4904
  memset(&st, 0, sizeof(struct stat));
1✔
4905

1✔
4906
  st.st_gid = gid;
1✔
4907

4908
  mark_point();
4909
  res = pr_fs_have_access(&st, R_OK, uid, gid, NULL);
1✔
4910
  ck_assert_msg(res < 0, "Failed to handle missing group R_OK access");
1✔
4911
  ck_assert_msg(errno == EACCES, "Expected EACCES (%d), got %s (%d)", EACCES,
1✔
4912
    strerror(errno), errno);
4913

4914
  mark_point();
1✔
4915
  res = pr_fs_have_access(&st, W_OK, uid, gid, NULL);
1✔
4916
  ck_assert_msg(res < 0, "Failed to handle missing group W_OK access");
1✔
4917
  ck_assert_msg(errno == EACCES, "Expected EACCES (%d), got %s (%d)", EACCES,
4918
    strerror(errno), errno);
1✔
4919

4920
  mark_point();
4921
  res = pr_fs_have_access(&st, X_OK, uid, gid, NULL);
1✔
4922
  ck_assert_msg(res < 0, "Failed to handle missing group X_OK access");
1✔
4923
  ck_assert_msg(errno == EACCES, "Expected EACCES (%d), got %s (%d)", EACCES,
4924
    strerror(errno), errno);
1✔
4925

1✔
4926
  st.st_mode = S_IFMT|S_IRGRP|S_IWGRP|S_IXGRP;
1✔
4927

4928
  mark_point();
4929
  res = pr_fs_have_access(&st, R_OK, uid, gid, NULL);
1✔
4930
  ck_assert_msg(res == 0, "Failed to handle group R_OK access: %s",
1✔
4931
    strerror(errno));
1✔
4932

4933
  mark_point();
4934
  res = pr_fs_have_access(&st, W_OK, uid, gid, NULL);
1✔
4935
  ck_assert_msg(res == 0, "Failed to handle group W_OK access: %s",
1✔
4936
    strerror(errno));
1✔
4937

1✔
4938
  mark_point();
4939
  res = pr_fs_have_access(&st, X_OK, uid, gid, NULL);
1✔
4940
  ck_assert_msg(res == 0, "Failed to handle group X_OK access: %s",
1✔
4941
    strerror(errno));
1✔
4942

4943
  /* Use cases: matching suppl GID, not UID; R_OK, W_OK, X_OK. */
4944
  memset(&st, 0, sizeof(struct stat));
1✔
4945

1✔
4946
  suppl_gids = make_array(p, 1, sizeof(gid_t));
1✔
4947
  *((gid_t *) push_array(suppl_gids)) = 100;
4948
  *((gid_t *) push_array(suppl_gids)) = gid;
1✔
4949
  st.st_gid = gid;
1✔
4950

1✔
4951
  mark_point();
1✔
4952
  res = pr_fs_have_access(&st, R_OK, uid, 0, suppl_gids);
4953
  ck_assert_msg(res < 0, "Failed to handle missing group R_OK access");
4954
  ck_assert_msg(errno == EACCES, "Expected EACCES (%d), got %s (%d)", EACCES,
1✔
4955
    strerror(errno), errno);
1✔
4956

4957
  mark_point();
1✔
4958
  res = pr_fs_have_access(&st, W_OK, uid, 0, suppl_gids);
1✔
4959
  ck_assert_msg(res < 0, "Failed to handle missing group W_OK access");
4960
  ck_assert_msg(errno == EACCES, "Expected EACCES (%d), got %s (%d)", EACCES,
1✔
4961
    strerror(errno), errno);
1✔
4962

4963
  mark_point();
1✔
4964
  res = pr_fs_have_access(&st, X_OK, uid, 0, suppl_gids);
1✔
4965
  ck_assert_msg(res < 0, "Failed to handle missing group X_OK access");
1✔
4966
  ck_assert_msg(errno == EACCES, "Expected EACCES (%d), got %s (%d)", EACCES,
4967
    strerror(errno), errno);
4968

1✔
4969
  st.st_mode = S_IFMT|S_IRGRP|S_IWGRP|S_IXGRP;
1✔
4970

1✔
4971
  mark_point();
1✔
4972
  res = pr_fs_have_access(&st, R_OK, uid, 0, suppl_gids);
1✔
4973
  ck_assert_msg(res == 0, "Failed to handle group R_OK access: %s",
1✔
4974
    strerror(errno));
4975

1✔
4976
  mark_point();
1✔
4977
  res = pr_fs_have_access(&st, W_OK, uid, 0, suppl_gids);
1✔
4978
  ck_assert_msg(res == 0, "Failed to handle group W_OK access: %s",
4979
    strerror(errno));
4980

1✔
4981
  mark_point();
1✔
4982
  res = pr_fs_have_access(&st, X_OK, uid, 0, suppl_gids);
1✔
4983
  ck_assert_msg(res == 0, "Failed to handle group X_OK access: %s",
4984
    strerror(errno));
4985
}
1✔
4986
END_TEST
1✔
4987

1✔
4988
START_TEST (fs_is_nfs_test) {
4989
  int res;
1✔
4990

4991
  res = pr_fs_is_nfs(NULL);
1✔
4992
  ck_assert_msg(res < 0, "Failed to handle null argument");
1✔
4993
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
4994
    strerror(errno), errno);
4995

4996
  res = pr_fs_is_nfs("/tmp");
4997
  ck_assert_msg(res == FALSE, "Expected FALSE, got %d", res);
1✔
4998
}
1✔
4999
END_TEST
5000

1✔
5001
START_TEST (fs_valid_path_test) {
1✔
5002
  int res;
5003
  const char *path;
1✔
5004
  pr_fs_t *fs;
5005

1✔
5006
  res = pr_fs_valid_path(NULL);
1✔
5007
  ck_assert_msg(res < 0, "Failed to handle null arguments");
5008
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
5009
    strerror(errno), errno);
5010

5011
  path = "/";
5012
  res = pr_fs_valid_path(path);
5013
  ck_assert_msg(res == 0, "'%s' is not a valid path: %s", path, strerror(errno));
5014

5015
  path = ":tmp";
1✔
5016
  res = pr_fs_valid_path(path);
1✔
5017
  ck_assert_msg(res < 0, "Failed to handle invalid path");
5018
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
5019
    strerror(errno), errno);
1✔
5020

1✔
5021
  fs = pr_register_fs(p, "testsuite", "&");
1✔
5022
  ck_assert_msg(fs != NULL, "Failed to register FS: %s", strerror(errno));
1✔
5023

5024
  fs = pr_register_fs(p, "testsuite2", ":");
1✔
5025
  ck_assert_msg(fs != NULL, "Failed to register FS: %s", strerror(errno));
1✔
5026

1✔
5027
  res = pr_fs_valid_path(path);
5028
  ck_assert_msg(res == 0, "Failed to handle valid path: %s", strerror(errno));
5029

1✔
5030
  (void) pr_remove_fs("/testsuite2");
1✔
5031
  (void) pr_remove_fs("/testsuite");
1✔
5032
}
5033
END_TEST
5034

1✔
5035
START_TEST (fsio_smkdir_test) {
1✔
5036
  int res;
1✔
5037
  const char *path;
5038
  mode_t mode = 0755;
5039
  uid_t uid = getuid();
1✔
5040
  gid_t gid = getgid();
1✔
5041

5042
  res = pr_fsio_smkdir(NULL, NULL, mode, uid, gid);
1✔
5043
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
5044
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
5045
    strerror(errno), errno);
5046

1✔
5047
  res = pr_fsio_smkdir(p, NULL, mode, uid, gid);
1✔
5048
  ck_assert_msg(res < 0, "Failed to handle null path");
1✔
5049
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
5050
    strerror(errno), errno);
5051

1✔
5052
  path = fsio_testdir_path;
1✔
5053
  res = pr_fsio_smkdir(p, path, mode, uid, gid);
1✔
5054
  ck_assert_msg(res == 0, "Failed to securely create '%s': %s", fsio_testdir_path,
5055
    strerror(errno));
5056
  (void) pr_fsio_rmdir(fsio_testdir_path);
1✔
5057

1✔
5058
  res = pr_fsio_set_use_mkdtemp(-1);
1✔
5059
  ck_assert_msg(res < 0, "Failed to handle invalid setting");
5060
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
5061
    strerror(errno), errno);
1✔
5062

1✔
5063
#ifdef HAVE_MKDTEMP
5064
  res = pr_fsio_set_use_mkdtemp(FALSE);
5065
  ck_assert_msg(res == TRUE, "Expected TRUE, got %d", res);
1✔
5066

1✔
5067
  res = pr_fsio_smkdir(p, path, mode, uid, gid);
1✔
5068
  ck_assert_msg(res == 0, "Failed to securely create '%s': %s", fsio_testdir_path,
5069
    strerror(errno));
5070
  (void) pr_fsio_rmdir(fsio_testdir_path);
1✔
5071

1✔
5072
  res = pr_fsio_set_use_mkdtemp(TRUE);
1✔
5073
  ck_assert_msg(res == FALSE, "Expected FALSE, got %d", res);
5074
#else
1✔
5075
  res = pr_fsio_set_use_mkdtemp(TRUE);
1✔
5076
  ck_assert_msg(res == FALSE, "Expected FALSE, got %d", res);
5077

1✔
5078
  res = pr_fsio_set_use_mkdtemp(FALSE);
1✔
5079
  ck_assert_msg(res == FALSE, "Expected FALSE, got %d", res);
1✔
5080
#endif /* HAVE_MKDTEMP */
5081

1✔
5082
  (void) pr_fsio_rmdir(fsio_testdir_path);
5083
}
1✔
5084
END_TEST
1✔
5085

1✔
5086
START_TEST (fsio_getpipebuf_test) {
5087
  char *res;
5088
  int fd = -1;
1✔
5089
  long bufsz = 0;
1✔
5090

1✔
5091
  res = pr_fsio_getpipebuf(NULL, fd, NULL);
1✔
5092
  ck_assert_msg(res == NULL, "Failed to handle null arguments");
1✔
5093
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
5094
    strerror(errno), errno);
1✔
5095

1✔
5096
  res = pr_fsio_getpipebuf(p, fd, NULL);
1✔
5097
  ck_assert_msg(res == NULL, "Failed to handle bad file descriptor");
5098
  ck_assert_msg(errno == EBADF, "Expected EBADF (%d), got %s (%d)", EBADF,
5099
    strerror(errno), errno);
1✔
5100

1✔
5101
  fd = 0;
1✔
5102
  res = pr_fsio_getpipebuf(p, fd, NULL);
5103
  ck_assert_msg(res != NULL, "Failed to get pipebuf for fd %d: %s", fd,
5104
    strerror(errno));
1✔
5105

1✔
5106
  res = pr_fsio_getpipebuf(p, fd, &bufsz);
5107
  ck_assert_msg(res != NULL, "Failed to get pipebuf for fd %d: %s", fd,
5108
    strerror(errno));
1✔
5109
  ck_assert_msg(bufsz > 0, "Expected >0, got %ld", bufsz);
1✔
5110
}
1✔
5111
END_TEST
5112

5113
START_TEST (fsio_gets_test) {
1✔
5114
  char buf[PR_TUNABLE_PATH_MAX], short_buf[14], *res, *text, *short_text;
1✔
5115
  pr_fh_t *fh;
5116
  int res2;
1✔
5117

1✔
5118
  mark_point();
1✔
5119
  res = pr_fsio_gets(NULL, 0, NULL);
5120
  ck_assert_msg(res == NULL, "Failed to handle null arguments");
5121
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
5122
    strerror(errno), errno);
1✔
5123

1✔
5124
  res = pr_fsio_gets(buf, 0, NULL);
5125
  ck_assert_msg(res == NULL, "Failed to handle null file handle");
5126
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
5127
    strerror(errno), errno);
1✔
5128

5129
  fh = pr_fsio_open(fsio_test_path, O_CREAT|O_EXCL|O_RDWR);
1✔
5130
  ck_assert_msg(fh != NULL, "Failed to open '%s': %s", fsio_test_path,
1✔
5131
    strerror(errno));
1✔
5132

5133
  mark_point();
1✔
5134
  res = pr_fsio_gets(buf, 0, fh);
5135
  ck_assert_msg(res == NULL, "Failed to handle zero buffer length");
1✔
5136
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
5137
    strerror(errno), errno);
1✔
5138

1✔
5139
  mark_point();
1✔
5140
  text = "Hello, World!\n";
5141
  res2 = pr_fsio_puts(text, fh);
1✔
5142
  ck_assert_msg(res2 >= 0, "Error writing to '%s': %s", fsio_test_path,
5143
    strerror(errno));
1✔
5144

5145
  mark_point();
1✔
5146
  pr_fsio_fsync(fh);
1✔
5147
  pr_fsio_lseek(fh, 0, SEEK_SET);
1✔
5148

5149
  memset(buf, '\0', sizeof(buf));
5150
  res = pr_fsio_gets(buf, sizeof(buf)-1, fh);
1✔
5151
  ck_assert_msg(res != NULL, "Failed reading from '%s': %s", fsio_test_path,
1✔
5152
    strerror(errno));
1✔
5153
  ck_assert_msg(strcmp(res, text) == 0, "Expected '%s', got '%s'", text, res);
1✔
5154

5155
  /* For this test, we want to read the number of bytes of text into an
1✔
5156
   * exactly sized buffer, in order to see what happens for the "always NUL
1✔
5157
   * terminate" behavior.
1✔
5158
   */
5159
  mark_point();
5160
  pr_fsio_fsync(fh);
1✔
5161
  pr_fsio_lseek(fh, 0, SEEK_SET);
1✔
5162

1✔
5163
  /* Deliberately null out the already-allocated buffer object associated
1✔
5164
   * with this filehandle, so that we can dictate the buffer size to be
5165
   * allocated for this short text test.
5166
   */
1✔
5167
  fh->fh_buf = NULL;
1✔
5168
  fh->fh_iosz = sizeof(short_buf);
5169

5170
  short_text = "Hello, World!";
1✔
5171
  memset(short_buf, '\0', sizeof(short_buf));
1✔
5172
  res = pr_fsio_gets(short_buf, sizeof(short_buf), fh);
1✔
5173
  ck_assert_msg(res != NULL, "Failed reading from '%s': %s", fsio_test_path,
5174
    strerror(errno));
5175
  ck_assert_msg(strcmp(res, short_text) == 0,"Expected '%s', got '%s'",
1✔
5176
    short_text, res);
1✔
5177

1✔
5178
  (void) pr_fsio_close(fh);
5179
  (void) pr_fsio_unlink(fsio_test_path);
5180
}
1✔
5181
END_TEST
1✔
5182

1✔
5183
START_TEST (fsio_getline_test) {
5184
  char buf[PR_TUNABLE_PATH_MAX], *res, *text;
1✔
5185
  pr_fh_t *fh;
1✔
5186
  unsigned int lineno = 0;
1✔
5187
  int res2;
5188

5189
  res = pr_fsio_getline(NULL, 0, NULL, NULL);
1✔
5190
  ck_assert_msg(res == NULL, "Failed to handle null arguments");
1✔
5191
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
5192
    strerror(errno), errno);
5193

1✔
5194
  res = pr_fsio_getline(buf, 0, NULL, NULL);
1✔
5195
  ck_assert_msg(res == NULL, "Failed to handle file handle");
5196
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
5197
    strerror(errno), errno);
1✔
5198

1✔
5199
  fh = pr_fsio_open(fsio_test_path, O_CREAT|O_EXCL|O_RDWR);
5200
  ck_assert_msg(fh != NULL, "Failed to open '%s': %s", fsio_test_path,
5201
    strerror(errno));
1✔
5202

1✔
5203
  res = pr_fsio_getline(buf, 0, fh, NULL);
1✔
5204
  ck_assert_msg(res == NULL, "Failed to handle zero buffer length");
5205
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
5206
    strerror(errno), errno);
1✔
5207

1✔
5208
  res = pr_fsio_getline(buf, sizeof(buf)-1, fh, &lineno);
1✔
5209
  ck_assert_msg(res == NULL, "Failed to read empty '%s' file", fsio_test_path);
5210

5211
  text = "Hello, World!\n";
890✔
5212
  res2 = pr_fsio_puts(text, fh);
890✔
5213
  ck_assert_msg(res2 >= 0, "Error writing to '%s': %s", fsio_test_path,
890✔
5214
    strerror(errno));
5215

890✔
5216
  text = "How\\\n are you?\n";
5217
  res2 = pr_fsio_puts(text, fh);
890✔
5218
  ck_assert_msg(res2 >= 0, "Error writing to '%s': %s", fsio_test_path,
890✔
5219
    strerror(errno));
5220

5221
  pr_fsio_fsync(fh);
890✔
5222
  pr_fsio_lseek(fh, 0, SEEK_SET);
890✔
5223

890✔
5224
  memset(buf, '\0', sizeof(buf));
890✔
5225
  res = pr_fsio_getline(buf, sizeof(buf)-1, fh, &lineno);
890✔
5226
  ck_assert_msg(res != NULL, "Failed to read line from '%s': %s", fsio_test_path,
890✔
5227
    strerror(errno));
890✔
5228
  ck_assert_msg(strcmp(res, "Hello, World!\n") == 0,
890✔
5229
    "Expected 'Hello, World!\n', got '%s'", res);
890✔
5230
  ck_assert_msg(lineno == 1, "Expected 1, got %u", lineno);
890✔
5231

890✔
5232
  memset(buf, '\0', sizeof(buf));
890✔
5233
  res = pr_fsio_getline(buf, sizeof(buf)-1, fh, &lineno);
890✔
5234
  ck_assert_msg(res != NULL, "Failed to read line from '%s': %s", fsio_test_path,
890✔
5235
    strerror(errno));
890✔
5236
  ck_assert_msg(strcmp(res, "How are you?\n") == 0,
890✔
5237
    "Expected 'How are you?\n', got '%s'", res);
890✔
5238
  ck_assert_msg(lineno == 3, "Expected 3, got %u", lineno);
890✔
5239

890✔
5240
  (void) pr_fsio_close(fh);
890✔
5241
  (void) pr_fsio_unlink(fsio_test_path);
890✔
5242
}
890✔
5243
END_TEST
890✔
5244

890✔
5245
START_TEST (fsio_puts_test) {
890✔
5246
  int res;
890✔
5247
  const char *text;
890✔
5248
  pr_fh_t *fh;
890✔
5249

890✔
5250
  res = pr_fsio_puts(NULL, NULL);
890✔
5251
  ck_assert_msg(res < 0, "Failed to handle null arguments");
890✔
5252
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
890✔
5253
    strerror(errno), errno);
890✔
5254

890✔
5255
  text = "Hello, World!\n";
890✔
5256
  res = pr_fsio_puts(text, NULL);
890✔
5257
  ck_assert_msg(res < 0, "Failed to handle null file handle");
890✔
5258
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
890✔
5259
    strerror(errno), errno);
890✔
5260

5261
  fh = pr_fsio_open(fsio_test_path, O_CREAT|O_EXCL|O_WRONLY);
890✔
5262
  ck_assert_msg(fh != NULL, "Failed to open '%s': %s", fsio_test_path,
5263
    strerror(errno));
5264

890✔
5265
  res = pr_fsio_puts(NULL, fh);
890✔
5266
  ck_assert_msg(res < 0, "Failed to handle null buffer");
890✔
5267
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
890✔
5268
    strerror(errno), errno);
890✔
5269

890✔
5270
  (void) pr_fsio_close(fh);
890✔
5271
  (void) pr_fsio_unlink(fsio_test_path);
890✔
5272
}
890✔
5273
END_TEST
890✔
5274

890✔
5275
START_TEST (fsio_blocking_test) {
890✔
5276
  int fd, res;
5277
  pr_fh_t *fh;
890✔
5278

890✔
5279
  res = pr_fsio_set_block(NULL);
890✔
5280
  ck_assert_msg(res < 0, "Failed to handle null argument");
890✔
5281
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
890✔
5282
    strerror(errno), errno);
890✔
5283

890✔
5284
  fh = pr_fsio_open(fsio_test_path, O_CREAT|O_EXCL|O_WRONLY);
890✔
5285
  ck_assert_msg(fh != NULL, "Failed to open '%s': %s", fsio_test_path,
890✔
5286
    strerror(errno));
890✔
5287

5288
  fd = fh->fh_fd;
5289
  fh->fh_fd = -1;
890✔
5290

890✔
5291
  res = pr_fsio_set_block(fh);
890✔
5292
  ck_assert_msg(res < 0, "Failed to handle bad file descriptor");
890✔
5293
  ck_assert_msg(errno == EBADF, "Expected EBADF (%d), got %s (%d)", EBADF,
890✔
5294
    strerror(errno), errno);
890✔
5295

890✔
5296
  fh->fh_fd = fd;
890✔
5297
  res = pr_fsio_set_block(fh);
890✔
5298
  ck_assert_msg(res == 0, "Failed to make '%s' blocking: %s", fsio_test_path,
890✔
5299
    strerror(errno));
890✔
5300

890✔
5301
  (void) pr_fsio_close(fh);
890✔
5302
  (void) pr_fsio_unlink(fsio_test_path);
890✔
5303
}
890✔
5304
END_TEST
890✔
5305

5306
Suite *tests_get_fsio_suite(void) {
5307
  Suite *suite;
890✔
5308
  TCase *testcase;
890✔
5309

890✔
5310
  suite = suite_create("fsio");
890✔
5311

890✔
5312
  testcase = tcase_create("base");
5313
  tcase_add_checked_fixture(testcase, set_up, tear_down);
5314

890✔
5315
  /* Main FSIO API tests */
890✔
5316
  tcase_add_test(testcase, fsio_sys_open_test);
890✔
5317
  tcase_add_test(testcase, fsio_sys_open_canon_test);
890✔
5318
  tcase_add_test(testcase, fsio_sys_open_chroot_guard_test);
890✔
5319
  tcase_add_test(testcase, fsio_sys_close_test);
890✔
5320
  tcase_add_test(testcase, fsio_sys_unlink_test);
890✔
5321
  tcase_add_test(testcase, fsio_sys_unlink_chroot_guard_test);
890✔
5322
  tcase_add_test(testcase, fsio_sys_stat_test);
890✔
5323
  tcase_add_test(testcase, fsio_sys_fstat_test);
5324
  tcase_add_test(testcase, fsio_sys_read_test);
890✔
5325
  tcase_add_test(testcase, fsio_sys_pread_test);
5326
  tcase_add_test(testcase, fsio_sys_write_test);
5327
  tcase_add_test(testcase, fsio_sys_pwrite_test);
5328
  tcase_add_test(testcase, fsio_sys_lseek_test);
890✔
5329
  tcase_add_test(testcase, fsio_sys_link_test);
5330
  tcase_add_test(testcase, fsio_sys_link_chroot_guard_test);
5331
  tcase_add_test(testcase, fsio_sys_symlink_test);
890✔
5332
  tcase_add_test(testcase, fsio_sys_symlink_chroot_guard_test);
890✔
5333
  tcase_add_test(testcase, fsio_sys_readlink_test);
5334
  tcase_add_test(testcase, fsio_sys_lstat_test);
890✔
5335
  tcase_add_test(testcase, fsio_sys_access_dir_test);
890✔
5336
  tcase_add_test(testcase, fsio_sys_access_file_test);
890✔
5337
  tcase_add_test(testcase, fsio_sys_faccess_test);
890✔
5338
  tcase_add_test(testcase, fsio_sys_truncate_test);
890✔
5339
  tcase_add_test(testcase, fsio_sys_truncate_chroot_guard_test);
890✔
5340
  tcase_add_test(testcase, fsio_sys_ftruncate_test);
890✔
5341
  tcase_add_test(testcase, fsio_sys_chmod_test);
890✔
5342
  tcase_add_test(testcase, fsio_sys_chmod_chroot_guard_test);
890✔
5343
  tcase_add_test(testcase, fsio_sys_fchmod_test);
890✔
5344
  tcase_add_test(testcase, fsio_sys_chown_test);
890✔
5345
  tcase_add_test(testcase, fsio_sys_chown_chroot_guard_test);
890✔
5346
  tcase_add_test(testcase, fsio_sys_fchown_test);
890✔
5347
  tcase_add_test(testcase, fsio_sys_lchown_test);
890✔
5348
  tcase_add_test(testcase, fsio_sys_lchown_chroot_guard_test);
5349
  tcase_add_test(testcase, fsio_sys_rename_test);
5350
  tcase_add_test(testcase, fsio_sys_rename_chroot_guard_test);
5351
  tcase_add_test(testcase, fsio_sys_utimes_test);
890✔
5352
  tcase_add_test(testcase, fsio_sys_utimes_chroot_guard_test);
890✔
5353
  tcase_add_test(testcase, fsio_sys_futimes_test);
890✔
5354
  tcase_add_test(testcase, fsio_sys_fsync_test);
890✔
5355

890✔
5356
  tcase_add_test(testcase, fsio_sys_realpath_test);
890✔
5357

890✔
5358
  /* Extended attribute tests */
5359
  tcase_add_test(testcase, fsio_sys_getxattr_test);
890✔
5360
  tcase_add_test(testcase, fsio_sys_lgetxattr_test);
5361
  tcase_add_test(testcase, fsio_sys_fgetxattr_test);
890✔
5362
  tcase_add_test(testcase, fsio_sys_listxattr_test);
890✔
5363
  tcase_add_test(testcase, fsio_sys_llistxattr_test);
890✔
5364
  tcase_add_test(testcase, fsio_sys_flistxattr_test);
890✔
5365
  tcase_add_test(testcase, fsio_sys_removexattr_test);
890✔
5366
  tcase_add_test(testcase, fsio_sys_lremovexattr_test);
890✔
5367
  tcase_add_test(testcase, fsio_sys_fremovexattr_test);
890✔
5368
  tcase_add_test(testcase, fsio_sys_setxattr_test);
5369
  tcase_add_test(testcase, fsio_sys_lsetxattr_test);
890✔
5370
  tcase_add_test(testcase, fsio_sys_fsetxattr_test);
890✔
5371

5372
  tcase_add_test(testcase, fsio_sys_mkdir_test);
5373
  tcase_add_test(testcase, fsio_sys_mkdir_chroot_guard_test);
5374
  tcase_add_test(testcase, fsio_sys_rmdir_test);
5375
  tcase_add_test(testcase, fsio_sys_rmdir_chroot_guard_test);
5376
  tcase_add_test(testcase, fsio_sys_chdir_test);
5377
  tcase_add_test(testcase, fsio_sys_chdir_canon_test);
5378
  tcase_add_test(testcase, fsio_sys_chroot_test);
5379
  tcase_add_test(testcase, fsio_sys_opendir_test);
5380
  tcase_add_test(testcase, fsio_sys_readdir_test);
5381
  tcase_add_test(testcase, fsio_sys_closedir_test);
5382

5383
  /* FSIO with error tests */
5384
  tcase_add_test(testcase, fsio_sys_chmod_with_error_test);
5385
  tcase_add_test(testcase, fsio_sys_chown_with_error_test);
5386
  tcase_add_test(testcase, fsio_sys_chroot_with_error_test);
5387
  tcase_add_test(testcase, fsio_sys_close_with_error_test);
5388
  tcase_add_test(testcase, fsio_sys_fchmod_with_error_test);
5389
  tcase_add_test(testcase, fsio_sys_fchown_with_error_test);
5390
  tcase_add_test(testcase, fsio_sys_lchown_with_error_test);
5391
  tcase_add_test(testcase, fsio_sys_lstat_with_error_test);
5392
  tcase_add_test(testcase, fsio_sys_mkdir_with_error_test);
5393
  tcase_add_test(testcase, fsio_sys_open_with_error_test);
5394
  tcase_add_test(testcase, fsio_sys_read_with_error_test);
5395
  tcase_add_test(testcase, fsio_sys_rename_with_error_test);
5396
  tcase_add_test(testcase, fsio_sys_rmdir_with_error_test);
5397
  tcase_add_test(testcase, fsio_sys_stat_with_error_test);
5398
  tcase_add_test(testcase, fsio_sys_unlink_with_error_test);
5399
  tcase_add_test(testcase, fsio_sys_write_with_error_test);
5400

5401
  /* FSIO statcache tests */
5402
  tcase_add_test(testcase, fsio_statcache_clear_cache_test);
5403
  tcase_add_test(testcase, fsio_statcache_cache_hit_test);
5404
  tcase_add_test(testcase, fsio_statcache_negative_cache_test);
5405
  tcase_add_test(testcase, fsio_statcache_expired_test);
5406
  tcase_add_test(testcase, fsio_statcache_dump_test);
5407

5408
  /* Custom FSIO management tests */
5409
  tcase_add_test(testcase, fs_create_fs_test);
5410
  tcase_add_test(testcase, fs_insert_fs_test);
5411
  tcase_add_test(testcase, fs_get_fs_test);
5412
  tcase_add_test(testcase, fs_unmount_fs_test);
5413
  tcase_add_test(testcase, fs_remove_fs_test);
5414
  tcase_add_test(testcase, fs_register_fs_test);
5415
  tcase_add_test(testcase, fs_register_fs2_test);
5416
  tcase_add_test(testcase, fs_unregister_fs_test);
5417
  tcase_add_test(testcase, fs_resolve_fs_map_test);
5418
#if defined(PR_USE_DEVEL)
5419
  tcase_add_test(testcase, fs_dump_fs_test);
5420
#endif /* PR_USE_DEVEL */
5421

5422
  /* Custom FSIO tests */
5423
  tcase_add_test(testcase, fsio_custom_chroot_test);
5424

5425
  /* Misc */
5426
  tcase_add_test(testcase, fs_clean_path_test);
5427
  tcase_add_test(testcase, fs_clean_path2_test);
5428

5429
  tcase_add_test(testcase, fs_dircat_test);
5430
  tcase_add_test(testcase, fs_setcwd_test);
5431
  tcase_add_test(testcase, fs_glob_test);
5432
  tcase_add_test(testcase, fs_copy_file_test);
5433
  tcase_add_test(testcase, fs_copy_file2_test);
5434
  tcase_add_test(testcase, fs_interpolate_test);
5435
  tcase_add_test(testcase, fs_resolve_partial_test);
5436
  tcase_add_test(testcase, fs_resolve_path_test);
5437
  tcase_add_test(testcase, fs_use_encoding_test);
5438
  tcase_add_test(testcase, fs_decode_path2_test);
5439
  tcase_add_test(testcase, fs_encode_path_test);
5440
  tcase_add_test(testcase, fs_split_path_test);
5441
  tcase_add_test(testcase, fs_join_path_test);
5442
  tcase_add_test(testcase, fs_virtual_path_test);
5443
#if 0
5444
  tcase_add_test(testcase, fs_close_extra_fds_test);
5445
#endif
5446
  tcase_add_test(testcase, fs_get_usable_fd_test);
5447
  tcase_add_test(testcase, fs_get_usable_fd2_test);
5448
  tcase_add_test(testcase, fs_getsize_test);
5449
  tcase_add_test(testcase, fs_getsize2_test);
5450
  tcase_add_test(testcase, fs_fgetsize_test);
5451
  tcase_add_test(testcase, fs_fadvise_test);
5452
  tcase_add_test(testcase, fs_have_access_test);
5453
#if defined(HAVE_STATFS_F_TYPE) || defined(HAVE_STATFS_F_FSTYPENAME)
5454
  tcase_add_test(testcase, fs_is_nfs_test);
5455
#endif
5456
  tcase_add_test(testcase, fs_valid_path_test);
5457
  tcase_add_test(testcase, fsio_smkdir_test);
5458
  tcase_add_test(testcase, fsio_getpipebuf_test);
5459
  tcase_add_test(testcase, fsio_gets_test);
5460
  tcase_add_test(testcase, fsio_getline_test);
5461
  tcase_add_test(testcase, fsio_puts_test);
5462
  tcase_add_test(testcase, fsio_blocking_test);
5463

5464
  suite_add_tcase(suite, testcase);
5465
  return suite;
5466
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc