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

proftpd / proftpd / 14526507026

17 Apr 2025 11:25PM UTC coverage: 93.03% (+0.4%) from 92.667%
14526507026

push

github

51358 of 55206 relevant lines covered (93.03%)

234.02 hits per line

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

98.76
/tests/api/fsio.c
1
/*
2
 * ProFTPD - FTP server testsuite
3
 * Copyright (c) 2008-2024 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, write to the Free Software
17
 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
18
 *
19
 * As a special exemption, The ProFTPD Project team and other respective
20
 * copyright holders give permission to link this program with OpenSSL, and
21
 * distribute the resulting executable, without including the source code for
22
 * OpenSSL in the source distribution.
23
 */
24

25
/* FSIO API tests */
26

27
#include "tests.h"
28

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

36
static pool *p = NULL;
37

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

47
/* Fixtures */
48

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

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

60
  fsio_cwd = getcwd(NULL, 0);
125✔
61

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

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

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

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

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

87
  pr_unregister_fs("/testuite");
125✔
88

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

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

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

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

114
/* Tests */
115

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

219
  (void) pr_fsio_guard_chroot(FALSE);
1✔
220

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

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

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

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

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

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

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

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

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

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

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

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

278
  (void) pr_fsio_guard_chroot(FALSE);
1✔
279

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

594
  (void) pr_fsio_guard_chroot(FALSE);
1✔
595

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

879
  (void) rmdir(fsio_testdir_path);
1✔
880
}
1✔
881
END_TEST
882

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

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

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

902
  /* First, check that we ourselves can access our own file. */
903

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

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

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

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

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

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

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

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

942
  (void) unlink(fsio_test_path);
1✔
943
}
1✔
944
END_TEST
945

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

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

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

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

969
  /* First, check that we ourselves can access our own file. */
970

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

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

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

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

991
  (void) pr_fsio_close(fh);
1✔
992
  (void) pr_fsio_unlink(fsio_test_path);
1✔
993
}
1✔
994
END_TEST
995

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

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

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

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

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

1019
  (void) pr_fsio_close(fh);
1✔
1020
  (void) pr_fsio_unlink(fsio_test_path);
1✔
1021
}
1✔
1022
END_TEST
1023

1024
START_TEST (fsio_sys_truncate_chroot_guard_test) {
1✔
1025
  int res;
1✔
1026

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

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

1035
  (void) pr_fsio_guard_chroot(FALSE);
1✔
1036

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

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

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

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

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

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

1069
  fh->fh_buf = buf;
1✔
1070

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

1079
  (void) pr_fsio_close(fh);
1✔
1080
  (void) pr_fsio_unlink(fsio_test_path);
1✔
1081
}
1✔
1082
END_TEST
1083

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

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

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

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

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

1107
  (void) pr_fsio_close(fh);
1✔
1108
  (void) pr_fsio_unlink(fsio_test_path);
1✔
1109
}
1✔
1110
END_TEST
1111

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

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

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

1124
  (void) pr_fsio_guard_chroot(FALSE);
1✔
1125

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

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

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

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

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

1151
  (void) pr_fsio_close(fh);
1✔
1152
  (void) pr_fsio_unlink(fsio_test_path);
1✔
1153
}
1✔
1154
END_TEST
1155

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

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

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

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

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

1181
  (void) pr_fsio_close(fh);
1✔
1182
  (void) pr_fsio_unlink(fsio_test_path);
1✔
1183
}
1✔
1184
END_TEST
1185

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

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

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

1199
  (void) pr_fsio_guard_chroot(FALSE);
1✔
1200

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

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

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

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

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

1227
  (void) pr_fsio_close(fh);
1✔
1228
  (void) pr_fsio_unlink(fsio_test_path);
1✔
1229
}
1✔
1230
END_TEST
1231

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

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

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

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

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

1257
  (void) pr_fsio_close(fh);
1✔
1258
  (void) pr_fsio_unlink(fsio_test_path);
1✔
1259
}
1✔
1260
END_TEST
1261

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

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

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

1275
  (void) pr_fsio_guard_chroot(FALSE);
1✔
1276

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

1284
START_TEST (fsio_sys_rename_test) {
1✔
1285
  int res;
1✔
1286
  pr_fh_t *fh;
1✔
1287

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

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

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

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

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

1312
  (void) pr_fsio_unlink(fsio_test_path);
1✔
1313
  (void) pr_fsio_unlink(fsio_test2_path);
1✔
1314
}
1✔
1315
END_TEST
1316

1317
START_TEST (fsio_sys_rename_chroot_guard_test) {
1✔
1318
  int res;
1✔
1319
  pr_fh_t *fh;
1✔
1320

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

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

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

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

1339
  (void) pr_fsio_guard_chroot(FALSE);
1✔
1340

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

1346
  (void) pr_fsio_unlink(fsio_test_path);
1✔
1347
}
1✔
1348
END_TEST
1349

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

1355
  memset(tvs, 0, sizeof(tvs));
1✔
1356

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

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

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

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

1377
  (void) pr_fsio_close(fh);
1✔
1378
  (void) pr_fsio_unlink(fsio_test_path);
1✔
1379
}
1✔
1380
END_TEST
1381

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

1386
  memset(tvs, 0, sizeof(tvs));
1✔
1387

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

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

1396
  (void) pr_fsio_guard_chroot(FALSE);
1✔
1397

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

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

1411
  memset(tvs, 0, sizeof(tvs));
1✔
1412

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

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

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

1427
  (void) pr_fsio_close(fh);
1✔
1428
  (void) pr_fsio_unlink(fsio_test_path);
1✔
1429
}
1✔
1430
END_TEST
1431

1432
START_TEST (fsio_sys_fsync_test) {
1✔
1433
  int res;
1✔
1434
  pr_fh_t *fh;
1✔
1435

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

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

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

1455
  (void) pr_fsio_close(fh);
1✔
1456
  (void) pr_fsio_unlink(fsio_test_path);
1✔
1457
}
1✔
1458
END_TEST
1459

1460
START_TEST (fsio_sys_realpath_test) {
1✔
1461
  const char *res;
1✔
1462

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

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

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

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

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

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

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

1503
  name = "foo.bar";
1✔
1504

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

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

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

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

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

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

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

1548
  name = "foo.bar";
1✔
1549

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

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

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

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

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

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

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

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

1598
  name = "foo.bar";
1✔
1599

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

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

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

1620
  pr_fsio_close(fh);
1✔
1621
  (void) unlink(fsio_test_path);
1✔
1622
}
1✔
1623
END_TEST
1624

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1779
  pr_fsio_close(fh);
1✔
1780
  (void) unlink(fsio_test_path);
1✔
1781
}
1✔
1782
END_TEST
1783

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

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

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

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

1805
  name = "foo.bar";
1✔
1806

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

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

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

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

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

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

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

1850
  name = "foo.bar";
1✔
1851

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

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

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

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

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

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

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

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

1900
  name = "foo.bar";
1✔
1901

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

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

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

1922
  pr_fsio_close(fh);
1✔
1923
  (void) unlink(fsio_test_path);
1✔
1924
}
1✔
1925
END_TEST
1926

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

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

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

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

1949
  name = "foo.bar";
1✔
1950
  flags = PR_FSIO_XATTR_FL_CREATE;
1✔
1951

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

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

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

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

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

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

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

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

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

2009
  name = "foo.bar";
1✔
2010
  flags = PR_FSIO_XATTR_FL_CREATE;
1✔
2011

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

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

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

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

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

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

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

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

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

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

2073
  name = "foo.bar";
1✔
2074
  flags = PR_FSIO_XATTR_FL_CREATE;
1✔
2075

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

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

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

2096
  pr_fsio_close(fh);
1✔
2097
  (void) unlink(fsio_test_path);
1✔
2098
}
1✔
2099
END_TEST
2100

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

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

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

2114
  (void) pr_fsio_rmdir(fsio_testdir_path);
1✔
2115
}
1✔
2116
END_TEST
2117

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

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

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

2130
  (void) pr_fsio_guard_chroot(FALSE);
1✔
2131

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

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

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

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

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

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

2163
START_TEST (fsio_sys_rmdir_chroot_guard_test) {
1✔
2164
  int res;
1✔
2165

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

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

2174
  (void) pr_fsio_guard_chroot(FALSE);
1✔
2175

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

2183
START_TEST (fsio_sys_chdir_test) {
1✔
2184
  int res;
1✔
2185

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

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

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

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

2207
START_TEST (fsio_sys_chdir_canon_test) {
1✔
2208
  int res;
1✔
2209

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

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

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

2225
START_TEST (fsio_sys_chroot_test) {
1✔
2226
  int res;
1✔
2227

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

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

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

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

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

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

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

2269
  (void) pr_fsio_closedir(res);
1✔
2270
  (void) pr_fsio_closedir(res2);
1✔
2271
}
1✔
2272
END_TEST
2273

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

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

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

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

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

2296
  (void) pr_fsio_closedir(dirh);
1✔
2297
}
1✔
2298
END_TEST
2299

2300
START_TEST (fsio_sys_closedir_test) {
1✔
2301
  void *dirh;
1✔
2302
  int res;
1✔
2303

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

2766
  path = "/tmp/foo/bar/baz/quxx/quzz.d";
1✔
2767

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

3181
  mark_point();
1✔
3182
  pr_fs_clear_cache();
1✔
3183

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

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

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

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

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

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

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

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

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

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

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

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

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

3228
  free(cwd);
1✔
3229
}
1✔
3230
END_TEST
3231

3232
START_TEST (fsio_statcache_cache_hit_test) {
1✔
3233
  int res;
1✔
3234
  struct stat st;
1✔
3235

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

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

3244
  pr_fs_clear_cache();
1✔
3245
}
1✔
3246
END_TEST
3247

3248
START_TEST (fsio_statcache_negative_cache_test) {
1✔
3249
  int res;
1✔
3250
  struct stat st;
1✔
3251

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

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

3264
  pr_fs_clear_cache();
1✔
3265
}
1✔
3266
END_TEST
3267

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

3273
  cache_size = max_age = 1;
1✔
3274
  pr_fs_statcache_set_policy(cache_size, max_age, 0);
1✔
3275

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

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

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

3291
  mark_point();
1✔
3292
  pr_fs_clear_cache();
1✔
3293
}
1✔
3294
END_TEST
3295

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

3302
START_TEST (fs_create_fs_test) {
1✔
3303
  pr_fs_t *fs;
1✔
3304

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

3457
  (void) pr_remove_fs("/testsuite");
1✔
3458
  (void) pr_remove_fs("/testsuite");
1✔
3459
}
1✔
3460
END_TEST
3461

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

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

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

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

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

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

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

3493
START_TEST (fs_register_fs_test) {
1✔
3494
  pr_fs_t *fs, *fs2;
1✔
3495

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

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

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

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

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

3519
  (void) pr_remove_fs("/testsuite");
1✔
3520
}
1✔
3521
END_TEST
3522

3523
START_TEST (fs_register_fs2_test) {
1✔
3524
  pr_fs_t *fs, *fs2;
1✔
3525

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

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

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

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

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

3549
  (void) pr_remove_fs("/testsuite");
1✔
3550
}
1✔
3551
END_TEST
3552

3553
START_TEST (fs_unregister_fs_test) {
1✔
3554
  pr_fs_t *fs;
1✔
3555
  int res;
1✔
3556

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

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

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

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

3576
START_TEST (fs_resolve_fs_map_test) {
1✔
3577
  pr_fs_t *fs;
1✔
3578
  int res;
1✔
3579

3580
  mark_point();
1✔
3581
  pr_resolve_fs_map();
1✔
3582

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

3586
  mark_point();
1✔
3587
  pr_resolve_fs_map();
1✔
3588

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

3593
  mark_point();
1✔
3594
  pr_resolve_fs_map();
1✔
3595
}
1✔
3596
END_TEST
3597

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

3602
  mark_point();
1✔
3603
  pr_fs_dump(NULL);
1✔
3604

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

3608
  mark_point();
1✔
3609
  pr_fs_dump(NULL);
1✔
3610

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

3644
  mark_point();
1✔
3645
  pr_fs_dump(NULL);
1✔
3646

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

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

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

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

3664
  fs->chroot = fsio_chroot_cb;
1✔
3665

3666
  mark_point();
1✔
3667
  pr_resolve_fs_map();
1✔
3668

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

3674
  pr_unregister_fs("/testsuite");
1✔
3675
}
1✔
3676
END_TEST
3677

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

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

3686
  path = "/";
1✔
3687

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

3693
  res[sizeof(res)-1] = '\0';
1✔
3694

3695
  mark_point();
1✔
3696
  pr_fs_clean_path(path, res, 0);
1✔
3697

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

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'",
1✔
3706
    path, res);
