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