libfuse: test/test_syscalls.c Source File

libfuse

test_syscalls.c
1#define _GNU_SOURCE
2#include "fuse_config.h"
3
4#include <stdio.h>
5#include <stdlib.h>
6#include <stdarg.h>
7#include <string.h>
8#include <unistd.h>
9#include <fcntl.h>
10#include <dirent.h>
11#include <utime.h>
12#include <errno.h>
13#include <assert.h>
14#include <time.h>
15#include <sys/socket.h>
16#include <sys/types.h>
17#include <sys/stat.h>
18#include <sys/un.h>
19
20#ifndef ALLPERMS
21# define ALLPERMS (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO)/* 07777 */
22#endif
23
24
25static const char *basepath;
26static const char *basepath_r;
27static char testfile[1024];
28static char testfile2[1024];
29static char testdir[1024];
30static char testdir2[1024];
31static char testsock[1024];
32static char subfile[1280];
33
34static char testfile_r[1024];
35static char testfile2_r[1024];
36static char testdir_r[1024];
37static char testdir2_r[1024];
38static char subfile_r[1280];
39
40static char testname[256];
41static char testdata[] = "abcdefghijklmnopqrstuvwxyz";
42static char testdata2[] = "1234567890-=qwertyuiop[]\asdfghjkl;'zxcvbnm,./";
43static const char *testdir_files[] = { "f1", "f2", NULL};
44static long seekdir_offsets[4];
45static char zerodata[4096];
46static int testdatalen = sizeof(testdata) - 1;
47static int testdata2len = sizeof(testdata2) - 1;
48static unsigned int testnum = 0;
49static unsigned int select_test = 0;
50static unsigned int skip_test = 0;
51static unsigned int unlinked_test = 0;
52
53#define MAX_ENTRIES 1024
54#define MAX_TESTS 100
55
56static struct test {
57 int fd;
58 struct stat stat;
59} tests[MAX_TESTS];
60
61static void test_perror(const char *func, const char *msg)
62{
63 fprintf(stderr, "%s %s() - %s: %s\n", testname, func, msg,
64 strerror(errno));
65}
66
67static void test_error(const char *func, const char *msg, ...)
68 __attribute__ ((format (printf, 2, 3)));
69
70static void __start_test(const char *fmt, ...)
71 __attribute__ ((format (printf, 1, 2)));
72
73static void test_error(const char *func, const char *msg, ...)
74{
75 va_list ap;
76 fprintf(stderr, "%s %s() - ", testname, func);
77 va_start(ap, msg);
78 vfprintf(stderr, msg, ap);
79 va_end(ap);
80 fprintf(stderr, "\n");
81}
82
83static int is_dot_or_dotdot(const char *name) {
84 return name[0] == '.' &&
85 (name[1] == '\0' || (name[1] == '.' && name[2] == '\0'));
86}
87
88static void success(void)
89{
90 fprintf(stderr, "%s OK\n", testname);
91}
92
93#define this_test (&tests[testnum-1])
94#define next_test (&tests[testnum])
95
96static void __start_test(const char *fmt, ...)
97{
98 unsigned int n;
99 va_list ap;
100 n = sprintf(testname, "%3i [", testnum);
101 va_start(ap, fmt);
102 n += vsprintf(testname + n, fmt, ap);
103 va_end(ap);
104 sprintf(testname + n, "]");
105 // Use dedicated testfile per test
106 sprintf(testfile, "%s/testfile.%d", basepath, testnum);
107 sprintf(testfile_r, "%s/testfile.%d", basepath_r, testnum);
108 if (testnum > MAX_TESTS) {
109 fprintf(stderr, "%s - too many tests\n", testname);
110 exit(1);
111 }
112 this_test->fd = -1;
113}
114
115#define start_test(msg, args...) { \
116 testnum++; \
117 if ((select_test && testnum != select_test) || \
118 (testnum == skip_test)) { \
119 return 0; \
120 } \
121 __start_test(msg, ##args); \
122}
123
124#define PERROR(msg) test_perror(__FUNCTION__, msg)
125#define ERROR(msg, args...) test_error(__FUNCTION__, msg, ##args)
126
127#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
128
129static int st_check_size(struct stat *st, int len)
130{
131 if (st->st_size != len) {
132 ERROR("length %u instead of %u", (int) st->st_size,
133 (int) len);
134 return -1;
135 }
136 return 0;
137}
138
139static int check_size(const char *path, int len)
140{
141 struct stat stbuf;
142 int res = stat(path, &stbuf);
143 if (res == -1) {
144 PERROR("stat");
145 return -1;
146 }
147 return st_check_size(&stbuf, len);
148}
149
150static int check_testfile_size(const char *path, int len)
151{
152 this_test->stat.st_size = len;
153 return check_size(path, len);
154}
155
156static int st_check_type(struct stat *st, mode_t type)
157{
158 if ((st->st_mode & S_IFMT) != type) {
159 ERROR("type 0%o instead of 0%o", st->st_mode & S_IFMT, type);
160 return -1;
161 }
162 return 0;
163}
164
165static int check_type(const char *path, mode_t type)
166{
167 struct stat stbuf;
168 int res = lstat(path, &stbuf);
169 if (res == -1) {
170 PERROR("lstat");
171 return -1;
172 }
173 return st_check_type(&stbuf, type);
174}
175
176static int st_check_mode(struct stat *st, mode_t mode)
177{
178 if ((st->st_mode & ALLPERMS) != mode) {
179 ERROR("mode 0%o instead of 0%o", st->st_mode & ALLPERMS,
180 mode);
181 return -1;
182 }
183 return 0;
184}
185
186static int check_mode(const char *path, mode_t mode)
187{
188 struct stat stbuf;
189 int res = lstat(path, &stbuf);
190 if (res == -1) {
191 PERROR("lstat");
192 return -1;
193 }
194 return st_check_mode(&stbuf, mode);
195}
196
197static int check_testfile_mode(const char *path, mode_t mode)
198{
199 this_test->stat.st_mode &= ~ALLPERMS;
200 this_test->stat.st_mode |= mode;
201 return check_mode(path, mode);
202}
203
204static int check_times(const char *path, time_t atime, time_t mtime)
205{
206 int err = 0;
207 struct stat stbuf;
208 int res = lstat(path, &stbuf);
209 if (res == -1) {
210 PERROR("lstat");
211 return -1;
212 }
213 if (stbuf.st_atime != atime) {
214 ERROR("atime %li instead of %li", stbuf.st_atime, atime);
215 err--;
216 }
217 if (stbuf.st_mtime != mtime) {
218 ERROR("mtime %li instead of %li", stbuf.st_mtime, mtime);
219 err--;
220 }
221 if (err)
222 return -1;
223
224 return 0;
225}
226
227#if 0
228static int fcheck_times(int fd, time_t atime, time_t mtime)
229{
230 int err = 0;
231 struct stat stbuf;
232 int res = fstat(fd, &stbuf);
233 if (res == -1) {
234 PERROR("fstat");
235 return -1;
236 }
237 if (stbuf.st_atime != atime) {
238 ERROR("atime %li instead of %li", stbuf.st_atime, atime);
239 err--;
240 }
241 if (stbuf.st_mtime != mtime) {
242 ERROR("mtime %li instead of %li", stbuf.st_mtime, mtime);
243 err--;
244 }
245 if (err)
246 return -1;
247
248 return 0;
249}
250#endif
251
252static int st_check_nlink(struct stat *st, nlink_t nlink)
253{
254 if (st->st_nlink != nlink) {
255 ERROR("nlink %li instead of %li", (long) st->st_nlink,
256 (long) nlink);
257 return -1;
258 }
259 return 0;
260}
261
262static int check_nlink(const char *path, nlink_t nlink)
263{
264 struct stat stbuf;
265 int res = lstat(path, &stbuf);
266 if (res == -1) {
267 PERROR("lstat");
268 return -1;
269 }
270 return st_check_nlink(&stbuf, nlink);
271}
272
273static int fcheck_stat(int fd, int flags, struct stat *st)
274{
275 struct stat stbuf;
276 int res = fstat(fd, &stbuf);
277 if (res == -1) {
278 if (flags & O_PATH) {
279 // With O_PATH fd, the server does not have to keep
280 // the inode alive so FUSE inode may be stale or bad
281 if (errno == ESTALE || errno == EIO ||
282 errno == ENOENT || errno == EBADF)
283 return 0;
284 }
285 PERROR("fstat");
286 return -1;
287 }
288
289 int err = 0;
290 err += st_check_type(&stbuf, st->st_mode & S_IFMT);
291 err += st_check_mode(&stbuf, st->st_mode & ALLPERMS);
292 err += st_check_size(&stbuf, st->st_size);
293 err += st_check_nlink(&stbuf, st->st_nlink);
294
295 return err;
296}
297
298static int check_nonexist(const char *path)
299{
300 struct stat stbuf;
301 int res = lstat(path, &stbuf);
302 if (res == 0) {
303 ERROR("file should not exist");
304 return -1;
305 }
306 if (errno != ENOENT) {
307 ERROR("file should not exist: %s", strerror(errno));
308 return -1;
309 }
310 return 0;
311}
312
313static int check_buffer(const char *buf, const char *data, unsigned len)
314{
315 if (memcmp(buf, data, len) != 0) {
316 ERROR("data mismatch");
317 return -1;
318 }
319 return 0;
320}
321
322static int check_data(const char *path, const char *data, int offset,
323 unsigned len)
324{
325 char buf[4096];
326 int res;
327 int fd = open(path, O_RDONLY);
328 if (fd == -1) {
329 PERROR("open");
330 return -1;
331 }
332 if (lseek(fd, offset, SEEK_SET) == (off_t) -1) {
333 PERROR("lseek");
334 close(fd);
335 return -1;
336 }
337 while (len) {
338 int rdlen = len < sizeof(buf) ? len : sizeof(buf);
339 res = read(fd, buf, rdlen);
340 if (res == -1) {
341 PERROR("read");
342 close(fd);
343 return -1;
344 }
345 if (res != rdlen) {
346 ERROR("short read: %u instead of %u", res, rdlen);
347 close(fd);
348 return -1;
349 }
350 if (check_buffer(buf, data, rdlen) != 0) {
351 close(fd);
352 return -1;
353 }
354 data += rdlen;
355 len -= rdlen;
356 }
357 res = close(fd);
358 if (res == -1) {
359 PERROR("close");
360 return -1;
361 }
362 return 0;
363}
364
365static int fcheck_data(int fd, const char *data, int offset,
366 unsigned len)
367{
368 char buf[4096];
369 int res;
370 if (lseek(fd, offset, SEEK_SET) == (off_t) -1) {
371 PERROR("lseek");
372 return -1;
373 }
374 while (len) {
375 int rdlen = len < sizeof(buf) ? len : sizeof(buf);
376 res = read(fd, buf, rdlen);
377 if (res == -1) {
378 PERROR("read");
379 return -1;
380 }
381 if (res != rdlen) {
382 ERROR("short read: %u instead of %u", res, rdlen);
383 return -1;
384 }
385 if (check_buffer(buf, data, rdlen) != 0) {
386 return -1;
387 }
388 data += rdlen;
389 len -= rdlen;
390 }
391 return 0;
392}
393
394static int check_dir_contents(const char *path, const char **contents)
395{
396 int i;
397 int res;
398 int err = 0;
399 int found[MAX_ENTRIES];
400 const char *cont[MAX_ENTRIES];
401 DIR *dp;
402
403 for (i = 0; contents[i]; i++) {
404 assert(i < MAX_ENTRIES - 3);
405 found[i] = 0;
406 cont[i] = contents[i];
407 }
408 cont[i] = NULL;
409
410 dp = opendir(path);
411 if (dp == NULL) {
412 PERROR("opendir");
413 return -1;
414 }
415 memset(found, 0, sizeof(found));
416 while(1) {
417 struct dirent *de;
418 errno = 0;
419 de = readdir(dp);
420 if (de == NULL) {
421 if (errno) {
422 PERROR("readdir");
423 closedir(dp);
424 return -1;
425 }
426 break;
427 }
428 if (is_dot_or_dotdot(de->d_name))
429 continue;
430 for (i = 0; cont[i] != NULL; i++) {
431 assert(i < MAX_ENTRIES);
432 if (strcmp(cont[i], de->d_name) == 0) {
433 if (found[i]) {
434 ERROR("duplicate entry <%s>",
435 de->d_name);
436 err--;
437 } else
438 found[i] = 1;
439 break;
440 }
441 }
442 if (!cont[i]) {
443 ERROR("unexpected entry <%s>", de->d_name);
444 err --;
445 }
446 }
447 for (i = 0; cont[i] != NULL; i++) {
448 if (!found[i]) {
449 ERROR("missing entry <%s>", cont[i]);
450 err--;
451 }
452 }
453 res = closedir(dp);
454 if (res == -1) {
455 PERROR("closedir");
456 return -1;
457 }
458 if (err)
459 return -1;
460
461 return 0;
462}
463
464static int create_file(const char *path, const char *data, int len)
465{
466 int res;
467 int fd;
468
469 unlink(path);
470 fd = creat(path, 0644);
471 if (fd == -1) {
472 PERROR("creat");
473 return -1;
474 }
475 if (len) {
476 res = write(fd, data, len);
477 if (res == -1) {
478 PERROR("write");
479 close(fd);
480 return -1;
481 }
482 if (res != len) {
483 ERROR("write is short: %u instead of %u", res, len);
484 close(fd);
485 return -1;
486 }
487 }
488 res = close(fd);
489 if (res == -1) {
490 PERROR("close");
491 return -1;
492 }
493 res = check_type(path, S_IFREG);
494 if (res == -1)
495 return -1;
496 res = check_mode(path, 0644);
497 if (res == -1)
498 return -1;
499 res = check_nlink(path, 1);
500 if (res == -1)
501 return -1;
502 res = check_size(path, len);
503 if (res == -1)
504 return -1;
505
506 if (len) {
507 res = check_data(path, data, 0, len);
508 if (res == -1)
509 return -1;
510 }
511
512 return 0;
513}
514
515static int create_path_fd(const char *path, const char *data, int len)
516{
517 int path_fd;
518 int res;
519
520 res = create_file(path, data, len);
521 if (res == -1)
522 return -1;
523
524 path_fd = open(path, O_PATH);
525 if (path_fd == -1)
526 PERROR("open(O_PATH)");
527
528 return path_fd;
529}
530
531// Can be called once per test
532static int create_testfile(const char *path, const char *data, int len)
533{
534 struct test *t = this_test;
535 struct stat *st = &t->stat;
536 int res, fd;
537
538 if (t->fd > 0) {
539 ERROR("testfile already created");
540 return -1;
541 }
542
543 fd = create_path_fd(path, data, len);
544 if (fd == -1)
545 return -1;
546
547 t->fd = fd;
548
549 res = fstat(fd, st);
550 if (res == -1) {
551 PERROR("fstat");
552 return -1;
553 }
554
555 return 0;
556}
557
558static int check_unlinked_testfile(int fd)
559{
560 struct stat *st = &this_test->stat;
561
562 st->st_nlink = 0;
563 return fcheck_stat(fd, O_PATH, st);
564}
565
566// Check recorded testfiles after all tests completed
567static int check_unlinked_testfiles(void)
568{
569 int fd;
570 int res, err = 0;
571 int num = testnum;
572
573 if (!unlinked_test)
574 return 0;
575
576 testnum = 0;
577 while (testnum < num) {
578 fd = next_test->fd;
579 start_test("check_unlinked_testfile");
580 if (fd == -1)
581 continue;
582
583 err += check_unlinked_testfile(fd);
584 res = close(fd);
585 if (res == -1) {
586 PERROR("close(test_fd)");
587 err--;
588 }
589 }
590
591 if (err) {
592 fprintf(stderr, "%i unlinked testfile checks failed\n", -err);
593 return 1;
594 }
595
596 return err;
597}
598
599static int cleanup_dir(const char *path, const char **dir_files, int quiet)
600{
601 int i;
602 int err = 0;
603
604 for (i = 0; dir_files[i]; i++) {
605 int res;
606 char fpath[1280];
607 sprintf(fpath, "%s/%s", path, dir_files[i]);
608 res = unlink(fpath);
609 if (res == -1 && !quiet) {
610 PERROR("unlink");
611 err --;
612 }
613 }
614 if (err)
615 return -1;
616
617 return 0;
618}
619
620static int create_dir(const char *path, const char **dir_files)
621{
622 int res;
623 int i;
624
625 rmdir(path);
626 res = mkdir(path, 0755);
627 if (res == -1) {
628 PERROR("mkdir");
629 return -1;
630 }
631 res = check_type(path, S_IFDIR);
632 if (res == -1)
633 return -1;
634 res = check_mode(path, 0755);
635 if (res == -1)
636 return -1;
637
638 for (i = 0; dir_files[i]; i++) {
639 char fpath[1280];
640 sprintf(fpath, "%s/%s", path, dir_files[i]);
641 res = create_file(fpath, "", 0);
642 if (res == -1) {
643 cleanup_dir(path, dir_files, 1);
644 return -1;
645 }
646 }
647 res = check_dir_contents(path, dir_files);
648 if (res == -1) {
649 cleanup_dir(path, dir_files, 1);
650 return -1;
651 }
652
653 return 0;
654}
655
656static int test_truncate(int len)
657{
658 const char *data = testdata;
659 int datalen = testdatalen;
660 int res;
661
662 start_test("truncate(%u)", (int) len);
663 res = create_testfile(testfile, data, datalen);
664 if (res == -1)
665 return -1;
666
667 res = truncate(testfile, len);
668 if (res == -1) {
669 PERROR("truncate");
670 return -1;
671 }
672 res = check_testfile_size(testfile, len);
673 if (res == -1)
674 return -1;
675
676 if (len > 0) {
677 if (len <= datalen) {
678 res = check_data(testfile, data, 0, len);
679 if (res == -1)
680 return -1;
681 } else {
682 res = check_data(testfile, data, 0, datalen);
683 if (res == -1)
684 return -1;
685 res = check_data(testfile, zerodata, datalen,
686 len - datalen);
687 if (res == -1)
688 return -1;
689 }
690 }
691 res = unlink(testfile);
692 if (res == -1) {
693 PERROR("unlink");
694 return -1;
695 }
696 res = check_nonexist(testfile);
697 if (res == -1)
698 return -1;
699
700 success();
701 return 0;
702}
703
704static int test_ftruncate(int len, int mode)
705{
706 const char *data = testdata;
707 int datalen = testdatalen;
708 int res;
709 int fd;
710
711 start_test("ftruncate(%u) mode: 0%03o", len, mode);
712 res = create_testfile(testfile, data, datalen);
713 if (res == -1)
714 return -1;
715
716 fd = open(testfile, O_WRONLY);
717 if (fd == -1) {
718 PERROR("open");
719 return -1;
720 }
721
722 res = fchmod(fd, mode);
723 if (res == -1) {
724 PERROR("fchmod");
725 close(fd);
726 return -1;
727 }
728 res = check_testfile_mode(testfile, mode);
729 if (res == -1) {
730 close(fd);
731 return -1;
732 }
733 res = ftruncate(fd, len);
734 if (res == -1) {
735 PERROR("ftruncate");
736 close(fd);
737 return -1;
738 }
739 close(fd);
740 res = check_testfile_size(testfile, len);
741 if (res == -1)
742 return -1;
743
744 if (len > 0) {
745 if (len <= datalen) {
746 res = check_data(testfile, data, 0, len);
747 if (res == -1)
748 return -1;
749 } else {
750 res = check_data(testfile, data, 0, datalen);
751 if (res == -1)
752 return -1;
753 res = check_data(testfile, zerodata, datalen,
754 len - datalen);
755 if (res == -1)
756 return -1;
757 }
758 }
759 res = unlink(testfile);
760 if (res == -1) {
761 PERROR("unlink");
762 return -1;
763 }
764 res = check_nonexist(testfile);
765 if (res == -1)
766 return -1;
767
768 success();
769 return 0;
770}
771
772static int test_seekdir(void)
773{
774 int i;
775 int res;
776 DIR *dp;
777 struct dirent *de = NULL;
778
779 start_test("seekdir");
780 res = create_dir(testdir, testdir_files);
781 if (res == -1)
782 return res;
783
784 dp = opendir(testdir);
785 if (dp == NULL) {
786 PERROR("opendir");
787 return -1;
788 }
789
790 /* Remember dir offsets */
791 for (i = 0; i < ARRAY_SIZE(seekdir_offsets); i++) {
792 seekdir_offsets[i] = telldir(dp);
793 errno = 0;
794 de = readdir(dp);
795 if (de == NULL) {
796 if (errno) {
797 PERROR("readdir");
798 goto fail;
799 }
800 break;
801 }
802 }
803
804 /* Walk until the end of directory */
805 while (de)
806 de = readdir(dp);
807
808 /* Start from the last valid dir offset and seek backwards */
809 for (i--; i >= 0; i--) {
810 seekdir(dp, seekdir_offsets[i]);
811 de = readdir(dp);
812 if (de == NULL) {
813 ERROR("Unexpected end of directory after seekdir()");
814 goto fail;
815 }
816 }
817
818 closedir(dp);
819 res = cleanup_dir(testdir, testdir_files, 0);
820 if (!res)
821 success();
822 return res;
823fail:
824 closedir(dp);
825 cleanup_dir(testdir, testdir_files, 1);
826 return -1;
827}
828
829#ifdef HAVE_COPY_FILE_RANGE
830static int test_copy_file_range(void)
831{
832 const char *data = testdata;
833 int datalen = testdatalen;
834 int err = 0;
835 int res;
836 int fd_in, fd_out;
837 off_t pos_in = 0, pos_out = 0;
838
839 start_test("copy_file_range");
840 unlink(testfile);
841 fd_in = open(testfile, O_CREAT | O_RDWR, 0644);
842 if (fd_in == -1) {
843 PERROR("creat");
844 return -1;
845 }
846 res = write(fd_in, data, datalen);
847 if (res == -1) {
848 PERROR("write");
849 close(fd_in);
850 return -1;
851 }
852 if (res != datalen) {
853 ERROR("write is short: %u instead of %u", res, datalen);
854 close(fd_in);
855 return -1;
856 }
857
858 unlink(testfile2);
859 fd_out = creat(testfile2, 0644);
860 if (fd_out == -1) {
861 PERROR("creat");
862 close(fd_in);
863 return -1;
864 }
865 res = copy_file_range(fd_in, &pos_in, fd_out, &pos_out, datalen, 0);
866 if (res == -1) {
867 PERROR("copy_file_range");
868 close(fd_in);
869 close(fd_out);
870 return -1;
871 }
872 if (res != datalen) {
873 ERROR("copy is short: %u instead of %u", res, datalen);
874 close(fd_in);
875 close(fd_out);
876 return -1;
877 }
878
879 res = close(fd_in);
880 if (res == -1) {
881 PERROR("close");
882 close(fd_out);
883 return -1;
884 }
885 res = close(fd_out);
886 if (res == -1) {
887 PERROR("close");
888 return -1;
889 }
890
891 err = check_data(testfile2, data, 0, datalen);
892
893 res = unlink(testfile);
894 if (res == -1) {
895 PERROR("unlink");
896 return -1;
897 }
898 res = check_nonexist(testfile);
899 if (res == -1)
900 return -1;
901 if (err)
902 return -1;
903
904 res = unlink(testfile2);
905 if (res == -1) {
906 PERROR("unlink");
907 return -1;
908 }
909 res = check_nonexist(testfile2);
910 if (res == -1)
911 return -1;
912 if (err)
913 return -1;
914
915 success();
916 return 0;
917}
918#else
919static int test_copy_file_range(void)
920{
921 return 0;
922}
923#endif
924
925#ifdef HAVE_STATX
926static int test_statx(void)
927{
928 struct statx sb;
929 char msg[] = "hi";
930 size_t msg_size = sizeof(msg);
931 struct timespec tp;
932 int res;
933
934 memset(&sb, 0, sizeof(sb));
935 unlink(testfile);
936
937 start_test("statx");
938
939 res = create_testfile(testfile, msg, msg_size);
940 if (res == -1)
941 return -1;
942
943 res = statx(-1, testfile, AT_EMPTY_PATH,
944 STATX_BASIC_STATS | STATX_BTIME, &sb);
945 if (res == -1)
946 return -1;
947
948 if (sb.stx_size != msg_size)
949 return -1;
950
951 clock_gettime(CLOCK_REALTIME, &tp);
952
953 if (sb.stx_btime.tv_sec > tp.tv_sec)
954 return -1;
955
956 if (sb.stx_btime.tv_sec == tp.tv_sec &&
957 sb.stx_btime.tv_nsec >= tp.tv_nsec)
958 return -1;
959
960 unlink(testfile);
961
962 success();
963 return 0;
964}
965#else
966static int test_statx(void)
967{
968 return 0;
969}
970#endif
971
972static int test_utime(void)
973{
974 struct utimbuf utm;
975 time_t atime = 987631200;
976 time_t mtime = 123116400;
977 int res;
978
979 start_test("utime");
980 res = create_testfile(testfile, NULL, 0);
981 if (res == -1)
982 return -1;
983
984 utm.actime = atime;
985 utm.modtime = mtime;
986 res = utime(testfile, &utm);
987 if (res == -1) {
988 PERROR("utime");
989 return -1;
990 }
991 res = check_times(testfile, atime, mtime);
992 if (res == -1) {
993 return -1;
994 }
995 res = unlink(testfile);
996 if (res == -1) {
997 PERROR("unlink");
998 return -1;
999 }
1000 res = check_nonexist(testfile);
1001 if (res == -1)
1002 return -1;
1003
1004 success();
1005 return 0;
1006}
1007
1008static int test_create(void)
1009{
1010 const char *data = testdata;
1011 int datalen = testdatalen;
1012 int err = 0;
1013 int res;
1014 int fd;
1015
1016 start_test("create");
1017 unlink(testfile);
1018 fd = creat(testfile, 0644);
1019 if (fd == -1) {
1020 PERROR("creat");
1021 return -1;
1022 }
1023 res = write(fd, data, datalen);
1024 if (res == -1) {
1025 PERROR("write");
1026 close(fd);
1027 return -1;
1028 }
1029 if (res != datalen) {
1030 ERROR("write is short: %u instead of %u", res, datalen);
1031 close(fd);
1032 return -1;
1033 }
1034 res = close(fd);
1035 if (res == -1) {
1036 PERROR("close");
1037 return -1;
1038 }
1039 res = check_type(testfile, S_IFREG);
1040 if (res == -1)
1041 return -1;
1042 err += check_mode(testfile, 0644);
1043 err += check_nlink(testfile, 1);
1044 err += check_size(testfile, datalen);
1045 err += check_data(testfile, data, 0, datalen);
1046 res = unlink(testfile);
1047 if (res == -1) {
1048 PERROR("unlink");
1049 return -1;
1050 }
1051 res = check_nonexist(testfile);
1052 if (res == -1)
1053 return -1;
1054 if (err)
1055 return -1;
1056
1057 success();
1058 return 0;
1059}
1060
1061static int test_create_unlink(void)
1062{
1063 const char *data = testdata;
1064 int datalen = testdatalen;
1065 int err = 0;
1066 int res;
1067 int fd;
1068
1069 start_test("create+unlink");
1070 unlink(testfile);
1071 fd = open(testfile, O_CREAT | O_RDWR | O_TRUNC, 0644);
1072 if (fd == -1) {
1073 PERROR("creat");
1074 return -1;
1075 }
1076 res = unlink(testfile);
1077 if (res == -1) {
1078 PERROR("unlink");
1079 close(fd);
1080 return -1;
1081 }
1082 res = check_nonexist(testfile);
1083 if (res == -1) {
1084 close(fd);
1085 return -1;
1086 }
1087 res = write(fd, data, datalen);
1088 if (res == -1) {
1089 PERROR("write");
1090 close(fd);
1091 return -1;
1092 }
1093 if (res != datalen) {
1094 ERROR("write is short: %u instead of %u", res, datalen);
1095 close(fd);
1096 return -1;
1097 }
1098 struct stat st = {
1099 .st_mode = S_IFREG | 0644,
1100 .st_size = datalen,
1101 };
1102 err = fcheck_stat(fd, O_RDWR, &st);
1103 err += fcheck_data(fd, data, 0, datalen);
1104 res = close(fd);
1105 if (res == -1) {
1106 PERROR("close");
1107 err--;
1108 }
1109 if (err)
1110 return -1;
1111
1112 success();
1113 return 0;
1114}
1115
1116static int test_mknod(void)
1117{
1118 int err = 0;
1119 int res;
1120
1121 start_test("mknod");
1122 unlink(testfile);
1123 res = mknod(testfile, 0644, 0);
1124 if (res == -1) {
1125 PERROR("mknod");
1126 return -1;
1127 }
1128 res = check_type(testfile, S_IFREG);
1129 if (res == -1)
1130 return -1;
1131 err += check_mode(testfile, 0644);
1132 err += check_nlink(testfile, 1);
1133 err += check_size(testfile, 0);
1134 res = unlink(testfile);
1135 if (res == -1) {
1136 PERROR("unlink");
1137 return -1;
1138 }
1139 res = check_nonexist(testfile);
1140 if (res == -1)
1141 return -1;
1142 if (err)
1143 return -1;
1144
1145 success();
1146 return 0;
1147}
1148
1149#define test_open(exist, flags, mode) do_test_open(exist, flags, #flags, mode)
1150
1151static int do_test_open(int exist, int flags, const char *flags_str, int mode)
1152{
1153 char buf[4096];
1154 const char *data = testdata;
1155 int datalen = testdatalen;
1156 unsigned currlen = 0;
1157 int err = 0;
1158 int res;
1159 int fd;
1160 off_t off;
1161
1162 start_test("open(%s, %s, 0%03o)", exist ? "+" : "-", flags_str, mode);
1163 unlink(testfile);
1164 if (exist) {
1165 res = create_file(testfile_r, testdata2, testdata2len);
1166 if (res == -1)
1167 return -1;
1168
1169 currlen = testdata2len;
1170 }
1171
1172 fd = open(testfile, flags, mode);
1173 if ((flags & O_CREAT) && (flags & O_EXCL) && exist) {
1174 if (fd != -1) {
1175 ERROR("open should have failed");
1176 close(fd);
1177 return -1;
1178 } else if (errno == EEXIST)
1179 goto succ;
1180 }
1181 if (!(flags & O_CREAT) && !exist) {
1182 if (fd != -1) {
1183 ERROR("open should have failed");
1184 close(fd);
1185 return -1;
1186 } else if (errno == ENOENT)
1187 goto succ;
1188 }
1189 if (fd == -1) {
1190 PERROR("open");
1191 return -1;
1192 }
1193
1194 if (flags & O_TRUNC)
1195 currlen = 0;
1196
1197 err += check_type(testfile, S_IFREG);
1198 if (exist)
1199 err += check_mode(testfile, 0644);
1200 else
1201 err += check_mode(testfile, mode);
1202 err += check_nlink(testfile, 1);
1203 err += check_size(testfile, currlen);
1204 if (exist && !(flags & O_TRUNC) && (mode & S_IRUSR))
1205 err += check_data(testfile, testdata2, 0, testdata2len);
1206
1207 res = write(fd, data, datalen);
1208 if ((flags & O_ACCMODE) != O_RDONLY) {
1209 if (res == -1) {
1210 PERROR("write");
1211 err --;
1212 } else if (res != datalen) {
1213 ERROR("write is short: %u instead of %u", res, datalen);
1214 err --;
1215 } else {
1216 if (datalen > (int) currlen)
1217 currlen = datalen;
1218
1219 err += check_size(testfile, currlen);
1220
1221 if (mode & S_IRUSR) {
1222 err += check_data(testfile, data, 0, datalen);
1223 if (exist && !(flags & O_TRUNC) &&
1224 testdata2len > datalen)
1225 err += check_data(testfile,
1226 testdata2 + datalen,
1227 datalen,
1228 testdata2len - datalen);
1229 }
1230 }
1231 } else {
1232 if (res != -1) {
1233 ERROR("write should have failed");
1234 err --;
1235 } else if (errno != EBADF) {
1236 PERROR("write");
1237 err --;
1238 }
1239 }
1240 off = lseek(fd, SEEK_SET, 0);
1241 if (off == (off_t) -1) {
1242 PERROR("lseek");
1243 err--;
1244 } else if (off != 0) {
1245 ERROR("offset should have returned 0");
1246 err --;
1247 }
1248 res = read(fd, buf, sizeof(buf));
1249 if ((flags & O_ACCMODE) != O_WRONLY) {
1250 if (res == -1) {
1251 PERROR("read");
1252 err--;
1253 } else {
1254 int readsize =
1255 currlen < sizeof(buf) ? currlen : sizeof(buf);
1256 if (res != readsize) {
1257 ERROR("read is short: %i instead of %u",
1258 res, readsize);
1259 err--;
1260 } else {
1261 if ((flags & O_ACCMODE) != O_RDONLY) {
1262 err += check_buffer(buf, data, datalen);
1263 if (exist && !(flags & O_TRUNC) &&
1264 testdata2len > datalen)
1265 err += check_buffer(buf + datalen,
1266 testdata2 + datalen,
1267 testdata2len - datalen);
1268 } else if (exist)
1269 err += check_buffer(buf, testdata2,
1270 testdata2len);
1271 }
1272 }
1273 } else {
1274 if (res != -1) {
1275 ERROR("read should have failed");
1276 err --;
1277 } else if (errno != EBADF) {
1278 PERROR("read");
1279 err --;
1280 }
1281 }
1282
1283 res = close(fd);
1284 if (res == -1) {
1285 PERROR("close");
1286 return -1;
1287 }
1288 res = unlink(testfile);
1289 if (res == -1) {
1290 PERROR("unlink");
1291 return -1;
1292 }
1293 res = check_nonexist(testfile);
1294 if (res == -1)
1295 return -1;
1296 res = check_nonexist(testfile_r);
1297 if (res == -1)
1298 return -1;
1299 if (err)
1300 return -1;
1301
1302succ:
1303 success();
1304 return 0;
1305}
1306
1307#define test_open_acc(flags, mode, err) \
1308 do_test_open_acc(flags, #flags, mode, err)
1309
1310static int do_test_open_acc(int flags, const char *flags_str, int mode, int err)
1311{
1312 const char *data = testdata;
1313 int datalen = testdatalen;
1314 int res;
1315 int fd;
1316
1317 start_test("open_acc(%s) mode: 0%03o message: '%s'", flags_str, mode,
1318 strerror(err));
1319 unlink(testfile);
1320 res = create_testfile(testfile, data, datalen);
1321 if (res == -1)
1322 return -1;
1323
1324 res = chmod(testfile, mode);
1325 if (res == -1) {
1326 PERROR("chmod");
1327 return -1;
1328 }
1329
1330 res = check_testfile_mode(testfile, mode);
1331 if (res == -1)
1332 return -1;
1333
1334 fd = open(testfile, flags);
1335 if (fd == -1) {
1336 if (err != errno) {
1337 PERROR("open");
1338 return -1;
1339 }
1340 } else {
1341 if (err) {
1342 ERROR("open should have failed");
1343 close(fd);
1344 return -1;
1345 }
1346 close(fd);
1347 }
1348
1349 res = unlink(testfile);
1350 if (res == -1) {
1351 PERROR("unlink");
1352 return -1;
1353 }
1354 res = check_nonexist(testfile);
1355 if (res == -1)
1356 return -1;
1357 res = check_nonexist(testfile_r);
1358 if (res == -1)
1359 return -1;
1360
1361 success();
1362 return 0;
1363}
1364
1365static int test_symlink(void)
1366{
1367 char buf[1024];
1368 const char *data = testdata;
1369 int datalen = testdatalen;
1370 int linklen = strlen(testfile);
1371 int err = 0;
1372 int res;
1373
1374 start_test("symlink");
1375 res = create_testfile(testfile, data, datalen);
1376 if (res == -1)
1377 return -1;
1378
1379 unlink(testfile2);
1380 res = symlink(testfile, testfile2);
1381 if (res == -1) {
1382 PERROR("symlink");
1383 return -1;
1384 }
1385 res = check_type(testfile2, S_IFLNK);
1386 if (res == -1)
1387 return -1;
1388 err += check_mode(testfile2, 0777);
1389 err += check_nlink(testfile2, 1);
1390 res = readlink(testfile2, buf, sizeof(buf));
1391 if (res == -1) {
1392 PERROR("readlink");
1393 err--;
1394 }
1395 if (res != linklen) {
1396 ERROR("short readlink: %u instead of %u", res, linklen);
1397 err--;
1398 }
1399 if (memcmp(buf, testfile, linklen) != 0) {
1400 ERROR("link mismatch");
1401 err--;
1402 }
1403 err += check_size(testfile2, datalen);
1404 err += check_data(testfile2, data, 0, datalen);
1405 res = unlink(testfile2);
1406 if (res == -1) {
1407 PERROR("unlink");
1408 return -1;
1409 }
1410 res = check_nonexist(testfile2);
1411 if (res == -1)
1412 return -1;
1413 if (err)
1414 return -1;
1415
1416 res = unlink(testfile);
1417 if (res == -1) {
1418 PERROR("unlink");
1419 return -1;
1420 }
1421 res = check_nonexist(testfile);
1422 if (res == -1)
1423 return -1;
1424
1425 success();
1426 return 0;
1427}
1428
1429static int test_link(void)
1430{
1431 const char *data = testdata;
1432 int datalen = testdatalen;
1433 int err = 0;
1434 int res;
1435
1436 start_test("link");
1437 res = create_testfile(testfile, data, datalen);
1438 if (res == -1)
1439 return -1;
1440
1441 unlink(testfile2);
1442 res = link(testfile, testfile2);
1443 if (res == -1) {
1444 PERROR("link");
1445 return -1;
1446 }
1447 res = check_type(testfile2, S_IFREG);
1448 if (res == -1)
1449 return -1;
1450 err += check_mode(testfile2, 0644);
1451 err += check_nlink(testfile2, 2);
1452 err += check_size(testfile2, datalen);
1453 err += check_data(testfile2, data, 0, datalen);
1454 res = unlink(testfile);
1455 if (res == -1) {
1456 PERROR("unlink");
1457 return -1;
1458 }
1459 res = check_nonexist(testfile);
1460 if (res == -1)
1461 return -1;
1462
1463 err += check_nlink(testfile2, 1);
1464 res = unlink(testfile2);
1465 if (res == -1) {
1466 PERROR("unlink");
1467 return -1;
1468 }
1469 res = check_nonexist(testfile2);
1470 if (res == -1)
1471 return -1;
1472 if (err)
1473 return -1;
1474
1475 success();
1476 return 0;
1477}
1478
1479static int test_link2(void)
1480{
1481 const char *data = testdata;
1482 int datalen = testdatalen;
1483 int err = 0;
1484 int res;
1485
1486 start_test("link-unlink-link");
1487 res = create_testfile(testfile, data, datalen);
1488 if (res == -1)
1489 return -1;
1490
1491 unlink(testfile2);
1492 res = link(testfile, testfile2);
1493 if (res == -1) {
1494 PERROR("link");
1495 return -1;
1496 }
1497 res = unlink(testfile);
1498 if (res == -1) {
1499 PERROR("unlink");
1500 return -1;
1501 }
1502 res = check_nonexist(testfile);
1503 if (res == -1)
1504 return -1;
1505 res = link(testfile2, testfile);
1506 if (res == -1) {
1507 PERROR("link");
1508 }
1509 res = check_type(testfile, S_IFREG);
1510 if (res == -1)
1511 return -1;
1512 err += check_mode(testfile, 0644);
1513 err += check_nlink(testfile, 2);
1514 err += check_size(testfile, datalen);
1515 err += check_data(testfile, data, 0, datalen);
1516
1517 res = unlink(testfile2);
1518 if (res == -1) {
1519 PERROR("unlink");
1520 return -1;
1521 }
1522 err += check_nlink(testfile, 1);
1523 res = unlink(testfile);
1524 if (res == -1) {
1525 PERROR("unlink");
1526 return -1;
1527 }
1528 res = check_nonexist(testfile);
1529 if (res == -1)
1530 return -1;
1531 if (err)
1532 return -1;
1533
1534 success();
1535 return 0;
1536}
1537
1538static int test_rename_file(void)
1539{
1540 const char *data = testdata;
1541 int datalen = testdatalen;
1542 int err = 0;
1543 int res;
1544
1545 start_test("rename file");
1546 res = create_testfile(testfile, data, datalen);
1547 if (res == -1)
1548 return -1;
1549
1550 unlink(testfile2);
1551 res = rename(testfile, testfile2);
1552 if (res == -1) {
1553 PERROR("rename");
1554 return -1;
1555 }
1556 res = check_nonexist(testfile);
1557 if (res == -1)
1558 return -1;
1559 res = check_type(testfile2, S_IFREG);
1560 if (res == -1)
1561 return -1;
1562 err += check_mode(testfile2, 0644);
1563 err += check_nlink(testfile2, 1);
1564 err += check_size(testfile2, datalen);
1565 err += check_data(testfile2, data, 0, datalen);
1566 res = unlink(testfile2);
1567 if (res == -1) {
1568 PERROR("unlink");
1569 return -1;
1570 }
1571 res = check_nonexist(testfile2);
1572 if (res == -1)
1573 return -1;
1574 if (err)
1575 return -1;
1576
1577 success();
1578 return 0;
1579}
1580
1581static int test_rename_dir(void)
1582{
1583 int err = 0;
1584 int res;
1585
1586 start_test("rename dir");
1587 res = create_dir(testdir, testdir_files);
1588 if (res == -1)
1589 return -1;
1590
1591 rmdir(testdir2);
1592 res = rename(testdir, testdir2);
1593 if (res == -1) {
1594 PERROR("rename");
1595 cleanup_dir(testdir, testdir_files, 1);
1596 return -1;
1597 }
1598 res = check_nonexist(testdir);
1599 if (res == -1) {
1600 cleanup_dir(testdir, testdir_files, 1);
1601 return -1;
1602 }
1603 res = check_type(testdir2, S_IFDIR);
1604 if (res == -1) {
1605 cleanup_dir(testdir2, testdir_files, 1);
1606 return -1;
1607 }
1608 err += check_mode(testdir2, 0755);
1609 err += check_dir_contents(testdir2, testdir_files);
1610 err += cleanup_dir(testdir2, testdir_files, 0);
1611 res = rmdir(testdir2);
1612 if (res == -1) {
1613 PERROR("rmdir");
1614 return -1;
1615 }
1616 res = check_nonexist(testdir2);
1617 if (res == -1)
1618 return -1;
1619 if (err)
1620 return -1;
1621
1622 success();
1623 return 0;
1624}
1625
1626static int test_rename_dir_loop(void)
1627{
1628#define PATH(p) (snprintf(path, sizeof path, "%s/%s", testdir, p), path)
1629#define PATH2(p) (snprintf(path2, sizeof path2, "%s/%s", testdir, p), path2)
1630
1631 char path[1280], path2[1280];
1632 int err = 0;
1633 int res;
1634
1635 start_test("rename dir loop");
1636
1637 res = create_dir(testdir, testdir_files);
1638 if (res == -1)
1639 return -1;
1640
1641 res = mkdir(PATH("a"), 0755);
1642 if (res == -1) {
1643 PERROR("mkdir");
1644 goto fail;
1645 }
1646
1647 res = rename(PATH("a"), PATH2("a"));
1648 if (res == -1) {
1649 PERROR("rename");
1650 goto fail;
1651 }
1652
1653 errno = 0;
1654 res = rename(PATH("a"), PATH2("a/b"));
1655 if (res == 0 || errno != EINVAL) {
1656 PERROR("rename");
1657 goto fail;
1658 }
1659
1660 res = mkdir(PATH("a/b"), 0755);
1661 if (res == -1) {
1662 PERROR("mkdir");
1663 goto fail;
1664 }
1665
1666 res = mkdir(PATH("a/b/c"), 0755);
1667 if (res == -1) {
1668 PERROR("mkdir");
1669 goto fail;
1670 }
1671
1672 errno = 0;
1673 res = rename(PATH("a"), PATH2("a/b/c"));
1674 if (res == 0 || errno != EINVAL) {
1675 PERROR("rename");
1676 goto fail;
1677 }
1678
1679 errno = 0;
1680 res = rename(PATH("a"), PATH2("a/b/c/a"));
1681 if (res == 0 || errno != EINVAL) {
1682 PERROR("rename");
1683 goto fail;
1684 }
1685
1686 errno = 0;
1687 res = rename(PATH("a/b/c"), PATH2("a"));
1688 if (res == 0 || errno != ENOTEMPTY) {
1689 PERROR("rename");
1690 goto fail;
1691 }
1692
1693 res = open(PATH("a/foo"), O_CREAT, 0644);
1694 if (res == -1) {
1695 PERROR("open");
1696 goto fail;
1697 }
1698 close(res);
1699
1700 res = rename(PATH("a/foo"), PATH2("a/bar"));
1701 if (res == -1) {
1702 PERROR("rename");
1703 goto fail;
1704 }
1705
1706 res = rename(PATH("a/bar"), PATH2("a/foo"));
1707 if (res == -1) {
1708 PERROR("rename");
1709 goto fail;
1710 }
1711
1712 res = rename(PATH("a/foo"), PATH2("a/b/bar"));
1713 if (res == -1) {
1714 PERROR("rename");
1715 goto fail;
1716 }
1717
1718 res = rename(PATH("a/b/bar"), PATH2("a/foo"));
1719 if (res == -1) {
1720 PERROR("rename");
1721 goto fail;
1722 }
1723
1724 res = rename(PATH("a/foo"), PATH2("a/b/c/bar"));
1725 if (res == -1) {
1726 PERROR("rename");
1727 goto fail;
1728 }
1729
1730 res = rename(PATH("a/b/c/bar"), PATH2("a/foo"));
1731 if (res == -1) {
1732 PERROR("rename");
1733 goto fail;
1734 }
1735
1736 res = open(PATH("a/bar"), O_CREAT, 0644);
1737 if (res == -1) {
1738 PERROR("open");
1739 goto fail;
1740 }
1741 close(res);
1742
1743 res = rename(PATH("a/foo"), PATH2("a/bar"));
1744 if (res == -1) {
1745 PERROR("rename");
1746 goto fail;
1747 }
1748
1749 unlink(PATH("a/bar"));
1750
1751 res = rename(PATH("a/b"), PATH2("a/d"));
1752 if (res == -1) {
1753 PERROR("rename");
1754 goto fail;
1755 }
1756
1757 res = rename(PATH("a/d"), PATH2("a/b"));
1758 if (res == -1) {
1759 PERROR("rename");
1760 goto fail;
1761 }
1762
1763 res = mkdir(PATH("a/d"), 0755);
1764 if (res == -1) {
1765 PERROR("mkdir");
1766 goto fail;
1767 }
1768
1769 res = rename(PATH("a/b"), PATH2("a/d"));
1770 if (res == -1) {
1771 PERROR("rename");
1772 goto fail;
1773 }
1774
1775 res = rename(PATH("a/d"), PATH2("a/b"));
1776 if (res == -1) {
1777 PERROR("rename");
1778 goto fail;
1779 }
1780
1781 res = mkdir(PATH("a/d"), 0755);
1782 if (res == -1) {
1783 PERROR("mkdir");
1784 goto fail;
1785 }
1786
1787 res = mkdir(PATH("a/d/e"), 0755);
1788 if (res == -1) {
1789 PERROR("mkdir");
1790 goto fail;
1791 }
1792
1793 errno = 0;
1794 res = rename(PATH("a/b"), PATH2("a/d"));
1795 if (res == 0 || (errno != ENOTEMPTY && errno != EEXIST)) {
1796 PERROR("rename");
1797 goto fail;
1798 }
1799
1800 rmdir(PATH("a/d/e"));
1801 rmdir(PATH("a/d"));
1802
1803 rmdir(PATH("a/b/c"));
1804 rmdir(PATH("a/b"));
1805 rmdir(PATH("a"));
1806
1807 err += cleanup_dir(testdir, testdir_files, 0);
1808 res = rmdir(testdir);
1809 if (res == -1) {
1810 PERROR("rmdir");
1811 goto fail;
1812 }
1813 res = check_nonexist(testdir);
1814 if (res == -1)
1815 return -1;
1816 if (err)
1817 return -1;
1818
1819 success();
1820 return 0;
1821
1822fail:
1823 unlink(PATH("a/bar"));
1824
1825 rmdir(PATH("a/d/e"));
1826 rmdir(PATH("a/d"));
1827
1828 rmdir(PATH("a/b/c"));
1829 rmdir(PATH("a/b"));
1830 rmdir(PATH("a"));
1831
1832 cleanup_dir(testdir, testdir_files, 1);
1833 rmdir(testdir);
1834
1835 return -1;
1836
1837#undef PATH2
1838#undef PATH
1839}
1840
1841static int test_mkfifo(void)
1842{
1843 int res;
1844 int err = 0;
1845
1846 start_test("mkfifo");
1847 unlink(testfile);
1848 res = mkfifo(testfile, 0644);
1849 if (res == -1) {
1850 PERROR("mkfifo");
1851 return -1;
1852 }
1853 res = check_type(testfile, S_IFIFO);
1854 if (res == -1)
1855 return -1;
1856 err += check_mode(testfile, 0644);
1857 err += check_nlink(testfile, 1);
1858 res = unlink(testfile);
1859 if (res == -1) {
1860 PERROR("unlink");
1861 return -1;
1862 }
1863 res = check_nonexist(testfile);
1864 if (res == -1)
1865 return -1;
1866 if (err)
1867 return -1;
1868
1869 success();
1870 return 0;
1871}
1872
1873static int test_mkdir(void)
1874{
1875 int res;
1876 int err = 0;
1877 const char *dir_contents[] = {NULL};
1878
1879 start_test("mkdir");
1880 rmdir(testdir);
1881 res = mkdir(testdir, 0755);
1882 if (res == -1) {
1883 PERROR("mkdir");
1884 return -1;
1885 }
1886 res = check_type(testdir, S_IFDIR);
1887 if (res == -1)
1888 return -1;
1889 err += check_mode(testdir, 0755);
1890 /* Some file systems (like btrfs) don't track link
1891 count for directories */
1892 //err += check_nlink(testdir, 2);
1893 err += check_dir_contents(testdir, dir_contents);
1894 res = rmdir(testdir);
1895 if (res == -1) {
1896 PERROR("rmdir");
1897 return -1;
1898 }
1899 res = check_nonexist(testdir);
1900 if (res == -1)
1901 return -1;
1902 if (err)
1903 return -1;
1904
1905 success();
1906 return 0;
1907}
1908
1909static int test_socket(void)
1910{
1911 struct sockaddr_un su;
1912 int fd;
1913 int res;
1914 int err = 0;
1915 const size_t test_sock_len = strlen(testsock) + 1;
1916
1917 start_test("socket");
1918 if (test_sock_len > sizeof(su.sun_path)) {
1919 fprintf(stderr, "Need to shorten mount point by %zu chars\n",
1920 strlen(testsock) + 1 - sizeof(su.sun_path));
1921 return -1;
1922 }
1923 unlink(testsock);
1924 fd = socket(AF_UNIX, SOCK_STREAM, 0);
1925 if (fd < 0) {
1926 PERROR("socket");
1927 return -1;
1928 }
1929 su.sun_family = AF_UNIX;
1930
1931 strncpy(su.sun_path, testsock, test_sock_len);
1932 su.sun_path[sizeof(su.sun_path) - 1] = '\0';
1933 res = bind(fd, (struct sockaddr*)&su, sizeof(su));
1934 if (res == -1) {
1935 PERROR("bind");
1936 return -1;
1937 }
1938
1939 res = check_type(testsock, S_IFSOCK);
1940 if (res == -1) {
1941 close(fd);
1942 return -1;
1943 }
1944 err += check_nlink(testsock, 1);
1945 close(fd);
1946 res = unlink(testsock);
1947 if (res == -1) {
1948 PERROR("unlink");
1949 return -1;
1950 }
1951 res = check_nonexist(testsock);
1952 if (res == -1)
1953 return -1;
1954 if (err)
1955 return -1;
1956
1957 success();
1958 return 0;
1959}
1960
1961#define test_create_ro_dir(flags) \
1962 do_test_create_ro_dir(flags, #flags)
1963
1964static int do_test_create_ro_dir(int flags, const char *flags_str)
1965{
1966 int res;
1967 int err = 0;
1968 int fd;
1969
1970 start_test("open(%s) in read-only directory", flags_str);
1971 rmdir(testdir);
1972 res = mkdir(testdir, 0555);
1973 if (res == -1) {
1974 PERROR("mkdir");
1975 return -1;
1976 }
1977 fd = open(subfile, flags, 0644);
1978 if (fd != -1) {
1979 close(fd);
1980 unlink(subfile);
1981 ERROR("open should have failed");
1982 err--;
1983 } else {
1984 res = check_nonexist(subfile);
1985 if (res == -1)
1986 err--;
1987 }
1988 unlink(subfile);
1989 res = rmdir(testdir);
1990 if (res == -1) {
1991 PERROR("rmdir");
1992 return -1;
1993 }
1994 res = check_nonexist(testdir);
1995 if (res == -1)
1996 return -1;
1997 if (err)
1998 return -1;
1999
2000 success();
2001 return 0;
2002}
2003
2004#ifndef __FreeBSD__
2005/* this tests open with O_TMPFILE
2006 note that this will only work with the fuse low level api
2007 you will get ENOTSUP with the high level api */
2008static int test_create_tmpfile(void)
2009{
2010 rmdir(testdir);
2011 int res = mkdir(testdir, 0777);
2012 if (res)
2013 return -1;
2014
2015 start_test("create tmpfile");
2016
2017 int fd = open(testdir, O_TMPFILE | O_RDWR, S_IRUSR | S_IWUSR);
2018 if(fd == -1) {
2019 if (errno == ENOTSUP) {
2020 /* don't bother if we're working on an old kernel
2021 or on the high level API */
2022 return 0;
2023 }
2024
2025 PERROR("open O_TMPFILE | O_RDWR");
2026 return -1;
2027 }
2028 close(fd);
2029
2030 fd = open(testdir, O_TMPFILE | O_WRONLY | O_EXCL, S_IRUSR | S_IWUSR);
2031 if(fd == -1){
2032 PERROR("open with O_TMPFILE | O_WRONLY | O_EXCL");
2033 return -1;
2034 };
2035 close(fd);
2036
2037 fd = open(testdir, O_TMPFILE | O_RDONLY, S_IRUSR);
2038 if (fd != -1) {
2039 ERROR("open with O_TMPFILE | O_RDONLY succeeded");
2040 return -1;
2041 }
2042
2043 success();
2044 return 0;
2045}
2046
2047static int test_create_and_link_tmpfile(void)
2048{
2049 /* skip this test for now since the github runner will fail in the linkat call below */
2050 return 0;
2051
2052 rmdir(testdir);
2053 unlink(testfile);
2054
2055 int res = mkdir(testdir, 0777);
2056 if (res)
2057 return -1;
2058
2059 start_test("create and link tmpfile");
2060
2061 int fd = open(testdir, O_TMPFILE | O_RDWR | O_EXCL, S_IRUSR | S_IWUSR);
2062 if(fd == -1) {
2063 if (errno == ENOTSUP) {
2064 /* don't bother if we're working on an old kernel
2065 or on the high level API */
2066 return 0;
2067 }
2068 PERROR("open with O_TMPFILE | O_RDWR | O_EXCL");
2069 return -1;
2070 }
2071
2072 if (!linkat(fd, "", AT_FDCWD, testfile, AT_EMPTY_PATH)) {
2073 ERROR("linkat succeeded on a tmpfile opened with O_EXCL");
2074 return -1;
2075 }
2076 close(fd);
2077
2078 fd = open(testdir, O_TMPFILE | O_RDWR, S_IRUSR | S_IWUSR);
2079 if(fd == -1) {
2080 PERROR("open O_TMPFILE");
2081 return -1;
2082 }
2083
2084 if (check_nonexist(testfile)) {
2085 return -1;
2086 }
2087
2088 if (linkat(fd, "", AT_FDCWD, testfile, AT_EMPTY_PATH)) {
2089 PERROR("linkat tempfile");
2090 return -1;
2091 }
2092 close(fd);
2093
2094 if (check_nlink(testfile, 1)) {
2095 return -1;
2096 }
2097 unlink(testfile);
2098
2099 success();
2100 return 0;
2101}
2102#endif
2103
2104int main(int argc, char *argv[])
2105{
2106 int err = 0;
2107 int a;
2108 int is_root;
2109
2110 umask(0);
2111 if (argc < 2 || argc > 4) {
2112 fprintf(stderr, "usage: %s testdir [:realdir] [[-]test#] [-u]\n", argv[0]);
2113 return 1;
2114 }
2115 basepath = argv[1];
2116 basepath_r = basepath;
2117 for (a = 2; a < argc; a++) {
2118 char *endptr;
2119 char *arg = argv[a];
2120 if (arg[0] == ':') {
2121 basepath_r = arg + 1;
2122 } else {
2123 if (arg[0] == '-') {
2124 arg++;
2125 if (arg[0] == 'u') {
2126 unlinked_test = 1;
2127 endptr = arg + 1;
2128 } else {
2129 skip_test = strtoul(arg, &endptr, 10);
2130 }
2131 } else {
2132 select_test = strtoul(arg, &endptr, 10);
2133 }
2134 if (arg[0] == '\0' || *endptr != '\0') {
2135 fprintf(stderr, "invalid option: '%s'\n", argv[a]);
2136 return 1;
2137 }
2138 }
2139 }
2140 assert(strlen(basepath) < 512);
2141 assert(strlen(basepath_r) < 512);
2142 if (basepath[0] != '/') {
2143 fprintf(stderr, "testdir must be an absolute path\n");
2144 return 1;
2145 }
2146
2147 sprintf(testfile, "%s/testfile", basepath);
2148 sprintf(testfile2, "%s/testfile2", basepath);
2149 sprintf(testdir, "%s/testdir", basepath);
2150 sprintf(testdir2, "%s/testdir2", basepath);
2151 sprintf(subfile, "%s/subfile", testdir2);
2152 sprintf(testsock, "%s/testsock", basepath);
2153
2154 sprintf(testfile_r, "%s/testfile", basepath_r);
2155 sprintf(testfile2_r, "%s/testfile2", basepath_r);
2156 sprintf(testdir_r, "%s/testdir", basepath_r);
2157 sprintf(testdir2_r, "%s/testdir2", basepath_r);
2158 sprintf(subfile_r, "%s/subfile", testdir2_r);
2159
2160 is_root = (geteuid() == 0);
2161
2162 err += test_create();
2163 err += test_create_unlink();
2164 err += test_symlink();
2165 err += test_link();
2166 err += test_link2();
2167 err += test_mknod();
2168 err += test_mkfifo();
2169 err += test_mkdir();
2170 err += test_rename_file();
2171 err += test_rename_dir();
2172 err += test_rename_dir_loop();
2173 err += test_seekdir();
2174 err += test_socket();
2175 err += test_utime();
2176 err += test_truncate(0);
2177 err += test_truncate(testdatalen / 2);
2178 err += test_truncate(testdatalen);
2179 err += test_truncate(testdatalen + 100);
2180 err += test_ftruncate(0, 0600);
2181 err += test_ftruncate(testdatalen / 2, 0600);
2182 err += test_ftruncate(testdatalen, 0600);
2183 err += test_ftruncate(testdatalen + 100, 0600);
2184 err += test_ftruncate(0, 0400);
2185 err += test_ftruncate(0, 0200);
2186 err += test_ftruncate(0, 0000);
2187 err += test_open(0, O_RDONLY, 0);
2188 err += test_open(1, O_RDONLY, 0);
2189 err += test_open(1, O_RDWR, 0);
2190 err += test_open(1, O_WRONLY, 0);
2191 err += test_open(0, O_RDWR | O_CREAT, 0600);
2192 err += test_open(1, O_RDWR | O_CREAT, 0600);
2193 err += test_open(0, O_RDWR | O_CREAT | O_TRUNC, 0600);
2194 err += test_open(1, O_RDWR | O_CREAT | O_TRUNC, 0600);
2195 err += test_open(0, O_RDONLY | O_CREAT, 0600);
2196 err += test_open(0, O_RDONLY | O_CREAT, 0400);
2197 err += test_open(0, O_RDONLY | O_CREAT, 0200);
2198 err += test_open(0, O_RDONLY | O_CREAT, 0000);
2199 err += test_open(0, O_WRONLY | O_CREAT, 0600);
2200 err += test_open(0, O_WRONLY | O_CREAT, 0400);
2201 err += test_open(0, O_WRONLY | O_CREAT, 0200);
2202 err += test_open(0, O_WRONLY | O_CREAT, 0000);
2203 err += test_open(0, O_RDWR | O_CREAT, 0400);
2204 err += test_open(0, O_RDWR | O_CREAT, 0200);
2205 err += test_open(0, O_RDWR | O_CREAT, 0000);
2206 err += test_open(0, O_RDWR | O_CREAT | O_EXCL, 0600);
2207 err += test_open(1, O_RDWR | O_CREAT | O_EXCL, 0600);
2208 err += test_open(0, O_RDWR | O_CREAT | O_EXCL, 0000);
2209 err += test_open(1, O_RDWR | O_CREAT | O_EXCL, 0000);
2210 err += test_open_acc(O_RDONLY, 0600, 0);
2211 err += test_open_acc(O_WRONLY, 0600, 0);
2212 err += test_open_acc(O_RDWR, 0600, 0);
2213 err += test_open_acc(O_RDONLY, 0400, 0);
2214 err += test_open_acc(O_WRONLY, 0200, 0);
2215 if(!is_root) {
2216 err += test_open_acc(O_RDONLY | O_TRUNC, 0400, EACCES);
2217 err += test_open_acc(O_WRONLY, 0400, EACCES);
2218 err += test_open_acc(O_RDWR, 0400, EACCES);
2219 err += test_open_acc(O_RDONLY, 0200, EACCES);
2220 err += test_open_acc(O_RDWR, 0200, EACCES);
2221 err += test_open_acc(O_RDONLY, 0000, EACCES);
2222 err += test_open_acc(O_WRONLY, 0000, EACCES);
2223 err += test_open_acc(O_RDWR, 0000, EACCES);
2224 }
2225 err += test_create_ro_dir(O_CREAT);
2226 err += test_create_ro_dir(O_CREAT | O_EXCL);
2227 err += test_create_ro_dir(O_CREAT | O_WRONLY);
2228 err += test_create_ro_dir(O_CREAT | O_TRUNC);
2229 err += test_copy_file_range();
2230 err += test_statx();
2231#ifndef __FreeBSD__
2232 err += test_create_tmpfile();
2233 err += test_create_and_link_tmpfile();
2234#endif
2235
2236 unlink(testfile2);
2237 unlink(testsock);
2238 rmdir(testdir);
2239 rmdir(testdir2);
2240
2241 if (err) {
2242 fprintf(stderr, "%i tests failed\n", -err);
2243 return 1;
2244 }
2245
2246 return check_unlinked_testfiles();
2247}