1 /*
2 * ProFTPD - FTP server testsuite
3 * Copyright (c) 2008-2021 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
set_up(void)49 static void set_up(void) {
50 (void) unlink(fsio_test_path);
51 (void) unlink(fsio_test2_path);
52 (void) unlink(fsio_link_path);
53 (void) unlink(fsio_unlink_path);
54 (void) rmdir(fsio_testdir_path);
55
56 if (fsio_cwd != NULL) {
57 free(fsio_cwd);
58 }
59
60 fsio_cwd = getcwd(NULL, 0);
61
62 if (p == NULL) {
63 p = permanent_pool = make_sub_pool(NULL);
64 }
65
66 init_fs();
67 pr_fs_statcache_set_policy(PR_TUNABLE_FS_STATCACHE_SIZE,
68 PR_TUNABLE_FS_STATCACHE_MAX_AGE, 0);
69
70 if (getenv("TEST_VERBOSE") != NULL) {
71 pr_trace_set_levels("error", 1, 20);
72 pr_trace_set_levels("fsio", 1, 20);
73 pr_trace_set_levels("fs.statcache", 1, 20);
74 }
75 }
76
tear_down(void)77 static void tear_down(void) {
78 if (fsio_cwd != NULL) {
79 free(fsio_cwd);
80 fsio_cwd = NULL;
81 }
82
83 (void) pr_fsio_guard_chroot(FALSE);
84 pr_fs_statcache_set_policy(PR_TUNABLE_FS_STATCACHE_SIZE,
85 PR_TUNABLE_FS_STATCACHE_MAX_AGE, 0);
86
87 pr_unregister_fs("/testuite");
88
89 if (getenv("TEST_VERBOSE") != NULL) {
90 pr_trace_set_levels("error", 0, 0);
91 pr_trace_set_levels("fsio", 0, 0);
92 pr_trace_set_levels("fs.statcache", 0, 0);
93 }
94
95 (void) unlink(fsio_test_path);
96 (void) unlink(fsio_test2_path);
97 (void) unlink(fsio_link_path);
98 (void) unlink(fsio_unlink_path);
99 (void) rmdir(fsio_testdir_path);
100
101 if (p) {
102 destroy_pool(p);
103 p = permanent_pool = NULL;
104 }
105 }
106
get_errnum(pool * err_pool,int xerrno)107 static const char *get_errnum(pool *err_pool, int xerrno) {
108 char errnum[32];
109 memset(errnum, '\0', sizeof(errnum));
110 snprintf(errnum, sizeof(errnum)-1, "%d", xerrno);
111 return pstrdup(err_pool, errnum);
112 }
113
114 /* Tests */
115
START_TEST(fsio_sys_open_test)116 START_TEST (fsio_sys_open_test) {
117 int flags;
118 pr_fh_t *fh;
119
120 mark_point();
121 flags = O_CREAT|O_EXCL|O_RDONLY;
122 fh = pr_fsio_open(NULL, flags);
123 fail_unless(fh == NULL, "Failed to handle null arguments");
124 fail_unless(errno == EINVAL, "Expected EINVAL (%d), %s (%d)", EINVAL,
125 strerror(errno), errno);
126
127 mark_point();
128 flags = O_RDONLY;
129 fh = pr_fsio_open(fsio_test_path, flags);
130 fail_unless(fh == NULL, "Failed to handle non-existent file '%s'",
131 fsio_test_path);
132 fail_unless(errno == ENOENT, "Expected ENOENT (%d), %s (%d)", ENOENT,
133 strerror(errno), errno);
134
135 mark_point();
136 flags = O_RDONLY;
137 fh = pr_fsio_open("/etc/hosts", flags);
138 fail_unless(fh != NULL, "Failed to open /etc/hosts: %s", strerror(errno));
139
140 (void) pr_fsio_close(fh);
141 }
142 END_TEST
143
START_TEST(fsio_sys_open_canon_test)144 START_TEST (fsio_sys_open_canon_test) {
145 int flags;
146 pr_fh_t *fh;
147
148 flags = O_CREAT|O_EXCL|O_RDONLY;
149 fh = pr_fsio_open_canon(NULL, flags);
150 fail_unless(fh == NULL, "Failed to handle null arguments");
151 fail_unless(errno == EINVAL, "Expected EINVAL (%d), %s (%d)", EINVAL,
152 strerror(errno), errno);
153
154 flags = O_RDONLY;
155 fh = pr_fsio_open_canon(fsio_test_path, flags);
156 fail_unless(fh == NULL, "Failed to handle non-existent file '%s'",
157 fsio_test_path);
158 fail_unless(errno == ENOENT, "Expected ENOENT (%d), %s (%d)", ENOENT,
159 strerror(errno), errno);
160
161 flags = O_RDONLY;
162 fh = pr_fsio_open_canon("/etc/hosts", flags);
163 fail_unless(fh != NULL, "Failed to open /etc/hosts: %s", strerror(errno));
164
165 (void) pr_fsio_close(fh);
166 }
167 END_TEST
168
START_TEST(fsio_sys_open_chroot_guard_test)169 START_TEST (fsio_sys_open_chroot_guard_test) {
170 int flags, res;
171 pr_fh_t *fh;
172 const char *path;
173
174 res = pr_fsio_guard_chroot(TRUE);
175 fail_unless(res == FALSE, "Expected FALSE (%d), got %d", FALSE, res);
176
177 path = "/etc/hosts";
178 flags = O_CREAT|O_RDONLY;
179 fh = pr_fsio_open(path, flags);
180 if (fh != NULL) {
181 (void) pr_fsio_close(fh);
182 fail("open(2) of %s succeeded unexpectedly", path);
183 }
184
185 fail_unless(errno == EACCES, "Expected EACCES (%d), got %s (%d)", EACCES,
186 strerror(errno), errno);
187
188 path = "/&Z";
189 flags = O_WRONLY;
190 fh = pr_fsio_open(path, flags);
191 if (fh != NULL) {
192 (void) pr_fsio_close(fh);
193 fail("open(2) of %s succeeded unexpectedly", path);
194 }
195
196 fail_unless(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
197 strerror(errno));
198
199 path = "/etc";
200 fh = pr_fsio_open(path, flags);
201 if (fh != NULL) {
202 (void) pr_fsio_close(fh);
203 fail("open(2) of %s succeeded unexpectedly", path);
204 }
205
206 fail_unless(errno == EACCES, "Expected EACCES (%d), got %s (%d)", EACCES,
207 strerror(errno));
208
209 path = "/lib";
210 fh = pr_fsio_open(path, flags);
211 if (fh != NULL) {
212 (void) pr_fsio_close(fh);
213 fail("open(2) of %s succeeded unexpectedly", path);
214 }
215
216 fail_unless(errno == EACCES, "Expected EACCES (%d), got %s (%d)", EACCES,
217 strerror(errno));
218
219 (void) pr_fsio_guard_chroot(FALSE);
220
221 path = "/etc/hosts";
222 flags = O_RDONLY;
223 fh = pr_fsio_open(path, flags);
224 fail_unless(fh != NULL, "Failed to open '%s': %s", path, strerror(errno));
225 (void) pr_fsio_close(fh);
226 }
227 END_TEST
228
START_TEST(fsio_sys_close_test)229 START_TEST (fsio_sys_close_test) {
230 int res;
231 pr_fh_t *fh;
232
233 res = pr_fsio_close(NULL);
234 fail_unless(res < 0, "Failed to handle null arguments");
235 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s %d", EINVAL,
236 strerror(errno), errno);
237
238 fh = pr_fsio_open("/etc/hosts", O_RDONLY);
239 fail_unless(fh != NULL, "Failed to open /etc/hosts: %s",
240 strerror(errno));
241
242 res = pr_fsio_close(fh);
243 fail_unless(res == 0, "Failed to close file handle: %s", strerror(errno));
244 }
245 END_TEST
246
START_TEST(fsio_sys_unlink_test)247 START_TEST (fsio_sys_unlink_test) {
248 int res;
249 pr_fh_t *fh;
250
251 res = pr_fsio_unlink(NULL);
252 fail_unless(res < 0, "Failed to handle null arguments");
253 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
254 strerror(errno), errno);
255
256 fh = pr_fsio_open(fsio_unlink_path, O_CREAT|O_EXCL|O_WRONLY);
257 fail_unless(fh != NULL, "Failed to open '%s': %s", fsio_unlink_path,
258 strerror(errno));
259 (void) pr_fsio_close(fh);
260
261 res = pr_fsio_unlink(fsio_unlink_path);
262 fail_unless(res == 0, "Failed to unlink '%s': %s", fsio_unlink_path,
263 strerror(errno));
264 }
265 END_TEST
266
START_TEST(fsio_sys_unlink_chroot_guard_test)267 START_TEST (fsio_sys_unlink_chroot_guard_test) {
268 int res;
269
270 res = pr_fsio_guard_chroot(TRUE);
271 fail_unless(res == FALSE, "Expected FALSE (%d), got %d", FALSE, res);
272
273 res = pr_fsio_unlink("/etc/hosts");
274 fail_unless(res < 0, "Deleted /etc/hosts unexpectedly");
275 fail_unless(errno == EACCES, "Expected EACCES (%d), got %s %d", EACCES,
276 strerror(errno), errno);
277
278 (void) pr_fsio_guard_chroot(FALSE);
279
280 res = pr_fsio_unlink("/lib/foo.bar.baz");
281 fail_unless(res < 0, "Deleted /lib/foo.bar.baz unexpectedly");
282 fail_unless(errno == ENOENT, "Expected ENOENT (%d), got %s %d", ENOENT,
283 strerror(errno), errno);
284 }
285 END_TEST
286
START_TEST(fsio_sys_stat_test)287 START_TEST (fsio_sys_stat_test) {
288 int res;
289 struct stat st;
290 unsigned int cache_size = 3, max_age = 1, policy_flags = 0;
291
292 res = pr_fsio_stat(NULL, &st);
293 fail_unless(res < 0, "Failed to handle null path");
294 fail_unless(errno == EINVAL, "Expected EINVAL, got %s (%d)", strerror(errno),
295 errno);
296
297 res = pr_fsio_stat("/", NULL);
298 fail_unless(res < 0, "Failed to handle null struct stat");
299 fail_unless(errno == EINVAL, "Expected EINVAL, got %s (%d)", strerror(errno),
300 errno);
301
302 res = pr_fsio_stat("/", &st);
303 fail_unless(res == 0, "Unexpected stat(2) error on '/': %s",
304 strerror(errno));
305 fail_unless(S_ISDIR(st.st_mode), "'/' is not a directory as expected");
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);
311 fail_unless(res == 0, "Unexpected stat(2) error on '/': %s",
312 strerror(errno));
313 fail_unless(S_ISDIR(st.st_mode), "'/' is not a directory as expected");
314
315 pr_fs_statcache_reset();
316 res = pr_fs_statcache_set_policy(cache_size, max_age, policy_flags);
317 fail_unless(res == 0, "Failed to set statcache policy: %s", strerror(errno));
318
319 res = pr_fsio_stat("/foo/bar/baz/quxx", &st);
320 fail_unless(res < 0, "Failed to handle nonexistent path");
321 fail_unless(errno == ENOENT, "Expected ENOENT, got %s (%d)", strerror(errno),
322 errno);
323
324 res = pr_fsio_stat("/foo/bar/baz/quxx", &st);
325 fail_unless(res < 0, "Failed to handle nonexistent path");
326 fail_unless(errno == ENOENT, "Expected ENOENT, got %s (%d)", strerror(errno),
327 errno);
328
329 /* Now wait for longer than 1 second (our configured max age) */
330 sleep(max_age + 1);
331
332 res = pr_fsio_stat("/foo/bar/baz/quxx", &st);
333 fail_unless(res < 0, "Failed to handle nonexistent path");
334 fail_unless(errno == ENOENT, "Expected ENOENT, got %s (%d)", strerror(errno),
335 errno);
336
337 /* Stat a symlink path */
338 res = pr_fsio_symlink("/tmp", fsio_link_path);
339 fail_unless(res == 0, "Failed to create symlink to '%s': %s", fsio_link_path,
340 strerror(errno));
341
342 res = pr_fsio_stat(fsio_link_path, &st);
343 fail_unless(res == 0, "Failed to stat '%s': %s", fsio_link_path,
344 strerror(errno));
345
346 (void) unlink(fsio_link_path);
347 }
348 END_TEST
349
START_TEST(fsio_sys_fstat_test)350 START_TEST (fsio_sys_fstat_test) {
351 int res;
352 pr_fh_t *fh;
353 struct stat st;
354
355 res = pr_fsio_fstat(NULL, NULL);
356 fail_unless(res < 0, "Failed to handle null arguments");
357 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
358 strerror(errno), errno);
359
360 fh = pr_fsio_open("/etc/hosts", O_RDONLY);
361 fail_unless(fh != NULL, "Failed to open /etc/hosts: %s",
362 strerror(errno));
363
364 res = pr_fsio_fstat(fh, &st);
365 fail_unless(res == 0, "Failed to fstat /etc/hosts: %s",
366 strerror(errno));
367 (void) pr_fsio_close(fh);
368 }
369 END_TEST
370
START_TEST(fsio_sys_read_test)371 START_TEST (fsio_sys_read_test) {
372 int res;
373 pr_fh_t *fh;
374 char *buf;
375 size_t buflen;
376
377 res = pr_fsio_read(NULL, NULL, 0);
378 fail_unless(res < 0, "Failed to handle null arguments");
379 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
380 strerror(errno), errno);
381
382 fh = pr_fsio_open("/etc/hosts", O_RDONLY);
383 fail_unless(fh != NULL, "Failed to open /etc/hosts: %s",
384 strerror(errno));
385
386 res = pr_fsio_read(fh, NULL, 0);
387 fail_unless(res < 0, "Failed to handle null buffer");
388 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
389 strerror(errno), errno);
390
391 buflen = 32;
392 buf = palloc(p, buflen);
393
394 res = pr_fsio_read(fh, buf, 0);
395 fail_unless(res < 0, "Failed to handle zero buffer length");
396 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
397 strerror(errno), errno);
398
399 res = pr_fsio_read(fh, buf, 1);
400 fail_unless(res == 1, "Failed to read 1 byte: %s", strerror(errno));
401
402 (void) pr_fsio_close(fh);
403 }
404 END_TEST
405
START_TEST(fsio_sys_pread_test)406 START_TEST (fsio_sys_pread_test) {
407 ssize_t res;
408 pr_fh_t *fh;
409 char *buf;
410 size_t buflen;
411
412 res = pr_fsio_pread(NULL, NULL, 0, 0);
413 fail_unless(res < 0, "Failed to handle null arguments");
414 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
415 strerror(errno), errno);
416
417 fh = pr_fsio_open("/etc/hosts", O_RDONLY);
418 fail_unless(fh != NULL, "Failed to open /etc/hosts: %s",
419 strerror(errno));
420
421 res = pr_fsio_pread(fh, NULL, 0, 0);
422 fail_unless(res < 0, "Failed to handle null buffer");
423 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
424 strerror(errno), errno);
425
426 buflen = 32;
427 buf = palloc(p, buflen);
428
429 res = pr_fsio_pread(fh, buf, 0, 0);
430 fail_unless(res < 0, "Failed to handle zero buffer length");
431 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
432 strerror(errno), errno);
433
434 res = pr_fsio_pread(fh, buf, 1, 0);
435 fail_unless(res == 1, "Failed to read 1 byte: %s", strerror(errno));
436
437 (void) pr_fsio_close(fh);
438 }
439 END_TEST
440
START_TEST(fsio_sys_write_test)441 START_TEST (fsio_sys_write_test) {
442 int res;
443 pr_fh_t *fh;
444 char *buf;
445 size_t buflen;
446
447 res = pr_fsio_write(NULL, NULL, 0);
448 fail_unless(res < 0, "Failed to handle null arguments");
449 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
450 strerror(errno), errno);
451
452 fh = pr_fsio_open(fsio_test_path, O_CREAT|O_EXCL|O_WRONLY);
453 fail_unless(fh != NULL, "Failed to open '%s': %s", strerror(errno));
454
455 /* XXX What happens if we use NULL buffer, zero length? */
456 res = pr_fsio_write(fh, NULL, 0);
457 fail_unless(res < 0, "Failed to handle null buffer");
458 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
459 strerror(errno), errno);
460
461 buflen = 32;
462 buf = palloc(p, buflen);
463 memset(buf, 'c', buflen);
464
465 res = pr_fsio_write(fh, buf, 0);
466 fail_unless(res == 0, "Failed to handle zero buffer length");
467
468 res = pr_fsio_write(fh, buf, buflen);
469 fail_unless((size_t) res == buflen, "Failed to write %lu bytes: %s",
470 (unsigned long) buflen, strerror(errno));
471
472 (void) pr_fsio_close(fh);
473 (void) pr_fsio_unlink(fsio_test_path);
474 }
475 END_TEST
476
START_TEST(fsio_sys_pwrite_test)477 START_TEST (fsio_sys_pwrite_test) {
478 ssize_t res;
479 pr_fh_t *fh;
480 char *buf;
481 size_t buflen;
482
483 res = pr_fsio_pwrite(NULL, NULL, 0, 0);
484 fail_unless(res < 0, "Failed to handle null arguments");
485 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
486 strerror(errno), errno);
487
488 fh = pr_fsio_open(fsio_test_path, O_CREAT|O_EXCL|O_WRONLY);
489 fail_unless(fh != NULL, "Failed to open '%s': %s", strerror(errno));
490
491 /* XXX What happens if we use NULL buffer, zero length? */
492 res = pr_fsio_pwrite(fh, NULL, 0, 0);
493 fail_unless(res < 0, "Failed to handle null buffer");
494 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
495 strerror(errno), errno);
496
497 buflen = 32;
498 buf = palloc(p, buflen);
499 memset(buf, 'c', buflen);
500
501 res = pr_fsio_pwrite(fh, buf, 0, 0);
502 fail_unless(res == 0, "Failed to handle zero buffer length");
503
504 res = pr_fsio_pwrite(fh, buf, buflen, 0);
505 fail_unless((size_t) res == buflen, "Failed to write %lu bytes: %s",
506 (unsigned long) buflen, strerror(errno));
507
508 (void) pr_fsio_close(fh);
509 (void) pr_fsio_unlink(fsio_test_path);
510 }
511 END_TEST
512
START_TEST(fsio_sys_lseek_test)513 START_TEST (fsio_sys_lseek_test) {
514 int res;
515 pr_fh_t *fh;
516
517 res = pr_fsio_lseek(NULL, 0, 0);
518 fail_unless(res < 0, "Failed to handle null arguments");
519 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
520 strerror(errno), errno);
521
522 fh = pr_fsio_open("/etc/hosts", O_RDONLY);
523 fail_unless(fh != NULL, "Failed to open /etc/hosts: %s",
524 strerror(errno));
525
526 res = pr_fsio_lseek(fh, 0, 0);
527 fail_unless(res == 0, "Failed to seek to byte 0: %s", strerror(errno));
528
529 (void) pr_fsio_close(fh);
530 }
531 END_TEST
532
START_TEST(fsio_sys_link_test)533 START_TEST (fsio_sys_link_test) {
534 int res;
535 const char *target_path, *link_path;
536 pr_fh_t *fh;
537
538 target_path = link_path = NULL;
539 res = pr_fsio_link(target_path, link_path);
540 fail_unless(res < 0, "Failed to handle null arguments");
541 fail_unless(errno == EINVAL, "Expected EINVAL, got %s (%d)", strerror(errno),
542 errno);
543
544 target_path = fsio_test_path;
545 link_path = NULL;
546 res = pr_fsio_link(target_path, link_path);
547 fail_unless(res < 0, "Failed to handle null link_path argument");
548 fail_unless(errno == EINVAL, "Expected EINVAL, got %s (%d)", strerror(errno),
549 errno);
550
551 target_path = NULL;
552 link_path = fsio_link_path;
553 res = pr_fsio_link(target_path, link_path);
554 fail_unless(res < 0, "Failed to handle null target_path argument");
555 fail_unless(errno == EINVAL, "Expected EINVAL, got %s (%d)", strerror(errno),
556 errno);
557
558 fh = pr_fsio_open(fsio_test_path, O_CREAT|O_EXCL|O_WRONLY);
559 fail_unless(fh != NULL, "Failed to create '%s': %s", fsio_test_path,
560 strerror(errno));
561 (void) pr_fsio_close(fh);
562
563 /* Link a file (that exists) to itself */
564 link_path = target_path = fsio_test_path;
565 res = pr_fsio_link(target_path, link_path);
566 fail_unless(res < 0, "Failed to handle same existing source/destination");
567 fail_unless(errno == EEXIST, "Expected EEXIST, got %s (%d)", strerror(errno),
568 errno);
569
570 /* Create expected link */
571 link_path = fsio_link_path;
572 target_path = fsio_test_path;
573 res = pr_fsio_link(target_path, link_path);
574 fail_unless(res == 0, "Failed to create link from '%s' to '%s': %s",
575 link_path, target_path, strerror(errno));
576 (void) unlink(link_path);
577 (void) pr_fsio_unlink(fsio_test_path);
578 }
579 END_TEST
580
START_TEST(fsio_sys_link_chroot_guard_test)581 START_TEST (fsio_sys_link_chroot_guard_test) {
582 int res;
583
584 res = pr_fsio_guard_chroot(TRUE);
585 fail_unless(res == FALSE, "Expected FALSE (%d), got %d", FALSE, res);
586
587 res = pr_fsio_link(fsio_link_path, "/etc/foo.bar.baz");
588 fail_unless(res < 0, "Linked /etc/foo.bar.baz unexpectedly");
589 fail_unless(errno == EACCES, "Expected EACCES (%d), got %s %d", EACCES,
590 strerror(errno), errno);
591
592 (void) pr_fsio_guard_chroot(FALSE);
593
594 (void) pr_fsio_unlink(fsio_link_path);
595 res = pr_fsio_link(fsio_link_path, "/lib/foo/bar/baz");
596 fail_unless(res < 0, "Linked /lib/foo/bar/baz unexpectedly");
597 fail_unless(errno == ENOENT, "Expected ENOENT (%d), got %s %d", ENOENT,
598 strerror(errno), errno);
599 }
600 END_TEST
601
START_TEST(fsio_sys_symlink_test)602 START_TEST (fsio_sys_symlink_test) {
603 int res;
604 const char *target_path, *link_path;
605
606 target_path = link_path = NULL;
607 res = pr_fsio_symlink(target_path, link_path);
608 fail_unless(res < 0, "Failed to handle null arguments");
609 fail_unless(errno == EINVAL, "Expected EINVAL, got %s (%d)", strerror(errno),
610 errno);
611
612 target_path = "/tmp";
613 link_path = NULL;
614 res = pr_fsio_symlink(target_path, link_path);
615 fail_unless(res < 0, "Failed to handle null link_path argument");
616 fail_unless(errno == EINVAL, "Expected EINVAL, got %s (%d)", strerror(errno),
617 errno);
618
619 target_path = NULL;
620 link_path = fsio_link_path;
621 res = pr_fsio_symlink(target_path, link_path);
622 fail_unless(res < 0, "Failed to handle null target_path argument");
623 fail_unless(errno == EINVAL, "Expected EINVAL, got %s (%d)", strerror(errno),
624 errno);
625
626 /* Symlink a file (that exists) to itself */
627 link_path = target_path = "/tmp";
628 res = pr_fsio_symlink(target_path, link_path);
629 fail_unless(res < 0, "Failed to handle same existing source/destination");
630 fail_unless(errno == EEXIST, "Expected EEXIST, got %s (%d)", strerror(errno),
631 errno);
632
633 /* Create expected symlink */
634 link_path = fsio_link_path;
635 target_path = "/tmp";
636 res = pr_fsio_symlink(target_path, link_path);
637 fail_unless(res == 0, "Failed to create symlink from '%s' to '%s': %s",
638 link_path, target_path, strerror(errno));
639 (void) unlink(link_path);
640 }
641 END_TEST
642
START_TEST(fsio_sys_symlink_chroot_guard_test)643 START_TEST (fsio_sys_symlink_chroot_guard_test) {
644 int res;
645
646 res = pr_fsio_guard_chroot(TRUE);
647 fail_unless(res == FALSE, "Expected FALSE (%d), got %d", FALSE, res);
648
649 res = pr_fsio_symlink(fsio_link_path, "/etc/foo.bar.baz");
650 fail_unless(res < 0, "Symlinked /etc/foo.bar.baz unexpectedly");
651 fail_unless(errno == EACCES, "Expected EACCES (%d), got %s %d", EACCES,
652 strerror(errno), errno);
653
654 (void) pr_fsio_guard_chroot(FALSE);
655 (void) pr_fsio_unlink(fsio_link_path);
656
657 res = pr_fsio_symlink(fsio_link_path, "/lib/foo/bar/baz");
658 fail_unless(res < 0, "Symlinked /lib/foo/bar/baz unexpectedly");
659 fail_unless(errno == ENOENT, "Expected ENOENT (%d), got %s %d", ENOENT,
660 strerror(errno), errno);
661 }
662 END_TEST
663
START_TEST(fsio_sys_readlink_test)664 START_TEST (fsio_sys_readlink_test) {
665 int res;
666 char buf[PR_TUNABLE_BUFFER_SIZE];
667 const char *link_path, *target_path, *path;
668
669 res = pr_fsio_readlink(NULL, NULL, 0);
670 fail_unless(res < 0, "Failed to handle null arguments");
671 fail_unless(errno == EINVAL, "Expected EINVAL, got %s (%d)", strerror(errno),
672 errno);
673
674 /* Read a non-symlink file */
675 path = "/";
676 res = pr_fsio_readlink(path, buf, sizeof(buf)-1);
677 fail_unless(res < 0, "Failed to handle non-symlink path");
678 fail_unless(errno == EINVAL, "Expected EINVAL, got %s (%d)", strerror(errno),
679 errno);
680
681 /* Read a symlink file */
682 target_path = "/tmp";
683 link_path = fsio_link_path;
684 res = pr_fsio_symlink(target_path, link_path);
685 fail_unless(res == 0, "Failed to create symlink from '%s' to '%s': %s",
686 link_path, target_path, strerror(errno));
687
688 memset(buf, '\0', sizeof(buf));
689 res = pr_fsio_readlink(link_path, buf, sizeof(buf)-1);
690 fail_unless(res > 0, "Failed to read symlink '%s': %s", link_path,
691 strerror(errno));
692 buf[res] = '\0';
693 fail_unless(strcmp(buf, target_path) == 0, "Expected '%s', got '%s'",
694 target_path, buf);
695
696 /* Read a symlink file using a zero-length buffer */
697 res = pr_fsio_readlink(link_path, buf, 0);
698 fail_unless(res <= 0, "Expected length <= 0, got %d", res);
699
700 (void) unlink(link_path);
701 }
702 END_TEST
703
START_TEST(fsio_sys_lstat_test)704 START_TEST (fsio_sys_lstat_test) {
705 int res;
706 struct stat st;
707 unsigned int cache_size = 3, max_age = 1, policy_flags = 0;
708
709 res = pr_fsio_lstat(NULL, &st);
710 fail_unless(res < 0, "Failed to handle null path");
711 fail_unless(errno == EINVAL, "Expected EINVAL, got %s (%d)", strerror(errno),
712 errno);
713
714 res = pr_fsio_lstat("/", NULL);
715 fail_unless(res < 0, "Failed to handle null struct stat");
716 fail_unless(errno == EINVAL, "Expected EINVAL, got %s (%d)", strerror(errno),
717 errno);
718
719 res = pr_fsio_lstat("/", &st);
720 fail_unless(res == 0, "Unexpected lstat(2) error on '/': %s",
721 strerror(errno));
722 fail_unless(S_ISDIR(st.st_mode), "'/' is not a directory as expected");
723
724 /* Now, do the lstat(2) again, and make sure we get the same information
725 * from the cache.
726 */
727 res = pr_fsio_lstat("/", &st);
728 fail_unless(res == 0, "Unexpected lstat(2) error on '/': %s",
729 strerror(errno));
730 fail_unless(S_ISDIR(st.st_mode), "'/' is not a directory as expected");
731
732 pr_fs_statcache_reset();
733 res = pr_fs_statcache_set_policy(cache_size, max_age, policy_flags);
734 fail_unless(res == 0, "Failed to set statcache policy: %s", strerror(errno));
735
736 res = pr_fsio_lstat("/foo/bar/baz/quxx", &st);
737 fail_unless(res < 0, "Failed to handle nonexistent path");
738 fail_unless(errno == ENOENT, "Expected ENOENT, got %s (%d)", strerror(errno),
739 errno);
740
741 res = pr_fsio_lstat("/foo/bar/baz/quxx", &st);
742 fail_unless(res < 0, "Failed to handle nonexistent path");
743 fail_unless(errno == ENOENT, "Expected ENOENT, got %s (%d)", strerror(errno),
744 errno);
745
746 /* Now wait for longer than 1 second (our configured max age) */
747 sleep(max_age + 1);
748
749 res = pr_fsio_lstat("/foo/bar/baz/quxx", &st);
750 fail_unless(res < 0, "Failed to handle nonexistent path");
751 fail_unless(errno == ENOENT, "Expected ENOENT, got %s (%d)", strerror(errno),
752 errno);
753
754 /* lstat a symlink path */
755 res = pr_fsio_symlink("/tmp", fsio_link_path);
756 fail_unless(res == 0, "Failed to create symlink to '%s': %s", fsio_link_path,
757 strerror(errno));
758
759 res = pr_fsio_lstat(fsio_link_path, &st);
760 fail_unless(res == 0, "Failed to lstat '%s': %s", fsio_link_path,
761 strerror(errno));
762
763 (void) unlink(fsio_link_path);
764 }
765 END_TEST
766
START_TEST(fsio_sys_access_dir_test)767 START_TEST (fsio_sys_access_dir_test) {
768 int res;
769 uid_t uid = getuid();
770 gid_t gid = getgid();
771 mode_t perms;
772 array_header *suppl_gids;
773
774 res = pr_fsio_access(NULL, X_OK, uid, gid, NULL);
775 fail_unless(res < 0, "Failed to handle null path");
776 fail_unless(errno == EINVAL, "Expected EINVAL, got %s (%d)", strerror(errno),
777 errno);
778
779 res = pr_fsio_access("/baz/bar/foo", X_OK, uid, gid, NULL);
780 fail_unless(res < 0, "Failed to handle nonexistent path");
781 fail_unless(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
782 strerror(errno), errno);
783
784 /* Make the directory to check; we want it to have perms 771.*/
785 perms = (mode_t) 0771;
786 res = mkdir(fsio_testdir_path, perms);
787 fail_if(res < 0, "Unable to create directory '%s': %s", fsio_testdir_path,
788 strerror(errno));
789
790 /* Use chmod(2) to ensure that the directory has the perms we want,
791 * regardless of any umask settings.
792 */
793 res = chmod(fsio_testdir_path, perms);
794 fail_if(res < 0, "Unable to set perms %04o on directory '%s': %s", perms,
795 fsio_testdir_path, strerror(errno));
796
797 /* First, check that we ourselves can access our own directory. */
798
799 pr_fs_clear_cache2(fsio_testdir_path);
800 res = pr_fsio_access(fsio_testdir_path, F_OK, uid, gid, NULL);
801 fail_unless(res == 0, "Failed to check for file access on directory: %s",
802 strerror(errno));
803
804 pr_fs_clear_cache2(fsio_testdir_path);
805 res = pr_fsio_access(fsio_testdir_path, R_OK, uid, gid, NULL);
806 fail_unless(res == 0, "Failed to check for read access on directory: %s",
807 strerror(errno));
808
809 pr_fs_clear_cache2(fsio_testdir_path);
810 res = pr_fsio_access(fsio_testdir_path, W_OK, uid, gid, NULL);
811 fail_unless(res == 0, "Failed to check for write access on directory: %s",
812 strerror(errno));
813
814 pr_fs_clear_cache2(fsio_testdir_path);
815 res = pr_fsio_access(fsio_testdir_path, X_OK, uid, gid, NULL);
816 fail_unless(res == 0, "Failed to check for execute access on directory: %s",
817 strerror(errno));
818
819 suppl_gids = make_array(p, 1, sizeof(gid_t));
820 *((gid_t *) push_array(suppl_gids)) = gid;
821
822 pr_fs_clear_cache2(fsio_testdir_path);
823 res = pr_fsio_access(fsio_testdir_path, X_OK, uid, gid, suppl_gids);
824 fail_unless(res == 0, "Failed to check for execute access on directory: %s",
825 strerror(errno));
826
827 pr_fs_clear_cache2(fsio_testdir_path);
828 res = pr_fsio_access(fsio_testdir_path, R_OK, uid, gid, suppl_gids);
829 fail_unless(res == 0, "Failed to check for read access on directory: %s",
830 strerror(errno));
831
832 pr_fs_clear_cache2(fsio_testdir_path);
833 res = pr_fsio_access(fsio_testdir_path, W_OK, uid, gid, suppl_gids);
834 fail_unless(res == 0, "Failed to check for write access on directory: %s",
835 strerror(errno));
836
837 if (getenv("CI") == NULL &&
838 getenv("CIRRUS_CLONE_DEPTH") == NULL &&
839 getenv("TRAVIS") == NULL) {
840 uid_t other_uid;
841 gid_t other_gid;
842
843 /* Deliberately use IDs other than the current ones. */
844 other_uid = uid - 1;
845 other_gid = gid - 1;
846
847 /* Next, check that others can access the directory. */
848 pr_fs_clear_cache2(fsio_testdir_path);
849 res = pr_fsio_access(fsio_testdir_path, F_OK, other_uid, other_gid,
850 NULL);
851 fail_unless(res == 0,
852 "Failed to check for other file access on directory: %s",
853 strerror(errno));
854
855 pr_fs_clear_cache2(fsio_testdir_path);
856 res = pr_fsio_access(fsio_testdir_path, R_OK, other_uid, other_gid,
857 NULL);
858 fail_unless(res < 0,
859 "other read access on directory succeeded unexpectedly");
860 fail_unless(errno == EACCES, "Expected EACCES, got %s (%d)",
861 strerror(errno), errno);
862
863 pr_fs_clear_cache2(fsio_testdir_path);
864 res = pr_fsio_access(fsio_testdir_path, W_OK, other_uid, other_gid,
865 NULL);
866 fail_unless(res < 0,
867 "other write access on directory succeeded unexpectedly");
868 fail_unless(errno == EACCES, "Expected EACCES, got %s (%d)",
869 strerror(errno), errno);
870
871 pr_fs_clear_cache2(fsio_testdir_path);
872 res = pr_fsio_access(fsio_testdir_path, X_OK, other_uid, other_gid,
873 NULL);
874 fail_unless(res == 0, "Failed to check for execute access on directory: %s",
875 strerror(errno));
876 }
877
878 (void) rmdir(fsio_testdir_path);
879 }
880 END_TEST
881
START_TEST(fsio_sys_access_file_test)882 START_TEST (fsio_sys_access_file_test) {
883 int fd, res;
884 uid_t uid = getuid();
885 gid_t gid = getgid();
886 mode_t perms = 0665;
887 array_header *suppl_gids;
888
889 /* Make the file to check; we want it to have perms 664.*/
890 fd = open(fsio_test_path, O_CREAT|O_EXCL|O_WRONLY, S_IRUSR|S_IWUSR);
891 fail_if(fd < 0, "Unable to create file '%s': %s", fsio_test_path,
892 strerror(errno));
893
894 /* Use chmod(2) to ensure that the file has the perms we want,
895 * regardless of any umask settings.
896 */
897 res = chmod(fsio_test_path, perms);
898 fail_if(res < 0, "Unable to set perms %04o on file '%s': %s", perms,
899 fsio_test_path, strerror(errno));
900
901 /* First, check that we ourselves can access our own file. */
902
903 pr_fs_clear_cache2(fsio_test_path);
904 res = pr_fsio_access(fsio_test_path, F_OK, uid, gid, NULL);
905 fail_unless(res == 0, "Failed to check for file access on '%s': %s",
906 fsio_test_path, strerror(errno));
907
908 pr_fs_clear_cache2(fsio_test_path);
909 res = pr_fsio_access(fsio_test_path, R_OK, uid, gid, NULL);
910 fail_unless(res == 0, "Failed to check for read access on '%s': %s",
911 fsio_test_path, strerror(errno));
912
913 pr_fs_clear_cache2(fsio_test_path);
914 res = pr_fsio_access(fsio_test_path, W_OK, uid, gid, NULL);
915 fail_unless(res == 0, "Failed to check for write access on '%s': %s",
916 fsio_test_path, strerror(errno));
917
918 pr_fs_clear_cache2(fsio_test_path);
919 res = pr_fsio_access(fsio_test_path, X_OK, uid, gid, NULL);
920 fail_unless(res == 0, "Failed to check for execute access on '%s': %s",
921 fsio_test_path, strerror(errno));
922
923 suppl_gids = make_array(p, 1, sizeof(gid_t));
924 *((gid_t *) push_array(suppl_gids)) = gid;
925
926 pr_fs_clear_cache2(fsio_test_path);
927 res = pr_fsio_access(fsio_test_path, X_OK, uid, gid, suppl_gids);
928 fail_unless(res == 0, "Failed to check for execute access on '%s': %s",
929 fsio_test_path, strerror(errno));
930
931 pr_fs_clear_cache2(fsio_test_path);
932 res = pr_fsio_access(fsio_test_path, R_OK, uid, gid, suppl_gids);
933 fail_unless(res == 0, "Failed to check for read access on '%s': %s",
934 fsio_test_path, strerror(errno));
935
936 pr_fs_clear_cache2(fsio_test_path);
937 res = pr_fsio_access(fsio_test_path, W_OK, uid, gid, suppl_gids);
938 fail_unless(res == 0, "Failed to check for write access on '%s': %s",
939 fsio_test_path, strerror(errno));
940
941 (void) unlink(fsio_test_path);
942 }
943 END_TEST
944
START_TEST(fsio_sys_faccess_test)945 START_TEST (fsio_sys_faccess_test) {
946 int res;
947 uid_t uid = getuid();
948 gid_t gid = getgid();
949 mode_t perms = 0664;
950 pr_fh_t *fh;
951
952 res = pr_fsio_faccess(NULL, F_OK, uid, gid, NULL);
953 fail_unless(res < 0, "Failed to handle null arguments");
954 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
955 strerror(errno), errno);
956
957 fh = pr_fsio_open(fsio_test_path, O_CREAT|O_EXCL|O_WRONLY);
958 fail_unless(fh != NULL, "Unable to create file '%s': %s", fsio_test_path,
959 strerror(errno));
960
961 /* Use chmod(2) to ensure that the file has the perms we want,
962 * regardless of any umask settings.
963 */
964 res = chmod(fsio_test_path, perms);
965 fail_if(res < 0, "Unable to set perms %04o on file '%s': %s", perms,
966 fsio_test_path, strerror(errno));
967
968 /* First, check that we ourselves can access our own file. */
969
970 pr_fs_clear_cache2(fsio_test_path);
971 res = pr_fsio_faccess(fh, F_OK, uid, gid, NULL);
972 fail_unless(res == 0, "Failed to check for file access on '%s': %s",
973 fsio_test_path, strerror(errno));
974
975 pr_fs_clear_cache2(fsio_test_path);
976 res = pr_fsio_faccess(fh, R_OK, uid, gid, NULL);
977 fail_unless(res == 0, "Failed to check for read access on '%s': %s",
978 fsio_test_path, strerror(errno));
979
980 pr_fs_clear_cache2(fsio_test_path);
981 res = pr_fsio_faccess(fh, W_OK, uid, gid, NULL);
982 fail_unless(res == 0, "Failed to check for write access on '%s': %s",
983 fsio_test_path, strerror(errno));
984
985 pr_fs_clear_cache2(fsio_test_path);
986 res = pr_fsio_faccess(fh, X_OK, uid, gid, NULL);
987 fail_unless(res < 0,
988 "Check for execute access on '%s' succeeded unexpectedly", fsio_test_path);
989
990 (void) pr_fsio_close(fh);
991 (void) pr_fsio_unlink(fsio_test_path);
992 }
993 END_TEST
994
START_TEST(fsio_sys_truncate_test)995 START_TEST (fsio_sys_truncate_test) {
996 int res;
997 off_t len = 0;
998 pr_fh_t *fh;
999
1000 res = pr_fsio_truncate(NULL, 0);
1001 fail_unless(res < 0, "Failed to handle null arguments");
1002 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1003 strerror(errno), errno);
1004
1005 res = pr_fsio_truncate(fsio_test_path, 0);
1006 fail_unless(res < 0, "Truncated '%s' unexpectedly", fsio_test_path);
1007 fail_unless(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
1008 strerror(errno), errno);
1009
1010 fh = pr_fsio_open(fsio_test_path, O_CREAT|O_EXCL|O_WRONLY);
1011 fail_unless(fh != NULL, "Failed to create '%s': %s", fsio_test_path,
1012 strerror(errno));
1013
1014 res = pr_fsio_truncate(fsio_test_path, len);
1015 fail_unless(res == 0, "Failed to truncate '%s': %s", fsio_test_path,
1016 strerror(errno));
1017
1018 (void) pr_fsio_close(fh);
1019 (void) pr_fsio_unlink(fsio_test_path);
1020 }
1021 END_TEST
1022
START_TEST(fsio_sys_truncate_chroot_guard_test)1023 START_TEST (fsio_sys_truncate_chroot_guard_test) {
1024 int res;
1025
1026 res = pr_fsio_guard_chroot(TRUE);
1027 fail_unless(res == FALSE, "Expected FALSE (%d), got %d", FALSE, res);
1028
1029 res = pr_fsio_truncate("/etc/foo.bar.baz", 0);
1030 fail_unless(res < 0, "Truncated /etc/foo.bar.baz unexpectedly");
1031 fail_unless(errno == EACCES, "Expected EACCES (%d), got %s %d", EACCES,
1032 strerror(errno), errno);
1033
1034 (void) pr_fsio_guard_chroot(FALSE);
1035
1036 res = pr_fsio_truncate("/lib/foo/bar/baz", 0);
1037 fail_unless(res < 0, "Truncated /lib/foo/bar/baz unexpectedly");
1038 fail_unless(errno == ENOENT, "Expected ENOENT (%d), got %s %d", ENOENT,
1039 strerror(errno), errno);
1040 }
1041 END_TEST
1042
START_TEST(fsio_sys_ftruncate_test)1043 START_TEST (fsio_sys_ftruncate_test) {
1044 int res;
1045 off_t len = 0;
1046 pr_fh_t *fh;
1047 pr_buffer_t *buf;
1048
1049 res = pr_fsio_ftruncate(NULL, 0);
1050 fail_unless(res < 0, "Failed to handle null arguments");
1051 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1052 strerror(errno), errno);
1053
1054 fh = pr_fsio_open(fsio_test_path, O_CREAT|O_EXCL|O_WRONLY);
1055 fail_unless(fh != NULL, "Failed to create '%s': %s", fsio_test_path,
1056 strerror(errno));
1057
1058 mark_point();
1059 res = pr_fsio_ftruncate(fh, len);
1060 fail_unless(res == 0, "Failed to truncate '%s': %s", fsio_test_path,
1061 strerror(errno));
1062
1063 /* Attach a read buffer to the handle, make sure it is cleared. */
1064 buf = pcalloc(fh->fh_pool, sizeof(pr_buffer_t));
1065 buf->buflen = 100;
1066 buf->remaining = 1;
1067
1068 fh->fh_buf = buf;
1069
1070 mark_point();
1071 res = pr_fsio_ftruncate(fh, len);
1072 fail_unless(res == 0, "Failed to truncate '%s': %s", fsio_test_path,
1073 strerror(errno));
1074 fail_unless(buf->remaining == buf->buflen,
1075 "Expected %lu, got %lu", (unsigned long) buf->buflen,
1076 (unsigned long) buf->remaining);
1077
1078 (void) pr_fsio_close(fh);
1079 (void) pr_fsio_unlink(fsio_test_path);
1080 }
1081 END_TEST
1082
START_TEST(fsio_sys_chmod_test)1083 START_TEST (fsio_sys_chmod_test) {
1084 int res;
1085 mode_t mode = 0644;
1086 pr_fh_t *fh;
1087
1088 res = pr_fsio_chmod(NULL, mode);
1089 fail_unless(res < 0, "Failed to handle null arguments");
1090 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1091 strerror(errno), errno);
1092
1093 res = pr_fsio_chmod(fsio_test_path, 0);
1094 fail_unless(res < 0, "Changed perms of '%s' unexpectedly", fsio_test_path);
1095 fail_unless(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
1096 strerror(errno), errno);
1097
1098 fh = pr_fsio_open(fsio_test_path, O_CREAT|O_EXCL|O_WRONLY);
1099 fail_unless(fh != NULL, "Failed to create '%s': %s", fsio_test_path,
1100 strerror(errno));
1101
1102 res = pr_fsio_chmod(fsio_test_path, mode);
1103 fail_unless(res == 0, "Failed to set perms of '%s': %s", fsio_test_path,
1104 strerror(errno));
1105
1106 (void) pr_fsio_close(fh);
1107 (void) pr_fsio_unlink(fsio_test_path);
1108 }
1109 END_TEST
1110
START_TEST(fsio_sys_chmod_chroot_guard_test)1111 START_TEST (fsio_sys_chmod_chroot_guard_test) {
1112 int res;
1113 mode_t mode = 0644;
1114
1115 res = pr_fsio_guard_chroot(TRUE);
1116 fail_unless(res == FALSE, "Expected FALSE (%d), got %d", FALSE, res);
1117
1118 res = pr_fsio_chmod("/etc/foo.bar.baz", mode);
1119 fail_unless(res < 0, "Set mode on /etc/foo.bar.baz unexpectedly");
1120 fail_unless(errno == EACCES, "Expected EACCES (%d), got %s %d", EACCES,
1121 strerror(errno), errno);
1122
1123 (void) pr_fsio_guard_chroot(FALSE);
1124
1125 res = pr_fsio_chmod("/lib/foo/bar/baz", mode);
1126 fail_unless(res < 0, "Set mode on /lib/foo/bar/baz unexpectedly");
1127 fail_unless(errno == ENOENT, "Expected ENOENT (%d), got %s %d", ENOENT,
1128 strerror(errno), errno);
1129 }
1130 END_TEST
1131
START_TEST(fsio_sys_fchmod_test)1132 START_TEST (fsio_sys_fchmod_test) {
1133 int res;
1134 mode_t mode = 0644;
1135 pr_fh_t *fh;
1136
1137 res = pr_fsio_fchmod(NULL, mode);
1138 fail_unless(res < 0, "Failed to handle null arguments");
1139 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1140 strerror(errno), errno);
1141
1142 fh = pr_fsio_open(fsio_test_path, O_CREAT|O_EXCL|O_WRONLY);
1143 fail_unless(fh != NULL, "Failed to create '%s': %s", fsio_test_path,
1144 strerror(errno));
1145
1146 res = pr_fsio_fchmod(fh, mode);
1147 fail_unless(res == 0, "Failed to set perms of '%s': %s", fsio_test_path,
1148 strerror(errno));
1149
1150 (void) pr_fsio_close(fh);
1151 (void) pr_fsio_unlink(fsio_test_path);
1152 }
1153 END_TEST
1154
START_TEST(fsio_sys_chown_test)1155 START_TEST (fsio_sys_chown_test) {
1156 int res;
1157 uid_t uid = getuid();
1158 gid_t gid = getgid();
1159 pr_fh_t *fh;
1160
1161 res = pr_fsio_chown(NULL, uid, gid);
1162 fail_unless(res < 0, "Failed to handle null arguments");
1163 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1164 strerror(errno), errno);
1165
1166 res = pr_fsio_chown(fsio_test_path, uid, gid);
1167 fail_unless(res < 0, "Changed ownership of '%s' unexpectedly",
1168 fsio_test_path);
1169 fail_unless(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
1170 strerror(errno), errno);
1171
1172 fh = pr_fsio_open(fsio_test_path, O_CREAT|O_EXCL|O_WRONLY);
1173 fail_unless(fh != NULL, "Failed to create '%s': %s", fsio_test_path,
1174 strerror(errno));
1175
1176 res = pr_fsio_chown(fsio_test_path, uid, gid);
1177 fail_unless(res == 0, "Failed to set ownership of '%s': %s", fsio_test_path,
1178 strerror(errno));
1179
1180 (void) pr_fsio_close(fh);
1181 (void) pr_fsio_unlink(fsio_test_path);
1182 }
1183 END_TEST
1184
START_TEST(fsio_sys_chown_chroot_guard_test)1185 START_TEST (fsio_sys_chown_chroot_guard_test) {
1186 int res;
1187 uid_t uid = getuid();
1188 gid_t gid = getgid();
1189
1190 res = pr_fsio_guard_chroot(TRUE);
1191 fail_unless(res == FALSE, "Expected FALSE (%d), got %d", FALSE, res);
1192
1193 res = pr_fsio_chown("/etc/foo.bar.baz", uid, gid);
1194 fail_unless(res < 0, "Set ownership on /etc/foo.bar.baz unexpectedly");
1195 fail_unless(errno == EACCES, "Expected EACCES (%d), got %s %d", EACCES,
1196 strerror(errno), errno);
1197
1198 (void) pr_fsio_guard_chroot(FALSE);
1199
1200 res = pr_fsio_chown("/lib/foo/bar/baz", uid, gid);
1201 fail_unless(res < 0, "Set ownership on /lib/foo/bar/baz unexpectedly");
1202 fail_unless(errno == ENOENT, "Expected ENOENT (%d), got %s %d", ENOENT,
1203 strerror(errno), errno);
1204 }
1205 END_TEST
1206
START_TEST(fsio_sys_fchown_test)1207 START_TEST (fsio_sys_fchown_test) {
1208 int res;
1209 uid_t uid = getuid();
1210 gid_t gid = getgid();
1211 pr_fh_t *fh;
1212
1213 res = pr_fsio_fchown(NULL, uid, gid);
1214 fail_unless(res < 0, "Failed to handle null arguments");
1215 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1216 strerror(errno), errno);
1217
1218 fh = pr_fsio_open(fsio_test_path, O_CREAT|O_EXCL|O_WRONLY);
1219 fail_unless(fh != NULL, "Failed to create '%s': %s", fsio_test_path,
1220 strerror(errno));
1221
1222 res = pr_fsio_fchown(fh, uid, gid);
1223 fail_unless(res == 0, "Failed to set ownership of '%s': %s", fsio_test_path,
1224 strerror(errno));
1225
1226 (void) pr_fsio_close(fh);
1227 (void) pr_fsio_unlink(fsio_test_path);
1228 }
1229 END_TEST
1230
START_TEST(fsio_sys_lchown_test)1231 START_TEST (fsio_sys_lchown_test) {
1232 int res;
1233 uid_t uid = getuid();
1234 gid_t gid = getgid();
1235 pr_fh_t *fh;
1236
1237 res = pr_fsio_lchown(NULL, uid, gid);
1238 fail_unless(res < 0, "Failed to handle null arguments");
1239 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1240 strerror(errno), errno);
1241
1242 res = pr_fsio_lchown(fsio_test_path, uid, gid);
1243 fail_unless(res < 0, "Changed ownership of '%s' unexpectedly",
1244 fsio_test_path);
1245 fail_unless(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
1246 strerror(errno), errno);
1247
1248 fh = pr_fsio_open(fsio_test_path, O_CREAT|O_EXCL|O_WRONLY);
1249 fail_unless(fh != NULL, "Failed to create '%s': %s", fsio_test_path,
1250 strerror(errno));
1251
1252 res = pr_fsio_lchown(fsio_test_path, uid, gid);
1253 fail_unless(res == 0, "Failed to set ownership of '%s': %s", fsio_test_path,
1254 strerror(errno));
1255
1256 (void) pr_fsio_close(fh);
1257 (void) pr_fsio_unlink(fsio_test_path);
1258 }
1259 END_TEST
1260
START_TEST(fsio_sys_lchown_chroot_guard_test)1261 START_TEST (fsio_sys_lchown_chroot_guard_test) {
1262 int res;
1263 uid_t uid = getuid();
1264 gid_t gid = getgid();
1265
1266 res = pr_fsio_guard_chroot(TRUE);
1267 fail_unless(res == FALSE, "Expected FALSE (%d), got %d", FALSE, res);
1268
1269 res = pr_fsio_lchown("/etc/foo.bar.baz", uid, gid);
1270 fail_unless(res < 0, "Set ownership on /etc/foo.bar.baz unexpectedly");
1271 fail_unless(errno == EACCES, "Expected EACCES (%d), got %s %d", EACCES,
1272 strerror(errno), errno);
1273
1274 (void) pr_fsio_guard_chroot(FALSE);
1275
1276 res = pr_fsio_lchown("/lib/foo/bar/baz", uid, gid);
1277 fail_unless(res < 0, "Set ownership on /lib/foo/bar/baz unexpectedly");
1278 fail_unless(errno == ENOENT, "Expected ENOENT (%d), got %s %d", ENOENT,
1279 strerror(errno), errno);
1280 }
1281 END_TEST
1282
START_TEST(fsio_sys_rename_test)1283 START_TEST (fsio_sys_rename_test) {
1284 int res;
1285 pr_fh_t *fh;
1286
1287 res = pr_fsio_rename(NULL, NULL);
1288 fail_unless(res < 0, "Failed to handle null arguments");
1289 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1290 strerror(errno), errno);
1291
1292 res = pr_fsio_rename(fsio_test_path, NULL);
1293 fail_unless(res < 0, "Failed to handle null dst argument");
1294 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1295 strerror(errno), errno);
1296
1297 res = pr_fsio_rename(fsio_test_path, fsio_test2_path);
1298 fail_unless(res < 0, "Failed to handle non-existent files");
1299 fail_unless(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
1300 strerror(errno), errno);
1301
1302 fh = pr_fsio_open(fsio_test_path, O_CREAT|O_EXCL|O_WRONLY);
1303 fail_unless(fh != NULL, "Failed to create '%s': %s", fsio_test_path,
1304 strerror(errno));
1305 (void) pr_fsio_close(fh);
1306
1307 res = pr_fsio_rename(fsio_test_path, fsio_test2_path);
1308 fail_unless(res == 0, "Failed to rename '%s' to '%s': %s", fsio_test_path,
1309 fsio_test2_path, strerror(errno));
1310
1311 (void) pr_fsio_unlink(fsio_test_path);
1312 (void) pr_fsio_unlink(fsio_test2_path);
1313 }
1314 END_TEST
1315
START_TEST(fsio_sys_rename_chroot_guard_test)1316 START_TEST (fsio_sys_rename_chroot_guard_test) {
1317 int res;
1318 pr_fh_t *fh;
1319
1320 res = pr_fsio_guard_chroot(TRUE);
1321 fail_unless(res == FALSE, "Expected FALSE (%d), got %d", FALSE, res);
1322
1323 fh = pr_fsio_open(fsio_test_path, O_CREAT|O_EXCL|O_WRONLY);
1324 fail_unless(fh != NULL, "Failed to create '%s': %s", fsio_test_path,
1325 strerror(errno));
1326 (void) pr_fsio_close(fh);
1327
1328 res = pr_fsio_rename(fsio_test_path, "/etc/foo.bar.baz");
1329 fail_unless(res < 0, "Renamed '%s' unexpectedly", fsio_test_path);
1330 fail_unless(errno == EACCES, "Expected EACCES (%d), got %s (%d)", EACCES,
1331 strerror(errno), errno);
1332
1333 res = pr_fsio_rename("/etc/foo.bar.baz", fsio_test_path);
1334 fail_unless(res < 0, "Renamed '/etc/foo.bar.baz' unexpectedly");
1335 fail_unless(errno == EACCES, "Expected EACCES (%d), got %s (%d)", EACCES,
1336 strerror(errno), errno);
1337
1338 (void) pr_fsio_guard_chroot(FALSE);
1339
1340 res = pr_fsio_rename("/etc/foo/bar/baz", "/lib/quxx/quzz");
1341 fail_unless(res < 0, "Renamed '/etc/foo/bar/baz' unexpectedly");
1342 fail_unless(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
1343 strerror(errno), errno);
1344
1345 (void) pr_fsio_unlink(fsio_test_path);
1346 }
1347 END_TEST
1348
START_TEST(fsio_sys_utimes_test)1349 START_TEST (fsio_sys_utimes_test) {
1350 int res;
1351 struct timeval tvs[3];
1352 pr_fh_t *fh;
1353
1354 memset(tvs, 0, sizeof(tvs));
1355
1356 res = pr_fsio_utimes(NULL, NULL);
1357 fail_unless(res < 0, "Failed to handle null arguments");
1358 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1359 strerror(errno), errno);
1360
1361 res = pr_fsio_utimes(fsio_test_path, (struct timeval *) &tvs);
1362 fail_unless(res < 0, "Changed times of '%s' unexpectedly", fsio_test_path);
1363 fail_unless(errno == ENOENT || errno == EINVAL,
1364 "Expected ENOENT (%d) or EINVAL (%d), got %s (%d)", ENOENT, EINVAL,
1365 strerror(errno), errno);
1366
1367 fh = pr_fsio_open(fsio_test_path, O_CREAT|O_EXCL|O_WRONLY);
1368 fail_unless(fh != NULL, "Failed to create '%s': %s", fsio_test_path,
1369 strerror(errno));
1370
1371 memset(&tvs, 0, sizeof(tvs));
1372 res = pr_fsio_utimes(fsio_test_path, (struct timeval *) &tvs);
1373 fail_unless(res == 0, "Failed to set times of '%s': %s", fsio_test_path,
1374 strerror(errno));
1375
1376 (void) pr_fsio_close(fh);
1377 (void) pr_fsio_unlink(fsio_test_path);
1378 }
1379 END_TEST
1380
START_TEST(fsio_sys_utimes_chroot_guard_test)1381 START_TEST (fsio_sys_utimes_chroot_guard_test) {
1382 int res;
1383 struct timeval tvs[3];
1384
1385 memset(tvs, 0, sizeof(tvs));
1386
1387 res = pr_fsio_guard_chroot(TRUE);
1388 fail_unless(res == FALSE, "Expected FALSE (%d), got %d", FALSE, res);
1389
1390 res = pr_fsio_utimes("/etc/foo.bar.baz", (struct timeval *) &tvs);
1391 fail_unless(res < 0, "Set times on /etc/foo.bar.baz unexpectedly");
1392 fail_unless(errno == EACCES, "Expected EACCES (%d), got %s %d", EACCES,
1393 strerror(errno), errno);
1394
1395 (void) pr_fsio_guard_chroot(FALSE);
1396
1397 res = pr_fsio_utimes("/lib/foo/bar/baz", (struct timeval *) &tvs);
1398 fail_unless(res < 0, "Set times on /lib/foo/bar/baz unexpectedly");
1399 fail_unless(errno == ENOENT || errno == EINVAL,
1400 "Expected ENOENT (%d) or EINVAL (%d), got %s %d", ENOENT, EINVAL,
1401 strerror(errno), errno);
1402 }
1403 END_TEST
1404
START_TEST(fsio_sys_futimes_test)1405 START_TEST (fsio_sys_futimes_test) {
1406 int res;
1407 struct timeval tvs[3];
1408 pr_fh_t *fh;
1409
1410 memset(tvs, 0, sizeof(tvs));
1411
1412 res = pr_fsio_futimes(NULL, NULL);
1413 fail_unless(res < 0, "Failed to handle null arguments");
1414 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1415 strerror(errno), errno);
1416
1417 fh = pr_fsio_open(fsio_test_path, O_CREAT|O_EXCL|O_WRONLY);
1418 fail_unless(fh != NULL, "Failed to create '%s': %s", fsio_test_path,
1419 strerror(errno));
1420
1421 memset(&tvs, 0, sizeof(tvs));
1422 res = pr_fsio_futimes(fh, (struct timeval *) &tvs);
1423 fail_unless(res == 0, "Failed to set times of '%s': %s", fsio_test_path,
1424 strerror(errno));
1425
1426 (void) pr_fsio_close(fh);
1427 (void) pr_fsio_unlink(fsio_test_path);
1428 }
1429 END_TEST
1430
START_TEST(fsio_sys_fsync_test)1431 START_TEST (fsio_sys_fsync_test) {
1432 int res;
1433 pr_fh_t *fh;
1434
1435 res = pr_fsio_fsync(NULL);
1436 fail_unless(res < 0, "Failed to handle null arguments");
1437 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1438 strerror(errno), errno);
1439
1440 fh = pr_fsio_open(fsio_test_path, O_CREAT|O_EXCL|O_WRONLY);
1441 fail_unless(fh != NULL, "Failed to open '%s': %s", fsio_test_path,
1442 strerror(errno));
1443
1444 res = pr_fsio_fsync(fh);
1445 #ifdef HAVE_FSYNC
1446 fail_unless(res == 0, "fsync of '%s' failed: %s", fsio_test_path,
1447 strerror(errno));
1448 #else
1449 fail_unless(res < 0, "fsync of '%s' succeeded unexpectedly", fsio_test_path);
1450 fail_unless(errno == ENOSYS, "Expected ENOSYS (%d), got %s (%d)", ENOSYS,
1451 strerror(errno), errno);
1452 #endif /* HAVE_FSYNC */
1453
1454 (void) pr_fsio_close(fh);
1455 (void) pr_fsio_unlink(fsio_test_path);
1456 }
1457 END_TEST
1458
START_TEST(fsio_sys_getxattr_test)1459 START_TEST (fsio_sys_getxattr_test) {
1460 ssize_t res;
1461 const char *path, *name;
1462 unsigned long fsio_opts;
1463
1464 res = pr_fsio_getxattr(NULL, NULL, NULL, NULL, 0);
1465 fail_unless(res < 0, "Failed to handle null arguments");
1466 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1467 strerror(errno), errno);
1468
1469 res = pr_fsio_getxattr(p, NULL, NULL, NULL, 0);
1470 fail_unless(res < 0, "Failed to handle null path");
1471 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1472 strerror(errno), errno);
1473
1474 path = fsio_test_path;
1475 res = pr_fsio_getxattr(p, path, NULL, NULL, 0);
1476 fail_unless(res < 0, "Failed to handle null arguments");
1477 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1478 strerror(errno), errno);
1479
1480 name = "foo.bar";
1481
1482 fsio_opts = pr_fsio_set_options(PR_FSIO_OPT_IGNORE_XATTR);
1483 res = pr_fsio_getxattr(p, path, name, NULL, 0);
1484 fail_unless(res < 0, "Failed to handle disabled xattr");
1485 fail_unless(errno == ENOSYS, "Expected ENOSYS (%d), got %s (%d)", ENOSYS,
1486 strerror(errno), errno);
1487
1488 (void) pr_fsio_set_options(fsio_opts);
1489 res = pr_fsio_getxattr(p, path, name, NULL, 0);
1490 #ifdef PR_USE_XATTR
1491 fail_unless(res < 0, "Failed to handle nonexist attribute '%s'", name);
1492 fail_unless(errno == ENOENT || errno == ENOATTR || errno == ENOTSUP,
1493 "Expected ENOENT (%d), ENOATTR (%d) or ENOTSUP (%d), got %s (%d)",
1494 ENOENT, ENOATTR, ENOTSUP, strerror(errno), errno);
1495
1496 #else
1497 fail_unless(res < 0, "Failed to handle --disable-xattr");
1498 fail_unless(errno == ENOSYS, "Expected ENOSYS (%d), got %s (%d)", ENOSYS,
1499 strerror(errno), errno);
1500 #endif /* PR_USE_XATTR */
1501 }
1502 END_TEST
1503
START_TEST(fsio_sys_lgetxattr_test)1504 START_TEST (fsio_sys_lgetxattr_test) {
1505 ssize_t res;
1506 const char *path, *name;
1507 unsigned long fsio_opts;
1508
1509 res = pr_fsio_lgetxattr(NULL, NULL, NULL, NULL, 0);
1510 fail_unless(res < 0, "Failed to handle null arguments");
1511 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1512 strerror(errno), errno);
1513
1514 res = pr_fsio_lgetxattr(p, NULL, NULL, NULL, 0);
1515 fail_unless(res < 0, "Failed to handle null path");
1516 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1517 strerror(errno), errno);
1518
1519 path = fsio_test_path;
1520 res = pr_fsio_lgetxattr(p, path, NULL, NULL, 0);
1521 fail_unless(res < 0, "Failed to handle null xattr name");
1522 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1523 strerror(errno), errno);
1524
1525 name = "foo.bar";
1526
1527 fsio_opts = pr_fsio_set_options(PR_FSIO_OPT_IGNORE_XATTR);
1528 res = pr_fsio_lgetxattr(p, path, name, NULL, 0);
1529 fail_unless(res < 0, "Failed to handle disabled xattr");
1530 fail_unless(errno == ENOSYS, "Expected ENOSYS (%d), got %s (%d)", ENOSYS,
1531 strerror(errno), errno);
1532
1533 pr_fsio_set_options(fsio_opts);
1534 res = pr_fsio_lgetxattr(p, path, name, NULL, 0);
1535 #ifdef PR_USE_XATTR
1536 fail_unless(res < 0, "Failed to handle nonexist attribute '%s'", name);
1537 fail_unless(errno == ENOENT || errno == ENOATTR || errno == ENOTSUP,
1538 "Expected ENOENT (%d), ENOATTR (%d) or ENOTSUP (%d), got %s (%d)",
1539 ENOENT, ENOATTR, ENOTSUP, strerror(errno), errno);
1540
1541 #else
1542 fail_unless(res < 0, "Failed to handle --disable-xattr");
1543 fail_unless(errno == ENOSYS, "Expected ENOSYS (%d), got %s (%d)", ENOSYS,
1544 strerror(errno), errno);
1545 #endif /* PR_USE_XATTR */
1546 }
1547 END_TEST
1548
START_TEST(fsio_sys_fgetxattr_test)1549 START_TEST (fsio_sys_fgetxattr_test) {
1550 ssize_t res;
1551 pr_fh_t *fh;
1552 const char *name;
1553 unsigned long fsio_opts;
1554
1555 res = pr_fsio_fgetxattr(NULL, NULL, NULL, NULL, 0);
1556 fail_unless(res < 0, "Failed to handle null arguments");
1557 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1558 strerror(errno), errno);
1559
1560 res = pr_fsio_fgetxattr(p, NULL, NULL, NULL, 0);
1561 fail_unless(res < 0, "Failed to handle null file handle");
1562 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1563 strerror(errno), errno);
1564
1565 (void) unlink(fsio_test_path);
1566 fh = pr_fsio_open(fsio_test_path, O_CREAT|O_EXCL|O_RDWR);
1567 fail_unless(fh != NULL, "Failed to open '%s': %s", fsio_test_path,
1568 strerror(errno));
1569
1570 res = pr_fsio_fgetxattr(p, fh, NULL, NULL, 0);
1571 fail_unless(res < 0, "Failed to handle null xattr name");
1572 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1573 strerror(errno), errno);
1574
1575 name = "foo.bar";
1576
1577 fsio_opts = pr_fsio_set_options(PR_FSIO_OPT_IGNORE_XATTR);
1578 res = pr_fsio_fgetxattr(p, fh, name, NULL, 0);
1579 fail_unless(res < 0, "Failed to handle disabled xattr");
1580 fail_unless(errno == ENOSYS, "Expected ENOSYS (%d), got %s (%d)", ENOSYS,
1581 strerror(errno), errno);
1582
1583 pr_fsio_set_options(fsio_opts);
1584 res = pr_fsio_fgetxattr(p, fh, name, NULL, 0);
1585 #ifdef PR_USE_XATTR
1586 fail_unless(res < 0, "Failed to handle nonexist attribute '%s'", name);
1587 fail_unless(errno == ENOENT || errno == ENOATTR || errno == ENOTSUP,
1588 "Expected ENOENT (%d), ENOATTR (%d) or ENOTSUP (%d), got %s (%d)",
1589 ENOENT, ENOATTR, ENOTSUP, strerror(errno), errno);
1590
1591 #else
1592 fail_unless(res < 0, "Failed to handle --disable-xattr");
1593 fail_unless(errno == ENOSYS, "Expected ENOSYS (%d), got %s (%d)", ENOSYS,
1594 strerror(errno), errno);
1595 #endif /* PR_USE_XATTR */
1596
1597 pr_fsio_close(fh);
1598 (void) unlink(fsio_test_path);
1599 }
1600 END_TEST
1601
START_TEST(fsio_sys_listxattr_test)1602 START_TEST (fsio_sys_listxattr_test) {
1603 int res;
1604 const char *path;
1605 pr_fh_t *fh = NULL;
1606 array_header *names = NULL;
1607 unsigned long fsio_opts;
1608
1609 res = pr_fsio_listxattr(NULL, NULL, NULL);
1610 fail_unless(res < 0, "Failed to handle null arguments");
1611 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1612 strerror(errno), errno);
1613
1614 res = pr_fsio_listxattr(p, NULL, NULL);
1615 fail_unless(res < 0, "Failed to handle null path");
1616 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1617 strerror(errno), errno);
1618
1619 path = fsio_test_path;
1620 res = pr_fsio_listxattr(p, path, NULL);
1621 fail_unless(res < 0, "Failed to handle null array");
1622 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1623 strerror(errno), errno);
1624
1625 fsio_opts = pr_fsio_set_options(PR_FSIO_OPT_IGNORE_XATTR);
1626 res = pr_fsio_listxattr(p, path, &names);
1627 fail_unless(res < 0, "Failed to handle disabled xattr");
1628 fail_unless(errno == ENOSYS, "Expected ENOSYS (%d), got %s (%d)", ENOSYS,
1629 strerror(errno), errno);
1630
1631 pr_fsio_set_options(fsio_opts);
1632 res = pr_fsio_listxattr(p, path, &names);
1633 #ifdef PR_USE_XATTR
1634 fail_unless(res < 0, "Failed to handle nonexistent path '%s'", path);
1635 fail_unless(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
1636 strerror(errno), errno);
1637
1638 (void) unlink(fsio_test_path);
1639 fh = pr_fsio_open(fsio_test_path, O_CREAT|O_EXCL|O_WRONLY);
1640 fail_unless(fh != NULL, "Failed to open '%s': %s", fsio_test_path,
1641 strerror(errno));
1642 pr_fsio_close(fh);
1643
1644 res = pr_fsio_listxattr(p, path, &names);
1645 fail_if(res < 0, "Failed to list xattrs for '%s': %s", path, strerror(errno));
1646
1647 (void) unlink(fsio_test_path);
1648 #else
1649 (void) fh;
1650 fail_unless(res < 0, "Failed to handle --disable-xattr");
1651 fail_unless(errno == ENOSYS, "Expected ENOSYS (%d), got %s (%d)", ENOSYS,
1652 strerror(errno), errno);
1653 #endif /* PR_USE_XATTR */
1654 }
1655 END_TEST
1656
START_TEST(fsio_sys_llistxattr_test)1657 START_TEST (fsio_sys_llistxattr_test) {
1658 int res;
1659 const char *path;
1660 pr_fh_t *fh = NULL;
1661 array_header *names = NULL;
1662 unsigned long fsio_opts;
1663
1664 res = pr_fsio_llistxattr(NULL, NULL, NULL);
1665 fail_unless(res < 0, "Failed to handle null arguments");
1666 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1667 strerror(errno), errno);
1668
1669 res = pr_fsio_llistxattr(p, NULL, NULL);
1670 fail_unless(res < 0, "Failed to handle null path");
1671 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1672 strerror(errno), errno);
1673
1674 path = fsio_test_path;
1675 res = pr_fsio_llistxattr(p, path, NULL);
1676 fail_unless(res < 0, "Failed to handle null array");
1677 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1678 strerror(errno), errno);
1679
1680 fsio_opts = pr_fsio_set_options(PR_FSIO_OPT_IGNORE_XATTR);
1681 res = pr_fsio_llistxattr(p, path, &names);
1682 fail_unless(res < 0, "Failed to handle disabled xattr");
1683 fail_unless(errno == ENOSYS, "Expected ENOSYS (%d), got %s (%d)", ENOSYS,
1684 strerror(errno), errno);
1685
1686 pr_fsio_set_options(fsio_opts);
1687 res = pr_fsio_llistxattr(p, path, &names);
1688 #ifdef PR_USE_XATTR
1689 fail_unless(res < 0, "Failed to handle nonexistent path '%s'", path);
1690 fail_unless(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
1691 strerror(errno), errno);
1692
1693 (void) unlink(fsio_test_path);
1694 fh = pr_fsio_open(fsio_test_path, O_CREAT|O_EXCL|O_WRONLY);
1695 fail_unless(fh != NULL, "Failed to open '%s': %s", fsio_test_path,
1696 strerror(errno));
1697 pr_fsio_close(fh);
1698
1699 res = pr_fsio_listxattr(p, path, &names);
1700 fail_if(res < 0, "Failed to list xattrs for '%s': %s", path, strerror(errno));
1701
1702 (void) unlink(fsio_test_path);
1703 #else
1704 (void) fh;
1705 fail_unless(res < 0, "Failed to handle --disable-xattr");
1706 fail_unless(errno == ENOSYS, "Expected ENOSYS (%d), got %s (%d)", ENOSYS,
1707 strerror(errno), errno);
1708 #endif /* PR_USE_XATTR */
1709 }
1710 END_TEST
1711
START_TEST(fsio_sys_flistxattr_test)1712 START_TEST (fsio_sys_flistxattr_test) {
1713 int res;
1714 pr_fh_t *fh;
1715 array_header *names = NULL;
1716 unsigned long fsio_opts;
1717
1718 res = pr_fsio_flistxattr(NULL, NULL, NULL);
1719 fail_unless(res < 0, "Failed to handle null arguments");
1720 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1721 strerror(errno), errno);
1722
1723 res = pr_fsio_flistxattr(p, NULL, NULL);
1724 fail_unless(res < 0, "Failed to handle null file handle");
1725 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1726 strerror(errno), errno);
1727
1728 (void) unlink(fsio_test_path);
1729 fh = pr_fsio_open(fsio_test_path, O_CREAT|O_EXCL|O_RDWR);
1730 fail_unless(fh != NULL, "Failed to open '%s': %s", fsio_test_path,
1731 strerror(errno));
1732
1733 res = pr_fsio_flistxattr(p, fh, NULL);
1734 fail_unless(res < 0, "Failed to handle null array");
1735 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1736 strerror(errno), errno);
1737
1738 fsio_opts = pr_fsio_set_options(PR_FSIO_OPT_IGNORE_XATTR);
1739 res = pr_fsio_flistxattr(p, fh, &names);
1740 fail_unless(res < 0, "Failed to handle disabled xattr");
1741 fail_unless(errno == ENOSYS, "Expected ENOSYS (%d), got %s (%d)", ENOSYS,
1742 strerror(errno), errno);
1743
1744 pr_fsio_set_options(fsio_opts);
1745 res = pr_fsio_flistxattr(p, fh, &names);
1746 #ifdef PR_USE_XATTR
1747 fail_if(res < 0, "Failed to list xattrs for '%s': %s", fsio_test_path,
1748 strerror(errno));
1749
1750 #else
1751 fail_unless(res < 0, "Failed to handle --disable-xattr");
1752 fail_unless(errno == ENOSYS, "Expected ENOSYS (%d), got %s (%d)", ENOSYS,
1753 strerror(errno), errno);
1754 #endif /* PR_USE_XATTR */
1755
1756 pr_fsio_close(fh);
1757 (void) unlink(fsio_test_path);
1758 }
1759 END_TEST
1760
START_TEST(fsio_sys_removexattr_test)1761 START_TEST (fsio_sys_removexattr_test) {
1762 int res;
1763 const char *path, *name;
1764 unsigned long fsio_opts;
1765
1766 res = pr_fsio_removexattr(NULL, NULL, NULL);
1767 fail_unless(res < 0, "Failed to handle null arguments");
1768 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1769 strerror(errno), errno);
1770
1771 res = pr_fsio_removexattr(p, NULL, NULL);
1772 fail_unless(res < 0, "Failed to handle null path");
1773 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1774 strerror(errno), errno);
1775
1776 path = fsio_test_path;
1777 res = pr_fsio_removexattr(p, path, NULL);
1778 fail_unless(res < 0, "Failed to handle null attribute name");
1779 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1780 strerror(errno), errno);
1781
1782 name = "foo.bar";
1783
1784 fsio_opts = pr_fsio_set_options(PR_FSIO_OPT_IGNORE_XATTR);
1785 res = pr_fsio_removexattr(p, path, name);
1786 fail_unless(res < 0, "Failed to handle disabled xattr");
1787 fail_unless(errno == ENOSYS, "Expected ENOSYS (%d), got %s (%d)", ENOSYS,
1788 strerror(errno), errno);
1789
1790 pr_fsio_set_options(fsio_opts);
1791 res = pr_fsio_removexattr(p, path, name);
1792 #ifdef PR_USE_XATTR
1793 fail_unless(res < 0, "Failed to handle nonexistent attribute '%s'", name);
1794 fail_unless(errno == ENOENT || errno == ENOATTR || errno == ENOTSUP,
1795 "Expected ENOENT (%d), ENOATTR (%d) or ENOTSUP (%d), got %s (%d)",
1796 ENOENT, ENOATTR, ENOTSUP, strerror(errno), errno);
1797
1798 #else
1799 fail_unless(res < 0, "Failed to handle --disable-xattr");
1800 fail_unless(errno == ENOSYS, "Expected ENOSYS (%d), got %s (%d)", ENOSYS,
1801 strerror(errno), errno);
1802 #endif /* PR_USE_XATTR */
1803 }
1804 END_TEST
1805
START_TEST(fsio_sys_lremovexattr_test)1806 START_TEST (fsio_sys_lremovexattr_test) {
1807 int res;
1808 const char *path, *name;
1809 unsigned long fsio_opts;
1810
1811 res = pr_fsio_lremovexattr(NULL, NULL, NULL);
1812 fail_unless(res < 0, "Failed to handle null arguments");
1813 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1814 strerror(errno), errno);
1815
1816 res = pr_fsio_lremovexattr(p, NULL, NULL);
1817 fail_unless(res < 0, "Failed to handle null path");
1818 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1819 strerror(errno), errno);
1820
1821 path = fsio_test_path;
1822 res = pr_fsio_lremovexattr(p, path, NULL);
1823 fail_unless(res < 0, "Failed to handle null attribute name");
1824 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1825 strerror(errno), errno);
1826
1827 name = "foo.bar";
1828
1829 fsio_opts = pr_fsio_set_options(PR_FSIO_OPT_IGNORE_XATTR);
1830 res = pr_fsio_lremovexattr(p, path, name);
1831 fail_unless(res < 0, "Failed to handle disabled xattr");
1832 fail_unless(errno == ENOSYS, "Expected ENOSYS (%d), got %s (%d)", ENOSYS,
1833 strerror(errno), errno);
1834
1835 pr_fsio_set_options(fsio_opts);
1836 res = pr_fsio_lremovexattr(p, path, name);
1837 #ifdef PR_USE_XATTR
1838 fail_unless(res < 0, "Failed to handle nonexistent attribute '%s'", name);
1839 fail_unless(errno == ENOENT || errno == ENOATTR || errno == ENOTSUP,
1840 "Expected ENOENT (%d), ENOATTR (%d) or ENOTSUP (%d), got %s (%d)",
1841 ENOENT, ENOATTR, ENOTSUP, strerror(errno), errno);
1842
1843 #else
1844 fail_unless(res < 0, "Failed to handle --disable-xattr");
1845 fail_unless(errno == ENOSYS, "Expected ENOSYS (%d), got %s (%d)", ENOSYS,
1846 strerror(errno), errno);
1847 #endif /* PR_USE_XATTR */
1848 }
1849 END_TEST
1850
START_TEST(fsio_sys_fremovexattr_test)1851 START_TEST (fsio_sys_fremovexattr_test) {
1852 int res;
1853 pr_fh_t *fh;
1854 const char *name;
1855 unsigned long fsio_opts;
1856
1857 res = pr_fsio_fremovexattr(NULL, NULL, NULL);
1858 fail_unless(res < 0, "Failed to handle null arguments");
1859 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1860 strerror(errno), errno);
1861
1862 res = pr_fsio_fremovexattr(p, NULL, NULL);
1863 fail_unless(res < 0, "Failed to handle null arguments");
1864 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1865 strerror(errno), errno);
1866
1867 (void) unlink(fsio_test_path);
1868 fh = pr_fsio_open(fsio_test_path, O_CREAT|O_EXCL|O_RDWR);
1869 fail_unless(fh != NULL, "Failed to open '%s': %s", fsio_test_path,
1870 strerror(errno));
1871
1872 res = pr_fsio_fremovexattr(p, fh, NULL);
1873 fail_unless(res < 0, "Failed to handle null attribute name");
1874 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1875 strerror(errno), errno);
1876
1877 name = "foo.bar";
1878
1879 fsio_opts = pr_fsio_set_options(PR_FSIO_OPT_IGNORE_XATTR);
1880 res = pr_fsio_fremovexattr(p, fh, name);
1881 fail_unless(res < 0, "Failed to handle disabled xattr");
1882 fail_unless(errno == ENOSYS, "Expected ENOSYS (%d), got %s (%d)", ENOSYS,
1883 strerror(errno), errno);
1884
1885 pr_fsio_set_options(fsio_opts);
1886 res = pr_fsio_fremovexattr(p, fh, name);
1887 #ifdef PR_USE_XATTR
1888 fail_unless(res < 0, "Failed to handle nonexistent attribute '%s'", name);
1889 fail_unless(errno == ENOENT || errno == ENOATTR || errno == ENOTSUP,
1890 "Expected ENOENT (%d), ENOATTR (%d) or ENOTSUP (%d), got %s (%d)",
1891 ENOENT, ENOATTR, ENOTSUP, strerror(errno), errno);
1892
1893 #else
1894 fail_unless(res < 0, "Failed to handle --disable-xattr");
1895 fail_unless(errno == ENOSYS, "Expected ENOSYS (%d), got %s (%d)", ENOSYS,
1896 strerror(errno), errno);
1897 #endif /* PR_USE_XATTR */
1898
1899 pr_fsio_close(fh);
1900 (void) unlink(fsio_test_path);
1901 }
1902 END_TEST
1903
START_TEST(fsio_sys_setxattr_test)1904 START_TEST (fsio_sys_setxattr_test) {
1905 int res, flags;
1906 const char *path, *name;
1907 pr_fh_t *fh;
1908 unsigned long fsio_opts;
1909
1910 res = pr_fsio_setxattr(NULL, NULL, NULL, NULL, 0, 0);
1911 fail_unless(res < 0, "Failed to handle null arguments");
1912 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1913 strerror(errno), errno);
1914
1915 res = pr_fsio_setxattr(p, NULL, NULL, NULL, 0, 0);
1916 fail_unless(res < 0, "Failed to handle null path");
1917 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1918 strerror(errno), errno);
1919
1920 path = fsio_test_path;
1921 res = pr_fsio_setxattr(p, path, NULL, NULL, 0, 0);
1922 fail_unless(res < 0, "Failed to handle null attribute name");
1923 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1924 strerror(errno), errno);
1925
1926 name = "foo.bar";
1927 flags = PR_FSIO_XATTR_FL_CREATE;
1928
1929 fsio_opts = pr_fsio_set_options(PR_FSIO_OPT_IGNORE_XATTR);
1930 res = pr_fsio_setxattr(p, path, name, NULL, 0, flags);
1931 fail_unless(res < 0, "Failed to handle disabled xattr");
1932 fail_unless(errno == ENOSYS, "Expected ENOSYS (%d), got %s (%d)", ENOSYS,
1933 strerror(errno), errno);
1934
1935 pr_fsio_set_options(fsio_opts);
1936 res = pr_fsio_setxattr(p, path, name, NULL, 0, flags);
1937 #ifdef PR_USE_XATTR
1938 fail_unless(res < 0, "Failed to handle nonexistent file '%s'", path);
1939 fail_unless(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
1940 strerror(errno), errno);
1941
1942 (void) unlink(fsio_test_path);
1943 fh = pr_fsio_open(fsio_test_path, O_CREAT|O_EXCL|O_WRONLY);
1944 fail_unless(fh != NULL, "Failed to open '%s': %s", fsio_test_path,
1945 strerror(errno));
1946 pr_fsio_close(fh);
1947
1948 res = pr_fsio_setxattr(p, path, name, NULL, 0, flags);
1949 if (res < 0) {
1950 fail_unless(errno == ENOTSUP, "Expected ENOTSUP (%d), got %s (%d)", ENOTSUP,
1951 strerror(errno), errno);
1952 }
1953
1954 (void) unlink(fsio_test_path);
1955 #else
1956 (void) fh;
1957 fail_unless(res < 0, "Failed to handle --disable-xattr");
1958 fail_unless(errno == ENOSYS, "Expected ENOSYS (%d), got %s (%d)", ENOSYS,
1959 strerror(errno), errno);
1960 #endif /* PR_USE_XATTR */
1961 }
1962 END_TEST
1963
START_TEST(fsio_sys_lsetxattr_test)1964 START_TEST (fsio_sys_lsetxattr_test) {
1965 int res, flags;
1966 const char *path, *name;
1967 pr_fh_t *fh;
1968 unsigned long fsio_opts;
1969
1970 res = pr_fsio_lsetxattr(NULL, NULL, NULL, NULL, 0, 0);
1971 fail_unless(res < 0, "Failed to handle null arguments");
1972 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1973 strerror(errno), errno);
1974
1975 res = pr_fsio_lsetxattr(p, NULL, NULL, NULL, 0, 0);
1976 fail_unless(res < 0, "Failed to handle null path");
1977 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1978 strerror(errno), errno);
1979
1980 path = fsio_test_path;
1981 res = pr_fsio_lsetxattr(p, path, NULL, NULL, 0, 0);
1982 fail_unless(res < 0, "Failed to handle null attribute name");
1983 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1984 strerror(errno), errno);
1985
1986 name = "foo.bar";
1987 flags = PR_FSIO_XATTR_FL_CREATE;
1988
1989 fsio_opts = pr_fsio_set_options(PR_FSIO_OPT_IGNORE_XATTR);
1990 res = pr_fsio_lsetxattr(p, path, name, NULL, 0, flags);
1991 fail_unless(res < 0, "Failed to handle disabled xattr");
1992 fail_unless(errno == ENOSYS, "Expected ENOSYS (%d), got %s (%d)", ENOSYS,
1993 strerror(errno), errno);
1994
1995 pr_fsio_set_options(fsio_opts);
1996 res = pr_fsio_lsetxattr(p, path, name, NULL, 0, flags);
1997 #ifdef PR_USE_XATTR
1998 fail_unless(res < 0, "Failed to handle nonexistent file '%s'", path);
1999 fail_unless(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
2000 strerror(errno), errno);
2001
2002 (void) unlink(fsio_test_path);
2003 fh = pr_fsio_open(fsio_test_path, O_CREAT|O_EXCL|O_WRONLY);
2004 fail_unless(fh != NULL, "Failed to open '%s': %s", fsio_test_path,
2005 strerror(errno));
2006 pr_fsio_close(fh);
2007
2008 res = pr_fsio_lsetxattr(p, path, name, NULL, 0, flags);
2009 if (res < 0) {
2010 fail_unless(errno == ENOTSUP, "Expected ENOTSUP (%d), got %s (%d)", ENOTSUP,
2011 strerror(errno), errno);
2012 }
2013
2014 (void) unlink(fsio_test_path);
2015 #else
2016 (void) fh;
2017 fail_unless(res < 0, "Failed to handle --disable-xattr");
2018 fail_unless(errno == ENOSYS, "Expected ENOSYS (%d), got %s (%d)", ENOSYS,
2019 strerror(errno), errno);
2020 #endif /* PR_USE_XATTR */
2021 }
2022 END_TEST
2023
START_TEST(fsio_sys_fsetxattr_test)2024 START_TEST (fsio_sys_fsetxattr_test) {
2025 int res, flags;
2026 pr_fh_t *fh;
2027 const char *name;
2028 unsigned long fsio_opts;
2029
2030 res = pr_fsio_fsetxattr(NULL, NULL, NULL, NULL, 0, 0);
2031 fail_unless(res < 0, "Failed to handle null arguments");
2032 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2033 strerror(errno), errno);
2034
2035 res = pr_fsio_fsetxattr(p, NULL, NULL, NULL, 0, 0);
2036 fail_unless(res < 0, "Failed to handle null file handle");
2037 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2038 strerror(errno), errno);
2039
2040 (void) unlink(fsio_test_path);
2041 fh = pr_fsio_open(fsio_test_path, O_CREAT|O_EXCL|O_RDWR);
2042 fail_unless(fh != NULL, "Failed to open '%s': %s", fsio_test_path,
2043 strerror(errno));
2044
2045 res = pr_fsio_fsetxattr(p, fh, NULL, NULL, 0, 0);
2046 fail_unless(res < 0, "Failed to handle null attribute name");
2047 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2048 strerror(errno), errno);
2049
2050 name = "foo.bar";
2051 flags = PR_FSIO_XATTR_FL_CREATE;
2052
2053 fsio_opts = pr_fsio_set_options(PR_FSIO_OPT_IGNORE_XATTR);
2054 res = pr_fsio_fsetxattr(p, fh, name, NULL, 0, flags);
2055 fail_unless(res < 0, "Failed to handle disabled xattr");
2056 fail_unless(errno == ENOSYS, "Expected ENOSYS (%d), got %s (%d)", ENOSYS,
2057 strerror(errno), errno);
2058
2059 pr_fsio_set_options(fsio_opts);
2060 res = pr_fsio_fsetxattr(p, fh, name, NULL, 0, flags);
2061 #ifdef PR_USE_XATTR
2062 if (res < 0) {
2063 fail_unless(errno == ENOTSUP, "Expected ENOTSUP (%d), got %s (%d)", ENOTSUP,
2064 strerror(errno), errno);
2065 }
2066
2067 #else
2068 fail_unless(res < 0, "Failed to handle --disable-xattr");
2069 fail_unless(errno == ENOSYS, "Expected ENOSYS (%d), got %s (%d)", ENOSYS,
2070 strerror(errno), errno);
2071 #endif /* PR_USE_XATTR */
2072
2073 pr_fsio_close(fh);
2074 (void) unlink(fsio_test_path);
2075 }
2076 END_TEST
2077
START_TEST(fsio_sys_mkdir_test)2078 START_TEST (fsio_sys_mkdir_test) {
2079 int res;
2080 mode_t mode = 0755;
2081
2082 res = pr_fsio_mkdir(NULL, mode);
2083 fail_unless(res < 0, "Failed to handle null arguments");
2084 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2085 strerror(errno), errno);
2086
2087 res = pr_fsio_mkdir(fsio_testdir_path, mode);
2088 fail_unless(res == 0, "Failed to create '%s': %s", fsio_testdir_path,
2089 strerror(errno));
2090
2091 (void) pr_fsio_rmdir(fsio_testdir_path);
2092 }
2093 END_TEST
2094
START_TEST(fsio_sys_mkdir_chroot_guard_test)2095 START_TEST (fsio_sys_mkdir_chroot_guard_test) {
2096 int res;
2097 mode_t mode = 0755;
2098
2099 res = pr_fsio_guard_chroot(TRUE);
2100 fail_unless(res == FALSE, "Expected FALSE (%d), got %d", FALSE, res);
2101
2102 res = pr_fsio_mkdir("/etc/foo.bar.baz.d", mode);
2103 fail_unless(res < 0, "Created /etc/foo.bar.baz.d unexpectedly");
2104 fail_unless(errno == EACCES, "Expected EACCES (%d), got %s %d", EACCES,
2105 strerror(errno), errno);
2106
2107 (void) pr_fsio_guard_chroot(FALSE);
2108
2109 res = pr_fsio_mkdir("/lib/foo/bar/baz.d", mode);
2110 fail_unless(res < 0, "Created /lib/foo/bar/baz.d unexpectedly");
2111 fail_unless(errno == ENOENT, "Expected ENOENT (%d), got %s %d", ENOENT,
2112 strerror(errno), errno);
2113 }
2114 END_TEST
2115
START_TEST(fsio_sys_rmdir_test)2116 START_TEST (fsio_sys_rmdir_test) {
2117 int res;
2118 mode_t mode = 0755;
2119
2120 res = pr_fsio_rmdir(NULL);
2121 fail_unless(res < 0, "Failed to handle null arguments");
2122 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2123 strerror(errno), errno);
2124
2125 res = pr_fsio_rmdir(fsio_testdir_path);
2126 fail_unless(res < 0, "Failed to handle null arguments");
2127 fail_unless(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
2128 strerror(errno), errno);
2129
2130 res = pr_fsio_mkdir(fsio_testdir_path, mode);
2131 fail_unless(res == 0, "Failed to create '%s': %s", fsio_testdir_path,
2132 strerror(errno));
2133
2134 res = pr_fsio_rmdir(fsio_testdir_path);
2135 fail_unless(res == 0, "Failed to remove '%s': %s", fsio_testdir_path,
2136 strerror(errno));
2137 }
2138 END_TEST
2139
START_TEST(fsio_sys_rmdir_chroot_guard_test)2140 START_TEST (fsio_sys_rmdir_chroot_guard_test) {
2141 int res;
2142
2143 res = pr_fsio_guard_chroot(TRUE);
2144 fail_unless(res == FALSE, "Expected FALSE (%d), got %d", FALSE, res);
2145
2146 res = pr_fsio_rmdir("/etc/foo.bar.baz.d");
2147 fail_unless(res < 0, "Removed /etc/foo.bar.baz.d unexpectedly");
2148 fail_unless(errno == EACCES, "Expected EACCES (%d), got %s %d", EACCES,
2149 strerror(errno), errno);
2150
2151 (void) pr_fsio_guard_chroot(FALSE);
2152
2153 res = pr_fsio_rmdir("/lib/foo/bar/baz.d");
2154 fail_unless(res < 0, "Removed /lib/etc/foo.bar.baz.d unexpectedly");
2155 fail_unless(errno == ENOENT, "Expected ENOENT (%d), got %s %d", ENOENT,
2156 strerror(errno), errno);
2157 }
2158 END_TEST
2159
START_TEST(fsio_sys_chdir_test)2160 START_TEST (fsio_sys_chdir_test) {
2161 int res;
2162
2163 res = pr_fsio_chdir(NULL, FALSE);
2164 fail_unless(res < 0, "Failed to handle null arguments");
2165 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2166 strerror(errno), errno);
2167
2168 res = pr_fsio_chdir("/etc/hosts", FALSE);
2169 fail_unless(res < 0, "Failed to handle file argument");
2170 fail_unless(errno == EINVAL || errno == ENOTDIR,
2171 "Expected EINVAL (%d) or ENOTDIR (%d), got %s (%d)", EINVAL, ENOTDIR,
2172 strerror(errno), errno);
2173
2174 res = pr_fsio_chdir("/tmp", FALSE);
2175 fail_unless(res == 0, "Failed to chdir to '%s': %s", fsio_cwd,
2176 strerror(errno));
2177
2178 res = pr_fsio_chdir(fsio_cwd, FALSE);
2179 fail_unless(res == 0, "Failed to chdir to '%s': %s", fsio_cwd,
2180 strerror(errno));
2181 }
2182 END_TEST
2183
START_TEST(fsio_sys_chdir_canon_test)2184 START_TEST (fsio_sys_chdir_canon_test) {
2185 int res;
2186
2187 res = pr_fsio_chdir_canon(NULL, FALSE);
2188 fail_unless(res < 0, "Failed to handle null arguments");
2189 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2190 strerror(errno), errno);
2191
2192 res = pr_fsio_chdir_canon("/tmp", FALSE);
2193 fail_unless(res == 0, "Failed to chdir to '%s': %s", fsio_cwd,
2194 strerror(errno));
2195
2196 res = pr_fsio_chdir_canon(fsio_cwd, FALSE);
2197 fail_unless(res == 0, "Failed to chdir to '%s': %s", fsio_cwd,
2198 strerror(errno));
2199 }
2200 END_TEST
2201
START_TEST(fsio_sys_chroot_test)2202 START_TEST (fsio_sys_chroot_test) {
2203 int res;
2204
2205 res = pr_fsio_chroot(NULL);
2206 fail_unless(res < 0, "Failed to handle null arguments");
2207 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2208 strerror(errno), errno);
2209
2210 if (getuid() != 0) {
2211 res = pr_fsio_chroot("/tmp");
2212 fail_unless(res < 0, "Failed to chroot without root privs");
2213 fail_unless(errno == EPERM, "Expected EPERM (%d), got %s (%d)", EPERM,
2214 strerror(errno), errno);
2215 }
2216 }
2217 END_TEST
2218
START_TEST(fsio_sys_opendir_test)2219 START_TEST (fsio_sys_opendir_test) {
2220 void *res = NULL, *res2 = NULL;
2221 const char *path;
2222
2223 mark_point();
2224 res = pr_fsio_opendir(NULL);
2225 fail_unless(res == NULL, "Failed to handle null arguments");
2226 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2227 strerror(errno), errno);
2228
2229 mark_point();
2230 path = "/etc/hosts";
2231 res = pr_fsio_opendir(path);
2232 fail_unless(res == NULL, "Failed to handle file argument");
2233 fail_unless(errno == ENOTDIR, "Expected ENOTDIR (%d), got %s (%d)", ENOTDIR,
2234 strerror(errno), errno);
2235
2236 mark_point();
2237 path = "/tmp/";
2238 res = pr_fsio_opendir(path);
2239 fail_unless(res != NULL, "Failed to open '%s': %s", path, strerror(errno));
2240
2241 mark_point();
2242 path = "/usr/";
2243 res2 = pr_fsio_opendir(path);
2244 fail_unless(res != NULL, "Failed to open '%s': %s", path, strerror(errno));
2245
2246 (void) pr_fsio_closedir(res);
2247 (void) pr_fsio_closedir(res2);
2248 }
2249 END_TEST
2250
START_TEST(fsio_sys_readdir_test)2251 START_TEST (fsio_sys_readdir_test) {
2252 void *dirh;
2253 struct dirent *dent;
2254
2255 dent = pr_fsio_readdir(NULL);
2256 fail_unless(dent == NULL, "Failed to handle null arguments");
2257 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2258 strerror(errno), errno);
2259
2260 dent = pr_fsio_readdir("/etc/hosts");
2261 fail_unless(dent == NULL, "Failed to handle file argument");
2262 fail_unless(errno == ENOTDIR, "Expected ENOTDIR (%d), got %s (%d)", ENOTDIR,
2263 strerror(errno), errno);
2264
2265 mark_point();
2266 dirh = pr_fsio_opendir("/tmp/");
2267 fail_unless(dirh != NULL, "Failed to open '/tmp/': %s", strerror(errno));
2268
2269 dent = pr_fsio_readdir(dirh);
2270 fail_unless(dent != NULL, "Failed to read directory entry: %s",
2271 strerror(errno));
2272
2273 (void) pr_fsio_closedir(dirh);
2274 }
2275 END_TEST
2276
START_TEST(fsio_sys_closedir_test)2277 START_TEST (fsio_sys_closedir_test) {
2278 void *dirh;
2279 int res;
2280
2281 res = pr_fsio_closedir(NULL);
2282 fail_unless(res < 0, "Failed to handle null arguments");
2283 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
2284 strerror(errno), errno);
2285
2286 dirh = pr_fsio_opendir("/tmp/");
2287 fail_unless(dirh != NULL, "Failed to open '/tmp/': %s", strerror(errno));
2288
2289 res = pr_fsio_closedir(dirh);
2290 fail_unless(res == 0, "Failed to close '/tmp/': %s", strerror(errno));
2291
2292 /* Closing an already-closed directory descriptor should fail. */
2293 res = pr_fsio_closedir(dirh);
2294 fail_unless(res < 0, "Failed to handle already-closed directory handle");
2295 fail_unless(errno == ENOTDIR, "Expected ENOTDIR (%d), got %s (%d)", ENOTDIR,
2296 strerror(errno), errno);
2297 }
2298 END_TEST
2299
test_chmod_explainer(pool * err_pool,int xerrno,const char * path,mode_t mode,const char ** args)2300 static const char *test_chmod_explainer(pool *err_pool, int xerrno,
2301 const char *path, mode_t mode, const char **args) {
2302 *args = pstrdup(err_pool, "fake args");
2303 return pstrdup(err_pool, "test mode is not real");
2304 }
2305
START_TEST(fsio_sys_chmod_with_error_test)2306 START_TEST (fsio_sys_chmod_with_error_test) {
2307 int res;
2308 pr_error_t *err = NULL;
2309 const char *errstr, *expected;
2310 module m;
2311 pr_error_explainer_t *explainer;
2312
2313 mark_point();
2314 res = pr_fsio_chmod_with_error(NULL, fsio_test_path, 0755, NULL);
2315 fail_unless(res < 0, "Failed to handle non-existent file '%s'",
2316 fsio_test_path);
2317 fail_unless(errno == ENOENT, "Expected ENOENT (%d), %s (%d)", ENOENT,
2318 strerror(errno), errno);
2319
2320 mark_point();
2321 res = pr_fsio_chmod_with_error(p, fsio_test_path, 0755, &err);
2322 fail_unless(res < 0, "Failed to handle non-existent file '%s'",
2323 fsio_test_path);
2324 fail_unless(errno == ENOENT, "Expected ENOENT (%d), %s (%d)", ENOENT,
2325 strerror(errno), errno);
2326 fail_unless(err == NULL, "Unexpectedly populated error");
2327
2328 memset(&m, 0, sizeof(m));
2329 m.name = "error";
2330
2331 explainer = pr_error_register_explainer(p, &m, "error");
2332 explainer->explain_chmod = test_chmod_explainer;
2333
2334 mark_point();
2335 res = pr_fsio_chmod_with_error(p, fsio_test_path, 0755, &err);
2336 fail_unless(res < 0, "Failed to handle non-existent file '%s'",
2337 fsio_test_path);
2338 fail_unless(errno == ENOENT, "Expected ENOENT (%d), %s (%d)", ENOENT,
2339 strerror(errno), errno);
2340 fail_unless(err != NULL, "Failed to populate error");
2341
2342 expected = pstrcat(p,
2343 "chmod() failed with \"No such file or directory [ENOENT (",
2344 get_errnum(p, ENOENT), ")]\"", NULL);
2345 errstr = pr_error_strerror(err, PR_ERROR_FORMAT_USE_MINIMAL);
2346 fail_unless(strcmp(errstr, expected) == 0, "Expected '%s', got '%s'",
2347 expected, errstr);
2348
2349 (void) pr_error_unregister_explainer(p, &m, NULL);
2350 pr_error_destroy(err);
2351 }
2352 END_TEST
2353
test_chown_explainer(pool * err_pool,int xerrno,const char * path,uid_t uid,gid_t gid,const char ** args)2354 static const char *test_chown_explainer(pool *err_pool, int xerrno,
2355 const char *path, uid_t uid, gid_t gid, const char **args) {
2356 *args = pstrdup(err_pool, "fake args");
2357 return pstrdup(err_pool, "test mode is not real");
2358 }
2359
START_TEST(fsio_sys_chown_with_error_test)2360 START_TEST (fsio_sys_chown_with_error_test) {
2361 int res;
2362 pr_error_t *err = NULL;
2363 const char *errstr, *expected;
2364 module m;
2365 pr_error_explainer_t *explainer;
2366
2367 mark_point();
2368 res = pr_fsio_chown_with_error(NULL, fsio_test_path, 1, 1, NULL);
2369 fail_unless(res < 0, "Failed to handle non-existent file '%s'",
2370 fsio_test_path);
2371 fail_unless(errno == ENOENT, "Expected ENOENT (%d), %s (%d)", ENOENT,
2372 strerror(errno), errno);
2373
2374 mark_point();
2375 res = pr_fsio_chown_with_error(p, fsio_test_path, 1, 1, &err);
2376 fail_unless(res < 0, "Failed to handle non-existent file '%s'",
2377 fsio_test_path);
2378 fail_unless(errno == ENOENT, "Expected ENOENT (%d), %s (%d)", ENOENT,
2379 strerror(errno), errno);
2380 fail_unless(err == NULL, "Unexpectedly populated error");
2381
2382 memset(&m, 0, sizeof(m));
2383 m.name = "error";
2384
2385 explainer = pr_error_register_explainer(p, &m, "error");
2386 explainer->explain_chown = test_chown_explainer;
2387
2388 mark_point();
2389 res = pr_fsio_chown_with_error(p, fsio_test_path, 1, 1, &err);
2390 fail_unless(res < 0, "Failed to handle non-existent file '%s'",
2391 fsio_test_path);
2392 fail_unless(errno == ENOENT, "Expected ENOENT (%d), %s (%d)", ENOENT,
2393 strerror(errno), errno);
2394 fail_unless(err != NULL, "Failed to populate error");
2395
2396 expected = pstrcat(p,
2397 "chown() failed with \"No such file or directory [ENOENT (",
2398 get_errnum(p, ENOENT), ")]\"", NULL);
2399 errstr = pr_error_strerror(err, PR_ERROR_FORMAT_USE_MINIMAL);
2400 fail_unless(strcmp(errstr, expected) == 0, "Expected '%s', got '%s'",
2401 expected, errstr);
2402
2403 (void) pr_error_unregister_explainer(p, &m, NULL);
2404 pr_error_destroy(err);
2405 }
2406 END_TEST
2407
test_chroot_explainer(pool * err_pool,int xerrno,const char * path,const char ** args)2408 static const char *test_chroot_explainer(pool *err_pool, int xerrno,
2409 const char *path, const char **args) {
2410 *args = pstrdup(err_pool, "fake args");
2411 return pstrdup(err_pool, "test mode is not real");
2412 }
2413
START_TEST(fsio_sys_chroot_with_error_test)2414 START_TEST (fsio_sys_chroot_with_error_test) {
2415 int res, xerrno = 0;
2416 pr_error_t *err = NULL;
2417 const char *errstr, *expected;
2418 module m;
2419 pr_error_explainer_t *explainer;
2420
2421 mark_point();
2422 res = pr_fsio_chroot_with_error(NULL, fsio_testdir_path, NULL);
2423 fail_unless(res < 0, "Failed to handle non-existent file '%s'",
2424 fsio_testdir_path);
2425 fail_unless(errno == EPERM || errno == ENOENT,
2426 "Expected EPERM (%d) or ENOENT (%d), %s (%d)", EPERM, ENOENT,
2427 strerror(errno), errno);
2428
2429 mark_point();
2430 res = pr_fsio_chroot_with_error(p, fsio_testdir_path, &err);
2431 xerrno = errno;
2432 fail_unless(res < 0, "Failed to handle non-existent file '%s'",
2433 fsio_testdir_path);
2434 fail_unless(errno == EPERM || errno == ENOENT,
2435 "Expected EPERM (%d) or ENOENT (%d), %s (%d)", EPERM, ENOENT,
2436 strerror(errno), errno);
2437 fail_unless(err == NULL, "Unexpectedly populated error");
2438
2439 memset(&m, 0, sizeof(m));
2440 m.name = "error";
2441
2442 explainer = pr_error_register_explainer(p, &m, "error");
2443 explainer->explain_chroot = test_chroot_explainer;
2444
2445 mark_point();
2446 res = pr_fsio_chroot_with_error(p, fsio_testdir_path, &err);
2447 xerrno = errno;
2448 fail_unless(res < 0, "Failed to handle non-existent file '%s'",
2449 fsio_testdir_path);
2450 fail_unless(errno == EPERM || errno == ENOENT,
2451 "Expected EPERM (%d) or ENOENT (%d), %s (%d)", EPERM, ENOENT,
2452 strerror(errno), errno);
2453 fail_unless(err != NULL, "Failed to populate error");
2454
2455 expected = pstrcat(p,
2456 "chroot() failed with \"", strerror(xerrno), " [",
2457 xerrno == ENOENT ? "ENOENT" : "EPERM", " (",
2458 get_errnum(p, xerrno), ")]\"", NULL);
2459 errstr = pr_error_strerror(err, PR_ERROR_FORMAT_USE_MINIMAL);
2460 fail_unless(strcmp(errstr, expected) == 0, "Expected '%s', got '%s'",
2461 expected, errstr);
2462
2463 (void) pr_error_unregister_explainer(p, &m, NULL);
2464 pr_error_destroy(err);
2465 }
2466 END_TEST
2467
test_close_explainer(pool * err_pool,int xerrno,int fd,const char ** args)2468 static const char *test_close_explainer(pool *err_pool, int xerrno, int fd,
2469 const char **args) {
2470 *args = pstrdup(err_pool, "fake args");
2471 return pstrdup(err_pool, "test mode is not real");
2472 }
2473
START_TEST(fsio_sys_close_with_error_test)2474 START_TEST (fsio_sys_close_with_error_test) {
2475 int res;
2476 pr_error_t *err = NULL;
2477 const char *errstr, *expected;
2478 module m;
2479 pr_error_explainer_t *explainer;
2480
2481 mark_point();
2482 res = pr_fsio_close_with_error(NULL, NULL, NULL);
2483 fail_unless(res < 0, "Failed to handle null fh");
2484 fail_unless(errno == EINVAL, "Expected EINVAL (%d), %s (%d)", EINVAL,
2485 strerror(errno), errno);
2486
2487 mark_point();
2488 res = pr_fsio_close_with_error(p, NULL, &err);
2489 fail_unless(res < 0, "Failed to handle null fh");
2490 fail_unless(errno == EINVAL, "Expected EINVAL (%d), %s (%d)", EINVAL,
2491 strerror(errno), errno);
2492 fail_unless(err == NULL, "Unexpectedly populated error");
2493
2494 memset(&m, 0, sizeof(m));
2495 m.name = "error";
2496
2497 explainer = pr_error_register_explainer(p, &m, "error");
2498 explainer->explain_close = test_close_explainer;
2499
2500 mark_point();
2501 res = pr_fsio_close_with_error(p, NULL, &err);
2502 fail_unless(res < 0, "Failed to handle null fh");
2503 fail_unless(errno == EINVAL, "Expected EINVAL (%d), %s (%d)", EINVAL,
2504 strerror(errno), errno);
2505 fail_unless(err != NULL, "Failed to populate error");
2506
2507 expected = pstrcat(p,
2508 "close() failed with \"Invalid argument [EINVAL (",
2509 get_errnum(p, EINVAL), ")]\"", NULL);
2510 errstr = pr_error_strerror(err, PR_ERROR_FORMAT_USE_MINIMAL);
2511 fail_unless(strcmp(errstr, expected) == 0, "Expected '%s', got '%s'",
2512 expected, errstr);
2513
2514 (void) pr_error_unregister_explainer(p, &m, NULL);
2515 pr_error_destroy(err);
2516 }
2517 END_TEST
2518
test_fchmod_explainer(pool * err_pool,int xerrno,int fd,mode_t mode,const char ** args)2519 static const char *test_fchmod_explainer(pool *err_pool, int xerrno, int fd,
2520 mode_t mode, const char **args) {
2521 *args = pstrdup(err_pool, "fake args");
2522 return pstrdup(err_pool, "test mode is not real");
2523 }
2524
START_TEST(fsio_sys_fchmod_with_error_test)2525 START_TEST (fsio_sys_fchmod_with_error_test) {
2526 int res;
2527 pr_error_t *err = NULL;
2528 const char *errstr, *expected;
2529 module m;
2530 pr_error_explainer_t *explainer;
2531
2532 mark_point();
2533 res = pr_fsio_fchmod_with_error(NULL, NULL, 0755, NULL);
2534 fail_unless(res < 0, "Failed to handle null fh");
2535 fail_unless(errno == EINVAL, "Expected EINVAL (%d), %s (%d)", EINVAL,
2536 strerror(errno), errno);
2537
2538 mark_point();
2539 res = pr_fsio_fchmod_with_error(p, NULL, 0755, &err);
2540 fail_unless(res < 0, "Failed to handle null fh");
2541 fail_unless(errno == EINVAL, "Expected EINVAL (%d), %s (%d)", EINVAL,
2542 strerror(errno), errno);
2543 fail_unless(err == NULL, "Unexpectedly populated error");
2544
2545 memset(&m, 0, sizeof(m));
2546 m.name = "error";
2547
2548 explainer = pr_error_register_explainer(p, &m, "error");
2549 explainer->explain_fchmod = test_fchmod_explainer;
2550
2551 mark_point();
2552 res = pr_fsio_fchmod_with_error(p, NULL, 0755, &err);
2553 fail_unless(res < 0, "Failed to handle null fh");
2554 fail_unless(errno == EINVAL, "Expected EINVAL (%d), %s (%d)", EINVAL,
2555 strerror(errno), errno);
2556 fail_unless(err != NULL, "Failed to populate error");
2557
2558 expected = pstrcat(p,
2559 "fchmod() failed with \"Invalid argument [EINVAL (",
2560 get_errnum(p, EINVAL), ")]\"", NULL);
2561 errstr = pr_error_strerror(err, PR_ERROR_FORMAT_USE_MINIMAL);
2562 fail_unless(strcmp(errstr, expected) == 0, "Expected '%s', got '%s'",
2563 expected, errstr);
2564
2565 (void) pr_error_unregister_explainer(p, &m, NULL);
2566 pr_error_destroy(err);
2567 }
2568 END_TEST
2569
test_fchown_explainer(pool * err_pool,int xerrno,int fd,uid_t uid,gid_t gid,const char ** args)2570 static const char *test_fchown_explainer(pool *err_pool, int xerrno, int fd,
2571 uid_t uid, gid_t gid, const char **args) {
2572 *args = pstrdup(err_pool, "fake args");
2573 return pstrdup(err_pool, "test mode is not real");
2574 }
2575
START_TEST(fsio_sys_fchown_with_error_test)2576 START_TEST (fsio_sys_fchown_with_error_test) {
2577 int res;
2578 pr_error_t *err = NULL;
2579 const char *errstr, *expected;
2580 module m;
2581 pr_error_explainer_t *explainer;
2582
2583 mark_point();
2584 res = pr_fsio_fchown_with_error(NULL, NULL, 1, 1, NULL);
2585 fail_unless(res < 0, "Failed to handle null fh");
2586 fail_unless(errno == EINVAL, "Expected EINVAL (%d), %s (%d)", EINVAL,
2587 strerror(errno), errno);
2588
2589 mark_point();
2590 res = pr_fsio_fchown_with_error(p, NULL, 1, 1, &err);
2591 fail_unless(res < 0, "Failed to handle null fh");
2592 fail_unless(errno == EINVAL, "Expected EINVAL (%d), %s (%d)", EINVAL,
2593 strerror(errno), errno);
2594 fail_unless(err == NULL, "Unexpectedly populated error");
2595
2596 memset(&m, 0, sizeof(m));
2597 m.name = "error";
2598
2599 explainer = pr_error_register_explainer(p, &m, "error");
2600 explainer->explain_fchown = test_fchown_explainer;
2601
2602 mark_point();
2603 res = pr_fsio_fchown_with_error(p, NULL, 1, 1, &err);
2604 fail_unless(res < 0, "Failed to handle null fh");
2605 fail_unless(errno == EINVAL, "Expected EINVAL (%d), %s (%d)", EINVAL,
2606 strerror(errno), errno);
2607 fail_unless(err != NULL, "Failed to populate error");
2608
2609 expected = pstrcat(p,
2610 "fchown() failed with \"Invalid argument [EINVAL (",
2611 get_errnum(p, EINVAL), ")]\"", NULL);
2612 errstr = pr_error_strerror(err, PR_ERROR_FORMAT_USE_MINIMAL);
2613 fail_unless(strcmp(errstr, expected) == 0, "Expected '%s', got '%s'",
2614 expected, errstr);
2615
2616 (void) pr_error_unregister_explainer(p, &m, NULL);
2617 pr_error_destroy(err);
2618 }
2619 END_TEST
2620
test_lchown_explainer(pool * err_pool,int xerrno,const char * path,uid_t uid,gid_t gid,const char ** args)2621 static const char *test_lchown_explainer(pool *err_pool, int xerrno,
2622 const char *path, uid_t uid, gid_t gid, const char **args) {
2623 *args = pstrdup(err_pool, "fake args");
2624 return pstrdup(err_pool, "test mode is not real");
2625 }
2626
START_TEST(fsio_sys_lchown_with_error_test)2627 START_TEST (fsio_sys_lchown_with_error_test) {
2628 int res;
2629 pr_error_t *err = NULL;
2630 const char *errstr, *expected;
2631 module m;
2632 pr_error_explainer_t *explainer;
2633
2634 mark_point();
2635 res = pr_fsio_lchown_with_error(NULL, fsio_test_path, 1, 1, NULL);
2636 fail_unless(res < 0, "Failed to handle non-existent file '%s'",
2637 fsio_test_path);
2638 fail_unless(errno == ENOENT, "Expected ENOENT (%d), %s (%d)", ENOENT,
2639 strerror(errno), errno);
2640
2641 mark_point();
2642 res = pr_fsio_lchown_with_error(p, fsio_test_path, 1, 1, &err);
2643 fail_unless(res < 0, "Failed to handle non-existent file '%s'",
2644 fsio_test_path);
2645 fail_unless(errno == ENOENT, "Expected ENOENT (%d), %s (%d)", ENOENT,
2646 strerror(errno), errno);
2647 fail_unless(err == NULL, "Unexpectedly populated error");
2648
2649 memset(&m, 0, sizeof(m));
2650 m.name = "error";
2651
2652 explainer = pr_error_register_explainer(p, &m, "error");
2653 explainer->explain_lchown = test_lchown_explainer;
2654
2655 mark_point();
2656 res = pr_fsio_lchown_with_error(p, fsio_test_path, 1, 1, &err);
2657 fail_unless(res < 0, "Failed to handle non-existent file '%s'",
2658 fsio_test_path);
2659 fail_unless(errno == ENOENT, "Expected ENOENT (%d), %s (%d)", ENOENT,
2660 strerror(errno), errno);
2661 fail_unless(err != NULL, "Failed to populate error");
2662
2663 expected = pstrcat(p,
2664 "lchown() failed with \"No such file or directory [ENOENT (",
2665 get_errnum(p, ENOENT), ")]\"", NULL);
2666 errstr = pr_error_strerror(err, PR_ERROR_FORMAT_USE_MINIMAL);
2667 fail_unless(strcmp(errstr, expected) == 0, "Expected '%s', got '%s'",
2668 expected, errstr);
2669
2670 (void) pr_error_unregister_explainer(p, &m, NULL);
2671 pr_error_destroy(err);
2672 }
2673 END_TEST
2674
test_lstat_explainer(pool * err_pool,int xerrno,const char * path,struct stat * st,const char ** args)2675 static const char *test_lstat_explainer(pool *err_pool, int xerrno,
2676 const char *path, struct stat *st, const char **args) {
2677 *args = pstrdup(err_pool, "fake args");
2678 return pstrdup(err_pool, "test mode is not real");
2679 }
2680
START_TEST(fsio_sys_lstat_with_error_test)2681 START_TEST (fsio_sys_lstat_with_error_test) {
2682 int res;
2683 struct stat st;
2684 pr_error_t *err = NULL;
2685 const char *errstr, *expected;
2686 module m;
2687 pr_error_explainer_t *explainer;
2688
2689 mark_point();
2690 res = pr_fsio_lstat_with_error(NULL, fsio_test_path, &st, NULL);
2691 fail_unless(res < 0, "Failed to handle non-existent file '%s'",
2692 fsio_test_path);
2693 fail_unless(errno == ENOENT, "Expected ENOENT (%d), %s (%d)", ENOENT,
2694 strerror(errno), errno);
2695
2696 mark_point();
2697 res = pr_fsio_lstat_with_error(p, fsio_test_path, &st, &err);
2698 fail_unless(res < 0, "Failed to handle non-existent file '%s'",
2699 fsio_test_path);
2700 fail_unless(errno == ENOENT, "Expected ENOENT (%d), %s (%d)", ENOENT,
2701 strerror(errno), errno);
2702 fail_unless(err == NULL, "Unexpectedly populated error");
2703
2704 memset(&m, 0, sizeof(m));
2705 m.name = "error";
2706
2707 explainer = pr_error_register_explainer(p, &m, "error");
2708 explainer->explain_lstat = test_lstat_explainer;
2709
2710 mark_point();
2711 res = pr_fsio_lstat_with_error(p, fsio_test_path, &st, &err);
2712 fail_unless(res < 0, "Failed to handle non-existent file '%s'",
2713 fsio_test_path);
2714 fail_unless(errno == ENOENT, "Expected ENOENT (%d), %s (%d)", ENOENT,
2715 strerror(errno), errno);
2716 fail_unless(err != NULL, "Failed to populate error");
2717
2718 expected = pstrcat(p,
2719 "lstat() failed with \"No such file or directory [ENOENT (",
2720 get_errnum(p, ENOENT), ")]\"", NULL);
2721 errstr = pr_error_strerror(err, PR_ERROR_FORMAT_USE_MINIMAL);
2722 fail_unless(strcmp(errstr, expected) == 0, "Expected '%s', got '%s'",
2723 expected, errstr);
2724
2725 (void) pr_error_unregister_explainer(p, &m, NULL);
2726 pr_error_destroy(err);
2727 }
2728 END_TEST
2729
test_mkdir_explainer(pool * err_pool,int xerrno,const char * path,mode_t mode,const char ** args)2730 static const char *test_mkdir_explainer(pool *err_pool, int xerrno,
2731 const char *path, mode_t mode, const char **args) {
2732 *args = pstrdup(err_pool, "fake args");
2733 return pstrdup(err_pool, "test mode is not real");
2734 }
2735
START_TEST(fsio_sys_mkdir_with_error_test)2736 START_TEST (fsio_sys_mkdir_with_error_test) {
2737 int res;
2738 pr_error_t *err = NULL;
2739 const char *errstr, *expected, *path;
2740 module m;
2741 pr_error_explainer_t *explainer;
2742
2743 path = "/tmp/foo/bar/baz/quxx/quzz.d";
2744
2745 mark_point();
2746 res = pr_fsio_mkdir_with_error(NULL, path, 0755, NULL);
2747 fail_unless(res < 0, "Failed to handle non-existent file '%s'",
2748 fsio_testdir_path);
2749 fail_unless(errno == ENOENT, "Expected ENOENT (%d), %s (%d)", ENOENT,
2750 strerror(errno), errno);
2751
2752 mark_point();
2753 res = pr_fsio_mkdir_with_error(p, path, 0755, &err);
2754 fail_unless(res < 0, "Failed to handle non-existent file '%s'",
2755 fsio_testdir_path);
2756 fail_unless(errno == ENOENT, "Expected ENOENT (%d), %s (%d)", ENOENT,
2757 strerror(errno), errno);
2758 fail_unless(err == NULL, "Unexpectedly populated error");
2759
2760 memset(&m, 0, sizeof(m));
2761 m.name = "error";
2762
2763 explainer = pr_error_register_explainer(p, &m, "error");
2764 explainer->explain_mkdir = test_mkdir_explainer;
2765
2766 mark_point();
2767 res = pr_fsio_mkdir_with_error(p, path, 0755, &err);
2768 fail_unless(res < 0, "Failed to handle non-existent file '%s'",
2769 fsio_testdir_path);
2770 fail_unless(errno == ENOENT, "Expected ENOENT (%d), %s (%d)", ENOENT,
2771 strerror(errno), errno);
2772 fail_unless(err != NULL, "Failed to populate error");
2773
2774 expected = pstrcat(p,
2775 "mkdir() failed with \"No such file or directory [ENOENT (",
2776 get_errnum(p, ENOENT), ")]\"", NULL);
2777 errstr = pr_error_strerror(err, PR_ERROR_FORMAT_USE_MINIMAL);
2778 fail_unless(strcmp(errstr, expected) == 0, "Expected '%s', got '%s'",
2779 expected, errstr);
2780
2781 (void) pr_error_unregister_explainer(p, &m, NULL);
2782 pr_error_destroy(err);
2783 }
2784 END_TEST
2785
test_open_explainer(pool * err_pool,int xerrno,const char * path,int flags,mode_t mode,const char ** args)2786 static const char *test_open_explainer(pool *err_pool, int xerrno,
2787 const char *path, int flags, mode_t mode, const char **args) {
2788 *args = pstrdup(err_pool, "fake args");
2789 return pstrdup(err_pool, "test mode is not real");
2790 }
2791
START_TEST(fsio_sys_open_with_error_test)2792 START_TEST (fsio_sys_open_with_error_test) {
2793 pr_fh_t *fh;
2794 pr_error_t *err = NULL;
2795 const char *errstr, *expected;
2796 module m;
2797 pr_error_explainer_t *explainer;
2798
2799 mark_point();
2800 fh = pr_fsio_open_with_error(NULL, fsio_test_path, O_RDONLY, NULL);
2801 fail_unless(fh == NULL, "Failed to handle non-existent file '%s'",
2802 fsio_test_path);
2803 fail_unless(errno == ENOENT, "Expected ENOENT (%d), %s (%d)", ENOENT,
2804 strerror(errno), errno);
2805
2806 mark_point();
2807 fh = pr_fsio_open_with_error(p, fsio_test_path, O_RDONLY, &err);
2808 fail_unless(fh == NULL, "Failed to handle non-existent file '%s'",
2809 fsio_test_path);
2810 fail_unless(errno == ENOENT, "Expected ENOENT (%d), %s (%d)", ENOENT,
2811 strerror(errno), errno);
2812 fail_unless(err == NULL, "Unexpectedly populated error");
2813
2814 memset(&m, 0, sizeof(m));
2815 m.name = "error";
2816
2817 explainer = pr_error_register_explainer(p, &m, "error");
2818 explainer->explain_open = test_open_explainer;
2819
2820 mark_point();
2821 fh = pr_fsio_open_with_error(p, fsio_test_path, O_RDONLY, &err);
2822 fail_unless(fh == NULL, "Failed to handle non-existent file '%s'",
2823 fsio_test_path);
2824 fail_unless(errno == ENOENT, "Expected ENOENT (%d), %s (%d)", ENOENT,
2825 strerror(errno), errno);
2826 fail_unless(err != NULL, "Failed to populate error");
2827
2828 expected = pstrcat(p,
2829 "open() failed with \"No such file or directory [ENOENT (",
2830 get_errnum(p, ENOENT), ")]\"", NULL);
2831 errstr = pr_error_strerror(err, PR_ERROR_FORMAT_USE_MINIMAL);
2832 fail_unless(strcmp(errstr, expected) == 0, "Expected '%s', got '%s'",
2833 expected, errstr);
2834
2835 (void) pr_error_unregister_explainer(p, &m, NULL);
2836 pr_error_destroy(err);
2837 }
2838 END_TEST
2839
test_read_explainer(pool * err_pool,int xerrno,int fd,void * buf,size_t sz,const char ** args)2840 static const char *test_read_explainer(pool *err_pool, int xerrno, int fd,
2841 void *buf, size_t sz, const char **args) {
2842 *args = pstrdup(err_pool, "fake args");
2843 return pstrdup(err_pool, "test mode is not real");
2844 }
2845
START_TEST(fsio_sys_read_with_error_test)2846 START_TEST (fsio_sys_read_with_error_test) {
2847 int res;
2848 pr_error_t *err = NULL;
2849 const char *errstr, *expected;
2850 module m;
2851 pr_error_explainer_t *explainer;
2852
2853 mark_point();
2854 res = pr_fsio_read_with_error(NULL, NULL, NULL, 0, NULL);
2855 fail_unless(res < 0, "Failed to handle null fh");
2856 fail_unless(errno == EINVAL, "Expected EINVAL (%d), %s (%d)", EINVAL,
2857 strerror(errno), errno);
2858
2859 mark_point();
2860 res = pr_fsio_read_with_error(p, NULL, NULL, 0, &err);
2861 fail_unless(res < 0, "Failed to handle null fh");
2862 fail_unless(errno == EINVAL, "Expected EINVAL (%d), %s (%d)", EINVAL,
2863 strerror(errno), errno);
2864 fail_unless(err == NULL, "Unexpectedly populated error");
2865
2866 memset(&m, 0, sizeof(m));
2867 m.name = "error";
2868
2869 explainer = pr_error_register_explainer(p, &m, "error");
2870 explainer->explain_read = test_read_explainer;
2871
2872 mark_point();
2873 res = pr_fsio_read_with_error(p, NULL, NULL, 0, &err);
2874 fail_unless(res < 0, "Failed to handle null fh");
2875 fail_unless(errno == EINVAL, "Expected EINVAL (%d), %s (%d)", EINVAL,
2876 strerror(errno), errno);
2877 fail_unless(err != NULL, "Failed to populate error");
2878
2879 expected = pstrcat(p,
2880 "read() failed with \"Invalid argument [EINVAL (",
2881 get_errnum(p, EINVAL), ")]\"", NULL);
2882 errstr = pr_error_strerror(err, PR_ERROR_FORMAT_USE_MINIMAL);
2883 fail_unless(strcmp(errstr, expected) == 0, "Expected '%s', got '%s'",
2884 expected, errstr);
2885
2886 (void) pr_error_unregister_explainer(p, &m, NULL);
2887 pr_error_destroy(err);
2888 }
2889 END_TEST
2890
test_rename_explainer(pool * err_pool,int xerrno,const char * from,const char * to,const char ** args)2891 static const char *test_rename_explainer(pool *err_pool, int xerrno,
2892 const char *from, const char *to, const char **args) {
2893 *args = pstrdup(err_pool, "fake args");
2894 return pstrdup(err_pool, "test mode is not real");
2895 }
2896
START_TEST(fsio_sys_rename_with_error_test)2897 START_TEST (fsio_sys_rename_with_error_test) {
2898 int res;
2899 pr_error_t *err = NULL;
2900 const char *errstr, *expected;
2901 module m;
2902 pr_error_explainer_t *explainer;
2903
2904 mark_point();
2905 res = pr_fsio_rename_with_error(NULL, fsio_test_path, fsio_test2_path, NULL);
2906 fail_unless(res < 0, "Failed to handle non-existent file '%s'",
2907 fsio_test_path);
2908 fail_unless(errno == ENOENT, "Expected ENOENT (%d), %s (%d)", ENOENT,
2909 strerror(errno), errno);
2910
2911 mark_point();
2912 res = pr_fsio_rename_with_error(p, fsio_test_path, fsio_test2_path, &err);
2913 fail_unless(res < 0, "Failed to handle non-existent file '%s'",
2914 fsio_test_path);
2915 fail_unless(errno == ENOENT, "Expected ENOENT (%d), %s (%d)", ENOENT,
2916 strerror(errno), errno);
2917 fail_unless(err == NULL, "Unexpectedly populated error");
2918
2919 memset(&m, 0, sizeof(m));
2920 m.name = "error";
2921
2922 explainer = pr_error_register_explainer(p, &m, "error");
2923 explainer->explain_rename = test_rename_explainer;
2924
2925 mark_point();
2926 res = pr_fsio_rename_with_error(p, fsio_test_path, fsio_test2_path, &err);
2927 fail_unless(res < 0, "Failed to handle non-existent file '%s'",
2928 fsio_test_path);
2929 fail_unless(errno == ENOENT, "Expected ENOENT (%d), %s (%d)", ENOENT,
2930 strerror(errno), errno);
2931 fail_unless(err != NULL, "Failed to populate error");
2932
2933 expected = pstrcat(p,
2934 "rename() failed with \"No such file or directory [ENOENT (",
2935 get_errnum(p, ENOENT), ")]\"", NULL);
2936 errstr = pr_error_strerror(err, PR_ERROR_FORMAT_USE_MINIMAL);
2937 fail_unless(strcmp(errstr, expected) == 0, "Expected '%s', got '%s'",
2938 expected, errstr);
2939
2940 (void) pr_error_unregister_explainer(p, &m, NULL);
2941 pr_error_destroy(err);
2942 }
2943 END_TEST
2944
test_rmdir_explainer(pool * err_pool,int xerrno,const char * path,const char ** args)2945 static const char *test_rmdir_explainer(pool *err_pool, int xerrno,
2946 const char *path, const char **args) {
2947 *args = pstrdup(err_pool, "fake args");
2948 return pstrdup(err_pool, "test mode is not real");
2949 }
2950
START_TEST(fsio_sys_rmdir_with_error_test)2951 START_TEST (fsio_sys_rmdir_with_error_test) {
2952 int res;
2953 pr_error_t *err = NULL;
2954 const char *errstr, *expected;
2955 module m;
2956 pr_error_explainer_t *explainer;
2957
2958 mark_point();
2959 res = pr_fsio_rmdir_with_error(NULL, fsio_testdir_path, NULL);
2960 fail_unless(res < 0, "Failed to handle non-existent file '%s'",
2961 fsio_testdir_path);
2962 fail_unless(errno == ENOENT, "Expected ENOENT (%d), %s (%d)", ENOENT,
2963 strerror(errno), errno);
2964 fail_unless(err == NULL, "Unexpectedly populated error");
2965
2966 memset(&m, 0, sizeof(m));
2967 m.name = "error";
2968
2969 explainer = pr_error_register_explainer(p, &m, "error");
2970 explainer->explain_rmdir = test_rmdir_explainer;
2971
2972 mark_point();
2973 res = pr_fsio_rmdir_with_error(p, fsio_testdir_path, &err);
2974 fail_unless(res < 0, "Failed to handle non-existent file '%s'",
2975 fsio_testdir_path);
2976 fail_unless(errno == ENOENT, "Expected ENOENT (%d), %s (%d)", ENOENT,
2977 strerror(errno), errno);
2978 fail_unless(err != NULL, "Failed to populate error");
2979
2980 expected = pstrcat(p,
2981 "rmdir() failed with \"No such file or directory [ENOENT (",
2982 get_errnum(p, ENOENT), ")]\"", NULL);
2983 errstr = pr_error_strerror(err, PR_ERROR_FORMAT_USE_MINIMAL);
2984 fail_unless(strcmp(errstr, expected) == 0, "Expected '%s', got '%s'",
2985 expected, errstr);
2986
2987 (void) pr_error_unregister_explainer(p, &m, NULL);
2988 pr_error_destroy(err);
2989 }
2990 END_TEST
2991
test_stat_explainer(pool * err_pool,int xerrno,const char * path,struct stat * st,const char ** args)2992 static const char *test_stat_explainer(pool *err_pool, int xerrno,
2993 const char *path, struct stat *st, const char **args) {
2994 *args = pstrdup(err_pool, "fake args");
2995 return pstrdup(err_pool, "test mode is not real");
2996 }
2997
START_TEST(fsio_sys_stat_with_error_test)2998 START_TEST (fsio_sys_stat_with_error_test) {
2999 int res;
3000 struct stat st;
3001 pr_error_t *err = NULL;
3002 const char *errstr, *expected;
3003 module m;
3004 pr_error_explainer_t *explainer;
3005
3006 mark_point();
3007 res = pr_fsio_stat_with_error(NULL, fsio_test_path, &st, NULL);
3008 fail_unless(res < 0, "Failed to handle non-existent file '%s'",
3009 fsio_test_path);
3010 fail_unless(errno == ENOENT, "Expected ENOENT (%d), %s (%d)", ENOENT,
3011 strerror(errno), errno);
3012
3013 mark_point();
3014 res = pr_fsio_stat_with_error(p, fsio_test_path, &st, &err);
3015 fail_unless(res < 0, "Failed to handle non-existent file '%s'",
3016 fsio_test_path);
3017 fail_unless(errno == ENOENT, "Expected ENOENT (%d), %s (%d)", ENOENT,
3018 strerror(errno), errno);
3019 fail_unless(err == NULL, "Unexpectedly populated error");
3020
3021 memset(&m, 0, sizeof(m));
3022 m.name = "error";
3023
3024 explainer = pr_error_register_explainer(p, &m, "error");
3025 explainer->explain_stat = test_stat_explainer;
3026
3027 mark_point();
3028 res = pr_fsio_stat_with_error(p, fsio_test_path, &st, &err);
3029 fail_unless(res < 0, "Failed to handle non-existent file '%s'",
3030 fsio_test_path);
3031 fail_unless(errno == ENOENT, "Expected ENOENT (%d), %s (%d)", ENOENT,
3032 strerror(errno), errno);
3033 fail_unless(err != NULL, "Failed to populate error");
3034
3035 expected = pstrcat(p,
3036 "stat() failed with \"No such file or directory [ENOENT (",
3037 get_errnum(p, ENOENT), ")]\"", NULL);
3038 errstr = pr_error_strerror(err, PR_ERROR_FORMAT_USE_MINIMAL);
3039 fail_unless(strcmp(errstr, expected) == 0, "Expected '%s', got '%s'",
3040 expected, errstr);
3041
3042 (void) pr_error_unregister_explainer(p, &m, NULL);
3043 pr_error_destroy(err);
3044 }
3045 END_TEST
3046
test_unlink_explainer(pool * err_pool,int xerrno,const char * path,const char ** args)3047 static const char *test_unlink_explainer(pool *err_pool, int xerrno,
3048 const char *path, const char **args) {
3049 *args = pstrdup(err_pool, "fake args");
3050 return pstrdup(err_pool, "test mode is not real");
3051 }
3052
START_TEST(fsio_sys_unlink_with_error_test)3053 START_TEST (fsio_sys_unlink_with_error_test) {
3054 int res;
3055 pr_error_t *err = NULL;
3056 const char *errstr, *expected;
3057 module m;
3058 pr_error_explainer_t *explainer;
3059
3060 mark_point();
3061 res = pr_fsio_unlink_with_error(NULL, fsio_test_path, NULL);
3062 fail_unless(res < 0, "Failed to handle non-existent file '%s'",
3063 fsio_test_path);
3064 fail_unless(errno == ENOENT, "Expected ENOENT (%d), %s (%d)", ENOENT,
3065 strerror(errno), errno);
3066
3067 mark_point();
3068 res = pr_fsio_unlink_with_error(p, fsio_test_path, &err);
3069 fail_unless(res < 0, "Failed to handle non-existent file '%s'",
3070 fsio_test_path);
3071 fail_unless(errno == ENOENT, "Expected ENOENT (%d), %s (%d)", ENOENT,
3072 strerror(errno), errno);
3073 fail_unless(err == NULL, "Unexpectedly populated error");
3074
3075 memset(&m, 0, sizeof(m));
3076 m.name = "error";
3077
3078 explainer = pr_error_register_explainer(p, &m, "error");
3079 explainer->explain_unlink = test_unlink_explainer;
3080
3081 mark_point();
3082 res = pr_fsio_unlink_with_error(p, fsio_test_path, &err);
3083 fail_unless(res < 0, "Failed to handle non-existent file '%s'",
3084 fsio_test_path);
3085 fail_unless(errno == ENOENT, "Expected ENOENT (%d), %s (%d)", ENOENT,
3086 strerror(errno), errno);
3087 fail_unless(err != NULL, "Failed to populate error");
3088
3089 expected = pstrcat(p,
3090 "unlink() failed with \"No such file or directory [ENOENT (",
3091 get_errnum(p, ENOENT), ")]\"", NULL);
3092 errstr = pr_error_strerror(err, PR_ERROR_FORMAT_USE_MINIMAL);
3093 fail_unless(strcmp(errstr, expected) == 0, "Expected '%s', got '%s'",
3094 expected, errstr);
3095
3096 (void) pr_error_unregister_explainer(p, &m, NULL);
3097 pr_error_destroy(err);
3098 }
3099 END_TEST
3100
test_write_explainer(pool * err_pool,int xerrno,int fd,const void * buf,size_t sz,const char ** args)3101 static const char *test_write_explainer(pool *err_pool, int xerrno, int fd,
3102 const void *buf, size_t sz, const char **args) {
3103 *args = pstrdup(err_pool, "fake args");
3104 return pstrdup(err_pool, "test mode is not real");
3105 }
3106
START_TEST(fsio_sys_write_with_error_test)3107 START_TEST (fsio_sys_write_with_error_test) {
3108 int res;
3109 pr_error_t *err = NULL;
3110 const char *errstr, *expected;
3111 module m;
3112 pr_error_explainer_t *explainer;
3113
3114 mark_point();
3115 res = pr_fsio_write_with_error(NULL, NULL, NULL, 0, NULL);
3116 fail_unless(res < 0, "Failed to handle null pool");
3117 fail_unless(errno == EINVAL, "Expected EINVAL (%d), %s (%d)", EINVAL,
3118 strerror(errno), errno);
3119
3120 mark_point();
3121 res = pr_fsio_write_with_error(p, NULL, NULL, 0, &err);
3122 fail_unless(res < 0, "Failed to handle null fh");
3123 fail_unless(errno == EINVAL, "Expected EINVAL (%d), %s (%d)", EINVAL,
3124 strerror(errno), errno);
3125 fail_unless(err == NULL, "Unexpectedly populated error");
3126
3127 memset(&m, 0, sizeof(m));
3128 m.name = "error";
3129
3130 explainer = pr_error_register_explainer(p, &m, "error");
3131 explainer->explain_write = test_write_explainer;
3132
3133 mark_point();
3134 res = pr_fsio_write_with_error(p, NULL, NULL, 0, &err);
3135 fail_unless(res < 0, "Failed to handle null fh");
3136 fail_unless(errno == EINVAL, "Expected EINVAL (%d), %s (%d)", EINVAL,
3137 strerror(errno), errno);
3138 fail_unless(err != NULL, "Failed to populate error");
3139
3140 expected = pstrcat(p,
3141 "write() failed with \"Invalid argument [EINVAL (",
3142 get_errnum(p, EINVAL), ")]\"", NULL);
3143 expected = "write() failed with \"Invalid argument [EINVAL (22)]\"";
3144 errstr = pr_error_strerror(err, PR_ERROR_FORMAT_USE_MINIMAL);
3145 fail_unless(strcmp(errstr, expected) == 0, "Expected '%s', got '%s'",
3146 expected, errstr);
3147
3148 (void) pr_error_unregister_explainer(p, &m, NULL);
3149 pr_error_destroy(err);
3150 }
3151 END_TEST
3152
START_TEST(fsio_statcache_clear_cache_test)3153 START_TEST (fsio_statcache_clear_cache_test) {
3154 int expected, res;
3155 struct stat st;
3156 char *cwd;
3157
3158 mark_point();
3159 pr_fs_clear_cache();
3160
3161 res = pr_fs_clear_cache2("/testsuite");
3162 fail_unless(res == 0, "Failed to clear cache: %s", strerror(errno));
3163
3164 res = pr_fsio_stat("/tmp", &st);
3165 fail_unless(res == 0, "Failed to stat '/tmp': %s", strerror(errno));
3166
3167 res = pr_fs_clear_cache2("/tmp");
3168 expected = 1;
3169 fail_unless(res == expected, "Expected %d, got %d", expected, res);
3170
3171 res = pr_fs_clear_cache2("/testsuite");
3172 expected = 0;
3173 fail_unless(res == expected, "Expected %d, got %d", expected, res);
3174
3175 res = pr_fsio_stat("/tmp", &st);
3176 fail_unless(res == 0, "Failed to stat '/tmp': %s", strerror(errno));
3177
3178 res = pr_fsio_lstat("/tmp", &st);
3179 fail_unless(res == 0, "Failed to lstat '/tmp': %s", strerror(errno));
3180
3181 res = pr_fs_clear_cache2("/tmp");
3182 expected = 2;
3183 fail_unless(res == expected, "Expected %d, got %d", expected, res);
3184
3185 res = pr_fsio_stat("/tmp", &st);
3186 fail_unless(res == 0, "Failed to stat '/tmp': %s", strerror(errno));
3187
3188 res = pr_fsio_lstat("/tmp", &st);
3189 fail_unless(res == 0, "Failed to lstat '/tmp': %s", strerror(errno));
3190
3191 cwd = getcwd(NULL, 0);
3192 fail_unless(cwd != NULL, "Failed to get cwd: %s", strerror(errno));
3193
3194 res = pr_fs_setcwd("/");
3195 fail_unless(res == 0, "Failed to set cwd to '/': %s", strerror(errno));
3196
3197 res = pr_fs_clear_cache2("tmp");
3198 expected = 2;
3199 fail_unless(res == expected, "Expected %d, got %d", expected, res);
3200
3201 res = pr_fs_setcwd(cwd);
3202 fail_unless(res == 0, "Failed to set cwd to '%s': %s", cwd, strerror(errno));
3203
3204 free(cwd);
3205 }
3206 END_TEST
3207
START_TEST(fsio_statcache_cache_hit_test)3208 START_TEST (fsio_statcache_cache_hit_test) {
3209 int res;
3210 struct stat st;
3211
3212 /* First is a cache miss...*/
3213 res = pr_fsio_stat("/tmp", &st);
3214 fail_unless(res == 0, "Failed to stat '/tmp': %s", strerror(errno));
3215
3216 /* This is a cache hit, hopefully. */
3217 res = pr_fsio_stat("/tmp", &st);
3218 fail_unless(res == 0, "Failed to stat '/tmp': %s", strerror(errno));
3219
3220 pr_fs_clear_cache();
3221 }
3222 END_TEST
3223
START_TEST(fsio_statcache_negative_cache_test)3224 START_TEST (fsio_statcache_negative_cache_test) {
3225 int res;
3226 struct stat st;
3227
3228 /* First is a cache miss...*/
3229 res = pr_fsio_stat("/foo.bar.baz.d", &st);
3230 fail_unless(res < 0, "Check of '/foo.bar.baz.d' succeeded unexpectedly");
3231 fail_unless(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
3232 strerror(errno), errno);
3233
3234 /* This is a cache hit, hopefully. */
3235 res = pr_fsio_stat("/foo.bar.baz.d", &st);
3236 fail_unless(res < 0, "Check of '/foo.bar.baz.d' succeeded unexpectedly");
3237 fail_unless(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
3238 strerror(errno), errno);
3239
3240 pr_fs_clear_cache();
3241 }
3242 END_TEST
3243
START_TEST(fsio_statcache_expired_test)3244 START_TEST (fsio_statcache_expired_test) {
3245 unsigned int cache_size, max_age;
3246 int res;
3247 struct stat st;
3248
3249 cache_size = max_age = 1;
3250 pr_fs_statcache_set_policy(cache_size, max_age, 0);
3251
3252 /* First is a cache miss...*/
3253 mark_point();
3254 res = pr_fsio_stat("/tmp", &st);
3255 fail_unless(res == 0, "Failed to stat '/tmp': %s", strerror(errno));
3256
3257 /* Wait for that cached data to expire...*/
3258 sleep(max_age + 1);
3259
3260 /* This is another cache miss, hopefully. */
3261 mark_point();
3262 res = pr_fsio_stat("/tmp2", &st);
3263 fail_unless(res < 0, "Check of '/tmp2' succeeded unexpectedly");
3264 fail_unless(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
3265 strerror(errno), errno);
3266
3267 mark_point();
3268 pr_fs_clear_cache();
3269 }
3270 END_TEST
3271
START_TEST(fsio_statcache_dump_test)3272 START_TEST (fsio_statcache_dump_test) {
3273 mark_point();
3274 pr_fs_statcache_dump();
3275 }
3276 END_TEST
3277
START_TEST(fs_create_fs_test)3278 START_TEST (fs_create_fs_test) {
3279 pr_fs_t *fs;
3280
3281 fs = pr_create_fs(NULL, NULL);
3282 fail_unless(fs == NULL, "Failed to handle null arguments");
3283 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
3284 strerror(errno), errno);
3285
3286 fs = pr_create_fs(p, NULL);
3287 fail_unless(fs == NULL, "Failed to handle null name");
3288 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
3289 strerror(errno), errno);
3290
3291 fs = pr_create_fs(p, "testsuite");
3292 fail_unless(fs != NULL, "Failed to create FS: %s", strerror(errno));
3293 }
3294 END_TEST
3295
START_TEST(fs_insert_fs_test)3296 START_TEST (fs_insert_fs_test) {
3297 pr_fs_t *fs, *fs2;
3298 int res;
3299
3300 res = pr_insert_fs(NULL, NULL);
3301 fail_unless(res < 0, "Failed to handle null arguments");
3302 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
3303 strerror(errno), errno);
3304
3305 fs = pr_create_fs(p, "testsuite");
3306 fail_unless(fs != NULL, "Failed to create FS: %s", strerror(errno));
3307
3308 res = pr_insert_fs(fs, NULL);
3309 fail_unless(res < 0, "Failed to handle null path");
3310 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
3311 strerror(errno), errno);
3312
3313 res = pr_insert_fs(fs, "/testsuite");
3314 fail_unless(res == TRUE, "Failed to insert FS: %s", strerror(errno));
3315
3316 res = pr_insert_fs(fs, "/testsuite");
3317 fail_unless(res == FALSE, "Failed to handle duplicate paths");
3318 fail_unless(errno == EEXIST, "Expected EEXIST (%d), got %s (%d)", EEXIST,
3319 strerror(errno), errno);
3320
3321 fs2 = pr_create_fs(p, "testsuite2");
3322 fail_unless(fs2 != NULL, "Failed to create FS: %s", strerror(errno));
3323
3324 res = pr_insert_fs(fs2, "/testsuite2");
3325 fail_unless(res == TRUE, "Failed to insert FS: %s", strerror(errno));
3326
3327 fs2 = pr_create_fs(p, "testsuite3");
3328 fail_unless(fs2 != NULL, "Failed to create FS: %s", strerror(errno));
3329
3330 /* Push this FS on top of the previously registered path; FSes can be
3331 * stacked like this.
3332 */
3333 res = pr_insert_fs(fs2, "/testsuite2");
3334 fail_unless(res == TRUE, "Failed to insert FS: %s", strerror(errno));
3335
3336 (void) pr_remove_fs("/testsuite");
3337 (void) pr_remove_fs("/testsuite2");
3338 (void) pr_remove_fs("/testsuite3");
3339 }
3340 END_TEST
3341
START_TEST(fs_get_fs_test)3342 START_TEST (fs_get_fs_test) {
3343 pr_fs_t *fs, *fs2, *fs3;
3344 int exact_match = FALSE, res;
3345
3346 fs = pr_get_fs(NULL, NULL);
3347 fail_unless(fs == NULL, "Failed to handle null arguments");
3348
3349 fs = pr_get_fs("/testsuite", &exact_match);
3350 fail_unless(fs != NULL, "Failed to get FS: %s", strerror(errno));
3351 fail_unless(exact_match == FALSE, "Expected FALSE, got TRUE");
3352
3353 fs2 = pr_create_fs(p, "testsuite");
3354 fail_unless(fs2 != NULL, "Failed to create FS: %s", strerror(errno));
3355
3356 res = pr_insert_fs(fs2, "/testsuite");
3357 fail_unless(res == TRUE, "Failed to insert FS: %s", strerror(errno));
3358
3359 fs = pr_get_fs("/testsuite", &exact_match);
3360 fail_unless(fs != NULL, "Failed to get FS: %s", strerror(errno));
3361 fail_unless(exact_match == TRUE, "Expected TRUE, got FALSE");
3362
3363 fs3 = pr_create_fs(p, "testsuite2");
3364 fail_unless(fs3 != NULL, "Failed to create FS: %s", strerror(errno));
3365
3366 res = pr_insert_fs(fs3, "/testsuite2/");
3367 fail_unless(res == TRUE, "Failed to insert FS: %s", strerror(errno));
3368
3369 exact_match = FALSE;
3370 fs = pr_get_fs("/testsuite2/foo/bar/baz", &exact_match);
3371 fail_unless(fs != NULL, "Failed to get FS: %s", strerror(errno));
3372 fail_unless(exact_match == FALSE, "Expected FALSE, got TRUE");
3373
3374 (void) pr_remove_fs("/testsuite2");
3375 (void) pr_remove_fs("/testsuite");
3376 }
3377 END_TEST
3378
START_TEST(fs_unmount_fs_test)3379 START_TEST (fs_unmount_fs_test) {
3380 pr_fs_t *fs, *fs2;
3381 int res;
3382
3383 fs = pr_unmount_fs(NULL, NULL);
3384 fail_unless(fs == NULL, "Failed to handle null arguments");
3385 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
3386 strerror(errno), errno);
3387
3388 fs = pr_unmount_fs("/testsuite", NULL);
3389 fail_unless(fs == NULL, "Failed to handle absent FS");
3390 fail_unless(errno == EACCES, "Expected EACCES (%d), got %s (%d)", EACCES,
3391 strerror(errno), errno);
3392
3393 fs2 = pr_create_fs(p, "testsuite");
3394 fail_unless(fs2 != NULL, "Failed to create FS: %s", strerror(errno));
3395
3396 res = pr_insert_fs(fs2, "/testsuite");
3397 fail_unless(res == TRUE, "Failed to insert FS: %s", strerror(errno));
3398
3399 fs = pr_unmount_fs("/testsuite", "foo bar");
3400 fail_unless(fs == NULL, "Failed to mismatched path AND name");
3401 fail_unless(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
3402 strerror(errno), errno);
3403
3404 fs = pr_unmount_fs("/testsuite2", NULL);
3405 fail_unless(fs == NULL, "Failed to handle nonexistent path");
3406 fail_unless(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
3407 strerror(errno), errno);
3408
3409 fs2 = pr_unmount_fs("/testsuite", NULL);
3410 fail_unless(fs2 != NULL, "Failed to unmount '/testsuite': %s",
3411 strerror(errno));
3412
3413 fs2 = pr_create_fs(p, "testsuite");
3414 fail_unless(fs2 != NULL, "Failed to create FS: %s", strerror(errno));
3415
3416 res = pr_insert_fs(fs2, "/testsuite");
3417 fail_unless(res == TRUE, "Failed to insert FS: %s", strerror(errno));
3418
3419 fs2 = pr_create_fs(p, "testsuite2");
3420 fail_unless(fs2 != NULL, "Failed to create FS: %s", strerror(errno));
3421
3422 res = pr_insert_fs(fs2, "/testsuite");
3423 fail_unless(res == TRUE, "Failed to insert FS: %s", strerror(errno));
3424
3425 fs2 = pr_unmount_fs("/testsuite", NULL);
3426 fail_unless(fs2 != NULL, "Failed to unmount '/testsuite': %s",
3427 strerror(errno));
3428
3429 fs2 = pr_unmount_fs("/testsuite", NULL);
3430 fail_unless(fs2 != NULL, "Failed to unmount '/testsuite': %s",
3431 strerror(errno));
3432
3433 (void) pr_remove_fs("/testsuite");
3434 (void) pr_remove_fs("/testsuite");
3435 }
3436 END_TEST
3437
START_TEST(fs_remove_fs_test)3438 START_TEST (fs_remove_fs_test) {
3439 pr_fs_t *fs, *fs2;
3440 int res;
3441
3442 fs = pr_remove_fs(NULL);
3443 fail_unless(fs == NULL, "Failed to handle null arguments");
3444 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
3445 strerror(errno), errno);
3446
3447 fs = pr_remove_fs("/testsuite");
3448 fail_unless(fs == NULL, "Failed to handle absent FS");
3449 fail_unless(errno == EACCES, "Expected EACCES (%d), got %s (%d)", EACCES,
3450 strerror(errno), errno);
3451
3452 fs2 = pr_create_fs(p, "testsuite");
3453 fail_unless(fs2 != NULL, "Failed to create FS: %s", strerror(errno));
3454
3455 res = pr_insert_fs(fs2, "/testsuite");
3456 fail_unless(res == TRUE, "Failed to insert FS: %s", strerror(errno));
3457
3458 fs = pr_remove_fs("/testsuite2");
3459 fail_unless(fs == NULL, "Failed to handle nonexistent path");
3460 fail_unless(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
3461 strerror(errno), errno);
3462
3463 fs2 = pr_remove_fs("/testsuite");
3464 fail_unless(fs2 != NULL, "Failed to remove '/testsuite': %s",
3465 strerror(errno));
3466 }
3467 END_TEST
3468
START_TEST(fs_register_fs_test)3469 START_TEST (fs_register_fs_test) {
3470 pr_fs_t *fs, *fs2;
3471
3472 fs = pr_register_fs(NULL, NULL, NULL);
3473 fail_unless(fs == NULL, "Failed to handle null arguments");
3474 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
3475 strerror(errno), errno);
3476
3477 fs = pr_register_fs(p, NULL, NULL);
3478 fail_unless(fs == NULL, "Failed to handle null name");
3479 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
3480 strerror(errno), errno);
3481
3482 fs = pr_register_fs(p, "testsuite", NULL);
3483 fail_unless(fs == NULL, "Failed to handle null path");
3484 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
3485 strerror(errno), errno);
3486
3487 fs = pr_register_fs(p, "testsuite", "/testsuite");
3488 fail_unless(fs != NULL, "Failed to register FS: %s", strerror(errno));
3489
3490 fs2 = pr_register_fs(p, "testsuite", "/testsuite");
3491 fail_unless(fs2 == NULL, "Failed to handle duplicate names");
3492 fail_unless(errno == EEXIST, "Expected EEXIST (%d), got %s (%d)", EEXIST,
3493 strerror(errno), errno);
3494
3495 (void) pr_remove_fs("/testsuite");
3496 }
3497 END_TEST
3498
START_TEST(fs_unregister_fs_test)3499 START_TEST (fs_unregister_fs_test) {
3500 pr_fs_t *fs;
3501 int res;
3502
3503 res = pr_unregister_fs(NULL);
3504 fail_unless(res < 0, "Failed to handle null argument");
3505 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
3506 strerror(errno), errno);
3507
3508 res = pr_unregister_fs("/testsuite");
3509 fail_unless(res < 0, "Failed to handle nonexistent path");
3510 fail_unless(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
3511 strerror(errno), errno);
3512
3513 fs = pr_register_fs(p, "testsuite", "/testsuite");
3514 fail_unless(fs != NULL, "Failed to register FS: %s", strerror(errno));
3515
3516 res = pr_unregister_fs("/testsuite");
3517 fail_unless(res == 0, "Failed to unregister '/testsuite': %s",
3518 strerror(errno));
3519 }
3520 END_TEST
3521
START_TEST(fs_resolve_fs_map_test)3522 START_TEST (fs_resolve_fs_map_test) {
3523 pr_fs_t *fs;
3524 int res;
3525
3526 mark_point();
3527 pr_resolve_fs_map();
3528
3529 fs = pr_register_fs(p, "testsuite", "/testsuite");
3530 fail_unless(fs != NULL, "Failed to register FS: %s", strerror(errno));
3531
3532 mark_point();
3533 pr_resolve_fs_map();
3534
3535 res = pr_unregister_fs("/testsuite");
3536 fail_unless(res == 0, "Failed to unregister '/testsuite': %s",
3537 strerror(errno));
3538
3539 mark_point();
3540 pr_resolve_fs_map();
3541 }
3542 END_TEST
3543
3544 #if defined(PR_USE_DEVEL)
START_TEST(fs_dump_fs_test)3545 START_TEST (fs_dump_fs_test) {
3546 pr_fs_t *fs, *root_fs;
3547
3548 mark_point();
3549 pr_fs_dump(NULL);
3550
3551 root_fs = pr_get_fs("/", NULL);
3552 fs = pr_register_fs(p, "testsuite", "/testsuite");
3553
3554 mark_point();
3555 pr_fs_dump(NULL);
3556
3557 fs->stat = root_fs->stat;
3558 fs->fstat = root_fs->fstat;
3559 fs->lstat = root_fs->lstat;
3560 fs->rename = root_fs->rename;
3561 fs->unlink = root_fs->unlink;
3562 fs->open = root_fs->open;
3563 fs->close = root_fs->close;
3564 fs->read = root_fs->read;
3565 fs->write = root_fs->write;
3566 fs->lseek = root_fs->lseek;
3567 fs->link = root_fs->link;
3568 fs->readlink = root_fs->readlink;
3569 fs->symlink = root_fs->symlink;
3570 fs->ftruncate = root_fs->ftruncate;
3571 fs->truncate = root_fs->truncate;
3572 fs->chmod = root_fs->chmod;
3573 fs->fchmod = root_fs->fchmod;
3574 fs->chown = root_fs->chown;
3575 fs->fchown = root_fs->fchown;
3576 fs->lchown = root_fs->lchown;
3577 fs->access = root_fs->access;
3578 fs->faccess = root_fs->faccess;
3579 fs->utimes = root_fs->utimes;
3580 fs->futimes = root_fs->futimes;
3581 fs->fsync = root_fs->fsync;
3582 fs->chdir = root_fs->chdir;
3583 fs->chroot = root_fs->chroot;
3584 fs->opendir = root_fs->opendir;
3585 fs->closedir = root_fs->closedir;
3586 fs->readdir = root_fs->readdir;
3587 fs->mkdir = root_fs->mkdir;
3588 fs->rmdir = root_fs->rmdir;
3589
3590 mark_point();
3591 pr_fs_dump(NULL);
3592
3593 pr_unregister_fs("/testsuite");
3594 }
3595 END_TEST
3596 #endif /* PR_USE_DEVEL */
3597
fsio_chroot_cb(pr_fs_t * fs,const char * path)3598 static int fsio_chroot_cb(pr_fs_t *fs, const char *path) {
3599 return 0;
3600 }
3601
START_TEST(fsio_custom_chroot_test)3602 START_TEST (fsio_custom_chroot_test) {
3603 pr_fs_t *fs;
3604 int res;
3605 const char *path;
3606
3607 fs = pr_register_fs(p, "custom", "/testsuite/");
3608 fail_unless(fs != NULL, "Failed to register custom FS: %s", strerror(errno));
3609
3610 fs->chroot = fsio_chroot_cb;
3611
3612 mark_point();
3613 pr_resolve_fs_map();
3614
3615 path = "/testsuite/foo/bar";
3616 res = pr_fsio_chroot(path);
3617 fail_unless(res == 0, "Failed to chroot (via custom FS) to '%s': %s", path,
3618 strerror(errno));
3619
3620 pr_unregister_fs("/testsuite");
3621 }
3622 END_TEST
3623
START_TEST(fs_clean_path_test)3624 START_TEST (fs_clean_path_test) {
3625 char res[PR_TUNABLE_PATH_MAX+1], *path, *expected;
3626
3627 mark_point();
3628 pr_fs_clean_path(NULL, NULL, 0);
3629 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
3630 strerror(errno), errno);
3631
3632 path = "/";
3633
3634 mark_point();
3635 pr_fs_clean_path(path, NULL, 0);
3636 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
3637 strerror(errno), errno);
3638
3639 res[sizeof(res)-1] = '\0';
3640
3641 mark_point();
3642 pr_fs_clean_path(path, res, 0);
3643
3644 pr_fs_clean_path(path, res, sizeof(res)-1);
3645 fail_unless(strcmp(res, path) == 0, "Expected cleaned path '%s', got '%s'",
3646 path, res);
3647
3648 res[sizeof(res)-1] = '\0';
3649 path = "/test.txt";
3650 pr_fs_clean_path(path, res, sizeof(res)-1);
3651 fail_unless(strcmp(res, path) == 0, "Expected cleaned path '%s', got '%s'",
3652 path, res);
3653
3654 res[sizeof(res)-1] = '\0';
3655 path = "/test.txt";
3656 pr_fs_clean_path(path, res, sizeof(res)-1);
3657 fail_unless(strcmp(res, path) == 0, "Expected cleaned path '%s', got '%s'",
3658 path, res);
3659
3660 res[sizeof(res)-1] = '\0';
3661 path = "/./test.txt";
3662 pr_fs_clean_path(path, res, sizeof(res)-1);
3663 expected = "/test.txt";
3664 fail_unless(strcmp(res, expected) == 0,
3665 "Expected cleaned path '%s', got '%s'", expected, res);
3666
3667 res[sizeof(res)-1] = '\0';
3668 path = "test.txt";
3669 pr_fs_clean_path(path, res, sizeof(res)-1);
3670 expected = "/test.txt";
3671 fail_unless(strcmp(res, expected) == 0,
3672 "Expected cleaned path '%s', got '%s'", path, res);
3673 }
3674 END_TEST
3675
START_TEST(fs_clean_path2_test)3676 START_TEST (fs_clean_path2_test) {
3677 char res[PR_TUNABLE_PATH_MAX+1], *path, *expected;
3678 int code;
3679
3680 mark_point();
3681 code = pr_fs_clean_path2(NULL, NULL, 0, 0);
3682 fail_unless(code < 0, "Failed to handle null path");
3683 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
3684 strerror(errno), errno);
3685
3686 path = "/";
3687
3688 mark_point();
3689 code = pr_fs_clean_path2(path, NULL, 0, 0);
3690 fail_unless(code < 0, "Failed to handle null buf");
3691 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
3692 strerror(errno), errno);
3693
3694 res[sizeof(res)-1] = '\0';
3695
3696 mark_point();
3697 code = pr_fs_clean_path2(path, res, 0, 0);
3698 fail_unless(code == 0, "Failed to handle zero length buf: %s",
3699 strerror(errno));
3700
3701 res[sizeof(res)-1] = '\0';
3702 path = "test.txt";
3703 code = pr_fs_clean_path2(path, res, sizeof(res)-1, 0);
3704 fail_unless(code == 0, "Failed to clean path '%s': %s", path,
3705 strerror(errno));
3706 fail_unless(strcmp(res, path) == 0, "Expected cleaned path '%s', got '%s'",
3707 path, res);
3708
3709 res[sizeof(res)-1] = '\0';
3710 path = "/./test.txt";
3711 code = pr_fs_clean_path2(path, res, sizeof(res)-1, 0);
3712 fail_unless(code == 0, "Failed to clean path '%s': %s", path,
3713 strerror(errno));
3714 expected = "/test.txt";
3715 fail_unless(strcmp(res, expected) == 0,
3716 "Expected cleaned path '%s', got '%s'", expected, res);
3717
3718 res[sizeof(res)-1] = '\0';
3719 path = "test.d///test.txt";
3720 code = pr_fs_clean_path2(path, res, sizeof(res)-1, 0);
3721 fail_unless(code == 0, "Failed to clean path '%s': %s", path,
3722 strerror(errno));
3723 expected = "test.d/test.txt";
3724 fail_unless(strcmp(res, expected) == 0,
3725 "Expected cleaned path '%s', got '%s'", expected, res);
3726
3727 res[sizeof(res)-1] = '\0';
3728 path = "/test.d///test.txt";
3729 code = pr_fs_clean_path2(path, res, sizeof(res)-1,
3730 PR_FSIO_CLEAN_PATH_FL_MAKE_ABS_PATH);
3731 fail_unless(code == 0, "Failed to clean path '%s': %s", path,
3732 strerror(errno));
3733 expected = "/test.d/test.txt";
3734 fail_unless(strcmp(res, expected) == 0,
3735 "Expected cleaned path '%s', got '%s'", expected, res);
3736 }
3737 END_TEST
3738
START_TEST(fs_dircat_test)3739 START_TEST (fs_dircat_test) {
3740 char buf[PR_TUNABLE_PATH_MAX+1], *a, *b, *ok;
3741 int res;
3742
3743 res = pr_fs_dircat(NULL, 0, NULL, NULL);
3744 fail_unless(res == -1, "Failed to handle null arguments");
3745 fail_unless(errno == EINVAL,
3746 "Failed to set errno to EINVAL for null arguments");
3747
3748 res = pr_fs_dircat(buf, 0, "foo", "bar");
3749 fail_unless(res == -1, "Failed to handle zero-length buffer");
3750 fail_unless(errno == EINVAL,
3751 "Failed to set errno to EINVAL for zero-length buffer");
3752
3753 res = pr_fs_dircat(buf, -1, "foo", "bar");
3754 fail_unless(res == -1, "Failed to handle negative-length buffer");
3755 fail_unless(errno == EINVAL,
3756 "Failed to set errno to EINVAL for negative-length buffer");
3757
3758 a = pcalloc(p, PR_TUNABLE_PATH_MAX);
3759 memset(a, 'A', PR_TUNABLE_PATH_MAX-1);
3760
3761 b = "foo";
3762
3763 res = pr_fs_dircat(buf, sizeof(buf)-1, a, b);
3764 fail_unless(res == -1, "Failed to handle too-long paths");
3765 fail_unless(errno == ENAMETOOLONG,
3766 "Failed to set errno to ENAMETOOLONG for too-long paths");
3767
3768 a = "foo";
3769 b = "/bar";
3770 ok = b;
3771 res = pr_fs_dircat(buf, sizeof(buf)-1, a, b);
3772 fail_unless(res == 0, "Failed to concatenate abs-path path second dir");
3773 fail_unless(strcmp(buf, ok) == 0, "Expected concatenated dir '%s', got '%s'",
3774 ok, buf);
3775
3776 a = "foo";
3777 b = "bar";
3778 ok = "foo/bar";
3779 res = pr_fs_dircat(buf, sizeof(buf)-1, a, b);
3780 fail_unless(res == 0, "Failed to concatenate two normal paths");
3781 fail_unless(strcmp(buf, ok) == 0, "Expected concatenated dir '%s', got '%s'",
3782 ok, buf);
3783
3784 a = "foo/";
3785 b = "bar";
3786 ok = "foo/bar";
3787 res = pr_fs_dircat(buf, sizeof(buf)-1, a, b);
3788 fail_unless(res == 0, "Failed to concatenate first dir with trailing slash");
3789 fail_unless(strcmp(buf, ok) == 0, "Expected concatenated dir '%s', got '%s'",
3790 ok, buf);
3791
3792 a = "";
3793 b = "";
3794 ok = "/";
3795 res = pr_fs_dircat(buf, sizeof(buf)-1, a, b);
3796 fail_unless(res == 0, "Failed to concatenate two empty paths");
3797 fail_unless(strcmp(buf, ok) == 0, "Expected concatenated dir '%s', got '%s'",
3798 ok, buf);
3799
3800 a = "/foo";
3801 b = "";
3802 ok = "/foo/";
3803 res = pr_fs_dircat(buf, sizeof(buf)-1, a, b);
3804 fail_unless(res == 0, "Failed to concatenate two empty paths");
3805 fail_unless(strcmp(buf, ok) == 0, "Expected concatenated dir '%s', got '%s'",
3806 ok, buf);
3807
3808 a = "";
3809 b = "/bar";
3810 ok = "/bar/";
3811 res = pr_fs_dircat(buf, sizeof(buf)-1, a, b);
3812 fail_unless(res == 0, "Failed to concatenate two empty paths");
3813 fail_unless(strcmp(buf, ok) == 0, "Expected concatenated dir '%s', got '%s'",
3814 ok, buf);
3815 }
3816 END_TEST
3817
START_TEST(fs_setcwd_test)3818 START_TEST (fs_setcwd_test) {
3819 int res;
3820 const char *wd;
3821
3822 /* Make sure that we don't segfault if we call pr_fs_setcwd() on the
3823 * buffer that it is already using.
3824 */
3825 res = pr_fs_setcwd(pr_fs_getcwd());
3826 fail_unless(res == 0, "Failed to set cwd to '%s': %s", pr_fs_getcwd(),
3827 strerror(errno));
3828
3829 wd = pr_fs_getcwd();
3830 fail_unless(wd != NULL, "Failed to get working directory: %s",
3831 strerror(errno));
3832 fail_unless(strcmp(wd, fsio_cwd) == 0,
3833 "Expected '%s', got '%s'", fsio_cwd, wd);
3834
3835 wd = pr_fs_getvwd();
3836 fail_unless(wd != NULL, "Failed to get working directory: %s",
3837 strerror(errno));
3838 fail_unless(strcmp(wd, "/") == 0, "Expected '/', got '%s'", wd);
3839 }
3840 END_TEST
3841
START_TEST(fs_glob_test)3842 START_TEST (fs_glob_test) {
3843 glob_t pglob;
3844 int res;
3845
3846 res = pr_fs_glob(NULL, 0, NULL, NULL);
3847 fail_unless(res < 0, "Failed to handle null arguments");
3848 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
3849 strerror(errno), errno);
3850
3851 res = pr_fs_glob(NULL, 0, NULL, &pglob);
3852 fail_unless(res < 0, "Failed to handle null arguments");
3853 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
3854 strerror(errno), errno);
3855
3856 memset(&pglob, 0, sizeof(pglob));
3857 res = pr_fs_glob("*", 0, NULL, &pglob);
3858 fail_unless(res == 0, "Failed to glob: glob(3) returned %d: %s", res,
3859 strerror(errno));
3860 fail_unless(pglob.gl_pathc > 0, "Expected >0, got %lu",
3861 (unsigned long) pglob.gl_pathc);
3862
3863 mark_point();
3864 pr_fs_globfree(NULL);
3865 if (res == 0) {
3866 pr_fs_globfree(&pglob);
3867 }
3868 }
3869 END_TEST
3870
START_TEST(fs_copy_file_test)3871 START_TEST (fs_copy_file_test) {
3872 int res;
3873 char *src_path = NULL, *dst_path = NULL, *text;
3874 pr_fh_t *fh;
3875
3876 res = pr_fs_copy_file(NULL, NULL);
3877 fail_unless(res < 0, "Failed to handle null arguments");
3878 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
3879 strerror(errno), errno);
3880
3881 src_path = (char *) fsio_copy_src_path;
3882 res = pr_fs_copy_file(src_path, NULL);
3883 fail_unless(res < 0, "Failed to handle null destination path");
3884 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
3885 strerror(errno), errno);
3886
3887 dst_path = (char *) fsio_copy_dst_path;
3888 res = pr_fs_copy_file(src_path, dst_path);
3889 fail_unless(res < 0, "Failed to handle nonexistent source path");
3890 fail_unless(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
3891 strerror(errno), errno);
3892
3893 res = pr_fs_copy_file("/tmp", dst_path);
3894 fail_unless(res < 0, "Failed to handle directory source path");
3895 fail_unless(errno == EISDIR, "Expected EISDIR (%d), got %s (%d)", EISDIR,
3896 strerror(errno), errno);
3897
3898 (void) unlink(src_path);
3899 fh = pr_fsio_open(src_path, O_CREAT|O_EXCL|O_WRONLY);
3900 fail_unless(fh != NULL, "Failed to open '%s': %s", src_path, strerror(errno));
3901
3902 text = "Hello, World!\n";
3903 res = pr_fsio_write(fh, text, strlen(text));
3904 fail_if(res < 0, "Failed to write '%s' to '%s': %s", text, src_path,
3905 strerror(errno));
3906
3907 res = pr_fsio_close(fh);
3908 fail_unless(res == 0, "Failed to close '%s': %s", src_path, strerror(errno));
3909
3910 res = pr_fs_copy_file(src_path, "/tmp");
3911 fail_unless(res < 0, "Failed to handle directory destination path");
3912 fail_unless(errno == EISDIR, "Expected EISDIR (%d), got %s (%d)", EISDIR,
3913 strerror(errno), errno);
3914
3915 res = pr_fs_copy_file(src_path, "/tmp/foo/bar/baz/quxx/quzz.dat");
3916 fail_unless(res < 0, "Failed to handle nonexistent destination path");
3917 fail_unless(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
3918 strerror(errno), errno);
3919
3920 mark_point();
3921 res = pr_fs_copy_file(src_path, src_path);
3922 fail_unless(res == 0, "Failed to copy file to itself: %s", strerror(errno));
3923
3924 (void) unlink(dst_path);
3925
3926 mark_point();
3927 res = pr_fs_copy_file(src_path, dst_path);
3928 fail_unless(res == 0, "Failed to copy file: %s", strerror(errno));
3929
3930 (void) pr_fsio_unlink(src_path);
3931 (void) pr_fsio_unlink(dst_path);
3932 }
3933 END_TEST
3934
3935 static unsigned int copy_progress_iter = 0;
copy_progress_cb(int nwritten)3936 static void copy_progress_cb(int nwritten) {
3937 copy_progress_iter++;
3938 }
3939
START_TEST(fs_copy_file2_test)3940 START_TEST (fs_copy_file2_test) {
3941 int res, flags;
3942 char *src_path, *dst_path, *text;
3943 pr_fh_t *fh;
3944
3945 src_path = (char *) fsio_copy_src_path;
3946 dst_path = (char *) fsio_copy_dst_path;
3947 flags = PR_FSIO_COPY_FILE_FL_NO_DELETE_ON_FAILURE;
3948
3949 (void) unlink(src_path);
3950 (void) unlink(dst_path);
3951
3952 fh = pr_fsio_open(src_path, O_CREAT|O_EXCL|O_WRONLY);
3953 fail_unless(fh != NULL, "Failed to open '%s': %s", src_path, strerror(errno));
3954
3955 text = "Hello, World!\n";
3956 res = pr_fsio_write(fh, text, strlen(text));
3957 fail_if(res < 0, "Failed to write '%s' to '%s': %s", text, src_path,
3958 strerror(errno));
3959
3960 res = pr_fsio_close(fh);
3961 fail_unless(res == 0, "Failed to close '%s': %s", src_path, strerror(errno));
3962
3963 copy_progress_iter = 0;
3964
3965 mark_point();
3966 res = pr_fs_copy_file2(src_path, dst_path, flags, copy_progress_cb);
3967 fail_unless(res == 0, "Failed to copy file: %s", strerror(errno));
3968
3969 (void) pr_fsio_unlink(src_path);
3970 (void) pr_fsio_unlink(dst_path);
3971
3972 fail_unless(copy_progress_iter > 0, "Unexpected progress callback count (%u)",
3973 copy_progress_iter);
3974 }
3975 END_TEST
3976
START_TEST(fs_interpolate_test)3977 START_TEST (fs_interpolate_test) {
3978 int res;
3979 char buf[PR_TUNABLE_PATH_MAX], *path;
3980
3981 memset(buf, '\0', sizeof(buf));
3982
3983 res = pr_fs_interpolate(NULL, NULL, 0);
3984 fail_unless(res < 0, "Failed to handle null arguments");
3985 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
3986 strerror(errno), errno);
3987
3988 path = "/tmp";
3989 res = pr_fs_interpolate(path, NULL, 0);
3990 fail_unless(res < 0, "Failed to handle null buffer");
3991 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
3992 strerror(errno), errno);
3993
3994 res = pr_fs_interpolate(path, buf, 0);
3995 fail_unless(res < 0, "Failed to handle zero buffer length");
3996 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
3997 strerror(errno), errno);
3998
3999 res = pr_fs_interpolate(path, buf, sizeof(buf)-1);
4000 fail_unless(res == 1, "Failed to interpolate path '%s': %s", path,
4001 strerror(errno));
4002 fail_unless(strcmp(buf, path) == 0, "Expected '%s', got '%s'", path, buf);
4003
4004 path = "~/foo/bar/baz/quzz/quzz.d";
4005 res = pr_fs_interpolate(path, buf, sizeof(buf)-1);
4006 fail_unless(res == 1, "Failed to interpolate path '%s': %s", path,
4007 strerror(errno));
4008 fail_unless(strcmp(buf, path+1) == 0, "Expected '%s', got '%s'", path+1, buf);
4009
4010 path = "~";
4011 res = pr_fs_interpolate(path, buf, sizeof(buf)-1);
4012 fail_unless(res == 1, "Failed to interpolate path '%s': %s", path,
4013 strerror(errno));
4014 fail_unless(strcmp(buf, "/") == 0, "Expected '/', got '%s'", buf);
4015
4016 session.chroot_path = "/tmp";
4017 res = pr_fs_interpolate(path, buf, sizeof(buf)-1);
4018 fail_unless(res == 1, "Failed to interpolate path '%s': %s", path,
4019 strerror(errno));
4020 fail_unless(strcmp(buf, session.chroot_path) == 0, "Expected '%s', got '%s'",
4021 session.chroot_path, buf);
4022
4023 session.chroot_path = NULL;
4024
4025 path = "~foo.bar.baz.quzz";
4026 res = pr_fs_interpolate(path, buf, sizeof(buf)-1);
4027 fail_unless(res < 0, "Interpolated '%s' unexpectedly", path);
4028 fail_unless(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
4029 strerror(errno), errno);
4030
4031 session.user = "testsuite";
4032 path = "~/tmp.d/test.d/foo.d/bar.d";
4033 res = pr_fs_interpolate(path, buf, sizeof(buf)-1);
4034 fail_unless(res < 0, "Interpolated '%s' unexpectedly", path);
4035 fail_unless(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
4036 strerror(errno), errno);
4037 session.user = NULL;
4038 }
4039 END_TEST
4040
START_TEST(fs_resolve_partial_test)4041 START_TEST (fs_resolve_partial_test) {
4042 int op = FSIO_FILE_STAT, res;
4043 char buf[PR_TUNABLE_PATH_MAX], *path;
4044
4045 res = pr_fs_resolve_partial(NULL, NULL, 0, op);
4046 fail_unless(res < 0, "Failed to handle null arguments");
4047 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
4048 strerror(errno), errno);
4049
4050 path = "/tmp";
4051 res = pr_fs_resolve_partial(path, NULL, 0, op);
4052 fail_unless(res < 0, "Failed to handle null buffer");
4053 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
4054 strerror(errno), errno);
4055
4056 memset(buf, '\0', sizeof(buf));
4057 res = pr_fs_resolve_partial(path, buf, 0, op);
4058 fail_unless(res < 0, "Failed to handle zero buffer length");
4059 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
4060 strerror(errno), errno);
4061
4062 res = pr_fs_resolve_partial(path, buf, sizeof(buf)-1, op);
4063 fail_unless(res == 0, "Failed to resolve '%s': %s", path, strerror(errno));
4064 if (strcmp(buf, path) != 0) {
4065 /* Mac-specific hack */
4066 const char *prefix = "/private";
4067
4068 if (strncmp(buf, prefix, strlen(prefix)) != 0) {
4069 fail("Expected '%s', got '%s'", path, buf);
4070 }
4071 }
4072
4073 path = "/tmp/.////./././././.";
4074 res = pr_fs_resolve_partial(path, buf, sizeof(buf)-1, op);
4075 fail_unless(res == 0, "Failed to resolve '%s': %s", path, strerror(errno));
4076 if (strcmp(buf, path) != 0) {
4077 /* Mac-specific hack */
4078 const char *prefix = "/private";
4079
4080 if (strncmp(buf, prefix, strlen(prefix)) != 0 &&
4081 strcmp(buf, "/tmp/") != 0) {
4082 fail("Expected '%s', got '%s'", path, buf);
4083 }
4084 }
4085
4086 path = "/../../../.././..///../";
4087 res = pr_fs_resolve_partial(path, buf, sizeof(buf)-1, op);
4088 fail_unless(res == 0, "Failed to resolve '%s': %s", path, strerror(errno));
4089 if (strcmp(buf, "/") != 0) {
4090 /* Mac-specific hack */
4091 const char *prefix = "/private";
4092
4093 if (strncmp(buf, prefix, strlen(prefix)) != 0) {
4094 fail("Expected '%s', got '%s'", path, buf);
4095 }
4096 }
4097
4098 path = "/tmp/.///../../..../";
4099 res = pr_fs_resolve_partial(path, buf, sizeof(buf)-1, op);
4100 fail_unless(res < 0, "Resolved '%s' unexpectedly", path);
4101 fail_unless(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
4102 strerror(errno), errno);
4103
4104 path = "~foo/.///../../..../";
4105 res = pr_fs_resolve_partial(path, buf, sizeof(buf)-1, op);
4106 fail_unless(res < 0, "Resolved '%s' unexpectedly", path);
4107 fail_unless(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
4108 strerror(errno), errno);
4109
4110 path = "../../..../";
4111 res = pr_fs_resolve_partial(path, buf, sizeof(buf)-1, op);
4112 fail_unless(res < 0, "Resolved '%s' unexpectedly", path);
4113 fail_unless(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
4114 strerror(errno), errno);
4115
4116 /* Resolve a symlink path */
4117 res = pr_fsio_symlink("/tmp", fsio_link_path);
4118 fail_unless(res == 0, "Failed to create symlink to '%s': %s", fsio_link_path,
4119 strerror(errno));
4120
4121 res = pr_fs_resolve_partial(fsio_link_path, buf, sizeof(buf)-1, op);
4122 fail_unless(res == 0, "Failed to resolve '%s': %s", fsio_link_path,
4123 strerror(errno));
4124
4125 (void) unlink(fsio_link_path);
4126 }
4127 END_TEST
4128
START_TEST(fs_resolve_path_test)4129 START_TEST (fs_resolve_path_test) {
4130 int op = FSIO_FILE_STAT, res;
4131 char buf[PR_TUNABLE_PATH_MAX], *path;
4132
4133 memset(buf, '\0', sizeof(buf));
4134
4135 res = pr_fs_resolve_path(NULL, NULL, 0, op);
4136 fail_unless(res < 0, "Failed to handle null arguments");
4137 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
4138 strerror(errno), errno);
4139
4140 path = "/tmp";
4141 res = pr_fs_resolve_path(path, NULL, 0, op);
4142 fail_unless(res < 0, "Failed to handle null buffer");
4143 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
4144 strerror(errno), errno);
4145
4146 res = pr_fs_resolve_path(path, buf, 0, op);
4147 fail_unless(res < 0, "Failed to handle zero buffer length");
4148 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
4149 strerror(errno), errno);
4150
4151 res = pr_fs_resolve_path(path, buf, sizeof(buf)-1, op);
4152 fail_unless(res == 0, "Failed to resolve path '%s': %s", path,
4153 strerror(errno));
4154 if (strcmp(buf, path) != 0) {
4155 /* Mac-specific hack */
4156 const char *prefix = "/private";
4157
4158 if (strncmp(buf, prefix, strlen(prefix)) != 0) {
4159 fail("Expected '%s', got '%s'", path, buf);
4160 }
4161 }
4162
4163 /* Resolve a symlink path */
4164 res = pr_fsio_symlink("/tmp", fsio_link_path);
4165 fail_unless(res == 0, "Failed to create symlink to '%s': %s", fsio_link_path,
4166 strerror(errno));
4167
4168 res = pr_fs_resolve_path(fsio_link_path, buf, sizeof(buf)-1, op);
4169 fail_unless(res == 0, "Failed to resolve '%s': %s", fsio_link_path,
4170 strerror(errno));
4171
4172 (void) unlink(fsio_link_path);
4173 }
4174 END_TEST
4175
START_TEST(fs_use_encoding_test)4176 START_TEST (fs_use_encoding_test) {
4177 int res;
4178
4179 res = pr_fs_use_encoding(-1);
4180 fail_unless(res < 0, "Failed to handle invalid setting");
4181 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
4182 strerror(errno), errno);
4183
4184 res = pr_fs_use_encoding(TRUE);
4185 fail_unless(res == TRUE, "Expected TRUE, got %d", res);
4186
4187 res = pr_fs_use_encoding(FALSE);
4188 fail_unless(res == TRUE, "Expected TRUE, got %d", res);
4189
4190 res = pr_fs_use_encoding(TRUE);
4191 fail_unless(res == FALSE, "Expected FALSE, got %d", res);
4192 }
4193 END_TEST
4194
START_TEST(fs_decode_path2_test)4195 START_TEST (fs_decode_path2_test) {
4196 int flags = 0;
4197 char junk[32], *res;
4198 const char *path;
4199
4200 res = pr_fs_decode_path(NULL, NULL);
4201 fail_unless(res == NULL, "Failed to handle null arguments");
4202 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
4203 strerror(errno), errno);
4204
4205 res = pr_fs_decode_path(p, NULL);
4206 fail_unless(res == NULL, "Failed to handle null path");
4207 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
4208 strerror(errno), errno);
4209
4210 path = "/tmp";
4211 res = pr_fs_decode_path2(p, path, flags);
4212 fail_unless(res != NULL, "Failed to decode path '%s': %s", path,
4213 strerror(errno));
4214
4215 path = "/tmp";
4216 res = pr_fs_decode_path2(p, path, flags);
4217 fail_unless(res != NULL, "Failed to decode path '%s': %s", path,
4218 strerror(errno));
4219
4220 /* Test a path that cannot be decoded, using junk data from the stack */
4221 junk[sizeof(junk)-1] = '\0';
4222 path = junk;
4223 res = pr_fs_decode_path2(p, path, flags);
4224 fail_unless(res != NULL, "Failed to decode path: %s", strerror(errno));
4225
4226 /* XXX Use the FSIO_DECODE_FL_TELL_ERRORS flags, AND set the encode
4227 * policy to use PR_ENCODE_POLICY_FL_REQUIRE_VALID_ENCODING.
4228 */
4229 }
4230 END_TEST
4231
START_TEST(fs_encode_path_test)4232 START_TEST (fs_encode_path_test) {
4233 char junk[32], *res;
4234 const char *path;
4235
4236 res = pr_fs_encode_path(NULL, NULL);
4237 fail_unless(res == NULL, "Failed to handle null arguments");
4238 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
4239 strerror(errno), errno);
4240
4241 res = pr_fs_encode_path(p, NULL);
4242 fail_unless(res == NULL, "Failed to handle null path");
4243 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
4244 strerror(errno), errno);
4245
4246 path = "/tmp";
4247 res = pr_fs_encode_path(p, path);
4248 fail_unless(res != NULL, "Failed to encode path '%s': %s", path,
4249 strerror(errno));
4250
4251 /* Test a path that cannot be encoded, using junk data from the stack */
4252 junk[sizeof(junk)-1] = '\0';
4253 path = junk;
4254 res = pr_fs_encode_path(p, path);
4255 fail_unless(res != NULL, "Failed to encode path: %s", strerror(errno));
4256 }
4257 END_TEST
4258
START_TEST(fs_split_path_test)4259 START_TEST (fs_split_path_test) {
4260 array_header *res;
4261 const char *path, *elt;
4262
4263 mark_point();
4264 res = pr_fs_split_path(NULL, NULL);
4265 fail_unless(res == NULL, "Failed to handle null pool");
4266 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
4267 strerror(errno), errno);
4268
4269 mark_point();
4270 res = pr_fs_split_path(p, NULL);
4271 fail_unless(res == NULL, "Failed to handle null path");
4272 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
4273 strerror(errno), errno);
4274
4275 path = "";
4276
4277 mark_point();
4278 res = pr_fs_split_path(p, path);
4279 fail_unless(res == NULL, "Failed to handle empty path");
4280 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
4281 strerror(errno), errno);
4282
4283 path = "/";
4284
4285 mark_point();
4286 res = pr_fs_split_path(p, path);
4287 fail_unless(res != NULL, "Failed to split path '%s': %s", path,
4288 strerror(errno));
4289 fail_unless(res->nelts == 1, "Expected 1, got %u", res->nelts);
4290 elt = ((char **) res->elts)[0];
4291 fail_unless(strcmp(elt, "/") == 0, "Expected '/', got '%s'", elt);
4292
4293 path = "///";
4294
4295 mark_point();
4296 res = pr_fs_split_path(p, path);
4297 fail_unless(res != NULL, "Failed to split path '%s': %s", path,
4298 strerror(errno));
4299 fail_unless(res->nelts == 1, "Expected 1, got %u", res->nelts);
4300 elt = ((char **) res->elts)[0];
4301 fail_unless(strcmp(elt, "/") == 0, "Expected '/', got '%s'", elt);
4302
4303 path = "/foo/bar/baz/";
4304
4305 mark_point();
4306 res = pr_fs_split_path(p, path);
4307 fail_unless(res != NULL, "Failed to split path '%s': %s", path,
4308 strerror(errno));
4309 fail_unless(res->nelts == 4, "Expected 4, got %u", res->nelts);
4310 elt = ((char **) res->elts)[0];
4311 fail_unless(strcmp(elt, "/") == 0, "Expected '/', got '%s'", elt);
4312 elt = ((char **) res->elts)[1];
4313 fail_unless(strcmp(elt, "foo") == 0, "Expected 'foo', got '%s'", elt);
4314 elt = ((char **) res->elts)[2];
4315 fail_unless(strcmp(elt, "bar") == 0, "Expected 'bar', got '%s'", elt);
4316 elt = ((char **) res->elts)[3];
4317 fail_unless(strcmp(elt, "baz") == 0, "Expected 'baz', got '%s'", elt);
4318
4319 path = "/foo//bar//baz//";
4320
4321 mark_point();
4322 res = pr_fs_split_path(p, path);
4323 fail_unless(res != NULL, "Failed to split path '%s': %s", path,
4324 strerror(errno));
4325 fail_unless(res->nelts == 4, "Expected 4, got %u", res->nelts);
4326 elt = ((char **) res->elts)[0];
4327 fail_unless(strcmp(elt, "/") == 0, "Expected '/', got '%s'", elt);
4328 elt = ((char **) res->elts)[1];
4329 fail_unless(strcmp(elt, "foo") == 0, "Expected 'foo', got '%s'", elt);
4330 elt = ((char **) res->elts)[2];
4331 fail_unless(strcmp(elt, "bar") == 0, "Expected 'bar', got '%s'", elt);
4332 elt = ((char **) res->elts)[3];
4333 fail_unless(strcmp(elt, "baz") == 0, "Expected 'baz', got '%s'", elt);
4334
4335 path = "/foo/bar/baz";
4336
4337 mark_point();
4338 res = pr_fs_split_path(p, path);
4339 fail_unless(res != NULL, "Failed to split path '%s': %s", path,
4340 strerror(errno));
4341 fail_unless(res->nelts == 4, "Expected 4, got %u", res->nelts);
4342 elt = ((char **) res->elts)[0];
4343 fail_unless(strcmp(elt, "/") == 0, "Expected '/', got '%s'", elt);
4344 elt = ((char **) res->elts)[1];
4345 fail_unless(strcmp(elt, "foo") == 0, "Expected 'foo', got '%s'", elt);
4346 elt = ((char **) res->elts)[2];
4347 fail_unless(strcmp(elt, "bar") == 0, "Expected 'bar', got '%s'", elt);
4348 elt = ((char **) res->elts)[3];
4349 fail_unless(strcmp(elt, "baz") == 0, "Expected 'baz', got '%s'", elt);
4350
4351 path = "foo/bar/baz";
4352
4353 mark_point();
4354 res = pr_fs_split_path(p, path);
4355 fail_unless(res != NULL, "Failed to split path '%s': %s", path,
4356 strerror(errno));
4357 fail_unless(res->nelts == 3, "Expected 3, got %u", res->nelts);
4358 elt = ((char **) res->elts)[0];
4359 fail_unless(strcmp(elt, "foo") == 0, "Expected 'foo', got '%s'", elt);
4360 elt = ((char **) res->elts)[1];
4361 fail_unless(strcmp(elt, "bar") == 0, "Expected 'bar', got '%s'", elt);
4362 elt = ((char **) res->elts)[2];
4363 fail_unless(strcmp(elt, "baz") == 0, "Expected 'baz', got '%s'", elt);
4364 }
4365 END_TEST
4366
START_TEST(fs_join_path_test)4367 START_TEST (fs_join_path_test) {
4368 char *path;
4369 array_header *components;
4370
4371 mark_point();
4372 path = pr_fs_join_path(NULL, NULL, 0);
4373 fail_unless(path == NULL, "Failed to handle null pool");
4374 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
4375 strerror(errno), errno);
4376
4377 mark_point();
4378 path = pr_fs_join_path(p, NULL, 0);
4379 fail_unless(path == NULL, "Failed to handle null components");
4380 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
4381 strerror(errno), errno);
4382
4383 components = make_array(p, 0, sizeof(char **));
4384
4385 mark_point();
4386 path = pr_fs_join_path(p, components, 0);
4387 fail_unless(path == NULL, "Failed to handle empty components");
4388 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
4389 strerror(errno), errno);
4390
4391 *((char **) push_array(components)) = pstrdup(p, "/");
4392
4393 mark_point();
4394 path = pr_fs_join_path(p, components, 0);
4395 fail_unless(path == NULL, "Failed to handle empty count");
4396 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
4397 strerror(errno), errno);
4398
4399 mark_point();
4400 path = pr_fs_join_path(p, components, 3);
4401 fail_unless(path == NULL, "Failed to handle invalid count");
4402 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
4403 strerror(errno), errno);
4404
4405 mark_point();
4406 path = pr_fs_join_path(p, components, 1);
4407 fail_unless(path != NULL, "Failed to join path: %s", strerror(errno));
4408 fail_unless(strcmp(path, "/") == 0, "Expected '/', got '%s'", path);
4409
4410 *((char **) push_array(components)) = pstrdup(p, "foo");
4411 *((char **) push_array(components)) = pstrdup(p, "bar");
4412 *((char **) push_array(components)) = pstrdup(p, "baz");
4413
4414 mark_point();
4415 path = pr_fs_join_path(p, components, 4);
4416 fail_unless(path != NULL, "Failed to join path: %s", strerror(errno));
4417 fail_unless(strcmp(path, "/foo/bar/baz") == 0,
4418 "Expected '/foo/bar/baz', got '%s'", path);
4419
4420 mark_point();
4421 path = pr_fs_join_path(p, components, 3);
4422 fail_unless(path != NULL, "Failed to join path: %s", strerror(errno));
4423 fail_unless(strcmp(path, "/foo/bar") == 0, "Expected '/foo/bar', got '%s'",
4424 path);
4425 }
4426 END_TEST
4427
START_TEST(fs_virtual_path_test)4428 START_TEST (fs_virtual_path_test) {
4429 const char *path;
4430 char buf[PR_TUNABLE_PATH_MAX];
4431
4432 mark_point();
4433 pr_fs_virtual_path(NULL, NULL, 0);
4434
4435 mark_point();
4436 path = "/tmp";
4437 pr_fs_virtual_path(path, NULL, 0);
4438
4439 mark_point();
4440 memset(buf, '\0', sizeof(buf));
4441 pr_fs_virtual_path(path, buf, 0);
4442 fail_unless(*buf == '\0', "Expected empty buffer, got '%s'", buf);
4443
4444 mark_point();
4445 memset(buf, '\0', sizeof(buf));
4446 pr_fs_virtual_path(path, buf, sizeof(buf)-1);
4447 fail_unless(strcmp(buf, path) == 0, "Expected '%s', got '%s'", path, buf);
4448
4449 mark_point();
4450 memset(buf, '\0', sizeof(buf));
4451 path = "tmp";
4452 pr_fs_virtual_path(path, buf, sizeof(buf)-1);
4453 fail_unless(strcmp(buf, "/tmp") == 0, "Expected '/tmp', got '%s'", path, buf);
4454
4455 mark_point();
4456 memset(buf, '\0', sizeof(buf));
4457 path = "/tmp/././";
4458 pr_fs_virtual_path(path, buf, sizeof(buf)-1);
4459 fail_unless(strcmp(buf, "/tmp") == 0 || strcmp(buf, "/tmp/") == 0,
4460 "Expected '/tmp', got '%s'", path, buf);
4461
4462 mark_point();
4463 memset(buf, '\0', sizeof(buf));
4464 path = "tmp/../../";
4465 pr_fs_virtual_path(path, buf, sizeof(buf)-1);
4466 fail_unless(strcmp(buf, "/") == 0, "Expected '/', got '%s'", path, buf);
4467 }
4468 END_TEST
4469
4470 #if 0
4471 /* This test is commented out, since libcheck is very unhappy when we
4472 * close its logging fds out from underneath it. Thus we keep this
4473 * test here, for any future tinkering, just not enabled by default.
4474 */
4475 START_TEST (fs_close_extra_fds_test) {
4476 mark_point();
4477 pr_fs_close_extra_fds();
4478 }
4479 END_TEST
4480 #endif
4481
START_TEST(fs_get_usable_fd_test)4482 START_TEST (fs_get_usable_fd_test) {
4483 int fd, res;
4484
4485 fd = -1;
4486 res = pr_fs_get_usable_fd(fd);
4487 fail_unless(res < 0, "Failed to handle bad fd");
4488 fail_unless(errno == EBADF || errno == EINVAL,
4489 "Expected EBADF (%d) or EINVAL (%d), got %s (%d)", EBADF, EINVAL,
4490 strerror(errno), errno);
4491
4492 fd = STDERR_FILENO + 1;
4493 res = pr_fs_get_usable_fd(fd);
4494 fail_unless(res == fd, "Expected %d, got %d", fd, res);
4495
4496 fd = STDERR_FILENO - 1;
4497 res = pr_fs_get_usable_fd(fd);
4498 fail_unless(res > STDERR_FILENO, "Failed to get usable fd for %d: %s", fd,
4499 strerror(errno));
4500 (void) close(res);
4501 }
4502 END_TEST
4503
START_TEST(fs_get_usable_fd2_test)4504 START_TEST (fs_get_usable_fd2_test) {
4505 int fd, res;
4506
4507 res = pr_fs_get_usable_fd2(NULL);
4508 fail_unless(res < 0, "Failed to handle null argument");
4509 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
4510 strerror(errno), errno);
4511
4512 fd = -1;
4513 res = pr_fs_get_usable_fd2(&fd);
4514 fail_unless(res < 0, "Failed to handle bad fd");
4515 fail_unless(errno == EBADF || errno == EINVAL,
4516 "Expected EBADF (%d) or EINVAL (%d), got %s (%d)", EBADF, EINVAL,
4517 strerror(errno), errno);
4518
4519 fd = STDERR_FILENO + 1;
4520 res = pr_fs_get_usable_fd2(&fd);
4521 fail_unless(res == 0, "Failed to handle fd: %s", strerror(errno));
4522 fail_unless(fd == (STDERR_FILENO + 1), "Expected %d, got %d",
4523 STDERR_FILENO + 1, fd);
4524
4525 fd = STDERR_FILENO - 1;
4526 res = pr_fs_get_usable_fd2(&fd);
4527 fail_unless(res == 0, "Failed to handle fd: %s", strerror(errno));
4528 fail_unless(fd > STDERR_FILENO, "Expected >%d, got %d", STDERR_FILENO, fd);
4529 (void) close(fd);
4530 }
4531 END_TEST
4532
START_TEST(fs_getsize_test)4533 START_TEST (fs_getsize_test) {
4534 off_t res;
4535 char *path;
4536
4537 res = pr_fs_getsize(NULL);
4538 fail_unless(res == (off_t) -1, "Failed to handle null argument");
4539 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
4540 strerror(errno), errno);
4541
4542 path = "/tmp";
4543 res = pr_fs_getsize(path);
4544 fail_unless(res != (off_t) -1, "Failed to get fs size for '%s': %s", path,
4545 strerror(errno));
4546 }
4547 END_TEST
4548
START_TEST(fs_getsize2_test)4549 START_TEST (fs_getsize2_test) {
4550 int res;
4551 char *path;
4552 off_t sz = 0;
4553
4554 res = pr_fs_getsize2(NULL, NULL);
4555 fail_unless(res < 0, "Failed to handle null arguments");
4556 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
4557 strerror(errno), errno);
4558
4559 path = "/tmp";
4560 res = pr_fs_getsize2(path, NULL);
4561 fail_unless(res < 0, "Failed to handle null size argument");
4562 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
4563 strerror(errno), errno);
4564
4565 res = pr_fs_getsize2(path, &sz);
4566 fail_unless(res == 0, "Failed to get fs size for '%s': %s", path,
4567 strerror(errno));
4568 }
4569 END_TEST
4570
START_TEST(fs_fgetsize_test)4571 START_TEST (fs_fgetsize_test) {
4572 int fd = -1, res;
4573 off_t fs_sz = 0;
4574
4575 mark_point();
4576 res = pr_fs_fgetsize(fd, &fs_sz);
4577 fail_unless(res < 0, "Failed to handle bad file descriptor");
4578 fail_unless(errno == EBADF, "Expected EBADF (%d), got %s (%d)", EBADF,
4579 strerror(errno), errno);
4580
4581 mark_point();
4582 fd = 0;
4583 fs_sz = 0;
4584 res = pr_fs_fgetsize(fd, NULL);
4585 fail_unless(res < 0, "Failed to handle null size argument");
4586 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
4587 strerror(errno), errno);
4588
4589 mark_point();
4590 fd = 0;
4591 fs_sz = 0;
4592 res = pr_fs_fgetsize(fd, &fs_sz);
4593 fail_unless(res == 0, "Failed to get fs size for fd %d: %s", fd,
4594 strerror(errno));
4595 }
4596 END_TEST
4597
START_TEST(fs_fadvise_test)4598 START_TEST (fs_fadvise_test) {
4599 int advice, fd = -1;
4600 off_t off = 0, len = 0;
4601
4602 /* We make these function calls to exercise the code paths, even
4603 * though there's no good way to verify the behavior changed.
4604 */
4605
4606 advice = PR_FS_FADVISE_NORMAL;
4607 pr_fs_fadvise(fd, off, len, advice);
4608
4609 advice = PR_FS_FADVISE_RANDOM;
4610 pr_fs_fadvise(fd, off, len, advice);
4611
4612 advice = PR_FS_FADVISE_SEQUENTIAL;
4613 pr_fs_fadvise(fd, off, len, advice);
4614
4615 advice = PR_FS_FADVISE_WILLNEED;
4616 pr_fs_fadvise(fd, off, len, advice);
4617
4618 advice = PR_FS_FADVISE_DONTNEED;
4619 pr_fs_fadvise(fd, off, len, advice);
4620
4621 advice = PR_FS_FADVISE_NOREUSE;
4622 pr_fs_fadvise(fd, off, len, advice);
4623 }
4624 END_TEST
4625
START_TEST(fs_have_access_test)4626 START_TEST (fs_have_access_test) {
4627 int res;
4628 struct stat st;
4629 uid_t uid;
4630 gid_t gid;
4631 array_header *suppl_gids;
4632
4633 mark_point();
4634 res = pr_fs_have_access(NULL, R_OK, 0, 0, NULL);
4635 fail_unless(res < 0, "Failed to handle null stat");
4636 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
4637 strerror(errno), errno);
4638
4639 memset(&st, 0, sizeof(struct stat));
4640
4641 mark_point();
4642 res = pr_fs_have_access(&st, R_OK, 0, 0, NULL);
4643 fail_unless(res == 0, "Failed to handle root access: %s", strerror(errno));
4644
4645 /* Use cases: no matching UID or GID; R_OK, W_OK, X_OK. */
4646 memset(&st, 0, sizeof(struct stat));
4647 uid = 1;
4648 gid = 1;
4649
4650 mark_point();
4651 res = pr_fs_have_access(&st, R_OK, uid, gid, NULL);
4652 fail_unless(res < 0, "Failed to handle missing other R_OK access");
4653 fail_unless(errno == EACCES, "Expected EACCES (%d), got %s (%d)", EACCES,
4654 strerror(errno), errno);
4655
4656 mark_point();
4657 res = pr_fs_have_access(&st, W_OK, uid, gid, NULL);
4658 fail_unless(res < 0, "Failed to handle missing other W_OK access");
4659 fail_unless(errno == EACCES, "Expected EACCES (%d), got %s (%d)", EACCES,
4660 strerror(errno), errno);
4661
4662 mark_point();
4663 res = pr_fs_have_access(&st, X_OK, uid, gid, NULL);
4664 fail_unless(res < 0, "Failed to handle missing other X_OK access");
4665 fail_unless(errno == EACCES, "Expected EACCES (%d), got %s (%d)", EACCES,
4666 strerror(errno), errno);
4667
4668 st.st_mode = S_IFMT|S_IROTH|S_IWOTH|S_IXOTH;
4669
4670 mark_point();
4671 res = pr_fs_have_access(&st, R_OK, uid, gid, NULL);
4672 fail_unless(res == 0, "Failed to handle other R_OK access: %s",
4673 strerror(errno));
4674
4675 mark_point();
4676 res = pr_fs_have_access(&st, W_OK, uid, gid, NULL);
4677 fail_unless(res == 0, "Failed to handle other W_OK access: %s",
4678 strerror(errno));
4679
4680 mark_point();
4681 res = pr_fs_have_access(&st, X_OK, uid, gid, NULL);
4682 fail_unless(res == 0, "Failed to handle other X_OK access: %s",
4683 strerror(errno));
4684
4685 /* Use cases: matching UID, not GID; R_OK, W_OK, X_OK. */
4686 memset(&st, 0, sizeof(struct stat));
4687
4688 st.st_uid = uid;
4689
4690 mark_point();
4691 res = pr_fs_have_access(&st, R_OK, uid, gid, NULL);
4692 fail_unless(res < 0, "Failed to handle missing user R_OK access");
4693 fail_unless(errno == EACCES, "Expected EACCES (%d), got %s (%d)", EACCES,
4694 strerror(errno), errno);
4695
4696 mark_point();
4697 res = pr_fs_have_access(&st, W_OK, uid, gid, NULL);
4698 fail_unless(res < 0, "Failed to handle missing user W_OK access");
4699 fail_unless(errno == EACCES, "Expected EACCES (%d), got %s (%d)", EACCES,
4700 strerror(errno), errno);
4701
4702 mark_point();
4703 res = pr_fs_have_access(&st, X_OK, uid, gid, NULL);
4704 fail_unless(res < 0, "Failed to handle missing user X_OK access");
4705 fail_unless(errno == EACCES, "Expected EACCES (%d), got %s (%d)", EACCES,
4706 strerror(errno), errno);
4707
4708 st.st_mode = S_IFMT|S_IRUSR|S_IWUSR|S_IXUSR;
4709
4710 mark_point();
4711 res = pr_fs_have_access(&st, R_OK, uid, gid, NULL);
4712 fail_unless(res == 0, "Failed to handle user R_OK access: %s",
4713 strerror(errno));
4714
4715 mark_point();
4716 res = pr_fs_have_access(&st, W_OK, uid, gid, NULL);
4717 fail_unless(res == 0, "Failed to handle user W_OK access: %s",
4718 strerror(errno));
4719
4720 mark_point();
4721 res = pr_fs_have_access(&st, X_OK, uid, gid, NULL);
4722 fail_unless(res == 0, "Failed to handle user X_OK access: %s",
4723 strerror(errno));
4724
4725 /* Use cases: matching GID, not UID; R_OK, W_OK, X_OK. */
4726 memset(&st, 0, sizeof(struct stat));
4727
4728 st.st_gid = gid;
4729
4730 mark_point();
4731 res = pr_fs_have_access(&st, R_OK, uid, gid, NULL);
4732 fail_unless(res < 0, "Failed to handle missing group R_OK access");
4733 fail_unless(errno == EACCES, "Expected EACCES (%d), got %s (%d)", EACCES,
4734 strerror(errno), errno);
4735
4736 mark_point();
4737 res = pr_fs_have_access(&st, W_OK, uid, gid, NULL);
4738 fail_unless(res < 0, "Failed to handle missing group W_OK access");
4739 fail_unless(errno == EACCES, "Expected EACCES (%d), got %s (%d)", EACCES,
4740 strerror(errno), errno);
4741
4742 mark_point();
4743 res = pr_fs_have_access(&st, X_OK, uid, gid, NULL);
4744 fail_unless(res < 0, "Failed to handle missing group X_OK access");
4745 fail_unless(errno == EACCES, "Expected EACCES (%d), got %s (%d)", EACCES,
4746 strerror(errno), errno);
4747
4748 st.st_mode = S_IFMT|S_IRGRP|S_IWGRP|S_IXGRP;
4749
4750 mark_point();
4751 res = pr_fs_have_access(&st, R_OK, uid, gid, NULL);
4752 fail_unless(res == 0, "Failed to handle group R_OK access: %s",
4753 strerror(errno));
4754
4755 mark_point();
4756 res = pr_fs_have_access(&st, W_OK, uid, gid, NULL);
4757 fail_unless(res == 0, "Failed to handle group W_OK access: %s",
4758 strerror(errno));
4759
4760 mark_point();
4761 res = pr_fs_have_access(&st, X_OK, uid, gid, NULL);
4762 fail_unless(res == 0, "Failed to handle group X_OK access: %s",
4763 strerror(errno));
4764
4765 /* Use cases: matching suppl GID, not UID; R_OK, W_OK, X_OK. */
4766 memset(&st, 0, sizeof(struct stat));
4767
4768 suppl_gids = make_array(p, 1, sizeof(gid_t));
4769 *((gid_t *) push_array(suppl_gids)) = 100;
4770 *((gid_t *) push_array(suppl_gids)) = gid;
4771 st.st_gid = gid;
4772
4773 mark_point();
4774 res = pr_fs_have_access(&st, R_OK, uid, 0, suppl_gids);
4775 fail_unless(res < 0, "Failed to handle missing group R_OK access");
4776 fail_unless(errno == EACCES, "Expected EACCES (%d), got %s (%d)", EACCES,
4777 strerror(errno), errno);
4778
4779 mark_point();
4780 res = pr_fs_have_access(&st, W_OK, uid, 0, suppl_gids);
4781 fail_unless(res < 0, "Failed to handle missing group W_OK access");
4782 fail_unless(errno == EACCES, "Expected EACCES (%d), got %s (%d)", EACCES,
4783 strerror(errno), errno);
4784
4785 mark_point();
4786 res = pr_fs_have_access(&st, X_OK, uid, 0, suppl_gids);
4787 fail_unless(res < 0, "Failed to handle missing group X_OK access");
4788 fail_unless(errno == EACCES, "Expected EACCES (%d), got %s (%d)", EACCES,
4789 strerror(errno), errno);
4790
4791 st.st_mode = S_IFMT|S_IRGRP|S_IWGRP|S_IXGRP;
4792
4793 mark_point();
4794 res = pr_fs_have_access(&st, R_OK, uid, 0, suppl_gids);
4795 fail_unless(res == 0, "Failed to handle group R_OK access: %s",
4796 strerror(errno));
4797
4798 mark_point();
4799 res = pr_fs_have_access(&st, W_OK, uid, 0, suppl_gids);
4800 fail_unless(res == 0, "Failed to handle group W_OK access: %s",
4801 strerror(errno));
4802
4803 mark_point();
4804 res = pr_fs_have_access(&st, X_OK, uid, 0, suppl_gids);
4805 fail_unless(res == 0, "Failed to handle group X_OK access: %s",
4806 strerror(errno));
4807 }
4808 END_TEST
4809
START_TEST(fs_is_nfs_test)4810 START_TEST (fs_is_nfs_test) {
4811 int res;
4812
4813 res = pr_fs_is_nfs(NULL);
4814 fail_unless(res < 0, "Failed to handle null argument");
4815 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
4816 strerror(errno), errno);
4817
4818 res = pr_fs_is_nfs("/tmp");
4819 fail_unless(res == FALSE, "Expected FALSE, got %d", res);
4820 }
4821 END_TEST
4822
START_TEST(fs_valid_path_test)4823 START_TEST (fs_valid_path_test) {
4824 int res;
4825 const char *path;
4826 pr_fs_t *fs;
4827
4828 res = pr_fs_valid_path(NULL);
4829 fail_unless(res < 0, "Failed to handle null arguments");
4830 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
4831 strerror(errno), errno);
4832
4833 path = "/";
4834 res = pr_fs_valid_path(path);
4835 fail_unless(res == 0, "'%s' is not a valid path: %s", path, strerror(errno));
4836
4837 path = ":tmp";
4838 res = pr_fs_valid_path(path);
4839 fail_unless(res < 0, "Failed to handle invalid path");
4840 fail_unless(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
4841 strerror(errno), errno);
4842
4843 fs = pr_register_fs(p, "testsuite", "&");
4844 fail_unless(fs != NULL, "Failed to register FS: %s", strerror(errno));
4845
4846 fs = pr_register_fs(p, "testsuite2", ":");
4847 fail_unless(fs != NULL, "Failed to register FS: %s", strerror(errno));
4848
4849 res = pr_fs_valid_path(path);
4850 fail_unless(res == 0, "Failed to handle valid path: %s", strerror(errno));
4851
4852 (void) pr_remove_fs("/testsuite2");
4853 (void) pr_remove_fs("/testsuite");
4854 }
4855 END_TEST
4856
START_TEST(fsio_smkdir_test)4857 START_TEST (fsio_smkdir_test) {
4858 int res;
4859 const char *path;
4860 mode_t mode = 0755;
4861 uid_t uid = getuid();
4862 gid_t gid = getgid();
4863
4864 res = pr_fsio_smkdir(NULL, NULL, mode, uid, gid);
4865 fail_unless(res < 0, "Failed to handle null arguments");
4866 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
4867 strerror(errno), errno);
4868
4869 res = pr_fsio_smkdir(p, NULL, mode, uid, gid);
4870 fail_unless(res < 0, "Failed to handle null path");
4871 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
4872 strerror(errno), errno);
4873
4874 path = fsio_testdir_path;
4875 res = pr_fsio_smkdir(p, path, mode, uid, gid);
4876 fail_unless(res == 0, "Failed to securely create '%s': %s", fsio_testdir_path,
4877 strerror(errno));
4878 (void) pr_fsio_rmdir(fsio_testdir_path);
4879
4880 res = pr_fsio_set_use_mkdtemp(-1);
4881 fail_unless(res < 0, "Failed to handle invalid setting");
4882 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
4883 strerror(errno), errno);
4884
4885 #ifdef HAVE_MKDTEMP
4886 res = pr_fsio_set_use_mkdtemp(FALSE);
4887 fail_unless(res == TRUE, "Expected TRUE, got %d", res);
4888
4889 res = pr_fsio_smkdir(p, path, mode, uid, gid);
4890 fail_unless(res == 0, "Failed to securely create '%s': %s", fsio_testdir_path,
4891 strerror(errno));
4892 (void) pr_fsio_rmdir(fsio_testdir_path);
4893
4894 res = pr_fsio_set_use_mkdtemp(TRUE);
4895 fail_unless(res == FALSE, "Expected FALSE, got %d", res);
4896 #else
4897 res = pr_fsio_set_use_mkdtemp(TRUE);
4898 fail_unless(res == FALSE, "Expected FALSE, got %d", res);
4899
4900 res = pr_fsio_set_use_mkdtemp(FALSE);
4901 fail_unless(res == FALSE, "Expected FALSE, got %d", res);
4902 #endif /* HAVE_MKDTEMP */
4903
4904 (void) pr_fsio_rmdir(fsio_testdir_path);
4905 }
4906 END_TEST
4907
START_TEST(fsio_getpipebuf_test)4908 START_TEST (fsio_getpipebuf_test) {
4909 char *res;
4910 int fd = -1;
4911 long bufsz = 0;
4912
4913 res = pr_fsio_getpipebuf(NULL, fd, NULL);
4914 fail_unless(res == NULL, "Failed to handle null arguments");
4915 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
4916 strerror(errno), errno);
4917
4918 res = pr_fsio_getpipebuf(p, fd, NULL);
4919 fail_unless(res == NULL, "Failed to handle bad file descriptor");
4920 fail_unless(errno == EBADF, "Expected EBADF (%d), got %s (%d)", EBADF,
4921 strerror(errno), errno);
4922
4923 fd = 0;
4924 res = pr_fsio_getpipebuf(p, fd, NULL);
4925 fail_unless(res != NULL, "Failed to get pipebuf for fd %d: %s", fd,
4926 strerror(errno));
4927
4928 res = pr_fsio_getpipebuf(p, fd, &bufsz);
4929 fail_unless(res != NULL, "Failed to get pipebuf for fd %d: %s", fd,
4930 strerror(errno));
4931 fail_unless(bufsz > 0, "Expected >0, got %ld", bufsz);
4932 }
4933 END_TEST
4934
START_TEST(fsio_gets_test)4935 START_TEST (fsio_gets_test) {
4936 char buf[PR_TUNABLE_PATH_MAX], *res, *text;
4937 pr_fh_t *fh;
4938 int res2;
4939
4940 res = pr_fsio_gets(NULL, 0, NULL);
4941 fail_unless(res == NULL, "Failed to handle null arguments");
4942 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
4943 strerror(errno), errno);
4944
4945 res = pr_fsio_gets(buf, 0, NULL);
4946 fail_unless(res == NULL, "Failed to handle null file handle");
4947 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
4948 strerror(errno), errno);
4949
4950 fh = pr_fsio_open(fsio_test_path, O_CREAT|O_EXCL|O_RDWR);
4951 fail_unless(fh != NULL, "Failed to open '%s': %s", fsio_test_path,
4952 strerror(errno));
4953
4954 res = pr_fsio_gets(buf, 0, fh);
4955 fail_unless(res == NULL, "Failed to handle zero buffer length");
4956 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
4957 strerror(errno), errno);
4958
4959 text = "Hello, World!\n";
4960 res2 = pr_fsio_puts(text, fh);
4961 fail_if(res2 < 0, "Error writing to '%s': %s", fsio_test_path,
4962 strerror(errno));
4963 pr_fsio_fsync(fh);
4964 pr_fsio_lseek(fh, 0, SEEK_SET);
4965
4966 memset(buf, '\0', sizeof(buf));
4967 res = pr_fsio_gets(buf, sizeof(buf)-1, fh);
4968 fail_if(res == NULL, "Failed reading from '%s': %s", fsio_test_path,
4969 strerror(errno));
4970 fail_unless(strcmp(res, text) == 0, "Expected '%s', got '%s'", text, res);
4971
4972 (void) pr_fsio_close(fh);
4973 (void) pr_fsio_unlink(fsio_test_path);
4974 }
4975 END_TEST
4976
START_TEST(fsio_getline_test)4977 START_TEST (fsio_getline_test) {
4978 char buf[PR_TUNABLE_PATH_MAX], *res, *text;
4979 pr_fh_t *fh;
4980 unsigned int lineno = 0;
4981 int res2;
4982
4983 res = pr_fsio_getline(NULL, 0, NULL, NULL);
4984 fail_unless(res == NULL, "Failed to handle null arguments");
4985 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
4986 strerror(errno), errno);
4987
4988 res = pr_fsio_getline(buf, 0, NULL, NULL);
4989 fail_unless(res == NULL, "Failed to handle file handle");
4990 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
4991 strerror(errno), errno);
4992
4993 fh = pr_fsio_open(fsio_test_path, O_CREAT|O_EXCL|O_RDWR);
4994 fail_unless(fh != NULL, "Failed to open '%s': %s", fsio_test_path,
4995 strerror(errno));
4996
4997 res = pr_fsio_getline(buf, 0, fh, NULL);
4998 fail_unless(res == NULL, "Failed to handle zero buffer length");
4999 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
5000 strerror(errno), errno);
5001
5002 res = pr_fsio_getline(buf, sizeof(buf)-1, fh, &lineno);
5003 fail_unless(res == NULL, "Failed to read empty '%s' file", fsio_test_path);
5004
5005 text = "Hello, World!\n";
5006 res2 = pr_fsio_puts(text, fh);
5007 fail_if(res2 < 0, "Error writing to '%s': %s", fsio_test_path,
5008 strerror(errno));
5009
5010 text = "How\\\n are you?\n";
5011 res2 = pr_fsio_puts(text, fh);
5012 fail_if(res2 < 0, "Error writing to '%s': %s", fsio_test_path,
5013 strerror(errno));
5014
5015 pr_fsio_fsync(fh);
5016 pr_fsio_lseek(fh, 0, SEEK_SET);
5017
5018 memset(buf, '\0', sizeof(buf));
5019 res = pr_fsio_getline(buf, sizeof(buf)-1, fh, &lineno);
5020 fail_if(res == NULL, "Failed to read line from '%s': %s", fsio_test_path,
5021 strerror(errno));
5022 fail_unless(strcmp(res, "Hello, World!\n") == 0,
5023 "Expected 'Hello, World!\n', got '%s'", res);
5024 fail_unless(lineno == 1, "Expected 1, got %u", lineno);
5025
5026 memset(buf, '\0', sizeof(buf));
5027 res = pr_fsio_getline(buf, sizeof(buf)-1, fh, &lineno);
5028 fail_if(res == NULL, "Failed to read line from '%s': %s", fsio_test_path,
5029 strerror(errno));
5030 fail_unless(strcmp(res, "How are you?\n") == 0,
5031 "Expected 'How are you?\n', got '%s'", res);
5032 fail_unless(lineno == 3, "Expected 3, got %u", lineno);
5033
5034 (void) pr_fsio_close(fh);
5035 (void) pr_fsio_unlink(fsio_test_path);
5036 }
5037 END_TEST
5038
START_TEST(fsio_puts_test)5039 START_TEST (fsio_puts_test) {
5040 int res;
5041 const char *text;
5042 pr_fh_t *fh;
5043
5044 res = pr_fsio_puts(NULL, NULL);
5045 fail_unless(res < 0, "Failed to handle null arguments");
5046 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
5047 strerror(errno), errno);
5048
5049 text = "Hello, World!\n";
5050 res = pr_fsio_puts(text, NULL);
5051 fail_unless(res < 0, "Failed to handle null file handle");
5052 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
5053 strerror(errno), errno);
5054
5055 fh = pr_fsio_open(fsio_test_path, O_CREAT|O_EXCL|O_WRONLY);
5056 fail_unless(fh != NULL, "Failed to open '%s': %s", fsio_test_path,
5057 strerror(errno));
5058
5059 res = pr_fsio_puts(NULL, fh);
5060 fail_unless(res < 0, "Failed to handle null buffer");
5061 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
5062 strerror(errno), errno);
5063
5064 (void) pr_fsio_close(fh);
5065 (void) pr_fsio_unlink(fsio_test_path);
5066 }
5067 END_TEST
5068
START_TEST(fsio_blocking_test)5069 START_TEST (fsio_blocking_test) {
5070 int fd, res;
5071 pr_fh_t *fh;
5072
5073 res = pr_fsio_set_block(NULL);
5074 fail_unless(res < 0, "Failed to handle null argument");
5075 fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
5076 strerror(errno), errno);
5077
5078 fh = pr_fsio_open(fsio_test_path, O_CREAT|O_EXCL|O_WRONLY);
5079 fail_unless(fh != NULL, "Failed to open '%s': %s", fsio_test_path,
5080 strerror(errno));
5081
5082 fd = fh->fh_fd;
5083 fh->fh_fd = -1;
5084
5085 res = pr_fsio_set_block(fh);
5086 fail_unless(res < 0, "Failed to handle bad file descriptor");
5087 fail_unless(errno == EBADF, "Expected EBADF (%d), got %s (%d)", EBADF,
5088 strerror(errno), errno);
5089
5090 fh->fh_fd = fd;
5091 res = pr_fsio_set_block(fh);
5092 fail_unless(res == 0, "Failed to make '%s' blocking: %s", fsio_test_path,
5093 strerror(errno));
5094
5095 (void) pr_fsio_close(fh);
5096 (void) pr_fsio_unlink(fsio_test_path);
5097 }
5098 END_TEST
5099
tests_get_fsio_suite(void)5100 Suite *tests_get_fsio_suite(void) {
5101 Suite *suite;
5102 TCase *testcase;
5103
5104 suite = suite_create("fsio");
5105
5106 testcase = tcase_create("base");
5107 tcase_add_checked_fixture(testcase, set_up, tear_down);
5108
5109 /* Main FSIO API tests */
5110 tcase_add_test(testcase, fsio_sys_open_test);
5111 tcase_add_test(testcase, fsio_sys_open_canon_test);
5112 tcase_add_test(testcase, fsio_sys_open_chroot_guard_test);
5113 tcase_add_test(testcase, fsio_sys_close_test);
5114 tcase_add_test(testcase, fsio_sys_unlink_test);
5115 tcase_add_test(testcase, fsio_sys_unlink_chroot_guard_test);
5116 tcase_add_test(testcase, fsio_sys_stat_test);
5117 tcase_add_test(testcase, fsio_sys_fstat_test);
5118 tcase_add_test(testcase, fsio_sys_read_test);
5119 tcase_add_test(testcase, fsio_sys_pread_test);
5120 tcase_add_test(testcase, fsio_sys_write_test);
5121 tcase_add_test(testcase, fsio_sys_pwrite_test);
5122 tcase_add_test(testcase, fsio_sys_lseek_test);
5123 tcase_add_test(testcase, fsio_sys_link_test);
5124 tcase_add_test(testcase, fsio_sys_link_chroot_guard_test);
5125 tcase_add_test(testcase, fsio_sys_symlink_test);
5126 tcase_add_test(testcase, fsio_sys_symlink_chroot_guard_test);
5127 tcase_add_test(testcase, fsio_sys_readlink_test);
5128 tcase_add_test(testcase, fsio_sys_lstat_test);
5129 tcase_add_test(testcase, fsio_sys_access_dir_test);
5130 tcase_add_test(testcase, fsio_sys_access_file_test);
5131 tcase_add_test(testcase, fsio_sys_faccess_test);
5132 tcase_add_test(testcase, fsio_sys_truncate_test);
5133 tcase_add_test(testcase, fsio_sys_truncate_chroot_guard_test);
5134 tcase_add_test(testcase, fsio_sys_ftruncate_test);
5135 tcase_add_test(testcase, fsio_sys_chmod_test);
5136 tcase_add_test(testcase, fsio_sys_chmod_chroot_guard_test);
5137 tcase_add_test(testcase, fsio_sys_fchmod_test);
5138 tcase_add_test(testcase, fsio_sys_chown_test);
5139 tcase_add_test(testcase, fsio_sys_chown_chroot_guard_test);
5140 tcase_add_test(testcase, fsio_sys_fchown_test);
5141 tcase_add_test(testcase, fsio_sys_lchown_test);
5142 tcase_add_test(testcase, fsio_sys_lchown_chroot_guard_test);
5143 tcase_add_test(testcase, fsio_sys_rename_test);
5144 tcase_add_test(testcase, fsio_sys_rename_chroot_guard_test);
5145 tcase_add_test(testcase, fsio_sys_utimes_test);
5146 tcase_add_test(testcase, fsio_sys_utimes_chroot_guard_test);
5147 tcase_add_test(testcase, fsio_sys_futimes_test);
5148 tcase_add_test(testcase, fsio_sys_fsync_test);
5149
5150 /* Extended attribute tests */
5151 tcase_add_test(testcase, fsio_sys_getxattr_test);
5152 tcase_add_test(testcase, fsio_sys_lgetxattr_test);
5153 tcase_add_test(testcase, fsio_sys_fgetxattr_test);
5154 tcase_add_test(testcase, fsio_sys_listxattr_test);
5155 tcase_add_test(testcase, fsio_sys_llistxattr_test);
5156 tcase_add_test(testcase, fsio_sys_flistxattr_test);
5157 tcase_add_test(testcase, fsio_sys_removexattr_test);
5158 tcase_add_test(testcase, fsio_sys_lremovexattr_test);
5159 tcase_add_test(testcase, fsio_sys_fremovexattr_test);
5160 tcase_add_test(testcase, fsio_sys_setxattr_test);
5161 tcase_add_test(testcase, fsio_sys_lsetxattr_test);
5162 tcase_add_test(testcase, fsio_sys_fsetxattr_test);
5163
5164 tcase_add_test(testcase, fsio_sys_mkdir_test);
5165 tcase_add_test(testcase, fsio_sys_mkdir_chroot_guard_test);
5166 tcase_add_test(testcase, fsio_sys_rmdir_test);
5167 tcase_add_test(testcase, fsio_sys_rmdir_chroot_guard_test);
5168 tcase_add_test(testcase, fsio_sys_chdir_test);
5169 tcase_add_test(testcase, fsio_sys_chdir_canon_test);
5170 tcase_add_test(testcase, fsio_sys_chroot_test);
5171 tcase_add_test(testcase, fsio_sys_opendir_test);
5172 tcase_add_test(testcase, fsio_sys_readdir_test);
5173 tcase_add_test(testcase, fsio_sys_closedir_test);
5174
5175 /* FSIO with error tests */
5176 tcase_add_test(testcase, fsio_sys_chmod_with_error_test);
5177 tcase_add_test(testcase, fsio_sys_chown_with_error_test);
5178 tcase_add_test(testcase, fsio_sys_chroot_with_error_test);
5179 tcase_add_test(testcase, fsio_sys_close_with_error_test);
5180 tcase_add_test(testcase, fsio_sys_fchmod_with_error_test);
5181 tcase_add_test(testcase, fsio_sys_fchown_with_error_test);
5182 tcase_add_test(testcase, fsio_sys_lchown_with_error_test);
5183 tcase_add_test(testcase, fsio_sys_lstat_with_error_test);
5184 tcase_add_test(testcase, fsio_sys_mkdir_with_error_test);
5185 tcase_add_test(testcase, fsio_sys_open_with_error_test);
5186 tcase_add_test(testcase, fsio_sys_read_with_error_test);
5187 tcase_add_test(testcase, fsio_sys_rename_with_error_test);
5188 tcase_add_test(testcase, fsio_sys_rmdir_with_error_test);
5189 tcase_add_test(testcase, fsio_sys_stat_with_error_test);
5190 tcase_add_test(testcase, fsio_sys_unlink_with_error_test);
5191 tcase_add_test(testcase, fsio_sys_write_with_error_test);
5192
5193 /* FSIO statcache tests */
5194 tcase_add_test(testcase, fsio_statcache_clear_cache_test);
5195 tcase_add_test(testcase, fsio_statcache_cache_hit_test);
5196 tcase_add_test(testcase, fsio_statcache_negative_cache_test);
5197 tcase_add_test(testcase, fsio_statcache_expired_test);
5198 tcase_add_test(testcase, fsio_statcache_dump_test);
5199
5200 /* Custom FSIO management tests */
5201 tcase_add_test(testcase, fs_create_fs_test);
5202 tcase_add_test(testcase, fs_insert_fs_test);
5203 tcase_add_test(testcase, fs_get_fs_test);
5204 tcase_add_test(testcase, fs_unmount_fs_test);
5205 tcase_add_test(testcase, fs_remove_fs_test);
5206 tcase_add_test(testcase, fs_register_fs_test);
5207 tcase_add_test(testcase, fs_unregister_fs_test);
5208 tcase_add_test(testcase, fs_resolve_fs_map_test);
5209 #if defined(PR_USE_DEVEL)
5210 tcase_add_test(testcase, fs_dump_fs_test);
5211 #endif /* PR_USE_DEVEL */
5212
5213 /* Custom FSIO tests */
5214 tcase_add_test(testcase, fsio_custom_chroot_test);
5215
5216 /* Misc */
5217 tcase_add_test(testcase, fs_clean_path_test);
5218 tcase_add_test(testcase, fs_clean_path2_test);
5219
5220 tcase_add_test(testcase, fs_dircat_test);
5221 tcase_add_test(testcase, fs_setcwd_test);
5222 tcase_add_test(testcase, fs_glob_test);
5223 tcase_add_test(testcase, fs_copy_file_test);
5224 tcase_add_test(testcase, fs_copy_file2_test);
5225 tcase_add_test(testcase, fs_interpolate_test);
5226 tcase_add_test(testcase, fs_resolve_partial_test);
5227 tcase_add_test(testcase, fs_resolve_path_test);
5228 tcase_add_test(testcase, fs_use_encoding_test);
5229 tcase_add_test(testcase, fs_decode_path2_test);
5230 tcase_add_test(testcase, fs_encode_path_test);
5231 tcase_add_test(testcase, fs_split_path_test);
5232 tcase_add_test(testcase, fs_join_path_test);
5233 tcase_add_test(testcase, fs_virtual_path_test);
5234 #if 0
5235 tcase_add_test(testcase, fs_close_extra_fds_test);
5236 #endif
5237 tcase_add_test(testcase, fs_get_usable_fd_test);
5238 tcase_add_test(testcase, fs_get_usable_fd2_test);
5239 tcase_add_test(testcase, fs_getsize_test);
5240 tcase_add_test(testcase, fs_getsize2_test);
5241 tcase_add_test(testcase, fs_fgetsize_test);
5242 tcase_add_test(testcase, fs_fadvise_test);
5243 tcase_add_test(testcase, fs_have_access_test);
5244 #if defined(HAVE_STATFS_F_TYPE) || defined(HAVE_STATFS_F_FSTYPENAME)
5245 tcase_add_test(testcase, fs_is_nfs_test);
5246 #endif
5247 tcase_add_test(testcase, fs_valid_path_test);
5248 tcase_add_test(testcase, fsio_smkdir_test);
5249 tcase_add_test(testcase, fsio_getpipebuf_test);
5250 tcase_add_test(testcase, fsio_gets_test);
5251 tcase_add_test(testcase, fsio_getline_test);
5252 tcase_add_test(testcase, fsio_puts_test);
5253 tcase_add_test(testcase, fsio_blocking_test);
5254
5255 suite_add_tcase(suite, testcase);
5256 return suite;
5257 }
5258