3707

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

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

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

3730
START_TEST (fs_clean_path2_test) {
1✔
3731
  char res[PR_TUNABLE_PATH_MAX+1], *path, *expected;
1✔
3732
  int code;
1✔
3733

3734
  mark_point();
1✔
3735
  code = pr_fs_clean_path2(NULL, NULL, 0, 0);
1✔
3736
  ck_assert_msg(code < 0, "Failed to handle null path");
1✔
3737
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
3738
    strerror(errno), errno);
3739

3740
  path = "/";
1✔
3741

3742
  mark_point();
1✔
3743
  code = pr_fs_clean_path2(path, NULL, 0, 0);
1✔
3744
  ck_assert_msg(code < 0, "Failed to handle null buf");
1✔
3745
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
3746
    strerror(errno), errno);
3747

3748
  res[sizeof(res)-1] = '\0';
1✔
3749

3750
  mark_point();
1✔
3751
  code = pr_fs_clean_path2(path, res, 0, 0);
1✔
3752
  ck_assert_msg(code == 0, "Failed to handle zero length buf: %s",
1✔
3753
    strerror(errno));
3754

3755
  res[sizeof(res)-1] = '\0';
1✔
3756
  path = "test.txt";
1✔
3757
  code = pr_fs_clean_path2(path, res, sizeof(res)-1, 0);
1✔
3758
  ck_assert_msg(code == 0, "Failed to clean path '%s': %s", path,
1✔
3759
    strerror(errno));
3760
  ck_assert_msg(strcmp(res, path) == 0, "Expected cleaned path '%s', got '%s'",
1✔
3761
    path, res);
3762

3763
  res[sizeof(res)-1] = '\0';
1✔
3764
  path = "/./test.txt";
1✔
3765
  code = pr_fs_clean_path2(path, res, sizeof(res)-1, 0);
1✔
3766
  ck_assert_msg(code == 0, "Failed to clean path '%s': %s", path,
1✔
3767
    strerror(errno));
3768
  expected = "/test.txt";
1✔
3769
  ck_assert_msg(strcmp(res, expected) == 0,
1✔
3770
    "Expected cleaned path '%s', got '%s'", expected, res);
3771

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

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

3793
START_TEST (fs_dircat_test) {
1✔
3794
  char buf[PR_TUNABLE_PATH_MAX+1], *a, *b, *ok;
1✔
3795
  int res;
1✔
3796

3797
  res = pr_fs_dircat(NULL, 0, NULL, NULL);
1✔
3798
  ck_assert_msg(res == -1, "Failed to handle null arguments");
1✔
3799
  ck_assert_msg(errno == EINVAL,
1✔
3800
    "Failed to set errno to EINVAL for null arguments");
3801

3802
  res = pr_fs_dircat(buf, 0, "foo", "bar");
1✔
3803
  ck_assert_msg(res == -1, "Failed to handle zero-length buffer");
1✔
3804
  ck_assert_msg(errno == EINVAL,
1✔
3805
    "Failed to set errno to EINVAL for zero-length buffer");
3806

3807
  res = pr_fs_dircat(buf, -1, "foo", "bar");
1✔
3808
  ck_assert_msg(res == -1, "Failed to handle negative-length buffer");
1✔
3809
  ck_assert_msg(errno == EINVAL,
1✔
3810
    "Failed to set errno to EINVAL for negative-length buffer");
3811

3812
  a = pcalloc(p, PR_TUNABLE_PATH_MAX);
1✔
3813
  memset(a, 'A', PR_TUNABLE_PATH_MAX-1);
1✔
3814

3815
  b = "foo";
1✔
3816

3817
  res = pr_fs_dircat(buf, sizeof(buf)-1, a, b);
1✔
3818
  ck_assert_msg(res == -1, "Failed to handle too-long paths");
1✔
3819
  ck_assert_msg(errno == ENAMETOOLONG,
1✔
3820
    "Failed to set errno to ENAMETOOLONG for too-long paths");
3821

3822
  a = "foo";
1✔
3823
  b = "/bar";
1✔
3824
  ok = b;
1✔
3825
  res = pr_fs_dircat(buf, sizeof(buf)-1, a, b);
1✔
3826
  ck_assert_msg(res == 0, "Failed to concatenate abs-path path second dir");
1✔
3827
  ck_assert_msg(strcmp(buf, ok) == 0,
1✔
3828
    "Expected concatenated dir '%s', got '%s'", ok, buf);
3829

3830
  a = "foo";
1✔
3831
  b = "bar";
1✔
3832
  ok = "foo/bar";
1✔
3833
  res = pr_fs_dircat(buf, sizeof(buf)-1, a, b);
1✔
3834
  ck_assert_msg(res == 0, "Failed to concatenate two normal paths");
1✔
3835
  ck_assert_msg(strcmp(buf, ok) == 0,
1✔
3836
    "Expected concatenated dir '%s', got '%s'", ok, buf);
3837

3838
  a = "foo/";
1✔
3839
  b = "bar";
1✔
3840
  ok = "foo/bar";
1✔
3841
  res = pr_fs_dircat(buf, sizeof(buf)-1, a, b);
1✔
3842
  ck_assert_msg(res == 0, "Failed to concatenate first dir with trailing slash");
1✔
3843
  ck_assert_msg(strcmp(buf, ok) == 0, "Expected concatenated dir '%s', got '%s'",
1✔
3844
    ok, buf);
3845

3846
  a = "";
1✔
3847
  b = "";
1✔
3848
  ok = "/";
1✔
3849
  res = pr_fs_dircat(buf, sizeof(buf)-1, a, b);
1✔
3850
  ck_assert_msg(res == 0, "Failed to concatenate two empty paths");
1✔
3851
  ck_assert_msg(strcmp(buf, ok) == 0, "Expected concatenated dir '%s', got '%s'",
1✔
3852
    ok, buf);
3853

3854
  a = "/foo";
1✔
3855
  b = "";
1✔
3856
  ok = "/foo/";
1✔
3857
  res = pr_fs_dircat(buf, sizeof(buf)-1, a, b);
1✔
3858
  ck_assert_msg(res == 0, "Failed to concatenate two empty paths");
1✔
3859
  ck_assert_msg(strcmp(buf, ok) == 0, "Expected concatenated dir '%s', got '%s'",
1✔
3860
    ok, buf);
3861

3862
  a = "";
1✔
3863
  b = "/bar";
1✔
3864
  ok = "/bar/";
1✔
3865
  res = pr_fs_dircat(buf, sizeof(buf)-1, a, b);
1✔
3866
  ck_assert_msg(res == 0, "Failed to concatenate two empty paths");
1✔
3867
  ck_assert_msg(strcmp(buf, ok) == 0, "Expected concatenated dir '%s', got '%s'",
1✔
3868
    ok, buf);
3869
}
1✔
3870
END_TEST
3871

3872
START_TEST (fs_setcwd_test) {
1✔
3873
  int res;
1✔
3874
  const char *wd;
1✔
3875

3876
  /* Make sure that we don't segfault if we call pr_fs_setcwd() on the
3877
   * buffer that it is already using.
3878
   */
3879
  res = pr_fs_setcwd(pr_fs_getcwd());
1✔
3880
  ck_assert_msg(res == 0, "Failed to set cwd to '%s': %s", pr_fs_getcwd(),
1✔
3881
    strerror(errno));
3882

3883
  wd = pr_fs_getcwd();
1✔
3884
  ck_assert_msg(wd != NULL, "Failed to get working directory: %s",
1✔
3885
    strerror(errno));
3886
  ck_assert_msg(strcmp(wd, fsio_cwd) == 0,
1✔
3887
    "Expected '%s', got '%s'", fsio_cwd, wd);
3888

3889
  wd = pr_fs_getvwd();
1✔
3890
  ck_assert_msg(wd != NULL, "Failed to get working directory: %s",
1✔
3891
    strerror(errno));
3892
  ck_assert_msg(strcmp(wd, "/") == 0, "Expected '/', got '%s'", wd);
1✔
3893
}
1✔
3894
END_TEST
3895

3896
START_TEST (fs_glob_test) {
1✔
3897
  glob_t pglob;
1✔
3898
  int res;
1✔
3899

3900
  res = pr_fs_glob(NULL, 0, NULL, NULL);
1✔
3901
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
3902
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
3903
    strerror(errno), errno);
3904

3905
  res = pr_fs_glob(NULL, 0, NULL, &pglob);
1✔
3906
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
3907
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
3908
    strerror(errno), errno);
3909

3910
  memset(&pglob, 0, sizeof(pglob));
1✔
3911
  res = pr_fs_glob("*", 0, NULL, &pglob);
1✔
3912
  ck_assert_msg(res == 0, "Failed to glob: glob(3) returned %d: %s", res,
1✔
3913
    strerror(errno));
3914
  ck_assert_msg(pglob.gl_pathc > 0, "Expected >0, got %lu",
1✔
3915
    (unsigned long) pglob.gl_pathc);
3916

3917
  mark_point();
1✔
3918
  pr_fs_globfree(NULL);
1✔
3919
  if (res == 0) {
1✔
3920
    pr_fs_globfree(&pglob);
1✔
3921
  }
3922
}
1✔
3923
END_TEST
3924

3925
START_TEST (fs_copy_file_test) {
1✔
3926
  int res;
1✔
3927
  char *src_path = NULL, *dst_path = NULL, *text;
1✔
3928
  pr_fh_t *fh;
1✔
3929

3930
  res = pr_fs_copy_file(NULL, NULL);
1✔
3931
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
3932
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
3933
    strerror(errno), errno);
3934

3935
  src_path = (char *) fsio_copy_src_path;
1✔
3936
  res = pr_fs_copy_file(src_path, NULL);
1✔
3937
  ck_assert_msg(res < 0, "Failed to handle null destination path");
1✔
3938
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
3939
    strerror(errno), errno);
3940

3941
  dst_path = (char *) fsio_copy_dst_path;
1✔
3942
  res = pr_fs_copy_file(src_path, dst_path);
1✔
3943
  ck_assert_msg(res < 0, "Failed to handle nonexistent source path");
1✔
3944
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
1✔
3945
    strerror(errno), errno);
3946

3947
  res = pr_fs_copy_file("/tmp", dst_path);
1✔
3948
  ck_assert_msg(res < 0, "Failed to handle directory source path");
1✔
3949
  ck_assert_msg(errno == EISDIR, "Expected EISDIR (%d), got %s (%d)", EISDIR,
1✔
3950
    strerror(errno), errno);
3951

3952
  (void) unlink(src_path);
1✔
3953
  fh = pr_fsio_open(src_path, O_CREAT|O_EXCL|O_WRONLY);
1✔
3954
  ck_assert_msg(fh != NULL, "Failed to open '%s': %s", src_path, strerror(errno));
1✔
3955

3956
  text = "Hello, World!\n";
1✔
3957
  res = pr_fsio_write(fh, text, strlen(text));
1✔
3958
  ck_assert_msg(res >= 0, "Failed to write '%s' to '%s': %s", text, src_path,
1✔
3959
    strerror(errno));
3960

3961
  res = pr_fsio_close(fh);
1✔
3962
  ck_assert_msg(res == 0, "Failed to close '%s': %s", src_path, strerror(errno));
1✔
3963

3964
  res = pr_fs_copy_file(src_path, "/tmp");
1✔
3965
  ck_assert_msg(res < 0, "Failed to handle directory destination path");
1✔
3966
  ck_assert_msg(errno == EISDIR, "Expected EISDIR (%d), got %s (%d)", EISDIR,
1✔
3967
    strerror(errno), errno);
3968

3969
  res = pr_fs_copy_file(src_path, "/tmp/foo/bar/baz/quxx/quzz.dat");
1✔
3970
  ck_assert_msg(res < 0, "Failed to handle nonexistent destination path");
1✔
3971
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
1✔
3972
    strerror(errno), errno);
3973

3974
  mark_point();
1✔
3975
  res = pr_fs_copy_file(src_path, src_path);
1✔
3976
  ck_assert_msg(res == 0, "Failed to copy file to itself: %s", strerror(errno));
1✔
3977

3978
  (void) unlink(dst_path);
