libfuse

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