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#ifndef __FreeBSD__
1069 static int test_mknod(void)
1070{
1071 int err = 0;
1072 int res;
1073
1074 start_test("mknod");
1075 unlink(testfile);
1076 res = mknod(testfile, 0644, 0);
1077 if (res == -1) {
1078 PERROR("mknod");
1079 return -1;
1080 }
1081 res = check_type(testfile, S_IFREG);
1082 if (res == -1)
1083 return -1;
1084 err += check_mode(testfile, 0644);
1085 err += check_nlink(testfile, 1);
1086 err += check_size(testfile, 0);
1087 res = unlink(testfile);
1088 if (res == -1) {
1089 PERROR("unlink");
1090 return -1;
1091 }
1092 res = check_nonexist(testfile);
1093 if (res == -1)
1094 return -1;
1095 if (err)
1096 return -1;
1097
1098 success();
1099 return 0;
1100}
1101#endif
1102
1103#define test_open(exist, flags, mode) do_test_open(exist, flags, #flags, mode)
1104
1105 static int do_test_open(int exist, int flags, const char *flags_str, int mode)
1106{
1107 char buf[4096];
1108 const char *data = testdata;
1109 int datalen = testdatalen;
1110 unsigned currlen = 0;
1111 int err = 0;
1112 int res;
1113 int fd;
1114 off_t off;
1115
1116 start_test("open(%s, %s, 0%03o)", exist ? "+" : "-", flags_str, mode);
1117 unlink(testfile);
1118 if (exist) {
1119 res = create_file(testfile_r, testdata2, testdata2len);
1120 if (res == -1)
1121 return -1;
1122
1123 currlen = testdata2len;
1124 }
1125
1126 fd = open(testfile, flags, mode);
1127 if ((flags & O_CREAT) && (flags & O_EXCL) && exist) {
1128 if (fd != -1) {
1129 ERROR("open should have failed");
1130 close(fd);
1131 return -1;
1132 } else if (errno == EEXIST)
1133 goto succ;
1134 }
1135 if (!(flags & O_CREAT) && !exist) {
1136 if (fd != -1) {
1137 ERROR("open should have failed");
1138 close(fd);
1139 return -1;
1140 } else if (errno == ENOENT)
1141 goto succ;
1142 }
1143 if (fd == -1) {
1144 PERROR("open");
1145 return -1;
1146 }
1147
1148 if (flags & O_TRUNC)
1149 currlen = 0;
1150
1151 err += check_type(testfile, S_IFREG);
1152 if (exist)
1153 err += check_mode(testfile, 0644);
1154 else
1155 err += check_mode(testfile, mode);
1156 err += check_nlink(testfile, 1);
1157 err += check_size(testfile, currlen);
1158 if (exist && !(flags & O_TRUNC) && (mode & S_IRUSR))
1159 err += check_data(testfile, testdata2, 0, testdata2len);
1160
1161 res = write(fd, data, datalen);
1162 if ((flags & O_ACCMODE) != O_RDONLY) {
1163 if (res == -1) {
1164 PERROR("write");
1165 err --;
1166 } else if (res != datalen) {
1167 ERROR("write is short: %u instead of %u", res, datalen);
1168 err --;
1169 } else {
1170 if (datalen > (int) currlen)
1171 currlen = datalen;
1172
1173 err += check_size(testfile, currlen);
1174
1175 if (mode & S_IRUSR) {
1176 err += check_data(testfile, data, 0, datalen);
1177 if (exist && !(flags & O_TRUNC) &&
1178 testdata2len > datalen)
1179 err += check_data(testfile,
1180 testdata2 + datalen,
1181 datalen,
1182 testdata2len - datalen);
1183 }
1184 }
1185 } else {
1186 if (res != -1) {
1187 ERROR("write should have failed");
1188 err --;
1189 } else if (errno != EBADF) {
1190 PERROR("write");
1191 err --;
1192 }
1193 }
1194 off = lseek(fd, SEEK_SET, 0);
1195 if (off == (off_t) -1) {
1196 PERROR("lseek");
1197 err--;
1198 } else if (off != 0) {
1199 ERROR("offset should have returned 0");
1200 err --;
1201 }
1202 res = read(fd, buf, sizeof(buf));
1203 if ((flags & O_ACCMODE) != O_WRONLY) {
1204 if (res == -1) {
1205 PERROR("read");
1206 err--;
1207 } else {
1208 int readsize =
1209 currlen < sizeof(buf) ? currlen : sizeof(buf);
1210 if (res != readsize) {
1211 ERROR("read is short: %i instead of %u",
1212 res, readsize);
1213 err--;
1214 } else {
1215 if ((flags & O_ACCMODE) != O_RDONLY) {
1216 err += check_buffer(buf, data, datalen);
1217 if (exist && !(flags & O_TRUNC) &&
1218 testdata2len > datalen)
1219 err += check_buffer(buf + datalen,
1220 testdata2 + datalen,
1221 testdata2len - datalen);
1222 } else if (exist)
1223 err += check_buffer(buf, testdata2,
1224 testdata2len);
1225 }
1226 }
1227 } else {
1228 if (res != -1) {
1229 ERROR("read should have failed");
1230 err --;
1231 } else if (errno != EBADF) {
1232 PERROR("read");
1233 err --;
1234 }
1235 }
1236
1237 res = close(fd);
1238 if (res == -1) {
1239 PERROR("close");
1240 return -1;
1241 }
1242 res = unlink(testfile);
1243 if (res == -1) {
1244 PERROR("unlink");
1245 return -1;
1246 }
1247 res = check_nonexist(testfile);
1248 if (res == -1)
1249 return -1;
1250 res = check_nonexist(testfile_r);
1251 if (res == -1)
1252 return -1;
1253 if (err)
1254 return -1;
1255
1256succ:
1257 success();
1258 return 0;
1259}
1260
1261#define test_open_acc(flags, mode, err) \
1262 do_test_open_acc(flags, #flags, mode, err)
1263
1264 static int do_test_open_acc(int flags, const char *flags_str, int mode, int err)
1265{
1266 const char *data = testdata;
1267 int datalen = testdatalen;
1268 int res;
1269 int fd;
1270
1271 start_test("open_acc(%s) mode: 0%03o message: '%s'", flags_str, mode,
1272 strerror(err));
1273 unlink(testfile);
1274 res = create_testfile(testfile, data, datalen);
1275 if (res == -1)
1276 return -1;
1277
1278 res = chmod(testfile, mode);
1279 if (res == -1) {
1280 PERROR("chmod");
1281 return -1;
1282 }
1283
1284 res = check_testfile_mode(testfile, mode);
1285 if (res == -1)
1286 return -1;
1287
1288 fd = open(testfile, flags);
1289 if (fd == -1) {
1290 if (err != errno) {
1291 PERROR("open");
1292 return -1;
1293 }
1294 } else {
1295 if (err) {
1296 ERROR("open should have failed");
1297 close(fd);
1298 return -1;
1299 }
1300 close(fd);
1301 }
1302
1303 res = unlink(testfile);
1304 if (res == -1) {
1305 PERROR("unlink");
1306 return -1;
1307 }
1308 res = check_nonexist(testfile);
1309 if (res == -1)
1310 return -1;
1311 res = check_nonexist(testfile_r);
1312 if (res == -1)
1313 return -1;
1314
1315 success();
1316 return 0;
1317}
1318
1319 static int test_symlink(void)
1320{
1321 char buf[1024];
1322 const char *data = testdata;
1323 int datalen = testdatalen;
1324 int linklen = strlen(testfile);
1325 int err = 0;
1326 int res;
1327
1328 start_test("symlink");
1329 res = create_testfile(testfile, data, datalen);
1330 if (res == -1)
1331 return -1;
1332
1333 unlink(testfile2);
1334 res = symlink(testfile, testfile2);
1335 if (res == -1) {
1336 PERROR("symlink");
1337 return -1;
1338 }
1339 res = check_type(testfile2, S_IFLNK);
1340 if (res == -1)
1341 return -1;
1342 err += check_mode(testfile2, 0777);
1343 err += check_nlink(testfile2, 1);
1344 res = readlink(testfile2, buf, sizeof(buf));
1345 if (res == -1) {
1346 PERROR("readlink");
1347 err--;
1348 }
1349 if (res != linklen) {
1350 ERROR("short readlink: %u instead of %u", res, linklen);
1351 err--;
1352 }
1353 if (memcmp(buf, testfile, linklen) != 0) {
1354 ERROR("link mismatch");
1355 err--;
1356 }
1357 err += check_size(testfile2, datalen);
1358 err += check_data(testfile2, data, 0, datalen);
1359 res = unlink(testfile2);
1360 if (res == -1) {
1361 PERROR("unlink");
1362 return -1;
1363 }
1364 res = check_nonexist(testfile2);
1365 if (res == -1)
1366 return -1;
1367 if (err)
1368 return -1;
1369
1370 res = unlink(testfile);
1371 if (res == -1) {
1372 PERROR("unlink");
1373 return -1;
1374 }
1375 res = check_nonexist(testfile);
1376 if (res == -1)
1377 return -1;
1378
1379 success();
1380 return 0;
1381}
1382
1383 static int test_link(void)
1384{
1385 const char *data = testdata;
1386 int datalen = testdatalen;
1387 int err = 0;
1388 int res;
1389
1390 start_test("link");
1391 res = create_testfile(testfile, data, datalen);
1392 if (res == -1)
1393 return -1;
1394
1395 unlink(testfile2);
1396 res = link(testfile, testfile2);
1397 if (res == -1) {
1398 PERROR("link");
1399 return -1;
1400 }
1401 res = check_type(testfile2, S_IFREG);
1402 if (res == -1)
1403 return -1;
1404 err += check_mode(testfile2, 0644);
1405 err += check_nlink(testfile2, 2);
1406 err += check_size(testfile2, datalen);
1407 err += check_data(testfile2, data, 0, datalen);
1408 res = unlink(testfile);
1409 if (res == -1) {
1410 PERROR("unlink");
1411 return -1;
1412 }
1413 res = check_nonexist(testfile);
1414 if (res == -1)
1415 return -1;
1416
1417 err += check_nlink(testfile2, 1);
1418 res = unlink(testfile2);
1419 if (res == -1) {
1420 PERROR("unlink");
1421 return -1;
1422 }
1423 res = check_nonexist(testfile2);
1424 if (res == -1)
1425 return -1;
1426 if (err)
1427 return -1;
1428
1429 success();
1430 return 0;
1431}
1432
1433 static int test_link2(void)
1434{
1435 const char *data = testdata;
1436 int datalen = testdatalen;
1437 int err = 0;
1438 int res;
1439
1440 start_test("link-unlink-link");
1441 res = create_testfile(testfile, data, datalen);
1442 if (res == -1)
1443 return -1;
1444
1445 unlink(testfile2);
1446 res = link(testfile, testfile2);
1447 if (res == -1) {
1448 PERROR("link");
1449 return -1;
1450 }
1451 res = unlink(testfile);
1452 if (res == -1) {
1453 PERROR("unlink");
1454 return -1;
1455 }
1456 res = check_nonexist(testfile);
1457 if (res == -1)
1458 return -1;
1459 res = link(testfile2, testfile);
1460 if (res == -1) {
1461 PERROR("link");
1462 }
1463 res = check_type(testfile, S_IFREG);
1464 if (res == -1)
1465 return -1;
1466 err += check_mode(testfile, 0644);
1467 err += check_nlink(testfile, 2);
1468 err += check_size(testfile, datalen);
1469 err += check_data(testfile, data, 0, datalen);
1470
1471 res = unlink(testfile2);
1472 if (res == -1) {
1473 PERROR("unlink");
1474 return -1;
1475 }
1476 err += check_nlink(testfile, 1);
1477 res = unlink(testfile);
1478 if (res == -1) {
1479 PERROR("unlink");
1480 return -1;
1481 }
1482 res = check_nonexist(testfile);
1483 if (res == -1)
1484 return -1;
1485 if (err)
1486 return -1;
1487
1488 success();
1489 return 0;
1490}
1491
1492 static int test_rename_file(void)
1493{
1494 const char *data = testdata;
1495 int datalen = testdatalen;
1496 int err = 0;
1497 int res;
1498
1499 start_test("rename file");
1500 res = create_testfile(testfile, data, datalen);
1501 if (res == -1)
1502 return -1;
1503
1504 unlink(testfile2);
1505 res = rename(testfile, testfile2);
1506 if (res == -1) {
1507 PERROR("rename");
1508 return -1;
1509 }
1510 res = check_nonexist(testfile);
1511 if (res == -1)
1512 return -1;
1513 res = check_type(testfile2, S_IFREG);
1514 if (res == -1)
1515 return -1;
1516 err += check_mode(testfile2, 0644);
1517 err += check_nlink(testfile2, 1);
1518 err += check_size(testfile2, datalen);
1519 err += check_data(testfile2, data, 0, datalen);
1520 res = unlink(testfile2);
1521 if (res == -1) {
1522 PERROR("unlink");
1523 return -1;
1524 }
1525 res = check_nonexist(testfile2);
1526 if (res == -1)
1527 return -1;
1528 if (err)
1529 return -1;
1530
1531 success();
1532 return 0;
1533}
1534
1535 static int test_rename_dir(void)
1536{
1537 int err = 0;
1538 int res;
1539
1540 start_test("rename dir");
1541 res = create_dir(testdir, testdir_files);
1542 if (res == -1)
1543 return -1;
1544
1545 rmdir(testdir2);
1546 res = rename(testdir, testdir2);
1547 if (res == -1) {
1548 PERROR("rename");
1549 cleanup_dir(testdir, testdir_files, 1);
1550 return -1;
1551 }
1552 res = check_nonexist(testdir);
1553 if (res == -1) {
1554 cleanup_dir(testdir, testdir_files, 1);
1555 return -1;
1556 }
1557 res = check_type(testdir2, S_IFDIR);
1558 if (res == -1) {
1559 cleanup_dir(testdir2, testdir_files, 1);
1560 return -1;
1561 }
1562 err += check_mode(testdir2, 0755);
1563 err += check_dir_contents(testdir2, testdir_files);
1564 err += cleanup_dir(testdir2, testdir_files, 0);
1565 res = rmdir(testdir2);
1566 if (res == -1) {
1567 PERROR("rmdir");
1568 return -1;
1569 }
1570 res = check_nonexist(testdir2);
1571 if (res == -1)
1572 return -1;
1573 if (err)
1574 return -1;
1575
1576 success();
1577 return 0;
1578}
1579
1580 static int test_rename_dir_loop(void)
1581{
1582#define PATH(p) (snprintf(path, sizeof path, "%s/%s", testdir, p), path)
1583#define PATH2(p) (snprintf(path2, sizeof path2, "%s/%s", testdir, p), path2)
1584
1585 char path[1280], path2[1280];
1586 int err = 0;
1587 int res;
1588
1589 start_test("rename dir loop");
1590
1591 res = create_dir(testdir, testdir_files);
1592 if (res == -1)
1593 return -1;
1594
1595 res = mkdir(PATH("a"), 0755);
1596 if (res == -1) {
1597 PERROR("mkdir");
1598 goto fail;
1599 }
1600
1601 res = rename(PATH("a"), PATH2("a"));
1602 if (res == -1) {
1603 PERROR("rename");
1604 goto fail;
1605 }
1606
1607 errno = 0;
1608 res = rename(PATH("a"), PATH2("a/b"));
1609 if (res == 0 || errno != EINVAL) {
1610 PERROR("rename");
1611 goto fail;
1612 }
1613
1614 res = mkdir(PATH("a/b"), 0755);
1615 if (res == -1) {
1616 PERROR("mkdir");
1617 goto fail;
1618 }
1619
1620 res = mkdir(PATH("a/b/c"), 0755);
1621 if (res == -1) {
1622 PERROR("mkdir");
1623 goto fail;
1624 }
1625
1626 errno = 0;
1627 res = rename(PATH("a"), PATH2("a/b/c"));
1628 if (res == 0 || errno != EINVAL) {
1629 PERROR("rename");
1630 goto fail;
1631 }
1632
1633 errno = 0;
1634 res = rename(PATH("a"), PATH2("a/b/c/a"));
1635 if (res == 0 || errno != EINVAL) {
1636 PERROR("rename");
1637 goto fail;
1638 }
1639
1640 errno = 0;
1641 res = rename(PATH("a/b/c"), PATH2("a"));
1642 if (res == 0 || errno != ENOTEMPTY) {
1643 PERROR("rename");
1644 goto fail;
1645 }
1646
1647 res = open(PATH("a/foo"), O_CREAT, 0644);
1648 if (res == -1) {
1649 PERROR("open");
1650 goto fail;
1651 }
1652 close(res);
1653
1654 res = rename(PATH("a/foo"), PATH2("a/bar"));
1655 if (res == -1) {
1656 PERROR("rename");
1657 goto fail;
1658 }
1659
1660 res = rename(PATH("a/bar"), PATH2("a/foo"));
1661 if (res == -1) {
1662 PERROR("rename");
1663 goto fail;
1664 }
1665
1666 res = rename(PATH("a/foo"), PATH2("a/b/bar"));
1667 if (res == -1) {
1668 PERROR("rename");
1669 goto fail;
1670 }
1671
1672 res = rename(PATH("a/b/bar"), PATH2("a/foo"));
1673 if (res == -1) {
1674 PERROR("rename");
1675 goto fail;
1676 }
1677
1678 res = rename(PATH("a/foo"), PATH2("a/b/c/bar"));
1679 if (res == -1) {
1680 PERROR("rename");
1681 goto fail;
1682 }
1683
1684 res = rename(PATH("a/b/c/bar"), PATH2("a/foo"));
1685 if (res == -1) {
1686 PERROR("rename");
1687 goto fail;
1688 }
1689
1690 res = open(PATH("a/bar"), O_CREAT, 0644);
1691 if (res == -1) {
1692 PERROR("open");
1693 goto fail;
1694 }
1695 close(res);
1696
1697 res = rename(PATH("a/foo"), PATH2("a/bar"));
1698 if (res == -1) {
1699 PERROR("rename");
1700 goto fail;
1701 }
1702
1703 unlink(PATH("a/bar"));
1704
1705 res = rename(PATH("a/b"), PATH2("a/d"));
1706 if (res == -1) {
1707 PERROR("rename");
1708 goto fail;
1709 }
1710
1711 res = rename(PATH("a/d"), PATH2("a/b"));
1712 if (res == -1) {
1713 PERROR("rename");
1714 goto fail;
1715 }
1716
1717 res = mkdir(PATH("a/d"), 0755);
1718 if (res == -1) {
1719 PERROR("mkdir");
1720 goto fail;
1721 }
1722
1723 res = rename(PATH("a/b"), PATH2("a/d"));
1724 if (res == -1) {
1725 PERROR("rename");
1726 goto fail;
1727 }
1728
1729 res = rename(PATH("a/d"), PATH2("a/b"));
1730 if (res == -1) {
1731 PERROR("rename");
1732 goto fail;
1733 }
1734
1735 res = mkdir(PATH("a/d"), 0755);
1736 if (res == -1) {
1737 PERROR("mkdir");
1738 goto fail;
1739 }
1740
1741 res = mkdir(PATH("a/d/e"), 0755);
1742 if (res == -1) {
1743 PERROR("mkdir");
1744 goto fail;
1745 }
1746
1747 errno = 0;
1748 res = rename(PATH("a/b"), PATH2("a/d"));
1749 if (res == 0 || (errno != ENOTEMPTY && errno != EEXIST)) {
1750 PERROR("rename");
1751 goto fail;
1752 }
1753
1754 rmdir(PATH("a/d/e"));
1755 rmdir(PATH("a/d"));
1756
1757 rmdir(PATH("a/b/c"));
1758 rmdir(PATH("a/b"));
1759 rmdir(PATH("a"));
1760
1761 err += cleanup_dir(testdir, testdir_files, 0);
1762 res = rmdir(testdir);
1763 if (res == -1) {
1764 PERROR("rmdir");
1765 goto fail;
1766 }
1767 res = check_nonexist(testdir);
1768 if (res == -1)
1769 return -1;
1770 if (err)
1771 return -1;
1772
1773 success();
1774 return 0;
1775
1776fail:
1777 unlink(PATH("a/bar"));
1778
1779 rmdir(PATH("a/d/e"));
1780 rmdir(PATH("a/d"));
1781
1782 rmdir(PATH("a/b/c"));
1783 rmdir(PATH("a/b"));
1784 rmdir(PATH("a"));
1785
1786 cleanup_dir(testdir, testdir_files, 1);
1787 rmdir(testdir);
1788
1789 return -1;
1790
1791#undef PATH2
1792#undef PATH
1793}
1794
1795#ifndef __FreeBSD__
1796 static int test_mkfifo(void)
1797{
1798 int res;
1799 int err = 0;
1800
1801 start_test("mkfifo");
1802 unlink(testfile);
1803 res = mkfifo(testfile, 0644);
1804 if (res == -1) {
1805 PERROR("mkfifo");
1806 return -1;
1807 }
1808 res = check_type(testfile, S_IFIFO);
1809 if (res == -1)
1810 return -1;
1811 err += check_mode(testfile, 0644);
1812 err += check_nlink(testfile, 1);
1813 res = unlink(testfile);
1814 if (res == -1) {
1815 PERROR("unlink");
1816 return -1;
1817 }
1818 res = check_nonexist(testfile);
1819 if (res == -1)
1820 return -1;
1821 if (err)
1822 return -1;
1823
1824 success();
1825 return 0;
1826}
1827#endif
1828
1829 static int test_mkdir(void)
1830{
1831 int res;
1832 int err = 0;
1833 const char *dir_contents[] = {NULL};
1834
1835 start_test("mkdir");
1836 rmdir(testdir);
1837 res = mkdir(testdir, 0755);
1838 if (res == -1) {
1839 PERROR("mkdir");
1840 return -1;
1841 }
1842 res = check_type(testdir, S_IFDIR);
1843 if (res == -1)
1844 return -1;
1845 err += check_mode(testdir, 0755);
1846 /* Some file systems (like btrfs) don't track link
1847 count for directories */
1848 //err += check_nlink(testdir, 2);
1849 err += check_dir_contents(testdir, dir_contents);
1850 res = rmdir(testdir);
1851 if (res == -1) {
1852 PERROR("rmdir");
1853 return -1;
1854 }
1855 res = check_nonexist(testdir);
1856 if (res == -1)
1857 return -1;
1858 if (err)
1859 return -1;
1860
1861 success();
1862 return 0;
1863}
1864
1865 static int test_socket(void)
1866{
1867 struct sockaddr_un su;
1868 int fd;
1869 int res;
1870 int err = 0;
1871 const size_t test_sock_len = strlen(testsock) + 1;
1872
1873 start_test("socket");
1874 if (test_sock_len > sizeof(su.sun_path)) {
1875 fprintf(stderr, "Need to shorten mount point by %zu chars\n",
1876 strlen(testsock) + 1 - sizeof(su.sun_path));
1877 return -1;
1878 }
1879 unlink(testsock);
1880 fd = socket(AF_UNIX, SOCK_STREAM, 0);
1881 if (fd < 0) {
1882 PERROR("socket");
1883 return -1;
1884 }
1885 su.sun_family = AF_UNIX;
1886
1887 strncpy(su.sun_path, testsock, test_sock_len);
1888 su.sun_path[sizeof(su.sun_path) - 1] = '\0';
1889 res = bind(fd, (struct sockaddr*)&su, sizeof(su));
1890 if (res == -1) {
1891 PERROR("bind");
1892 return -1;
1893 }
1894
1895 res = check_type(testsock, S_IFSOCK);
1896 if (res == -1) {
1897 close(fd);
1898 return -1;
1899 }
1900 err += check_nlink(testsock, 1);
1901 close(fd);
1902 res = unlink(testsock);
1903 if (res == -1) {
1904 PERROR("unlink");
1905 return -1;
1906 }
1907 res = check_nonexist(testsock);
1908 if (res == -1)
1909 return -1;
1910 if (err)
1911 return -1;
1912
1913 success();
1914 return 0;
1915}
1916
1917#define test_create_ro_dir(flags) \
1918 do_test_create_ro_dir(flags, #flags)
1919
1920 static int do_test_create_ro_dir(int flags, const char *flags_str)
1921{
1922 int res;
1923 int err = 0;
1924 int fd;
1925
1926 start_test("open(%s) in read-only directory", flags_str);
1927 rmdir(testdir);
1928 res = mkdir(testdir, 0555);
1929 if (res == -1) {
1930 PERROR("mkdir");
1931 return -1;
1932 }
1933 fd = open(subfile, flags, 0644);
1934 if (fd != -1) {
1935 close(fd);
1936 unlink(subfile);
1937 ERROR("open should have failed");
1938 err--;
1939 } else {
1940 res = check_nonexist(subfile);
1941 if (res == -1)
1942 err--;
1943 }
1944 unlink(subfile);
1945 res = rmdir(testdir);
1946 if (res == -1) {
1947 PERROR("rmdir");
1948 return -1;
1949 }
1950 res = check_nonexist(testdir);
1951 if (res == -1)
1952 return -1;
1953 if (err)
1954 return -1;
1955
1956 success();
1957 return 0;
1958}
1959
1960/* this tests open with O_TMPFILE
1961 note that this will only work with the fuse low level api
1962 you will get ENOTSUP with the high level api */
1963 static int test_create_tmpfile(void)
1964{
1965 rmdir(testdir);
1966 int res = mkdir(testdir, 0777);
1967 if (res)
1968 return -1;
1969
1970 start_test("create tmpfile");
1971
1972 int fd = open(testdir, O_TMPFILE | O_RDWR, S_IRUSR | S_IWUSR);
1973 if(fd == -1) {
1974 if (errno == ENOTSUP) {
1975 /* don't bother if we're working on an old kernel
1976 or on the high level API */
1977 return 0;
1978 }
1979
1980 PERROR("open O_TMPFILE | O_RDWR");
1981 return -1;
1982 }
1983 close(fd);
1984
1985 fd = open(testdir, O_TMPFILE | O_WRONLY | O_EXCL, S_IRUSR | S_IWUSR);
1986 if(fd == -1){
1987 PERROR("open with O_TMPFILE | O_WRONLY | O_EXCL");
1988 return -1;
1989 };
1990 close(fd);
1991
1992 fd = open(testdir, O_TMPFILE | O_RDONLY, S_IRUSR);
1993 if (fd != -1) {
1994 ERROR("open with O_TMPFILE | O_RDONLY succeeded");
1995 return -1;
1996 }
1997
1998 success();
1999 return 0;
2000}
2001
2002 static int test_create_and_link_tmpfile(void)
2003{
2004 /* skip this test for now since the github runner will fail in the linkat call below */
2005 return 0;
2006
2007 rmdir(testdir);
2008 unlink(testfile);
2009
2010 int res = mkdir(testdir, 0777);
2011 if (res)
2012 return -1;
2013
2014 start_test("create and link tmpfile");
2015
2016 int fd = open(testdir, O_TMPFILE | O_RDWR | O_EXCL, S_IRUSR | S_IWUSR);
2017 if(fd == -1) {
2018 if (errno == ENOTSUP) {
2019 /* don't bother if we're working on an old kernel
2020 or on the high level API */
2021 return 0;
2022 }
2023 PERROR("open with O_TMPFILE | O_RDWR | O_EXCL");
2024 return -1;
2025 }
2026
2027 if (!linkat(fd, "", AT_FDCWD, testfile, AT_EMPTY_PATH)) {
2028 ERROR("linkat succeeded on a tmpfile opened with O_EXCL");
2029 return -1;
2030 }
2031 close(fd);
2032
2033 fd = open(testdir, O_TMPFILE | O_RDWR, S_IRUSR | S_IWUSR);
2034 if(fd == -1) {
2035 PERROR("open O_TMPFILE");
2036 return -1;
2037 }
2038
2039 if (check_nonexist(testfile)) {
2040 return -1;
2041 }
2042
2043 if (linkat(fd, "", AT_FDCWD, testfile, AT_EMPTY_PATH)) {
2044 PERROR("linkat tempfile");
2045 return -1;
2046 }
2047 close(fd);
2048
2049 if (check_nlink(testfile, 1)) {
2050 return -1;
2051 }
2052 unlink(testfile);
2053
2054 success();
2055 return 0;
2056}
2057
2058 int main(int argc, char *argv[])
2059{
2060 int err = 0;
2061 int a;
2062 int is_root;
2063
2064 umask(0);
2065 if (argc < 2 || argc > 4) {
2066 fprintf(stderr, "usage: %s testdir [:realdir] [[-]test#] [-u]\n", argv[0]);
2067 return 1;
2068 }
2069 basepath = argv[1];
2070 basepath_r = basepath;
2071 for (a = 2; a < argc; a++) {
2072 char *endptr;
2073 char *arg = argv[a];
2074 if (arg[0] == ':') {
2075 basepath_r = arg + 1;
2076 } else {
2077 if (arg[0] == '-') {
2078 arg++;
2079 if (arg[0] == 'u') {
2080 unlinked_test = 1;
2081 endptr = arg + 1;
2082 } else {
2083 skip_test = strtoul(arg, &endptr, 10);
2084 }
2085 } else {
2086 select_test = strtoul(arg, &endptr, 10);
2087 }
2088 if (arg[0] == '\0' || *endptr != '\0') {
2089 fprintf(stderr, "invalid option: '%s'\n", argv[a]);
2090 return 1;
2091 }
2092 }
2093 }
2094 assert(strlen(basepath) < 512);
2095 assert(strlen(basepath_r) < 512);
2096 if (basepath[0] != '/') {
2097 fprintf(stderr, "testdir must be an absolute path\n");
2098 return 1;
2099 }
2100
2101 sprintf(testfile, "%s/testfile", basepath);
2102 sprintf(testfile2, "%s/testfile2", basepath);
2103 sprintf(testdir, "%s/testdir", basepath);
2104 sprintf(testdir2, "%s/testdir2", basepath);
2105 sprintf(subfile, "%s/subfile", testdir2);
2106 sprintf(testsock, "%s/testsock", basepath);
2107
2108 sprintf(testfile_r, "%s/testfile", basepath_r);
2109 sprintf(testfile2_r, "%s/testfile2", basepath_r);
2110 sprintf(testdir_r, "%s/testdir", basepath_r);
2111 sprintf(testdir2_r, "%s/testdir2", basepath_r);
2112 sprintf(subfile_r, "%s/subfile", testdir2_r);
2113
2114 is_root = (geteuid() == 0);
2115
2116 err += test_create();
2117 err += test_create_unlink();
2118 err += test_symlink();
2119 err += test_link();
2120 err += test_link2();
2121#ifndef __FreeBSD__
2122 err += test_mknod();
2123 err += test_mkfifo();
2124#endif
2125 err += test_mkdir();
2126 err += test_rename_file();
2127 err += test_rename_dir();
2128 err += test_rename_dir_loop();
2129 err += test_seekdir();
2130 err += test_socket();
2131 err += test_utime();
2132 err += test_truncate(0);
2133 err += test_truncate(testdatalen / 2);
2134 err += test_truncate(testdatalen);
2135 err += test_truncate(testdatalen + 100);
2136 err += test_ftruncate(0, 0600);
2137 err += test_ftruncate(testdatalen / 2, 0600);
2138 err += test_ftruncate(testdatalen, 0600);
2139 err += test_ftruncate(testdatalen + 100, 0600);
2140 err += test_ftruncate(0, 0400);
2141 err += test_ftruncate(0, 0200);
2142 err += test_ftruncate(0, 0000);
2143 err += test_open(0, O_RDONLY, 0);
2144 err += test_open(1, O_RDONLY, 0);
2145 err += test_open(1, O_RDWR, 0);
2146 err += test_open(1, O_WRONLY, 0);
2147 err += test_open(0, O_RDWR | O_CREAT, 0600);
2148 err += test_open(1, O_RDWR | O_CREAT, 0600);
2149 err += test_open(0, O_RDWR | O_CREAT | O_TRUNC, 0600);
2150 err += test_open(1, O_RDWR | O_CREAT | O_TRUNC, 0600);
2151 err += test_open(0, O_RDONLY | O_CREAT, 0600);
2152 err += test_open(0, O_RDONLY | O_CREAT, 0400);
2153 err += test_open(0, O_RDONLY | O_CREAT, 0200);
2154 err += test_open(0, O_RDONLY | O_CREAT, 0000);
2155 err += test_open(0, O_WRONLY | O_CREAT, 0600);
2156 err += test_open(0, O_WRONLY | O_CREAT, 0400);
2157 err += test_open(0, O_WRONLY | O_CREAT, 0200);
2158 err += test_open(0, O_WRONLY | O_CREAT, 0000);
2159 err += test_open(0, O_RDWR | O_CREAT, 0400);
2160 err += test_open(0, O_RDWR | O_CREAT, 0200);
2161 err += test_open(0, O_RDWR | O_CREAT, 0000);
2162 err += test_open(0, O_RDWR | O_CREAT | O_EXCL, 0600);
2163 err += test_open(1, O_RDWR | O_CREAT | O_EXCL, 0600);
2164 err += test_open(0, O_RDWR | O_CREAT | O_EXCL, 0000);
2165 err += test_open(1, O_RDWR | O_CREAT | O_EXCL, 0000);
2166 err += test_open_acc(O_RDONLY, 0600, 0);
2167 err += test_open_acc(O_WRONLY, 0600, 0);
2168 err += test_open_acc(O_RDWR, 0600, 0);
2169 err += test_open_acc(O_RDONLY, 0400, 0);
2170 err += test_open_acc(O_WRONLY, 0200, 0);
2171 if(!is_root) {
2172 err += test_open_acc(O_RDONLY | O_TRUNC, 0400, EACCES);
2173 err += test_open_acc(O_WRONLY, 0400, EACCES);
2174 err += test_open_acc(O_RDWR, 0400, EACCES);
2175 err += test_open_acc(O_RDONLY, 0200, EACCES);
2176 err += test_open_acc(O_RDWR, 0200, EACCES);
2177 err += test_open_acc(O_RDONLY, 0000, EACCES);
2178 err += test_open_acc(O_WRONLY, 0000, EACCES);
2179 err += test_open_acc(O_RDWR, 0000, EACCES);
2180 }
2181 err += test_create_ro_dir(O_CREAT);
2182 err += test_create_ro_dir(O_CREAT | O_EXCL);
2183 err += test_create_ro_dir(O_CREAT | O_WRONLY);
2184 err += test_create_ro_dir(O_CREAT | O_TRUNC);
2185 err += test_copy_file_range();
2186 err += test_create_tmpfile();
2187 err += test_create_and_link_tmpfile();
2188
2189 unlink(testfile2);
2190 unlink(testsock);
2191 rmdir(testdir);
2192 rmdir(testdir2);
2193
2194 if (err) {
2195 fprintf(stderr, "%i tests failed\n", -err);
2196 return 1;
2197 }
2198
2199 return check_unlinked_testfiles();
2200}