1✔
3979

3980
  mark_point();
1✔
3981
  res = pr_fs_copy_file(src_path, dst_path);
1✔
3982
  ck_assert_msg(res == 0, "Failed to copy file: %s", strerror(errno));
1✔
3983

3984
  (void) pr_fsio_unlink(src_path);
1✔
3985
  (void) pr_fsio_unlink(dst_path);
1✔
3986
}
1✔
3987
END_TEST
3988

3989
static unsigned int copy_progress_iter = 0;
3990
static void copy_progress_cb(int nwritten) {
2✔
3991
  copy_progress_iter++;
2✔
3992
}
2✔
3993

3994
START_TEST (fs_copy_file2_test) {
1✔
3995
  int res, flags;
1✔
3996
  char *src_path, *dst_path, *text;
1✔
3997
  pr_fh_t *fh;
1✔
3998

3999
  src_path = (char *) fsio_copy_src_path;
1✔
4000
  dst_path = (char *) fsio_copy_dst_path;
1✔
4001
  flags = PR_FSIO_COPY_FILE_FL_NO_DELETE_ON_FAILURE;
1✔
4002

4003
  (void) unlink(src_path);
1✔
4004
  (void) unlink(dst_path);
1✔
4005

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

4009
  text = "Hello, World!\n";
1✔
4010
  res = pr_fsio_write(fh, text, strlen(text));
1✔
4011
  ck_assert_msg(res >= 0, "Failed to write '%s' to '%s': %s", text, src_path,
1✔
4012
    strerror(errno));
4013

4014
  res = pr_fsio_close(fh);
1✔
4015
  ck_assert_msg(res == 0, "Failed to close '%s': %s", src_path, strerror(errno));
1✔
4016

4017
  copy_progress_iter = 0;
1✔
4018

4019
  mark_point();
1✔
4020
  res = pr_fs_copy_file2(src_path, dst_path, flags, copy_progress_cb);
1✔
4021
  ck_assert_msg(res == 0, "Failed to copy file: %s", strerror(errno));
1✔
4022

4023
  (void) pr_fsio_unlink(src_path);
1✔
4024
  (void) pr_fsio_unlink(dst_path);
1✔
4025

4026
  ck_assert_msg(copy_progress_iter > 0, "Unexpected progress callback count (%u)",
1✔
4027
    copy_progress_iter);
4028
}
1✔
4029
END_TEST
4030

4031
START_TEST (fs_interpolate_test) {
1✔
4032
  int res;
1✔
4033
  char buf[PR_TUNABLE_PATH_MAX], *path;
1✔
4034

4035
  memset(buf, '\0', sizeof(buf));
1✔
4036

4037
  mark_point();
1✔
4038
  res = pr_fs_interpolate(NULL, NULL, 0);
1✔
4039
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
4040
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
4041
    strerror(errno), errno);
4042

4043
  mark_point();
1✔
4044
  path = "/tmp";
1✔
4045
  res = pr_fs_interpolate(path, NULL, 0);
1✔
4046
  ck_assert_msg(res < 0, "Failed to handle null buffer");
1✔
4047
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
4048
    strerror(errno), errno);
4049

4050
  mark_point();
1✔
4051
  res = pr_fs_interpolate(path, buf, 0);
1✔
4052
  ck_assert_msg(res < 0, "Failed to handle zero buffer length");
1✔
4053
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
4054
    strerror(errno), errno);
4055

4056
  mark_point();
1✔
4057
  res = pr_fs_interpolate(path, buf, sizeof(buf)-1);
1✔
4058
  ck_assert_msg(res == 1, "Failed to interpolate path '%s': %s", path,
1✔
4059
    strerror(errno));
4060
  ck_assert_msg(strcmp(buf, path) == 0, "Expected '%s', got '%s'", path, buf);
1✔
4061

4062
  mark_point();
1✔
4063
  path = "~/foo/bar/baz/quzz/quzz.d";
1✔
4064
  res = pr_fs_interpolate(path, buf, sizeof(buf)-1);
1✔
4065
  ck_assert_msg(res == 1, "Failed to interpolate path '%s': %s", path,
1✔
4066
    strerror(errno));
4067
  ck_assert_msg(strcmp(buf, path+1) == 0, "Expected '%s', got '%s'",
1✔
4068
    path + 1, buf);
4069

4070
  mark_point();
1✔
4071
  path = "~";
1✔
4072
  res = pr_fs_interpolate(path, buf, sizeof(buf)-1);
1✔
4073
  ck_assert_msg(res == 1, "Failed to interpolate path '%s': %s", path,
1✔
4074
    strerror(errno));
4075
  ck_assert_msg(strcmp(buf, "/") == 0, "Expected '/', got '%s'", buf);
1✔
4076

4077
  mark_point();
1✔
4078
  session.chroot_path = "/tmp";
1✔
4079
  res = pr_fs_interpolate(path, buf, sizeof(buf)-1);
1✔
4080
  ck_assert_msg(res == 1, "Failed to interpolate path '%s': %s", path,
1✔
4081
    strerror(errno));
4082
  ck_assert_msg(strcmp(buf, session.chroot_path) == 0,
1✔
4083
    "Expected '%s', got '%s'", session.chroot_path, buf);
4084

4085
  session.chroot_path = NULL;
1✔
4086

4087
  mark_point();
1✔
4088
  session.user_homedir = "/foo";
1✔
4089
  res = pr_fs_interpolate(path, buf, sizeof(buf)-1);
1✔
4090
  ck_assert_msg(res == 1, "Failed to interpolate path '%s': %s", path,
1✔
4091
    strerror(errno));
4092
  ck_assert_msg(strcmp(buf, session.user_homedir) == 0,
1✔
4093
    "Expected '%s', got '%s'", session.user_homedir, buf);
4094

4095
  session.user_homedir = NULL;
1✔
4096

4097
  mark_point();
1✔
4098
  path = "~foo.bar.baz.quzz";
1✔
4099
  res = pr_fs_interpolate(path, buf, sizeof(buf)-1);
1✔
4100
  ck_assert_msg(res < 0, "Interpolated '%s' unexpectedly", path);
1✔
4101
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
1✔
4102
    strerror(errno), errno);
4103

4104
  mark_point();
1✔
4105
  session.user = "testsuite";
1✔
4106
  path = "~/tmp.d/test.d/foo.d/bar.d";
1✔
4107
  res = pr_fs_interpolate(path, buf, sizeof(buf)-1);
1✔
4108
  ck_assert_msg(res < 0, "Interpolated '%s' unexpectedly", path);
1✔
4109
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
1✔
4110
    strerror(errno), errno);
4111

4112
  mark_point();
1✔
4113
  session.user_homedir = "/cached";
1✔
4114
  path = "~/tmp.d/test.d/foo.d/bar.d";
1✔
4115
  res = pr_fs_interpolate(path, buf, sizeof(buf)-1);
1✔
4116
  ck_assert_msg(res == 1, "Failed to interpolate path '%s': %s", path,
1✔
4117
    strerror(errno));
4118
  ck_assert_msg(strcmp(buf, "/cached/tmp.d/test.d/foo.d/bar.d") == 0,
1✔
4119
    "Expected '/cached/tmp.d/test.d/foo.d/bar.d', got '%s'", buf);
4120

4121
  session.user = NULL;
1✔
4122
  session.user_homedir = NULL;
1✔
4123
}
1✔
4124
END_TEST
4125

4126
START_TEST (fs_resolve_partial_test) {
1✔
4127
  int op = FSIO_FILE_STAT, res;
1✔
4128
  char buf[PR_TUNABLE_PATH_MAX], *path;
1✔
4129

4130
  res = pr_fs_resolve_partial(NULL, NULL, 0, op);
1✔
4131
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
4132
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
4133
    strerror(errno), errno);
4134

4135
  path = "/tmp";
1✔
4136
  res = pr_fs_resolve_partial(path, NULL, 0, op);
1✔
4137
  ck_assert_msg(res < 0, "Failed to handle null buffer");
1✔
4138
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
4139
    strerror(errno), errno);
4140

4141
  memset(buf, '\0', sizeof(buf));
1✔
4142
  res = pr_fs_resolve_partial(path, buf, 0, op);
1✔
4143
  ck_assert_msg(res < 0, "Failed to handle zero buffer length");
1✔
4144
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
4145
    strerror(errno), errno);
4146

4147
  res = pr_fs_resolve_partial(path, buf, sizeof(buf)-1, op);
1✔
4148
  ck_assert_msg(res == 0, "Failed to resolve '%s': %s", path, strerror(errno));
1✔
4149
  if (strcmp(buf, path) != 0) {
1✔
4150
    /* Mac-specific hack */
4151
    const char *prefix = "/private";
×
4152

4153
    if (strncmp(buf, prefix, strlen(prefix)) != 0) {
×
4154
      ck_abort_msg("Expected '%s', got '%s'", path, buf);
×
4155
    }
4156
  }
4157

4158
  path = "/tmp/.////./././././.";
1✔
4159
  res = pr_fs_resolve_partial(path, buf, sizeof(buf)-1, op);
1✔
4160
  ck_assert_msg(res == 0, "Failed to resolve '%s': %s", path, strerror(errno));
1✔
4161
  if (strcmp(buf, path) != 0) {
1✔
4162
    /* Mac-specific hack */
4163
    const char *prefix = "/private";
1✔
4164

4165
    if (strncmp(buf, prefix, strlen(prefix)) != 0 &&
1✔
4166
        strcmp(buf, "/tmp/") != 0) {
1✔
4167
      ck_abort_msg("Expected '%s', got '%s'", path, buf);
×
4168
    }
4169
  }
4170

4171
  path = "/../../../.././..///../";
1✔
4172
  res = pr_fs_resolve_partial(path, buf, sizeof(buf)-1, op);
1✔
4173
  ck_assert_msg(res == 0, "Failed to resolve '%s': %s", path, strerror(errno));
1✔
4174
  if (strcmp(buf, "/") != 0) {
1✔
4175
    /* Mac-specific hack */
4176
    const char *prefix = "/private";
×
4177

4178
    if (strncmp(buf, prefix, strlen(prefix)) != 0) {
×
4179
      ck_abort_msg("Expected '%s', got '%s'", path, buf);
×
4180
    }
4181
  }
4182

4183
  path = "/tmp/.///../../..../";
1✔
4184
  res = pr_fs_resolve_partial(path, buf, sizeof(buf)-1, op);
1✔
4185
  ck_assert_msg(res < 0, "Resolved '%s' unexpectedly", path);
1✔
4186
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
1✔
4187
    strerror(errno), errno);
4188

4189
  path = "~foo/.///../../..../";
1✔
4190
  res = pr_fs_resolve_partial(path, buf, sizeof(buf)-1, op);
1✔
4191
  ck_assert_msg(res < 0, "Resolved '%s' unexpectedly", path);
1✔
4192
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
1✔
4193
    strerror(errno), errno);
4194

4195
  path = "../../..../";
1✔
4196
  res = pr_fs_resolve_partial(path, buf, sizeof(buf)-1, op);
1✔
4197
  ck_assert_msg(res < 0, "Resolved '%s' unexpectedly", path);
1✔
4198
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
1✔
4199
    strerror(errno), errno);
4200

4201
  /* Resolve a symlink path */
4202
  res = pr_fsio_symlink("/tmp", fsio_link_path);
1✔
4203
  ck_assert_msg(res == 0, "Failed to create symlink to '%s': %s", fsio_link_path,
1✔
4204
    strerror(errno));
4205

4206
  res = pr_fs_resolve_partial(fsio_link_path, buf, sizeof(buf)-1, op);
1✔
4207
  ck_assert_msg(res == 0, "Failed to resolve '%s': %s", fsio_link_path,
1✔
4208
    strerror(errno));
4209

4210
  (void) unlink(fsio_link_path);
1✔
4211
}
1✔
4212
END_TEST
4213

4214
START_TEST (fs_resolve_path_test) {
1✔
4215
  int op = FSIO_FILE_STAT, res;
1✔
4216
  char buf[PR_TUNABLE_PATH_MAX], *path;
1✔
4217

4218
  memset(buf, '\0', sizeof(buf));
1✔
4219

4220
  res = pr_fs_resolve_path(NULL, NULL, 0, op);
1✔
4221
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
4222
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
4223
    strerror(errno), errno);
4224

4225
  path = "/tmp";
1✔
4226
  res = pr_fs_resolve_path(path, NULL, 0, op);
