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 return -1;
783 }
784 res = close(fd_out);
785 if (res == -1) {
786 PERROR("close");
787 return -1;
788 }
789
790 err = check_data(testfile2, data, 0, datalen);
791
792 res = unlink(testfile);
793 if (res == -1) {
794 PERROR("unlink");
795 return -1;
796 }
797 res = check_nonexist(testfile);
798 if (res == -1)
799 return -1;
800 if (err)
801 return -1;
802
803 res = unlink(testfile2);
804 if (res == -1) {
805 PERROR("unlink");
806 return -1;
807 }
808 res = check_nonexist(testfile2);
809 if (res == -1)
810 return -1;
811 if (err)
812 return -1;
813
814 success();
815 return 0;
816 }
817 #else
818 static int test_copy_file_range(void)
819 {
820 return 0;
821 }
822 #endif
823
824 static int test_utime(void)
825 {
826 struct utimbuf utm;
827 time_t atime = 987631200;
828 time_t mtime = 123116400;
829 int res;
830
831 start_test("utime");
832 res = create_file(testfile, NULL, 0);
833 if (res == -1)
834 return -1;
835
836 utm.actime = atime;
837 utm.modtime = mtime;
838 res = utime(testfile, &utm);
839 if (res == -1) {
840 PERROR("utime");
841 return -1;
842 }
843 res = check_times(testfile, atime, mtime);
844 if (res == -1) {
845 return -1;
846 }
847 res = unlink(testfile);
848 if (res == -1) {
849 PERROR("unlink");
850 return -1;
851 }
852 res = check_nonexist(testfile);
853 if (res == -1)
854 return -1;
855
856 success();
857 return 0;
858 }
859
860 static int test_create(void)
861 {
862 const char *data = testdata;
863 int datalen = testdatalen;
864 int err = 0;
865 int res;
866 int fd;
867
868 start_test("create");
869 unlink(testfile);
870 fd = creat(testfile, 0644);
871 if (fd == -1) {
872 PERROR("creat");
873 return -1;
874 }
875 res = write(fd, data, datalen);
876 if (res == -1) {
877 PERROR("write");
878 close(fd);
879 return -1;
880 }
881 if (res != datalen) {
882 ERROR("write is short: %u instead of %u", res, datalen);
883 close(fd);
884 return -1;
885 }
886 res = close(fd);
887 if (res == -1) {
888 PERROR("close");
889 return -1;
890 }
891 res = check_type(testfile, S_IFREG);
892 if (res == -1)
893 return -1;
894 err += check_mode(testfile, 0644);
895 err += check_nlink(testfile, 1);
896 err += check_size(testfile, datalen);
897 err += check_data(testfile, data, 0, datalen);
898 res = unlink(testfile);
899 if (res == -1) {
900 PERROR("unlink");
901 return -1;
902 }
903 res = check_nonexist(testfile);
904 if (res == -1)
905 return -1;
906 if (err)
907 return -1;
908
909 success();
910 return 0;
911 }
912
913 static int test_create_unlink(void)
914 {
915 const char *data = testdata;
916 int datalen = testdatalen;
917 int err = 0;
918 int res;
919 int fd;
920
921 start_test("create+unlink");
922 unlink(testfile);
923 fd = open(testfile, O_CREAT | O_RDWR | O_TRUNC, 0644);
924 if (fd == -1) {
925 PERROR("creat");
926 return -1;
927 }
928 res = unlink(testfile);
929 if (res == -1) {
930 PERROR("unlink");
931 close(fd);
932 return -1;
933 }
934 res = check_nonexist(testfile);
935 if (res == -1)
936 return -1;
937 res = write(fd, data, datalen);
938 if (res == -1) {
939 PERROR("write");
940 close(fd);
941 return -1;
942 }
943 if (res != datalen) {
944 ERROR("write is short: %u instead of %u", res, datalen);
945 close(fd);
946 return -1;
947 }
948 err += fcheck_type(fd, S_IFREG);
949 err += fcheck_mode(fd, 0644);
950 err += fcheck_nlink(fd, 0);
951 err += fcheck_size(fd, datalen);
952 err += fcheck_data(fd, data, 0, datalen);
953 res = close(fd);
954 if (res == -1) {
955 PERROR("close");
956 err--;
957 }
958 if (err)
959 return -1;
960
961 success();
962 return 0;
963 }
964
965 #ifndef __FreeBSD__
966 static int test_mknod(void)
967 {
968 int err = 0;
969 int res;
970
971 start_test("mknod");
972 unlink(testfile);
973 res = mknod(testfile, 0644, 0);
974 if (res == -1) {
975 PERROR("mknod");
976 return -1;
977 }
978 res = check_type(testfile, S_IFREG);
979 if (res == -1)
980 return -1;
981 err += check_mode(testfile, 0644);
982 err += check_nlink(testfile, 1);
983 err += check_size(testfile, 0);
984 res = unlink(testfile);
985 if (res == -1) {
986 PERROR("unlink");
987 return -1;
988 }
989 res = check_nonexist(testfile);
990 if (res == -1)
991 return -1;
992 if (err)
993 return -1;
994
995 success();
996 return 0;
997 }
998 #endif
999
1000 #define test_open(exist, flags, mode) do_test_open(exist, flags, #flags, mode)
1001
1002 static int do_test_open(int exist, int flags, const char *flags_str, int mode)
1003 {
1004 char buf[4096];
1005 const char *data = testdata;
1006 int datalen = testdatalen;
1007 unsigned currlen = 0;
1008 int err = 0;
1009 int res;
1010 int fd;
1011 off_t off;
1012
1013 start_test("open(%s, %s, 0%03o)", exist ? "+" : "-", flags_str, mode);
1014 unlink(testfile);
1015 if (exist) {
1016 res = create_file(testfile_r, testdata2, testdata2len);
1017 if (res == -1)
1018 return -1;
1019
1020 currlen = testdata2len;
1021 }
1022
1023 fd = open(testfile, flags, mode);
1024 if ((flags & O_CREAT) && (flags & O_EXCL) && exist) {
1025 if (fd != -1) {
1026 ERROR("open should have failed");
1027 close(fd);
1028 return -1;
1029 } else if (errno == EEXIST)
1030 goto succ;
1031 }
1032 if (!(flags & O_CREAT) && !exist) {
1033 if (fd != -1) {
1034 ERROR("open should have failed");
1035 close(fd);
1036 return -1;
1037 } else if (errno == ENOENT)
1038 goto succ;
1039 }
1040 if (fd == -1) {
1041 PERROR("open");
1042 return -1;
1043 }
1044
1045 if (flags & O_TRUNC)
1046 currlen = 0;
1047
1048 err += check_type(testfile, S_IFREG);
1049 if (exist)
1050 err += check_mode(testfile, 0644);
1051 else
1052 err += check_mode(testfile, mode);
1053 err += check_nlink(testfile, 1);
1054 err += check_size(testfile, currlen);
1055 if (exist && !(flags & O_TRUNC) && (mode & S_IRUSR))
1056 err += check_data(testfile, testdata2, 0, testdata2len);
1057
1058 res = write(fd, data, datalen);
1059 if ((flags & O_ACCMODE) != O_RDONLY) {
1060 if (res == -1) {
1061 PERROR("write");
1062 err --;
1063 } else if (res != datalen) {
1064 ERROR("write is short: %u instead of %u", res, datalen);
1065 err --;
1066 } else {
1067 if (datalen > (int) currlen)
1068 currlen = datalen;
1069
1070 err += check_size(testfile, currlen);
1071
1072 if (mode & S_IRUSR) {
1073 err += check_data(testfile, data, 0, datalen);
1074 if (exist && !(flags & O_TRUNC) &&
1075 testdata2len > datalen)
1076 err += check_data(testfile,
1077 testdata2 + datalen,
1078 datalen,
1079 testdata2len - datalen);
1080 }
1081 }
1082 } else {
1083 if (res != -1) {
1084 ERROR("write should have failed");
1085 err --;
1086 } else if (errno != EBADF) {
1087 PERROR("write");
1088 err --;
1089 }
1090 }
1091 off = lseek(fd, SEEK_SET, 0);
1092 if (off == (off_t) -1) {
1093 PERROR("lseek");
1094 err--;
1095 } else if (off != 0) {
1096 ERROR("offset should have returned 0");
1097 err --;
1098 }
1099 res = read(fd, buf, sizeof(buf));
1100 if ((flags & O_ACCMODE) != O_WRONLY) {
1101 if (res == -1) {
1102 PERROR("read");
1103 err--;
1104 } else {
1105 int readsize =
1106 currlen < sizeof(buf) ? currlen : sizeof(buf);
1107 if (res != readsize) {
1108 ERROR("read is short: %i instead of %u",
1109 res, readsize);
1110 err--;
1111 } else {
1112 if ((flags & O_ACCMODE) != O_RDONLY) {
1113 err += check_buffer(buf, data, datalen);
1114 if (exist && !(flags & O_TRUNC) &&
1115 testdata2len > datalen)
1116 err += check_buffer(buf + datalen,
1117 testdata2 + datalen,
1118 testdata2len - datalen);
1119 } else if (exist)
1120 err += check_buffer(buf, testdata2,
1121 testdata2len);
1122 }
1123 }
1124 } else {
1125 if (res != -1) {
1126 ERROR("read should have failed");
1127 err --;
1128 } else if (errno != EBADF) {
1129 PERROR("read");
1130 err --;
1131 }
1132 }
1133
1134 res = close(fd);
1135 if (res == -1) {
1136 PERROR("close");
1137 return -1;
1138 }
1139 res = unlink(testfile);
1140 if (res == -1) {
1141 PERROR("unlink");
1142 return -1;
1143 }
1144 res = check_nonexist(testfile);
1145 if (res == -1)
1146 return -1;
1147 res = check_nonexist(testfile_r);
1148 if (res == -1)
1149 return -1;
1150 if (err)
1151 return -1;
1152
1153 succ:
1154 success();
1155 return 0;
1156 }
1157
1158 #define test_open_acc(flags, mode, err) \
1159 do_test_open_acc(flags, #flags, mode, err)
1160
1161 static int do_test_open_acc(int flags, const char *flags_str, int mode, int err)
1162 {
1163 const char *data = testdata;
1164 int datalen = testdatalen;
1165 int res;
1166 int fd;
1167
1168 start_test("open_acc(%s) mode: 0%03o message: '%s'", flags_str, mode,
1169 strerror(err));
1170 unlink(testfile);
1171 res = create_file(testfile, data, datalen);
1172 if (res == -1)
1173 return -1;
1174
1175 res = chmod(testfile, mode);
1176 if (res == -1) {
1177 PERROR("chmod");
1178 return -1;
1179 }
1180
1181 res = check_mode(testfile, mode);
1182 if (res == -1)
1183 return -1;
1184
1185 fd = open(testfile, flags);
1186 if (fd == -1) {
1187 if (err != errno) {
1188 PERROR("open");
1189 return -1;
1190 }
1191 } else {
1192 if (err) {
1193 ERROR("open should have failed");
1194 close(fd);
1195 return -1;
1196 }
1197 close(fd);
1198 }
1199 success();
1200 return 0;
1201 }
1202
1203 static int test_symlink(void)
1204 {
1205 char buf[1024];
1206 const char *data = testdata;
1207 int datalen = testdatalen;
1208 int linklen = strlen(testfile);
1209 int err = 0;
1210 int res;
1211
1212 start_test("symlink");
1213 res = create_file(testfile, data, datalen);
1214 if (res == -1)
1215 return -1;
1216
1217 unlink(testfile2);
1218 res = symlink(testfile, testfile2);
1219 if (res == -1) {
1220 PERROR("symlink");
1221 return -1;
1222 }
1223 res = check_type(testfile2, S_IFLNK);
1224 if (res == -1)
1225 return -1;
1226 err += check_mode(testfile2, 0777);
1227 err += check_nlink(testfile2, 1);
1228 res = readlink(testfile2, buf, sizeof(buf));
1229 if (res == -1) {
1230 PERROR("readlink");
1231 err--;
1232 }
1233 if (res != linklen) {
1234 ERROR("short readlink: %u instead of %u", res, linklen);
1235 err--;
1236 }
1237 if (memcmp(buf, testfile, linklen) != 0) {
1238 ERROR("link mismatch");
1239 err--;
1240 }
1241 err += check_size(testfile2, datalen);
1242 err += check_data(testfile2, data, 0, datalen);
1243 res = unlink(testfile2);
1244 if (res == -1) {
1245 PERROR("unlink");
1246 return -1;
1247 }
1248 res = check_nonexist(testfile2);
1249 if (res == -1)
1250 return -1;
1251 if (err)
1252 return -1;
1253
1254 success();
1255 return 0;
1256 }
1257
1258 static int test_link(void)
1259 {
1260 const char *data = testdata;
1261 int datalen = testdatalen;
1262 int err = 0;
1263 int res;
1264
1265 start_test("link");
1266 res = create_file(testfile, data, datalen);
1267 if (res == -1)
1268 return -1;
1269
1270 unlink(testfile2);
1271 res = link(testfile, testfile2);
1272 if (res == -1) {
1273 PERROR("link");
1274 return -1;
1275 }
1276 res = check_type(testfile2, S_IFREG);
1277 if (res == -1)
1278 return -1;
1279 err += check_mode(testfile2, 0644);
1280 err += check_nlink(testfile2, 2);
1281 err += check_size(testfile2, datalen);
1282 err += check_data(testfile2, data, 0, datalen);
1283 res = unlink(testfile);
1284 if (res == -1) {
1285 PERROR("unlink");
1286 return -1;
1287 }
1288 res = check_nonexist(testfile);
1289 if (res == -1)
1290 return -1;
1291
1292 err += check_nlink(testfile2, 1);
1293 res = unlink(testfile2);
1294 if (res == -1) {
1295 PERROR("unlink");
1296 return -1;
1297 }
1298 res = check_nonexist(testfile2);
1299 if (res == -1)
1300 return -1;
1301 if (err)
1302 return -1;
1303
1304 success();
1305 return 0;
1306 }
1307
1308 static int test_link2(void)
1309 {
1310 const char *data = testdata;
1311 int datalen = testdatalen;
1312 int err = 0;
1313 int res;
1314
1315 start_test("link-unlink-link");
1316 res = create_file(testfile, data, datalen);
1317 if (res == -1)
1318 return -1;
1319
1320 unlink(testfile2);
1321 res = link(testfile, testfile2);
1322 if (res == -1) {
1323 PERROR("link");
1324 return -1;
1325 }
1326 res = unlink(testfile);
1327 if (res == -1) {
1328 PERROR("unlink");
1329 return -1;
1330 }
1331 res = check_nonexist(testfile);
1332 if (res == -1)
1333 return -1;
1334 res = link(testfile2, testfile);
1335 if (res == -1) {
1336 PERROR("link");
1337 }
1338 res = check_type(testfile, S_IFREG);
1339 if (res == -1)
1340 return -1;
1341 err += check_mode(testfile, 0644);
1342 err += check_nlink(testfile, 2);
1343 err += check_size(testfile, datalen);
1344 err += check_data(testfile, data, 0, datalen);
1345
1346 res = unlink(testfile2);
1347 if (res == -1) {
1348 PERROR("unlink");
1349 return -1;
1350 }
1351 err += check_nlink(testfile, 1);
1352 res = unlink(testfile);
1353 if (res == -1) {
1354 PERROR("unlink");
1355 return -1;
1356 }
1357 res = check_nonexist(testfile);
1358 if (res == -1)
1359 return -1;
1360 if (err)
1361 return -1;
1362
1363 success();
1364 return 0;
1365 }
1366
1367 static int test_rename_file(void)
1368 {
1369 const char *data = testdata;
1370 int datalen = testdatalen;
1371 int err = 0;
1372 int res;
1373
1374 start_test("rename file");
1375 res = create_file(testfile, data, datalen);
1376 if (res == -1)
1377 return -1;
1378
1379 unlink(testfile2);
1380 res = rename(testfile, testfile2);
1381 if (res == -1) {
1382 PERROR("rename");
1383 return -1;
1384 }
1385 res = check_nonexist(testfile);
1386 if (res == -1)
1387 return -1;
1388 res = check_type(testfile2, S_IFREG);
1389 if (res == -1)
1390 return -1;
1391 err += check_mode(testfile2, 0644);
1392 err += check_nlink(testfile2, 1);
1393 err += check_size(testfile2, datalen);
1394 err += check_data(testfile2, data, 0, datalen);
1395 res = unlink(testfile2);
1396 if (res == -1) {
1397 PERROR("unlink");
1398 return -1;
1399 }
1400 res = check_nonexist(testfile2);
1401 if (res == -1)
1402 return -1;
1403 if (err)
1404 return -1;
1405
1406 success();
1407 return 0;
1408 }
1409
1410 static int test_rename_dir(void)
1411 {
1412 int err = 0;
1413 int res;
1414
1415 start_test("rename dir");
1416 res = create_dir(testdir, testdir_files);
1417 if (res == -1)
1418 return -1;
1419
1420 rmdir(testdir2);
1421 res = rename(testdir, testdir2);
1422 if (res == -1) {
1423 PERROR("rename");
1424 cleanup_dir(testdir, testdir_files, 1);
1425 return -1;
1426 }
1427 res = check_nonexist(testdir);
1428 if (res == -1) {
1429 cleanup_dir(testdir, testdir_files, 1);
1430 return -1;
1431 }
1432 res = check_type(testdir2, S_IFDIR);
1433 if (res == -1) {
1434 cleanup_dir(testdir2, testdir_files, 1);
1435 return -1;
1436 }
1437 err += check_mode(testdir2, 0755);
1438 err += check_dir_contents(testdir2, testdir_files);
1439 err += cleanup_dir(testdir2, testdir_files, 0);
1440 res = rmdir(testdir2);
1441 if (res == -1) {
1442 PERROR("rmdir");
1443 return -1;
1444 }
1445 res = check_nonexist(testdir2);
1446 if (res == -1)
1447 return -1;
1448 if (err)
1449 return -1;
1450
1451 success();
1452 return 0;
1453 }
1454
1455 static int test_rename_dir_loop(void)
1456 {
1457 #define PATH(p) (snprintf(path, sizeof path, "%s/%s", testdir, p), path)
1458 #define PATH2(p) (snprintf(path2, sizeof path2, "%s/%s", testdir, p), path2)
1459
1460 char path[1280], path2[1280];
1461 int err = 0;
1462 int res;
1463
1464 start_test("rename dir loop");
1465
1466 res = create_dir(testdir, testdir_files);
1467 if (res == -1)
1468 return -1;
1469
1470 res = mkdir(PATH("a"), 0755);
1471 if (res == -1) {
1472 PERROR("mkdir");
1473 goto fail;
1474 }
1475
1476 res = rename(PATH("a"), PATH2("a"));
1477 if (res == -1) {
1478 PERROR("rename");
1479 goto fail;
1480 }
1481
1482 errno = 0;
1483 res = rename(PATH("a"), PATH2("a/b"));
1484 if (res == 0 || errno != EINVAL) {
1485 PERROR("rename");
1486 goto fail;
1487 }
1488
1489 res = mkdir(PATH("a/b"), 0755);
1490 if (res == -1) {
1491 PERROR("mkdir");
1492 goto fail;
1493 }
1494
1495 res = mkdir(PATH("a/b/c"), 0755);
1496 if (res == -1) {
1497 PERROR("mkdir");
1498 goto fail;
1499 }
1500
1501 errno = 0;
1502 res = rename(PATH("a"), PATH2("a/b/c"));
1503 if (res == 0 || errno != EINVAL) {
1504 PERROR("rename");
1505 goto fail;
1506 }
1507
1508 errno = 0;
1509 res = rename(PATH("a"), PATH2("a/b/c/a"));
1510 if (res == 0 || errno != EINVAL) {
1511 PERROR("rename");
1512 goto fail;
1513 }
1514
1515 errno = 0;
1516 res = rename(PATH("a/b/c"), PATH2("a"));
1517 if (res == 0 || errno != ENOTEMPTY) {
1518 PERROR("rename");
1519 goto fail;
1520 }
1521
1522 res = open(PATH("a/foo"), O_CREAT, 0644);
1523 if (res == -1) {
1524 PERROR("open");
1525 goto fail;
1526 }
1527 close(res);
1528
1529 res = rename(PATH("a/foo"), PATH2("a/bar"));
1530 if (res == -1) {
1531 PERROR("rename");
1532 goto fail;
1533 }
1534
1535 res = rename(PATH("a/bar"), PATH2("a/foo"));
1536 if (res == -1) {
1537 PERROR("rename");
1538 goto fail;
1539 }
1540
1541 res = rename(PATH("a/foo"), PATH2("a/b/bar"));
1542 if (res == -1) {
1543 PERROR("rename");
1544 goto fail;
1545 }
1546
1547 res = rename(PATH("a/b/bar"), PATH2("a/foo"));
1548 if (res == -1) {
1549 PERROR("rename");
1550 goto fail;
1551 }
1552
1553 res = rename(PATH("a/foo"), PATH2("a/b/c/bar"));
1554 if (res == -1) {
1555 PERROR("rename");
1556 goto fail;
1557 }
1558
1559 res = rename(PATH("a/b/c/bar"), PATH2("a/foo"));
1560 if (res == -1) {
1561 PERROR("rename");
1562 goto fail;
1563 }
1564
1565 res = open(PATH("a/bar"), O_CREAT, 0644);
1566 if (res == -1) {
1567 PERROR("open");
1568 goto fail;
1569 }
1570 close(res);
1571
1572 res = rename(PATH("a/foo"), PATH2("a/bar"));
1573 if (res == -1) {
1574 PERROR("rename");
1575 goto fail;
1576 }
1577
1578 unlink(PATH("a/bar"));
1579
1580 res = rename(PATH("a/b"), PATH2("a/d"));
1581 if (res == -1) {
1582 PERROR("rename");
1583 goto fail;
1584 }
1585
1586 res = rename(PATH("a/d"), PATH2("a/b"));
1587 if (res == -1) {
1588 PERROR("rename");
1589 goto fail;
1590 }
1591
1592 res = mkdir(PATH("a/d"), 0755);
1593 if (res == -1) {
1594 PERROR("mkdir");
1595 goto fail;
1596 }
1597
1598 res = rename(PATH("a/b"), PATH2("a/d"));
1599 if (res == -1) {
1600 PERROR("rename");
1601 goto fail;
1602 }
1603
1604 res = rename(PATH("a/d"), PATH2("a/b"));
1605 if (res == -1) {
1606 PERROR("rename");
1607 goto fail;
1608 }
1609
1610 res = mkdir(PATH("a/d"), 0755);
1611 if (res == -1) {
1612 PERROR("mkdir");
1613 goto fail;
1614 }
1615
1616 res = mkdir(PATH("a/d/e"), 0755);
1617 if (res == -1) {
1618 PERROR("mkdir");
1619 goto fail;
1620 }
1621
1622 errno = 0;
1623 res = rename(PATH("a/b"), PATH2("a/d"));
1624 if (res == 0 || errno != ENOTEMPTY) {
1625 PERROR("rename");
1626 goto fail;
1627 }
1628
1629 rmdir(PATH("a/d/e"));
1630 rmdir(PATH("a/d"));
1631
1632 rmdir(PATH("a/b/c"));
1633 rmdir(PATH("a/b"));
1634 rmdir(PATH("a"));
1635
1636 err += cleanup_dir(testdir, testdir_files, 0);
1637 res = rmdir(testdir);
1638 if (res == -1) {
1639 PERROR("rmdir");
1640 goto fail;
1641 }
1642 res = check_nonexist(testdir);
1643 if (res == -1)
1644 return -1;
1645 if (err)
1646 return -1;
1647
1648 success();
1649 return 0;
1650
1651 fail:
1652 unlink(PATH("a/bar"));
1653
1654 rmdir(PATH("a/d/e"));
1655 rmdir(PATH("a/d"));
1656
1657 rmdir(PATH("a/b/c"));
1658 rmdir(PATH("a/b"));
1659 rmdir(PATH("a"));
1660
1661 cleanup_dir(testdir, testdir_files, 1);
1662 rmdir(testdir);
1663
1664 return -1;
1665
1666 #undef PATH2
1667 #undef PATH
1668 }
1669
1670 #ifndef __FreeBSD__
1671 static int test_mkfifo(void)
1672 {
1673 int res;
1674 int err = 0;
1675
1676 start_test("mkfifo");
1677 unlink(testfile);
1678 res = mkfifo(testfile, 0644);
1679 if (res == -1) {
1680 PERROR("mkfifo");
1681 return -1;
1682 }
1683 res = check_type(testfile, S_IFIFO);
1684 if (res == -1)
1685 return -1;
1686 err += check_mode(testfile, 0644);
1687 err += check_nlink(testfile, 1);
1688 res = unlink(testfile);
1689 if (res == -1) {
1690 PERROR("unlink");
1691 return -1;
1692 }
1693 res = check_nonexist(testfile);
1694 if (res == -1)
1695 return -1;
1696 if (err)
1697 return -1;
1698
1699 success();
1700 return 0;
1701 }
1702 #endif
1703
1704 static int test_mkdir(void)
1705 {
1706 int res;
1707 int err = 0;
1708 const char *dir_contents[] = {NULL};
1709
1710 start_test("mkdir");
1711 rmdir(testdir);
1712 res = mkdir(testdir, 0755);
1713 if (res == -1) {
1714 PERROR("mkdir");
1715 return -1;
1716 }
1717 res = check_type(testdir, S_IFDIR);
1718 if (res == -1)
1719 return -1;
1720 err += check_mode(testdir, 0755);
1721 /* Some file systems (like btrfs) don't track link
1722 count for directories */
1723 //err += check_nlink(testdir, 2);
1724 err += check_dir_contents(testdir, dir_contents);
1725 res = rmdir(testdir);
1726 if (res == -1) {
1727 PERROR("rmdir");
1728 return -1;
1729 }
1730 res = check_nonexist(testdir);
1731 if (res == -1)
1732 return -1;
1733 if (err)
1734 return -1;
1735
1736 success();
1737 return 0;
1738 }
1739
1740 static int test_socket(void)
1741 {
1742 struct sockaddr_un su;
1743 int fd;
1744 int res;
1745 int err = 0;
1746
1747 start_test("socket");
1748 if (strlen(testsock) + 1 > sizeof(su.sun_path)) {
1749 fprintf(stderr, "Need to shorten mount point by %lu chars\n",
1750 strlen(testsock) + 1 - sizeof(su.sun_path));
1751 return -1;
1752 }
1753 unlink(testsock);
1754 fd = socket(AF_UNIX, SOCK_STREAM, 0);
1755 if (fd < 0) {
1756 PERROR("socket");
1757 return -1;
1758 }
1759 su.sun_family = AF_UNIX;
1760 strncpy(su.sun_path, testsock, sizeof(su.sun_path) - 1);
1761 su.sun_path[sizeof(su.sun_path) - 1] = '\0';
1762 res = bind(fd, (struct sockaddr*)&su, sizeof(su));
1763 if (res == -1) {
1764 PERROR("bind");
1765 return -1;
1766 }
1767
1768 res = check_type(testsock, S_IFSOCK);
1769 if (res == -1)
1770 return -1;
1771 err += check_nlink(testsock, 1);
1772 close(fd);
1773 res = unlink(testsock);
1774 if (res == -1) {
1775 PERROR("unlink");
1776 return -1;
1777 }
1778 res = check_nonexist(testsock);
1779 if (res == -1)
1780 return -1;
1781 if (err)
1782 return -1;
1783
1784 success();
1785 return 0;
1786 }
1787
1788 #define test_create_ro_dir(flags) \
1789 do_test_create_ro_dir(flags, #flags)
1790
1791 static int do_test_create_ro_dir(int flags, const char *flags_str)
1792 {
1793 int res;
1794 int err = 0;
1795 int fd;
1796
1797 start_test("open(%s) in read-only directory", flags_str);
1798 rmdir(testdir);
1799 res = mkdir(testdir, 0555);
1800 if (res == -1) {
1801 PERROR("mkdir");
1802 return -1;
1803 }
1804 fd = open(subfile, flags, 0644);
1805 if (fd != -1) {
1806 close(fd);
1807 unlink(subfile);
1808 ERROR("open should have failed");
1809 err--;
1810 } else {
1811 res = check_nonexist(subfile);
1812 if (res == -1)
1813 err--;
1814 }
1815 unlink(subfile);
1816 res = rmdir(testdir);
1817 if (res == -1) {
1818 PERROR("rmdir");
1819 return -1;
1820 }
1821 res = check_nonexist(testdir);
1822 if (res == -1)
1823 return -1;
1824 if (err)
1825 return -1;
1826
1827 success();
1828 return 0;
1829 }
1830
1831 int main(int argc, char *argv[])
1832 {
1833 const char *basepath;
1834 const char *realpath;
1835 int err = 0;
1836 int a;
1837 int is_root;
1838
1839 umask(0);
1840 if (argc < 2 || argc > 4) {
1841 fprintf(stderr, "usage: %s testdir [:realdir] [[-]test#]\n", argv[0]);
1842 return 1;
1843 }
1844 basepath = argv[1];
1845 realpath = basepath;
1846 for (a = 2; a < argc; a++) {
1847 char *endptr;
1848 char *arg = argv[a];
1849 if (arg[0] == ':') {
1850 realpath = arg + 1;
1851 } else {
1852 if (arg[0] == '-') {
1853 arg++;
1854 skip_test = strtoul(arg, &endptr, 10);
1855 } else {
1856 select_test = strtoul(arg, &endptr, 10);
1857 }
1858 if (arg[0] == '\0' || *endptr != '\0') {
1859 fprintf(stderr, "invalid number: '%s'\n", arg);
1860 return 1;
1861 }
1862 }
1863 }
1864 assert(strlen(basepath) < 512);
1865 assert(strlen(realpath) < 512);
1866 if (basepath[0] != '/') {
1867 fprintf(stderr, "testdir must be an absolute path\n");
1868 return 1;
1869 }
1870
1871 sprintf(testfile, "%s/testfile", basepath);
1872 sprintf(testfile2, "%s/testfile2", basepath);
1873 sprintf(testdir, "%s/testdir", basepath);
1874 sprintf(testdir2, "%s/testdir2", basepath);
1875 sprintf(subfile, "%s/subfile", testdir2);
1876 sprintf(testsock, "%s/testsock", basepath);
1877
1878 sprintf(testfile_r, "%s/testfile", realpath);
1879 sprintf(testfile2_r, "%s/testfile2", realpath);
1880 sprintf(testdir_r, "%s/testdir", realpath);
1881 sprintf(testdir2_r, "%s/testdir2", realpath);
1882 sprintf(subfile_r, "%s/subfile", testdir2_r);
1883
1884 is_root = (geteuid() == 0);
1885
1886 err += test_create();
1887 err += test_create_unlink();
1888 err += test_symlink();
1889 err += test_link();
1890 err += test_link2();
1891 #ifndef __FreeBSD__
1892 err += test_mknod();
1893 err += test_mkfifo();
1894 #endif
1895 err += test_mkdir();
1896 err += test_rename_file();
1897 err += test_rename_dir();
1898 err += test_rename_dir_loop();
1899 err += test_seekdir();
1900 err += test_socket();
1901 err += test_utime();
1902 err += test_truncate(0);
1903 err += test_truncate(testdatalen / 2);
1904 err += test_truncate(testdatalen);
1905 err += test_truncate(testdatalen + 100);
1906 err += test_ftruncate(0, 0600);
1907 err += test_ftruncate(testdatalen / 2, 0600);
1908 err += test_ftruncate(testdatalen, 0600);
1909 err += test_ftruncate(testdatalen + 100, 0600);
1910 err += test_ftruncate(0, 0400);
1911 err += test_ftruncate(0, 0200);
1912 err += test_ftruncate(0, 0000);
1913 err += test_open(0, O_RDONLY, 0);
1914 err += test_open(1, O_RDONLY, 0);
1915 err += test_open(1, O_RDWR, 0);
1916 err += test_open(1, O_WRONLY, 0);
1917 err += test_open(0, O_RDWR | O_CREAT, 0600);
1918 err += test_open(1, O_RDWR | O_CREAT, 0600);
1919 err += test_open(0, O_RDWR | O_CREAT | O_TRUNC, 0600);
1920 err += test_open(1, O_RDWR | O_CREAT | O_TRUNC, 0600);
1921 err += test_open(0, O_RDONLY | O_CREAT, 0600);
1922 err += test_open(0, O_RDONLY | O_CREAT, 0400);
1923 err += test_open(0, O_RDONLY | O_CREAT, 0200);
1924 err += test_open(0, O_RDONLY | O_CREAT, 0000);
1925 err += test_open(0, O_WRONLY | O_CREAT, 0600);
1926 err += test_open(0, O_WRONLY | O_CREAT, 0400);
1927 err += test_open(0, O_WRONLY | O_CREAT, 0200);
1928 err += test_open(0, O_WRONLY | O_CREAT, 0000);
1929 err += test_open(0, O_RDWR | O_CREAT, 0400);
1930 err += test_open(0, O_RDWR | O_CREAT, 0200);
1931 err += test_open(0, O_RDWR | O_CREAT, 0000);
1932 err += test_open(0, O_RDWR | O_CREAT | O_EXCL, 0600);
1933 err += test_open(1, O_RDWR | O_CREAT | O_EXCL, 0600);
1934 err += test_open(0, O_RDWR | O_CREAT | O_EXCL, 0000);
1935 err += test_open(1, O_RDWR | O_CREAT | O_EXCL, 0000);
1936 err += test_open_acc(O_RDONLY, 0600, 0);
1937 err += test_open_acc(O_WRONLY, 0600, 0);
1938 err += test_open_acc(O_RDWR, 0600, 0);
1939 err += test_open_acc(O_RDONLY, 0400, 0);
1940 err += test_open_acc(O_WRONLY, 0200, 0);
1941 if(!is_root) {
1942 err += test_open_acc(O_RDONLY | O_TRUNC, 0400, EACCES);
1943 err += test_open_acc(O_WRONLY, 0400, EACCES);
1944 err += test_open_acc(O_RDWR, 0400, EACCES);
1945 err += test_open_acc(O_RDONLY, 0200, EACCES);
1946 err += test_open_acc(O_RDWR, 0200, EACCES);
1947 err += test_open_acc(O_RDONLY, 0000, EACCES);
1948 err += test_open_acc(O_WRONLY, 0000, EACCES);
1949 err += test_open_acc(O_RDWR, 0000, EACCES);
1950 }
1951 err += test_create_ro_dir(O_CREAT);
1952 err += test_create_ro_dir(O_CREAT | O_EXCL);
1953 err += test_create_ro_dir(O_CREAT | O_WRONLY);
1954 err += test_create_ro_dir(O_CREAT | O_TRUNC);
1955 err += test_copy_file_range();
1956
1957 unlink(testfile);
1958 unlink(testfile2);
1959 unlink(testsock);
1960 rmdir(testdir);
1961 rmdir(testdir2);
1962
1963 if (err) {
1964 fprintf(stderr, "%i tests failed\n", -err);
1965 return 1;
1966 }
1967
1968 return 0;
1969 }