1✔
4227
  ck_assert_msg(res < 0, "Failed to handle null buffer");
1✔
4228
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
4229
    strerror(errno), errno);
4230

4231
  res = pr_fs_resolve_path(path, buf, 0, op);
1✔
4232
  ck_assert_msg(res < 0, "Failed to handle zero buffer length");
1✔
4233
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
4234
    strerror(errno), errno);
4235

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

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

4248
  /* Resolve a symlink path */
4249
  res = pr_fsio_symlink("/tmp", fsio_link_path);
1✔
4250
  ck_assert_msg(res == 0, "Failed to create symlink to '%s': %s", fsio_link_path,
1✔
4251
    strerror(errno));
4252

4253
  res = pr_fs_resolve_path(fsio_link_path, buf, sizeof(buf)-1, op);
1✔
4254
  ck_assert_msg(res == 0, "Failed to resolve '%s': %s", fsio_link_path,
1✔
4255
    strerror(errno));
4256

4257
  (void) unlink(fsio_link_path);
1✔
4258
}
1✔
4259
END_TEST
4260

4261
START_TEST (fs_use_encoding_test) {
1✔
4262
  int res;
1✔
4263

4264
  res = pr_fs_use_encoding(-1);
1✔
4265
  ck_assert_msg(res < 0, "Failed to handle invalid setting");
1✔
4266
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
4267
    strerror(errno), errno);
4268

4269
  res = pr_fs_use_encoding(TRUE);
1✔
4270
  ck_assert_msg(res == TRUE, "Expected TRUE, got %d", res);
1✔
4271

4272
  res = pr_fs_use_encoding(FALSE);
1✔
4273
  ck_assert_msg(res == TRUE, "Expected TRUE, got %d", res);
1✔
4274

4275
  res = pr_fs_use_encoding(TRUE);
1✔
4276
  ck_assert_msg(res == FALSE, "Expected FALSE, got %d", res);
1✔
4277
}
1✔
4278
END_TEST
4279

4280
START_TEST (fs_decode_path2_test) {
1✔
4281
  int flags = 0;
1✔
4282
  char junk[32], *res;
1✔
4283
  const char *path;
1✔
4284

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

4290
  res = pr_fs_decode_path(p, NULL);
1✔
4291
  ck_assert_msg(res == NULL, "Failed to handle null path");
1✔
4292
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
4293
    strerror(errno), errno);
4294

4295
  path = "/tmp";
1✔
4296
  res = pr_fs_decode_path2(p, path, flags);
1✔
4297
  ck_assert_msg(res != NULL, "Failed to decode path '%s': %s", path,
1✔
4298
    strerror(errno));
4299

4300
  path = "/tmp";
1✔
4301
  res = pr_fs_decode_path2(p, path, flags);
1✔
4302
  ck_assert_msg(res != NULL, "Failed to decode path '%s': %s", path,
1✔
4303
    strerror(errno));
4304

4305
  /* Test a path that cannot be decoded, using junk data from the stack */
4306
  junk[sizeof(junk)-1] = '\0';
1✔
4307
  path = junk;
1✔
4308
  res = pr_fs_decode_path2(p, path, flags);
1✔
4309
  ck_assert_msg(res != NULL, "Failed to decode path: %s", strerror(errno));
1✔
4310

4311
  /* XXX Use the FSIO_DECODE_FL_TELL_ERRORS flags, AND set the encode
4312
   * policy to use PR_ENCODE_POLICY_FL_REQUIRE_VALID_ENCODING.
4313
   */
4314
}
1✔
4315
END_TEST
4316

4317
START_TEST (fs_encode_path_test) {
1✔
4318
  char junk[32], *res;
1✔
4319
  const char *path;
1✔
4320

4321
  res = pr_fs_encode_path(NULL, NULL);
1✔
4322
  ck_assert_msg(res == NULL, "Failed to handle null arguments");
1✔
4323
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
4324
    strerror(errno), errno);
4325

4326
  res = pr_fs_encode_path(p, NULL);
1✔
4327
  ck_assert_msg(res == NULL, "Failed to handle null path");
1✔
4328
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
4329
    strerror(errno), errno);
4330

4331
  path = "/tmp";
1✔
4332
  res = pr_fs_encode_path(p, path);
1✔
4333
  ck_assert_msg(res != NULL, "Failed to encode path '%s': %s", path,
1✔
4334
    strerror(errno));
4335

4336
  /* Test a path that cannot be encoded, using junk data from the stack */
4337
  junk[sizeof(junk)-1] = '\0';
1✔
4338
  path = junk;
1✔
4339
  res = pr_fs_encode_path(p, path);
1✔
4340
  ck_assert_msg(res != NULL, "Failed to encode path: %s", strerror(errno));
1✔
4341
}
1✔
4342
END_TEST
4343

4344
START_TEST (fs_split_path_test) {
1✔
4345
  array_header *res;
1✔
4346
  const char *path, *elt;
1✔
4347

4348
  mark_point();
1✔
4349
  res = pr_fs_split_path(NULL, NULL);
1✔
4350
  ck_assert_msg(res == NULL, "Failed to handle null pool");
1✔
4351
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
4352
    strerror(errno), errno);
4353

4354
  mark_point();
1✔
4355
  res = pr_fs_split_path(p, NULL);
1✔
4356
  ck_assert_msg(res == NULL, "Failed to handle null path");
1✔
4357
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
4358
    strerror(errno), errno);
4359

4360
  path = "";
1✔
4361

4362
  mark_point();
1✔
4363
  res = pr_fs_split_path(p, path);
1✔
4364
  ck_assert_msg(res == NULL, "Failed to handle empty path");
1✔
4365
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
4366
    strerror(errno), errno);
4367

4368
  path = ".";
1✔
4369

4370
  mark_point();
1✔
4371
  res = pr_fs_split_path(p, path);
1✔
4372
  ck_assert_msg(res != NULL, "Failed to split path '%s': %s", path,
1✔
4373
    strerror(errno));
4374
  ck_assert_msg(res->nelts == 1, "Expected 1, got %u", res->nelts);
1✔
4375
  elt = ((char **) res->elts)[0];
1✔
4376

4377
  /* Note: pr_fs_split_path() cleans the path into an absolute path.  And
4378
   * the default "cwd" test setting is "/", so yes, this is surprising but
4379
   * expected.  Subject to change in the future.
4380
   */
4381
  ck_assert_msg(strcmp(elt, "/") == 0, "Expected '/', got '%s'", elt);
1✔
4382

4383
  path = "/";
1✔
4384

4385
  mark_point();
1✔
4386
  res = pr_fs_split_path(p, path);
1✔
4387
  ck_assert_msg(res != NULL, "Failed to split path '%s': %s", path,
1✔
4388
    strerror(errno));
4389
  ck_assert_msg(res->nelts == 1, "Expected 1, got %u", res->nelts);
1✔
4390
  elt = ((char **) res->elts)[0];
1✔
4391
  ck_assert_msg(strcmp(elt, "/") == 0, "Expected '/', got '%s'", elt);
1✔
4392

4393
  path = "///";
1✔
4394

4395
  mark_point();
1✔
4396
  res = pr_fs_split_path(p, path);
1✔
4397
  ck_assert_msg(res != NULL, "Failed to split path '%s': %s", path,
1✔
4398
    strerror(errno));
4399
  ck_assert_msg(res->nelts == 1, "Expected 1, got %u", res->nelts);
1✔
4400
  elt = ((char **) res->elts)[0];
1✔
4401
  ck_assert_msg(strcmp(elt, "/") == 0, "Expected '/', got '%s'", elt);
1✔
4402

4403
  path = "/foo/bar/baz/";
1✔
4404

4405
  mark_point();
1✔
4406
  res = pr_fs_split_path(p, path);
1✔
4407
  ck_assert_msg(res != NULL, "Failed to split path '%s': %s", path,
1✔
4408
    strerror(errno));
4409
  ck_assert_msg(res->nelts == 4, "Expected 4, got %u", res->nelts);
1✔
4410
  elt = ((char **) res->elts)[0];
1✔
4411
  ck_assert_msg(strcmp(elt, "/") == 0, "Expected '/', got '%s'", elt);
1✔
4412
  elt = ((char **) res->elts)[1];
1✔
4413
  ck_assert_msg(strcmp(elt, "foo") == 0, "Expected 'foo', got '%s'", elt);
1✔
4414
  elt = ((char **) res->elts)[2];
1✔
4415
  ck_assert_msg(strcmp(elt, "bar") == 0, "Expected 'bar', got '%s'", elt);
1✔
4416
  elt = ((char **) res->elts)[3];
1✔
4417
  ck_assert_msg(strcmp(elt, "baz") == 0, "Expected 'baz', got '%s'", elt);
1✔
4418

4419
  path = "/foo//bar//baz//";
1✔
4420

4421
  mark_point();
1✔
4422
  res = pr_fs_split_path(p, path);
1✔
4423
  ck_assert_msg(res != NULL, "Failed to split path '%s': %s", path,
1✔
4424
    strerror(errno));
4425
  ck_assert_msg(res->nelts == 4, "Expected 4, got %u", res->nelts);
1✔
4426
  elt = ((char **) res->elts)[0];
1✔
4427
  ck_assert_msg(strcmp(elt, "/") == 0, "Expected '/', got '%s'", elt);
1✔
4428
  elt = ((char **) res->elts)[1];
1✔
4429
  ck_assert_msg(strcmp(elt, "foo") == 0, "Expected 'foo', got '%s'", elt);
1✔
4430
  elt = ((char **) res->elts)[2];
1✔
4431
  ck_assert_msg(strcmp(elt, "bar") == 0, "Expected 'bar', got '%s'", elt);
1✔
4432
  elt = ((char **) res->elts)[3];
1✔
4433
  ck_assert_msg(strcmp(elt, "baz") == 0, "Expected 'baz', got '%s'", elt);
1✔
4434

4435
  path = "/foo/bar/baz";
1✔
4436

4437
  mark_point();
1✔
4438
  res = pr_fs_split_path(p, path);
1✔
4439
  ck_assert_msg(res != NULL, "Failed to split path '%s': %s", path,
1✔
4440
    strerror(errno));
4441
  ck_assert_msg(res->nelts == 4, "Expected 4, got %u", res->nelts);
1✔
4442
  elt = ((char **) res->elts)[0];
1✔
4443
  ck_assert_msg(strcmp(elt, "/") == 0, "Expected '/', got '%s'", elt);
1✔
4444
  elt = ((char **) res->elts)[1];
1✔
4445
  ck_assert_msg(strcmp(elt, "foo") == 0, "Expected 'foo', got '%s'", elt);
1✔
4446
  elt = ((char **) res->elts)[2];
1✔
4447
  ck_assert_msg(strcmp(elt, "bar") == 0, "Expected 'bar', got '%s'", elt);
1✔
4448
  elt = ((char **) res->elts)[3];
1✔
4449
  ck_assert_msg(strcmp(elt, "baz") == 0, "Expected 'baz', got '%s'", elt);
1✔
4450

4451
  path = "foo/bar/baz";
1✔
4452

4453
  mark_point();
1✔
4454
  res = pr_fs_split_path(p, path);
1✔
4455
  ck_assert_msg(res != NULL, "Failed to split path '%s': %s", path,
1✔
4456
    strerror(errno));
4457
  ck_assert_msg(res->nelts == 3, "Expected 3, got %u", res->nelts);
1✔
4458
  elt = ((char **) res->elts)[0];
1✔
4459
  ck_assert_msg(strcmp(elt, "foo") == 0, "Expected 'foo', got '%s'", elt);
1✔
4460
  elt = ((char **) res->elts)[1];
1✔
4461
  ck_assert_msg(strcmp(elt, "bar") == 0, "Expected 'bar', got '%s'", elt);
1✔
4462
  elt = ((char **) res->elts)[2];
1✔
4463
  ck_assert_msg(strcmp(elt, "baz") == 0, "Expected 'baz', got '%s'", elt);
1✔
4464
}
1✔
4465
END_TEST
4466

4467
START_TEST (fs_join_path_test) {
1✔
4468
  char *path;
1✔
4469
  array_header *components;
1✔
4470

4471
  mark_point();
1✔
4472
  path = pr_fs_join_path(NULL, NULL, 0);
1✔
4473
  ck_assert_msg(path == NULL, "Failed to handle null pool");
1✔
4474
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
4475
    strerror(errno), errno);
4476

4477
  mark_point();
1✔
4478
  path = pr_fs_join_path(p, NULL, 0);
1✔
4479
  ck_assert_msg(path == NULL, "Failed to handle null components");
1✔
4480
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
4481
    strerror(errno), errno);
4482

4483
  components = make_array(p, 0, sizeof(char **));
1✔
4484

4485
  mark_point();
1✔
4486
  path = pr_fs_join_path(p, components, 0);
1✔
4487
  ck_assert_msg(path == NULL, "Failed to handle empty components");
1✔
4488
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
4489
    strerror(errno), errno);
4490

4491
  *((char **) push_array(components)) = pstrdup(p, "/");
1✔
4492

4493
  mark_point();
1✔
4494
  path = pr_fs_join_path(p, components, 0);
1✔
4495
  ck_assert_msg(path == NULL, "Failed to handle empty count");
1✔
4496
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
4497
    strerror(errno), errno);
4498

4499
  mark_point();
1✔
4500
  path = pr_fs_join_path(p, components, 3);
1✔
4501
  ck_assert_msg(path == NULL, "Failed to handle invalid count");
1✔
4502
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
4503
    strerror(errno), errno);
4504

4505
  mark_point();
1✔
4506
  path = pr_fs_join_path(p, components, 1);
1✔
4507
  ck_assert_msg(path != NULL, "Failed to join path: %s", strerror(errno));
1✔
4508
  ck_assert_msg(strcmp(path, "/") == 0, "Expected '/', got '%s'", path);
1✔
4509

4510
  *((char **) push_array(components)) = pstrdup(p, "foo");
1✔
4511
  *((char **) push_array(components)) = pstrdup(p, "bar");
1✔
4512
  *((char **) push_array(components)) = pstrdup(p, "baz");
1✔
4513

4514
  mark_point();
1✔
4515
  path = pr_fs_join_path(p, components, 4);
1✔
4516
  ck_assert_msg(path != NULL, "Failed to join path: %s", strerror(errno));
1✔
4517
  ck_assert_msg(strcmp(path, "/foo/bar/baz") == 0,
1✔
4518
    "Expected '/foo/bar/baz', got '%s'", path);
4519

4520
  mark_point();
1✔
4521
  path = pr_fs_join_path(p, components, 3);
1✔
4522
  ck_assert_msg(path != NULL, "Failed to join path: %s", strerror(errno));
1✔
4523
  ck_assert_msg(strcmp(path, "/foo/bar") == 0, "Expected '/foo/bar', got '%s'",
1✔
4524
    path);
4525

4526
  mark_point();
1✔
4527
  components = make_array(p, 0, sizeof(char **));
1✔
4528

4529
  *((char **) push_array(components)) = pstrdup(p, "foo");
1✔
4530
  *((char **) push_array(components)) = pstrdup(p, "bar");
1✔
4531
  *((char **) push_array(components)) = pstrdup(p, "baz");
1✔
4532

4533
  path = pr_fs_join_path(p, components, components->nelts);
1✔
4534
  ck_assert_msg(path != NULL, "Failed to join path: %s", strerror(errno));
1✔
4535
  ck_assert_msg(strcmp(path, "foo/bar/baz") == 0,
1✔
4536
    "Expected 'foo/bar/baz', got '%s'", path);
4537
}
1✔
4538
END_TEST
4539

4540
START_TEST (fs_virtual_path_test) {
1✔
4541
  const char *path;
1✔
4542
  char buf[PR_TUNABLE_PATH_MAX];
1✔
4543

4544
  mark_point();
1✔
4545
  pr_fs_virtual_path(NULL, NULL, 0);
1✔
4546

4547
  mark_point();
1✔
4548
  path = "/tmp";
1✔
4549
  pr_fs_virtual_path(path, NULL, 0);
1✔
4550

4551
  mark_point();
1✔
4552
  memset(buf, '\0', sizeof(buf));
1✔
4553
  pr_fs_virtual_path(path, buf, 0);
1✔
4554
  ck_assert_msg(*buf == '\0', "Expected empty buffer, got '%s'", buf);
1✔
4555

4556
  mark_point();
1✔
4557
  memset(buf, '\0', sizeof(buf));
1✔
4558
  pr_fs_virtual_path(path, buf, sizeof(buf)-1);
1✔
4559
  ck_assert_msg(strcmp(buf, path) == 0, "Expected '%s', got '%s'", path, buf);
1✔
4560

4561
  mark_point();
1✔
4562
  memset(buf, '\0', sizeof(buf));
1✔
4563
  path = "tmp";
1✔
4564
  pr_fs_virtual_path(path, buf, sizeof(buf)-1);
1✔
4565
  ck_assert_msg(strcmp(buf, "/tmp") == 0, "Expected '/tmp', got '%s'", buf);
1✔
4566

4567
  mark_point();
1✔
4568
  memset(buf, '\0', sizeof(buf));
1✔
4569
  path = "/tmp/././";
1✔
4570
  pr_fs_virtual_path(path, buf, sizeof(buf)-1);
1✔
4571
  ck_assert_msg(strcmp(buf, "/tmp") == 0 || strcmp(buf, "/tmp/") == 0,
1✔
4572
    "Expected '/tmp', got '%s'", buf);
4573

4574
  mark_point();
1✔
4575
  memset(buf, '\0', sizeof(buf));
1✔
4576
  path = "tmp/../../";
1✔
4577
  pr_fs_virtual_path(path, buf, sizeof(buf)-1);
1✔
4578
  ck_assert_msg(strcmp(buf, "/") == 0, "Expected '/', got '%s'", buf);
1✔
4579
}
1✔
4580
END_TEST
4581

4582
#if 0
4583
/* This test is commented out, since libcheck is very unhappy when we
4584
 * close its logging fds out from underneath it.  Thus we keep this
4585
 * test here, for any future tinkering, just not enabled by default.
4586
 */
4587
START_TEST (fs_close_extra_fds_test) {
4588
  mark_point();
4589
  pr_fs_close_extra_fds();
4590
}
4591
END_TEST
4592
#endif
4593

4594
START_TEST (fs_get_usable_fd_test) {
1✔
4595
  int fd, res;
1✔
4596

4597
  fd = -1;
1✔
4598
  res = pr_fs_get_usable_fd(fd);
1✔
4599
  ck_assert_msg(res < 0, "Failed to handle bad fd");
1✔
4600
  ck_assert_msg(errno == EBADF || errno == EINVAL,
1✔
4601
    "Expected EBADF (%d) or EINVAL (%d), got %s (%d)", EBADF, EINVAL,
4602
    strerror(errno), errno);
4603

4604
  fd = STDERR_FILENO + 1;
1✔
4605
  res = pr_fs_get_usable_fd(fd);
1✔
4606
  ck_assert_msg(res == fd, "Expected %d, got %d", fd, res);
1✔
4607

4608
  fd = STDERR_FILENO - 1;
1✔
4609
  res = pr_fs_get_usable_fd(fd);
1✔
4610
  ck_assert_msg(res > STDERR_FILENO, "Failed to get usable fd for %d: %s", fd,
1✔
4611
    strerror(errno));
4612
  (void) close(res);
1✔
4613
}
1✔
4614
END_TEST
4615

4616
START_TEST (fs_get_usable_fd2_test) {
1✔
4617
  int fd, res;
1✔
4618

4619
  res = pr_fs_get_usable_fd2(NULL);
1✔
4620
  ck_assert_msg(res < 0, "Failed to handle null argument");
1✔
4621
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
4622
    strerror(errno), errno);
4623

4624
  fd = -1;
1✔
4625
  res = pr_fs_get_usable_fd2(&fd);
1✔
4626
  ck_assert_msg(res < 0, "Failed to handle bad fd");
1✔
4627
  ck_assert_msg(errno == EBADF || errno == EINVAL,
1✔
4628
    "Expected EBADF (%d) or EINVAL (%d), got %s (%d)", EBADF, EINVAL,
4629
    strerror(errno), errno);
4630

4631
  fd = STDERR_FILENO + 1;
1✔
4632
  res = pr_fs_get_usable_fd2(&fd);
1✔
4633
  ck_assert_msg(res == 0, "Failed to handle fd: %s", strerror(errno));
1✔
4634
  ck_assert_msg(fd == (STDERR_FILENO + 1), "Expected %d, got %d",
1✔
4635
    STDERR_FILENO + 1, fd);
4636

4637
  fd = STDERR_FILENO - 1;
1✔
4638
  res = pr_fs_get_usable_fd2(&fd);
1✔
4639
  ck_assert_msg(res == 0, "Failed to handle fd: %s", strerror(errno));
1✔
4640
  ck_assert_msg(fd > STDERR_FILENO, "Expected >%d, got %d", STDERR_FILENO, fd);
1✔
4641
  (void) close(fd);
1✔
4642
}
1✔
4643
END_TEST
4644

4645
START_TEST (fs_getsize_test) {
1✔
4646
  off_t res;
1✔
4647
  char *path;
1✔
4648

4649
  res = pr_fs_getsize(NULL);
1✔
4650
  ck_assert_msg(res == (off_t) -1, "Failed to handle null argument");
1✔
4651
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
4652
    strerror(errno), errno);
4653

4654
  path = "/tmp";
1✔
4655
  res = pr_fs_getsize(path);
1✔
4656
  ck_assert_msg(res != (off_t) -1, "Failed to get fs size for '%s': %s", path,
1✔
4657
    strerror(errno));
4658
}
1✔
4659
END_TEST
4660

4661
START_TEST (fs_getsize2_test) {
1✔
4662
  int res;
1✔
4663
  char *path;
1✔
4664
  off_t sz = 0;
1✔
4665

4666
  res = pr_fs_getsize2(NULL, NULL);
1✔
4667
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
4668
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
4669
    strerror(errno), errno);
4670

4671
  path = "/tmp";
1✔
4672
  res = pr_fs_getsize2(path, NULL);
1✔
4673
  ck_assert_msg(res < 0, "Failed to handle null size argument");
1✔
4674
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
4675
    strerror(errno), errno);
4676

4677
  res = pr_fs_getsize2(path, &sz);
1✔
4678
  ck_assert_msg(res == 0, "Failed to get fs size for '%s': %s", path,
1✔
4679
    strerror(errno));
4680
}
1✔
4681
END_TEST
4682

4683
START_TEST (fs_fgetsize_test) {
1✔
4684
  int fd = -1, res;
1✔
4685
  off_t fs_sz = 0;
1✔
4686

4687
  mark_point();
1✔
4688
  res = pr_fs_fgetsize(fd, &fs_sz);
1✔
4689
  ck_assert_msg(res < 0, "Failed to handle bad file descriptor");
1✔
4690
  ck_assert_msg(errno == EBADF, "Expected EBADF (%d), got %s (%d)", EBADF,
1✔
4691
    strerror(errno), errno);
4692

4693
  mark_point();
1✔
4694
  fd = 0;
1✔
4695
  fs_sz = 0;
1✔
4696
  res = pr_fs_fgetsize(fd, NULL);
1✔
4697
  ck_assert_msg(res < 0, "Failed to handle null size argument");
1✔
4698
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
4699
    strerror(errno), errno);
4700

4701
  mark_point();
1✔
4702
  fd = 0;
1✔
4703
  fs_sz = 0;
1✔
4704
  res = pr_fs_fgetsize(fd, &fs_sz);
1✔
4705
  ck_assert_msg(res == 0, "Failed to get fs size for fd %d: %s", fd,
1✔
4706
    strerror(errno));
4707
}
1✔
4708
END_TEST
4709

4710
START_TEST (fs_fadvise_test) {
1✔
4711
  int advice, fd = -1;
1✔
4712
  off_t off = 0, len = 0;
1✔
4713

4714
  /* We make these function calls to exercise the code paths, even
4715
   * though there's no good way to verify the behavior changed.
4716
   */
4717

4718
  advice = PR_FS_FADVISE_NORMAL;
1✔
4719
  pr_fs_fadvise(fd, off, len, advice);
1✔
4720

4721
  advice = PR_FS_FADVISE_RANDOM;
1✔
4722
  pr_fs_fadvise(fd, off, len, advice);
1✔
4723

4724
  advice = PR_FS_FADVISE_SEQUENTIAL;
1✔
4725
  pr_fs_fadvise(fd, off, len, advice);
1✔
4726

4727
  advice = PR_FS_FADVISE_WILLNEED;
1✔
4728
  pr_fs_fadvise(fd, off, len, advice);
1✔
4729

4730
  advice = PR_FS_FADVISE_DONTNEED;
1✔
4731
  pr_fs_fadvise(fd, off, len, advice);
1✔
4732

4733
  advice = PR_FS_FADVISE_NOREUSE;
1✔
4734
  pr_fs_fadvise(fd, off, len, advice);
1✔
4735
}
1✔
4736
END_TEST
4737

4738
START_TEST (fs_have_access_test) {
1✔
4739
  int res;
1✔
4740
  struct stat st;
1✔
4741
  uid_t uid;
1✔
4742
  gid_t gid;
1✔
4743
  array_header *suppl_gids;
1✔
4744

4745
  mark_point();
1✔
4746
  res = pr_fs_have_access(NULL, R_OK, 0, 0, NULL);
1✔
4747
  ck_assert_msg(res < 0, "Failed to handle null stat");
1✔
4748
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
4749
    strerror(errno), errno);
4750

4751
  memset(&st, 0, sizeof(struct stat));
1✔
4752

4753
  mark_point();
1✔
4754
  res = pr_fs_have_access(&st, R_OK, 0, 0, NULL);
1✔
4755
  ck_assert_msg(res == 0, "Failed to handle root access: %s", strerror(errno));
1✔
4756

4757
  /* Use cases: no matching UID or GID; R_OK, W_OK, X_OK. */
4758
  memset(&st, 0, sizeof(struct stat));
1✔
4759
  uid = 1;
1✔
4760
  gid = 1;
1✔
4761

4762
  mark_point();
1✔
4763
  res = pr_fs_have_access(&st, R_OK, uid, gid, NULL);
1✔
4764
  ck_assert_msg(res < 0, "Failed to handle missing other R_OK access");
1✔
4765
  ck_assert_msg(errno == EACCES, "Expected EACCES (%d), got %s (%d)", EACCES,
1✔
4766
    strerror(errno), errno);
4767

4768
  mark_point();
1✔
4769
  res = pr_fs_have_access(&st, W_OK, uid, gid, NULL);
1✔
4770
  ck_assert_msg(res < 0, "Failed to handle missing other W_OK access");
1✔
4771
  ck_assert_msg(errno == EACCES, "Expected EACCES (%d), got %s (%d)", EACCES,
1✔
4772
    strerror(errno), errno);
4773

4774
  mark_point();
1✔
4775
  res = pr_fs_have_access(&st, X_OK, uid, gid, NULL);
1✔
4776
  ck_assert_msg(res < 0, "Failed to handle missing other X_OK access");
1✔
4777
  ck_assert_msg(errno == EACCES, "Expected EACCES (%d), got %s (%d)", EACCES,
1✔
4778
    strerror(errno), errno);
4779

4780
  st.st_mode = S_IFMT|S_IROTH|S_IWOTH|S_IXOTH;
1✔
4781

4782
  mark_point();
1✔
4783
  res = pr_fs_have_access(&st, R_OK, uid, gid, NULL);
1✔
4784
  ck_assert_msg(res == 0, "Failed to handle other R_OK access: %s",
1✔
4785
    strerror(errno));
4786

4787
  mark_point();
1✔
4788
  res = pr_fs_have_access(&st, W_OK, uid, gid, NULL);
1✔
4789
  ck_assert_msg(res == 0, "Failed to handle other W_OK access: %s",
1✔
4790
    strerror(errno));
4791

4792
  mark_point();
1✔
4793
  res = pr_fs_have_access(&st, X_OK, uid, gid, NULL);
1✔
4794
  ck_assert_msg(res == 0, "Failed to handle other X_OK access: %s",
1✔
4795
    strerror(errno));
4796

4797
  /* Use cases: matching UID, not GID; R_OK, W_OK, X_OK. */
4798
  memset(&st, 0, sizeof(struct stat));
1✔
4799

4800
  st.st_uid = uid;
1✔
4801

4802
  mark_point();
1✔
4803
  res = pr_fs_have_access(&st, R_OK, uid, gid, NULL);
1✔
4804
  ck_assert_msg(res < 0, "Failed to handle missing user R_OK access");
1✔
4805
  ck_assert_msg(errno == EACCES, "Expected EACCES (%d), got %s (%d)", EACCES,
1✔
4806
    strerror(errno), errno);
4807

4808
  mark_point();
1✔
4809
  res = pr_fs_have_access(&st, W_OK, uid, gid, NULL);
1✔
4810
  ck_assert_msg(res < 0, "Failed to handle missing user W_OK access");
1✔
4811
  ck_assert_msg(errno == EACCES, "Expected EACCES (%d), got %s (%d)", EACCES,
1✔
4812
    strerror(errno), errno);
4813

4814
  mark_point();
1✔
4815
  res = pr_fs_have_access(&st, X_OK, uid, gid, NULL);
1✔
4816
  ck_assert_msg(res < 0, "Failed to handle missing user X_OK access");
1✔
4817
  ck_assert_msg(errno == EACCES, "Expected EACCES (%d), got %s (%d)", EACCES,
1✔
4818
    strerror(errno), errno);
4819

4820
  st.st_mode = S_IFMT|S_IRUSR|S_IWUSR|S_IXUSR;
1✔
4821

4822
  mark_point();
1✔
4823
  res = pr_fs_have_access(&st, R_OK, uid, gid, NULL);
1✔
4824
  ck_assert_msg(res == 0, "Failed to handle user R_OK access: %s",
1✔
4825
    strerror(errno));
4826

4827
  mark_point();
1✔
4828
  res = pr_fs_have_access(&st, W_OK, uid, gid, NULL);
1✔
4829
  ck_assert_msg(res == 0, "Failed to handle user W_OK access: %s",
1✔
4830
    strerror(errno));
4831

4832
  mark_point();
1✔
4833
  res = pr_fs_have_access(&st, X_OK, uid, gid, NULL);
1✔
4834
  ck_assert_msg(res == 0, "Failed to handle user X_OK access: %s",
1✔
4835
    strerror(errno));
4836

4837
  /* Use cases: matching GID, not UID; R_OK, W_OK, X_OK. */
4838
  memset(&st, 0, sizeof(struct stat));
1✔
4839

4840
  st.st_gid = gid;
1✔
4841

4842
  mark_point();
1✔
4843
  res = pr_fs_have_access(&st, R_OK, uid, gid, NULL);
1✔
4844
  ck_assert_msg(res < 0, "Failed to handle missing group R_OK access");
1✔
4845
  ck_assert_msg(errno == EACCES, "Expected EACCES (%d), got %s (%d)", EACCES,
1✔
4846
    strerror(errno), errno);
4847

4848
  mark_point();
1✔
4849
  res = pr_fs_have_access(&st, W_OK, uid, gid, NULL);
1✔
4850
  ck_assert_msg(res < 0, "Failed to handle missing group W_OK access");
1✔
4851
  ck_assert_msg(errno == EACCES, "Expected EACCES (%d), got %s (%d)", EACCES,
1✔
4852
    strerror(errno), errno);
4853

4854
  mark_point();
1✔
4855
  res = pr_fs_have_access(&st, X_OK, uid, gid, NULL);
1✔
4856
  ck_assert_msg(res < 0, "Failed to handle missing group X_OK access");
1✔
4857
  ck_assert_msg(errno == EACCES, "Expected EACCES (%d), got %s (%d)", EACCES,
1✔
4858
    strerror(errno), errno);
4859

4860
  st.st_mode = S_IFMT|S_IRGRP|S_IWGRP|S_IXGRP;
1✔
4861

4862
  mark_point();
1✔
4863
  res = pr_fs_have_access(&st, R_OK, uid, gid, NULL);
1✔
4864
  ck_assert_msg(res == 0, "Failed to handle group R_OK access: %s",
1✔
4865
    strerror(errno));
4866

4867
  mark_point();
1✔
4868
  res = pr_fs_have_access(&st, W_OK, uid, gid, NULL);
1✔
4869
  ck_assert_msg(res == 0, "Failed to handle group W_OK access: %s",
1✔
4870
    strerror(errno));
4871

4872
  mark_point();
1✔
4873
  res = pr_fs_have_access(&st, X_OK, uid, gid, NULL);
1✔
4874
  ck_assert_msg(res == 0, "Failed to handle group X_OK access: %s",
1✔
4875
    strerror(errno));
4876

4877
  /* Use cases: matching suppl GID, not UID; R_OK, W_OK, X_OK. */
4878
  memset(&st, 0, sizeof(struct stat));
1✔
4879

4880
  suppl_gids = make_array(p, 1, sizeof(gid_t));
1✔
4881
  *((gid_t *) push_array(suppl_gids)) = 100;
1✔
4882
  *((gid_t *) push_array(suppl_gids)) = gid;
1✔
4883
  st.st_gid = gid;
1✔
4884

4885
  mark_point();
1✔
4886
  res = pr_fs_have_access(&st, R_OK, uid, 0, suppl_gids);
1✔
4887
  ck_assert_msg(res < 0, "Failed to handle missing group R_OK access");
1✔
4888
  ck_assert_msg(errno == EACCES, "Expected EACCES (%d), got %s (%d)", EACCES,
1✔
4889
    strerror(errno), errno);
4890

4891
  mark_point();
1✔
4892
  res = pr_fs_have_access(&st, W_OK, uid, 0, suppl_gids);
1✔
4893
  ck_assert_msg(res < 0, "Failed to handle missing group W_OK access");
1✔
4894
  ck_assert_msg(errno == EACCES, "Expected EACCES (%d), got %s (%d)", EACCES,
1✔
4895
    strerror(errno), errno);
4896

4897
  mark_point();
1✔
4898
  res = pr_fs_have_access(&st, X_OK, uid, 0, suppl_gids);
1✔
4899
  ck_assert_msg(res < 0, "Failed to handle missing group X_OK access");
1✔
4900
  ck_assert_msg(errno == EACCES, "Expected EACCES (%d), got %s (%d)", EACCES,
1✔
4901
    strerror(errno), errno);
4902

4903
  st.st_mode = S_IFMT|S_IRGRP|S_IWGRP|S_IXGRP;
1✔
4904

4905
  mark_point();
1✔
4906
  res = pr_fs_have_access(&st, R_OK, uid, 0, suppl_gids);
1✔
4907
  ck_assert_msg(res == 0, "Failed to handle group R_OK access: %s",
1✔
4908
    strerror(errno));
4909

4910
  mark_point();
1✔
4911
  res = pr_fs_have_access(&st, W_OK, uid, 0, suppl_gids);
1✔
4912
  ck_assert_msg(res == 0, "Failed to handle group W_OK access: %s",
1✔
4913
    strerror(errno));
4914

4915
  mark_point();
1✔
4916
  res = pr_fs_have_access(&st, X_OK, uid, 0, suppl_gids);
1✔
4917
  ck_assert_msg(res == 0, "Failed to handle group X_OK access: %s",
1✔
4918
    strerror(errno));
4919
}
1✔
4920
END_TEST
4921

4922
START_TEST (fs_is_nfs_test) {
1✔
4923
  int res;
1✔
4924

4925
  res = pr_fs_is_nfs(NULL);
1✔
4926
  ck_assert_msg(res < 0, "Failed to handle null argument");
1✔
4927
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
4928
    strerror(errno), errno);
4929

4930
  res = pr_fs_is_nfs("/tmp");
1✔
4931
  ck_assert_msg(res == FALSE, "Expected FALSE, got %d", res);
1✔
4932
}
1✔
4933
END_TEST
4934

4935
START_TEST (fs_valid_path_test) {
1✔
4936
  int res;
1✔
4937
  const char *path;
1✔
4938
  pr_fs_t *fs;
1✔
4939

4940
  res = pr_fs_valid_path(NULL);
1✔
4941
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
4942
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
4943
    strerror(errno), errno);
4944

4945
  path = "/";
1✔
4946
  res = pr_fs_valid_path(path);
1✔
4947
  ck_assert_msg(res == 0, "'%s' is not a valid path: %s", path, strerror(errno));
1✔
4948

4949
  path = ":tmp";
1✔
4950
  res = pr_fs_valid_path(path);
1✔
4951
  ck_assert_msg(res < 0, "Failed to handle invalid path");
1✔
4952
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
1✔
4953
    strerror(errno), errno);
4954

4955
  fs = pr_register_fs(p, "testsuite", "&");
1✔
4956
  ck_assert_msg(fs != NULL, "Failed to register FS: %s", strerror(errno));
1✔
4957

4958
  fs = pr_register_fs(p, "testsuite2", ":");
1✔
4959
  ck_assert_msg(fs != NULL, "Failed to register FS: %s", strerror(errno));
1✔
4960

4961
  res = pr_fs_valid_path(path);
1✔
4962
  ck_assert_msg(res == 0, "Failed to handle valid path: %s", strerror(errno));
1✔
4963

4964
  (void) pr_remove_fs("/testsuite2");
1✔
4965
  (void) pr_remove_fs("/testsuite");
1✔
4966
}
1✔
4967
END_TEST
4968

4969
START_TEST (fsio_smkdir_test) {
1✔
4970
  int res;
1✔
4971
  const char *path;
1✔
4972
  mode_t mode = 0755;
1✔
4973
  uid_t uid = getuid();
1✔
4974
  gid_t gid = getgid();
1✔
4975

4976
  res = pr_fsio_smkdir(NULL, NULL, mode, uid, gid);
1✔
4977
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
4978
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
4979
    strerror(errno), errno);
4980

4981
  res = pr_fsio_smkdir(p, NULL, mode, uid, gid);
1✔
4982
  ck_assert_msg(res < 0, "Failed to handle null path");
1✔
4983
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
4984
    strerror(errno), errno);
4985

4986
  path = fsio_testdir_path;
1✔
4987
  res = pr_fsio_smkdir(p, path, mode, uid, gid);
1✔
4988
  ck_assert_msg(res == 0, "Failed to securely create '%s': %s", fsio_testdir_path,
1✔
4989
    strerror(errno));
4990
  (void) pr_fsio_rmdir(fsio_testdir_path);
1✔
4991

4992
  res = pr_fsio_set_use_mkdtemp(-1);
1✔
4993
  ck_assert_msg(res < 0, "Failed to handle invalid setting");
1✔
4994
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
4995
    strerror(errno), errno);
4996

4997
#ifdef HAVE_MKDTEMP
4998
  res = pr_fsio_set_use_mkdtemp(FALSE);
1✔
4999
  ck_assert_msg(res == TRUE, "Expected TRUE, got %d", res);
1✔
5000

5001
  res = pr_fsio_smkdir(p, path, mode, uid, gid);
1✔
5002
  ck_assert_msg(res == 0, "Failed to securely create '%s': %s", fsio_testdir_path,
1✔
5003
    strerror(errno));
5004
  (void) pr_fsio_rmdir(fsio_testdir_path);
1✔
5005

5006
  res = pr_fsio_set_use_mkdtemp(TRUE);
1✔
5007
  ck_assert_msg(res == FALSE, "Expected FALSE, got %d", res);
1✔
5008
#else
5009
  res = pr_fsio_set_use_mkdtemp(TRUE);
5010
  ck_assert_msg(res == FALSE, "Expected FALSE, got %d", res);
5011

5012
  res = pr_fsio_set_use_mkdtemp(FALSE);
5013
  ck_assert_msg(res == FALSE, "Expected FALSE, got %d", res);
5014
#endif /* HAVE_MKDTEMP */
5015

5016
  (void) pr_fsio_rmdir(fsio_testdir_path);
1✔
5017
}
1✔
5018
END_TEST
5019

5020
START_TEST (fsio_getpipebuf_test) {
1✔
5021
  char *res;
1✔
5022
  int fd = -1;
1✔
5023
  long bufsz = 0;
1✔
5024

5025
  res = pr_fsio_getpipebuf(NULL, fd, NULL);
1✔
5026
  ck_assert_msg(res == NULL, "Failed to handle null arguments");
1✔
5027
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
5028
    strerror(errno), errno);
5029

5030
  res = pr_fsio_getpipebuf(p, fd, NULL);
1✔
5031
  ck_assert_msg(res == NULL, "Failed to handle bad file descriptor");
1✔
5032
  ck_assert_msg(errno == EBADF, "Expected EBADF (%d), got %s (%d)", EBADF,
1✔
5033
    strerror(errno), errno);
5034

5035
  fd = 0;
1✔
5036
  res = pr_fsio_getpipebuf(p, fd, NULL);
1✔
5037
  ck_assert_msg(res != NULL, "Failed to get pipebuf for fd %d: %s", fd,
1✔
5038
    strerror(errno));
5039

5040
  res = pr_fsio_getpipebuf(p, fd, &bufsz);
1✔
5041
  ck_assert_msg(res != NULL, "Failed to get pipebuf for fd %d: %s", fd,
1✔
5042
    strerror(errno));
5043
  ck_assert_msg(bufsz > 0, "Expected >0, got %ld", bufsz);
1✔
5044
}
1✔
5045
END_TEST
5046

5047
START_TEST (fsio_gets_test) {
1✔
5048
  char buf[PR_TUNABLE_PATH_MAX], *res, *text;
1✔
5049
  pr_fh_t *fh;
1✔
5050
  int res2;
1✔
5051

5052
  res = pr_fsio_gets(NULL, 0, NULL);
1✔
5053
  ck_assert_msg(res == NULL, "Failed to handle null arguments");
1✔
5054
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
5055
    strerror(errno), errno);
5056

5057
  res = pr_fsio_gets(buf, 0, NULL);
1✔
5058
  ck_assert_msg(res == NULL, "Failed to handle null file handle");
1✔
5059
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
5060
    strerror(errno), errno);
5061

5062
  fh = pr_fsio_open(fsio_test_path, O_CREAT|O_EXCL|O_RDWR);
1✔
5063
  ck_assert_msg(fh != NULL, "Failed to open '%s': %s", fsio_test_path,
1✔
5064
    strerror(errno));
5065

5066
  res = pr_fsio_gets(buf, 0, fh);
1✔
5067
  ck_assert_msg(res == NULL, "Failed to handle zero buffer length");
1✔
5068
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
5069
    strerror(errno), errno);
5070

5071
  text = "Hello, World!\n";
1✔
5072
  res2 = pr_fsio_puts(text, fh);
1✔
5073
  ck_assert_msg(res2 >= 0, "Error writing to '%s': %s", fsio_test_path,
1✔
5074
    strerror(errno));
5075
  pr_fsio_fsync(fh);
1✔
5076
  pr_fsio_lseek(fh, 0, SEEK_SET);
1✔
5077

5078
  memset(buf, '\0', sizeof(buf));
1✔
5079
  res = pr_fsio_gets(buf, sizeof(buf)-1, fh);
1✔
5080
  ck_assert_msg(res != NULL, "Failed reading from '%s': %s", fsio_test_path,
1✔
5081
    strerror(errno));
5082
  ck_assert_msg(strcmp(res, text) == 0, "Expected '%s', got '%s'", text, res);
1✔
5083

5084
  (void) pr_fsio_close(fh);
1✔
5085
  (void) pr_fsio_unlink(fsio_test_path);
1✔
5086
}
1✔
5087
END_TEST
5088

5089
START_TEST (fsio_getline_test) {
1✔
5090
  char buf[PR_TUNABLE_PATH_MAX], *res, *text;
1✔
5091
  pr_fh_t *fh;
1✔
5092
  unsigned int lineno = 0;
1✔
5093
  int res2;
1✔
5094

5095
  res = pr_fsio_getline(NULL, 0, NULL, NULL);
1✔
5096
  ck_assert_msg(res == NULL, "Failed to handle null arguments");
1✔
5097
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
5098
    strerror(errno), errno);
5099

5100
  res = pr_fsio_getline(buf, 0, NULL, NULL);
1✔
5101
  ck_assert_msg(res == NULL, "Failed to handle file handle");
1✔
5102
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
5103
    strerror(errno), errno);
5104

5105
  fh = pr_fsio_open(fsio_test_path, O_CREAT|O_EXCL|O_RDWR);
1✔
5106
  ck_assert_msg(fh != NULL, "Failed to open '%s': %s", fsio_test_path,
1✔
5107
    strerror(errno));
5108

5109
  res = pr_fsio_getline(buf, 0, fh, NULL);
1✔
5110
  ck_assert_msg(res == NULL, "Failed to handle zero buffer length");
1✔
5111
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
5112
    strerror(errno), errno);
5113

5114
  res = pr_fsio_getline(buf, sizeof(buf)-1, fh, &lineno);
1✔
5115
  ck_assert_msg(res == NULL, "Failed to read empty '%s' file", fsio_test_path);
1✔
5116

5117
  text = "Hello, World!\n";
1✔
5118
  res2 = pr_fsio_puts(text, fh);
1✔
5119
  ck_assert_msg(res2 >= 0, "Error writing to '%s': %s", fsio_test_path,
1✔
5120
    strerror(errno));
5121

5122
  text = "How\\\n are you?\n";
1✔
5123
  res2 = pr_fsio_puts(text, fh);
1✔
5124
  ck_assert_msg(res2 >= 0, "Error writing to '%s': %s", fsio_test_path,
1✔
5125
    strerror(errno));
5126

5127
  pr_fsio_fsync(fh);
1✔
5128
  pr_fsio_lseek(fh, 0, SEEK_SET);
1✔
5129

5130
  memset(buf, '\0', sizeof(buf));
1✔
5131
  res = pr_fsio_getline(buf, sizeof(buf)-1, fh, &lineno);
1✔
5132
  ck_assert_msg(res != NULL, "Failed to read line from '%s': %s", fsio_test_path,
1✔
5133
    strerror(errno));
5134
  ck_assert_msg(strcmp(res, "Hello, World!\n") == 0,
1✔
5135
    "Expected 'Hello, World!\n', got '%s'", res);
5136
  ck_assert_msg(lineno == 1, "Expected 1, got %u", lineno);
1✔
5137

5138
  memset(buf, '\0', sizeof(buf));
1✔
5139
  res = pr_fsio_getline(buf, sizeof(buf)-1, fh, &lineno);
1✔
5140
  ck_assert_msg(res != NULL, "Failed to read line from '%s': %s", fsio_test_path,
1✔
5141
    strerror(errno));
5142
  ck_assert_msg(strcmp(res, "How are you?\n") == 0,
1✔
5143
    "Expected 'How are you?\n', got '%s'", res);
5144
  ck_assert_msg(lineno == 3, "Expected 3, got %u", lineno);
1✔
5145

5146
  (void) pr_fsio_close(fh);
1✔
5147
  (void) pr_fsio_unlink(fsio_test_path);
1✔
5148
}
1✔
5149
END_TEST
5150

5151
START_TEST (fsio_puts_test) {
1✔
5152
  int res;
1✔
5153
  const char *text;
1✔
5154
  pr_fh_t *fh;
1✔
5155

5156
  res = pr_fsio_puts(NULL, NULL);
1✔
5157
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
5158
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
5159
    strerror(errno), errno);
5160

5161
  text = "Hello, World!\n";
1✔
5162
  res = pr_fsio_puts(text, NULL);
1✔
5163
  ck_assert_msg(res < 0, "Failed to handle null file handle");
1✔
5164
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
5165
    strerror(errno), errno);
5166

5167
  fh = pr_fsio_open(fsio_test_path, O_CREAT|O_EXCL|O_WRONLY);
1✔
5168
  ck_assert_msg(fh != NULL, "Failed to open '%s': %s", fsio_test_path,
1✔
5169
    strerror(errno));
5170

5171
  res = pr_fsio_puts(NULL, fh);
1✔
5172
  ck_assert_msg(res < 0, "Failed to handle null buffer");
1✔
5173
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
5174
    strerror(errno), errno);
5175

5176
  (void) pr_fsio_close(fh);
1✔
5177
  (void) pr_fsio_unlink(fsio_test_path);
1✔
5178
}
1✔
5179
END_TEST
5180

5181
START_TEST (fsio_blocking_test) {
1✔
5182
  int fd, res;
1✔
5183
  pr_fh_t *fh;
1✔
5184

5185
  res = pr_fsio_set_block(NULL);
1✔
5186
  ck_assert_msg(res < 0, "Failed to handle null argument");
1✔
5187
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
5188
    strerror(errno), errno);
5189

5190
  fh = pr_fsio_open(fsio_test_path, O_CREAT|O_EXCL|O_WRONLY);
1✔
5191
  ck_assert_msg(fh != NULL, "Failed to open '%s': %s", fsio_test_path,
1✔
5192
    strerror(errno));
5193

5194
  fd = fh->fh_fd;
1✔
5195
  fh->fh_fd = -1;
1✔
5196

5197
  res = pr_fsio_set_block(fh);
1✔
5198
  ck_assert_msg(res < 0, "Failed to handle bad file descriptor");
1✔
5199
  ck_assert_msg(errno == EBADF, "Expected EBADF (%d), got %s (%d)", EBADF,
1✔
5200
    strerror(errno), errno);
5201

5202
  fh->fh_fd = fd;
1✔
5203
  res = pr_fsio_set_block(fh);
1✔
5204
  ck_assert_msg(res == 0, "Failed to make '%s' blocking: %s", fsio_test_path,
1✔
5205
    strerror(errno));
5206

5207
  (void) pr_fsio_close(fh);
1✔
5208
  (void) pr_fsio_unlink(fsio_test_path);
1✔
5209
}
1✔
5210
END_TEST
5211

5212
Suite *tests_get_fsio_suite(void) {
890✔
5213
  Suite *suite;
890✔
5214
  TCase *testcase;
890✔
5215

5216
  suite = suite_create("fsio");
890✔
5217

5218
  testcase = tcase_create("base");
890✔
5219
  tcase_add_checked_fixture(testcase, set_up, tear_down);
890✔
5220

5221
  /* Main FSIO API tests */
5222
  tcase_add_test(testcase, fsio_sys_open_test);
890✔
5223
  tcase_add_test(testcase, fsio_sys_open_canon_test);
890✔
5224
  tcase_add_test(testcase, fsio_sys_open_chroot_guard_test);
890✔
5225
  tcase_add_test(testcase, fsio_sys_close_test);
890✔
5226
  tcase_add_test(testcase, fsio_sys_unlink_test);
890✔
5227
  tcase_add_test(testcase, fsio_sys_unlink_chroot_guard_test);
890✔
5228
  tcase_add_test(testcase, fsio_sys_stat_test);
890✔
5229
  tcase_add_test(testcase, fsio_sys_fstat_test);
890✔
5230
  tcase_add_test(testcase, fsio_sys_read_test);
890✔
5231
  tcase_add_test(testcase, fsio_sys_pread_test);
890✔
5232
  tcase_add_test(testcase, fsio_sys_write_test);
890✔
5233
  tcase_add_test(testcase, fsio_sys_pwrite_test);
890✔
5234
  tcase_add_test(testcase, fsio_sys_lseek_test);
890✔
5235
  tcase_add_test(testcase, fsio_sys_link_test);
890✔
5236
  tcase_add_test(testcase, fsio_sys_link_chroot_guard_test);
890✔
5237
  tcase_add_test(testcase, fsio_sys_symlink_test);
890✔
5238
  tcase_add_test(testcase, fsio_sys_symlink_chroot_guard_test);
890✔
5239
  tcase_add_test(testcase, fsio_sys_readlink_test);
890✔
5240
  tcase_add_test(testcase, fsio_sys_lstat_test);
890✔
5241
  tcase_add_test(testcase, fsio_sys_access_dir_test);
890✔
5242
  tcase_add_test(testcase, fsio_sys_access_file_test);
890✔
5243
  tcase_add_test(testcase, fsio_sys_faccess_test);
890✔
5244
  tcase_add_test(testcase, fsio_sys_truncate_test);
890✔
5245
  tcase_add_test(testcase, fsio_sys_truncate_chroot_guard_test);
890✔
5246
  tcase_add_test(testcase, fsio_sys_ftruncate_test);
890✔
5247
  tcase_add_test(testcase, fsio_sys_chmod_test);
890✔
5248
  tcase_add_test(testcase, fsio_sys_chmod_chroot_guard_test);
890✔
5249
  tcase_add_test(testcase, fsio_sys_fchmod_test);
890✔
5250
  tcase_add_test(testcase, fsio_sys_chown_test);
890✔
5251
  tcase_add_test(testcase, fsio_sys_chown_chroot_guard_test);
890✔
5252
  tcase_add_test(testcase, fsio_sys_fchown_test);
890✔
5253
  tcase_add_test(testcase, fsio_sys_lchown_test);
890✔
5254
  tcase_add_test(testcase, fsio_sys_lchown_chroot_guard_test);
890✔
5255
  tcase_add_test(testcase, fsio_sys_rename_test);
890✔
5256
  tcase_add_test(testcase, fsio_sys_rename_chroot_guard_test);
890✔
5257
  tcase_add_test(testcase, fsio_sys_utimes_test);
890✔
5258
  tcase_add_test(testcase, fsio_sys_utimes_chroot_guard_test);
890✔
5259
  tcase_add_test(testcase, fsio_sys_futimes_test);
890✔
5260
  tcase_add_test(testcase, fsio_sys_fsync_test);
890✔
5261

5262
  tcase_add_test(testcase, fsio_sys_realpath_test);
890✔
5263

5264
  /* Extended attribute tests */
5265
  tcase_add_test(testcase, fsio_sys_getxattr_test);
890✔
5266
  tcase_add_test(testcase, fsio_sys_lgetxattr_test);
890✔
5267
  tcase_add_test(testcase, fsio_sys_fgetxattr_test);
890✔
5268
  tcase_add_test(testcase, fsio_sys_listxattr_test);
890✔
5269
  tcase_add_test(testcase, fsio_sys_llistxattr_test);
890✔
5270
  tcase_add_test(testcase, fsio_sys_flistxattr_test);
890✔
5271
  tcase_add_test(testcase, fsio_sys_removexattr_test);
890✔
5272
  tcase_add_test(testcase, fsio_sys_lremovexattr_test);
890✔
5273
  tcase_add_test(testcase, fsio_sys_fremovexattr_test);
890✔
5274
  tcase_add_test(testcase, fsio_sys_setxattr_test);
890✔
5275
  tcase_add_test(testcase, fsio_sys_lsetxattr_test);
890✔
5276
  tcase_add_test(testcase, fsio_sys_fsetxattr_test);
890✔
5277

5278
  tcase_add_test(testcase, fsio_sys_mkdir_test);
890✔
5279
  tcase_add_test(testcase, fsio_sys_mkdir_chroot_guard_test);
890✔
5280
  tcase_add_test(testcase, fsio_sys_rmdir_test);
890✔
5281
  tcase_add_test(testcase, fsio_sys_rmdir_chroot_guard_test);
890✔
5282
  tcase_add_test(testcase, fsio_sys_chdir_test);
890✔
5283
  tcase_add_test(testcase, fsio_sys_chdir_canon_test);
890✔
5284
  tcase_add_test(testcase, fsio_sys_chroot_test);
890✔
5285
  tcase_add_test(testcase, fsio_sys_opendir_test);
890✔
5286
  tcase_add_test(testcase, fsio_sys_readdir_test);
890✔
5287
  tcase_add_test(testcase, fsio_sys_closedir_test);
890✔
5288

5289
  /* FSIO with error tests */
5290
  tcase_add_test(testcase, fsio_sys_chmod_with_error_test);
890✔
5291
  tcase_add_test(testcase, fsio_sys_chown_with_error_test);
890✔
5292
  tcase_add_test(testcase, fsio_sys_chroot_with_error_test);
890✔
5293
  tcase_add_test(testcase, fsio_sys_close_with_error_test);
890✔
5294
  tcase_add_test(testcase, fsio_sys_fchmod_with_error_test);
890✔
5295
  tcase_add_test(testcase, fsio_sys_fchown_with_error_test);
890✔
5296
  tcase_add_test(testcase, fsio_sys_lchown_with_error_test);
890✔
5297
  tcase_add_test(testcase, fsio_sys_lstat_with_error_test);
890✔
5298
  tcase_add_test(testcase, fsio_sys_mkdir_with_error_test);
890✔
5299
  tcase_add_test(testcase, fsio_sys_open_with_error_test);
890✔
5300
  tcase_add_test(testcase, fsio_sys_read_with_error_test);
890✔
5301
  tcase_add_test(testcase, fsio_sys_rename_with_error_test);
890✔
5302
  tcase_add_test(testcase, fsio_sys_rmdir_with_error_test);
890✔
5303
  tcase_add_test(testcase, fsio_sys_stat_with_error_test);
890✔
5304
  tcase_add_test(testcase, fsio_sys_unlink_with_error_test);
890✔
5305
  tcase_add_test(testcase, fsio_sys_write_with_error_test);
890✔
5306

5307
  /* FSIO statcache tests */
5308
  tcase_add_test(testcase, fsio_statcache_clear_cache_test);
890✔
5309
  tcase_add_test(testcase, fsio_statcache_cache_hit_test);
890✔
5310
  tcase_add_test(testcase, fsio_statcache_negative_cache_test);
890✔
5311
  tcase_add_test(testcase, fsio_statcache_expired_test);
890✔
5312
  tcase_add_test(testcase, fsio_statcache_dump_test);
890✔
5313

5314
  /* Custom FSIO management tests */
5315
  tcase_add_test(testcase, fs_create_fs_test);
890✔
5316
  tcase_add_test(testcase, fs_insert_fs_test);
890✔
5317
  tcase_add_test(testcase, fs_get_fs_test);
890✔
5318
  tcase_add_test(testcase, fs_unmount_fs_test);
890✔
5319
  tcase_add_test(testcase, fs_remove_fs_test);
890✔
5320
  tcase_add_test(testcase, fs_register_fs_test);
890✔
5321
  tcase_add_test(testcase, fs_register_fs2_test);
890✔
5322
  tcase_add_test(testcase, fs_unregister_fs_test);
890✔
5323
  tcase_add_test(testcase, fs_resolve_fs_map_test);
890✔
5324
#if defined(PR_USE_DEVEL)
5325
  tcase_add_test(testcase, fs_dump_fs_test);
890✔
5326
#endif /* PR_USE_DEVEL */
5327

5328
  /* Custom FSIO tests */
5329
  tcase_add_test(testcase, fsio_custom_chroot_test);
890✔
5330

5331
  /* Misc */
5332
  tcase_add_test(testcase, fs_clean_path_test);
890✔
5333
  tcase_add_test(testcase, fs_clean_path2_test);
890✔
5334

5335
  tcase_add_test(testcase, fs_dircat_test);
890✔
5336
  tcase_add_test(testcase, fs_setcwd_test);
890✔
5337
  tcase_add_test(testcase, fs_glob_test);
890✔
5338
  tcase_add_test(testcase, fs_copy_file_test);
890✔
5339
  tcase_add_test(testcase, fs_copy_file2_test);
890✔
5340
  tcase_add_test(testcase, fs_interpolate_test);
890✔
5341
  tcase_add_test(testcase, fs_resolve_partial_test);
890✔
5342
  tcase_add_test(testcase, fs_resolve_path_test);
890✔
5343
  tcase_add_test(testcase, fs_use_encoding_test);
890✔
5344
  tcase_add_test(testcase, fs_decode_path2_test);
890✔
5345
  tcase_add_test(testcase, fs_encode_path_test);
890✔
5346
  tcase_add_test(testcase, fs_split_path_test);
890✔
5347
  tcase_add_test(testcase, fs_join_path_test);
890✔
5348
  tcase_add_test(testcase, fs_virtual_path_test);
890✔
5349
#if 0
5350
  tcase_add_test(testcase, fs_close_extra_fds_test);
5351
#endif
5352
  tcase_add_test(testcase, fs_get_usable_fd_test);
890✔
5353
  tcase_add_test(testcase, fs_get_usable_fd2_test);
890✔
5354
  tcase_add_test(testcase, fs_getsize_test);
890✔
5355
  tcase_add_test(testcase, fs_getsize2_test);
890✔
5356
  tcase_add_test(testcase, fs_fgetsize_test);
890✔
5357
  tcase_add_test(testcase, fs_fadvise_test);
890✔
5358
  tcase_add_test(testcase, fs_have_access_test);
890✔
5359
#if defined(HAVE_STATFS_F_TYPE) || defined(HAVE_STATFS_F_FSTYPENAME)
5360
  tcase_add_test(testcase, fs_is_nfs_test);
890✔
5361
#endif
5362
  tcase_add_test(testcase, fs_valid_path_test);
890✔
5363
  tcase_add_test(testcase, fsio_smkdir_test);
890✔
5364
  tcase_add_test(testcase, fsio_getpipebuf_test);
890✔
5365
  tcase_add_test(testcase, fsio_gets_test);
890✔
5366
  tcase_add_test(testcase, fsio_getline_test);
890✔
5367
  tcase_add_test(testcase, fsio_puts_test);
890✔
5368
  tcase_add_test(testcase, fsio_blocking_test);
890✔
5369

5370
  suite_add_tcase(suite, testcase);
890✔
5371
  return suite;
890✔
5372
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc