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 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
69 static void __start_test(const char *fmt, ...)
70 __attribute__ ((format (printf, 1, 2)));
71
72 static 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;
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;
822 fail:
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
1256 succ:
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
1776 fail:
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
1872 start_test("socket");
1873 if (strlen(testsock) + 1 > sizeof(su.sun_path)) {
1874 fprintf(stderr, "Need to shorten mount point by %zu chars\n",
1875 strlen(testsock) + 1 - sizeof(su.sun_path));
1876 return -1;
1877 }
1878 unlink(testsock);
1879 fd = socket(AF_UNIX, SOCK_STREAM, 0);
1880 if (fd < 0) {
1881 PERROR("socket");
1882 return -1;
1883 }
1884 su.sun_family = AF_UNIX;
1885 strncpy(su.sun_path, testsock, sizeof(su.sun_path) - 1);
1886 su.sun_path[sizeof(su.sun_path) - 1] = '\0';
1887 res = bind(fd, (struct sockaddr*)&su, sizeof(su));
1888 if (res == -1) {
1889 PERROR("bind");
1890 return -1;
1891 }
1892
1893 res = check_type(testsock, S_IFSOCK);
1894 if (res == -1) {
1895 close(fd);
1896 return -1;
1897 }
1898 err += check_nlink(testsock, 1);
1899 close(fd);
1900 res = unlink(testsock);
1901 if (res == -1) {
1902 PERROR("unlink");
1903 return -1;
1904 }
1905 res = check_nonexist(testsock);
1906 if (res == -1)
1907 return -1;
1908 if (err)
1909 return -1;
1910
1911 success();
1912 return 0;
1913 }
1914
1915 #define test_create_ro_dir(flags) \
1916 do_test_create_ro_dir(flags, #flags)
1917
1918 static int do_test_create_ro_dir(int flags, const char *flags_str)
1919 {
1920 int res;
1921 int err = 0;
1922 int fd;
1923
1924 start_test("open(%s) in read-only directory", flags_str);
1925 rmdir(testdir);
1926 res = mkdir(testdir, 0555);
1927 if (res == -1) {
1928 PERROR("mkdir");
1929 return -1;
1930 }
1931 fd = open(subfile, flags, 0644);
1932 if (fd != -1) {
1933 close(fd);
1934 unlink(subfile);
1935 ERROR("open should have failed");
1936 err--;
1937 } else {
1938 res = check_nonexist(subfile);
1939 if (res == -1)
1940 err--;
1941 }
1942 unlink(subfile);
1943 res = rmdir(testdir);
1944 if (res == -1) {
1945 PERROR("rmdir");
1946 return -1;
1947 }
1948 res = check_nonexist(testdir);
1949 if (res == -1)
1950 return -1;
1951 if (err)
1952 return -1;
1953
1954 success();
1955 return 0;
1956 }
1957
1958 int main(int argc, char *argv[])
1959 {
1960 int err = 0;
1961 int a;
1962 int is_root;
1963
1964 umask(0);
1965 if (argc < 2 || argc > 4) {
1966 fprintf(stderr, "usage: %s testdir [:realdir] [[-]test#] [-u]\n", argv[0]);
1967 return 1;
1968 }
1969 basepath = argv[1];
1970 basepath_r = basepath;
1971 for (a = 2; a < argc; a++) {
1972 char *endptr;
1973 char *arg = argv[a];
1974 if (arg[0] == ':') {
1975 basepath_r = arg + 1;
1976 } else {
1977 if (arg[0] == '-') {
1978 arg++;
1979 if (arg[0] == 'u') {
1980 unlinked_test = 1;
1981 endptr = arg + 1;
1982 } else {
1983 skip_test = strtoul(arg, &endptr, 10);
1984 }
1985 } else {
1986 select_test = strtoul(arg, &endptr, 10);
1987 }
1988 if (arg[0] == '\0' || *endptr != '\0') {
1989 fprintf(stderr, "invalid option: '%s'\n", argv[a]);
1990 return 1;
1991 }
1992 }
1993 }
1994 assert(strlen(basepath) < 512);
1995 assert(strlen(basepath_r) < 512);
1996 if (basepath[0] != '/') {
1997 fprintf(stderr, "testdir must be an absolute path\n");
1998 return 1;
1999 }
2000
2001 sprintf(testfile, "%s/testfile", basepath);
2002 sprintf(testfile2, "%s/testfile2", basepath);
2003 sprintf(testdir, "%s/testdir", basepath);
2004 sprintf(testdir2, "%s/testdir2", basepath);
2005 sprintf(subfile, "%s/subfile", testdir2);
2006 sprintf(testsock, "%s/testsock", basepath);
2007
2008 sprintf(testfile_r, "%s/testfile", basepath_r);
2009 sprintf(testfile2_r, "%s/testfile2", basepath_r);
2010 sprintf(testdir_r, "%s/testdir", basepath_r);
2011 sprintf(testdir2_r, "%s/testdir2", basepath_r);
2012 sprintf(subfile_r, "%s/subfile", testdir2_r);
2013
2014 is_root = (geteuid() == 0);
2015
2016 err += test_create();
2017 err += test_create_unlink();
2018 err += test_symlink();
2019 err += test_link();
2020 err += test_link2();
2021 #ifndef __FreeBSD__
2022 err += test_mknod();
2023 err += test_mkfifo();
2024 #endif
2025 err += test_mkdir();
2026 err += test_rename_file();
2027 err += test_rename_dir();
2028 err += test_rename_dir_loop();
2029 err += test_seekdir();
2030 err += test_socket();
2031 err += test_utime();
2032 err += test_truncate(0);
2033 err += test_truncate(testdatalen / 2);
2034 err += test_truncate(testdatalen);
2035 err += test_truncate(testdatalen + 100);
2036 err += test_ftruncate(0, 0600);
2037 err += test_ftruncate(testdatalen / 2, 0600);
2038 err += test_ftruncate(testdatalen, 0600);
2039 err += test_ftruncate(testdatalen + 100, 0600);
2040 err += test_ftruncate(0, 0400);
2041 err += test_ftruncate(0, 0200);
2042 err += test_ftruncate(0, 0000);
2043 err += test_open(0, O_RDONLY, 0);
2044 err += test_open(1, O_RDONLY, 0);
2045 err += test_open(1, O_RDWR, 0);
2046 err += test_open(1, O_WRONLY, 0);
2047 err += test_open(0, O_RDWR | O_CREAT, 0600);
2048 err += test_open(1, O_RDWR | O_CREAT, 0600);
2049 err += test_open(0, O_RDWR | O_CREAT | O_TRUNC, 0600);
2050 err += test_open(1, O_RDWR | O_CREAT | O_TRUNC, 0600);
2051 err += test_open(0, O_RDONLY | O_CREAT, 0600);
2052 err += test_open(0, O_RDONLY | O_CREAT, 0400);
2053 err += test_open(0, O_RDONLY | O_CREAT, 0200);
2054 err += test_open(0, O_RDONLY | O_CREAT, 0000);
2055 err += test_open(0, O_WRONLY | O_CREAT, 0600);
2056 err += test_open(0, O_WRONLY | O_CREAT, 0400);
2057 err += test_open(0, O_WRONLY | O_CREAT, 0200);
2058 err += test_open(0, O_WRONLY | O_CREAT, 0000);
2059 err += test_open(0, O_RDWR | O_CREAT, 0400);
2060 err += test_open(0, O_RDWR | O_CREAT, 0200);
2061 err += test_open(0, O_RDWR | O_CREAT, 0000);
2062 err += test_open(0, O_RDWR | O_CREAT | O_EXCL, 0600);
2063 err += test_open(1, O_RDWR | O_CREAT | O_EXCL, 0600);
2064 err += test_open(0, O_RDWR | O_CREAT | O_EXCL, 0000);
2065 err += test_open(1, O_RDWR | O_CREAT | O_EXCL, 0000);
2066 err += test_open_acc(O_RDONLY, 0600, 0);
2067 err += test_open_acc(O_WRONLY, 0600, 0);
2068 err += test_open_acc(O_RDWR, 0600, 0);
2069 err += test_open_acc(O_RDONLY, 0400, 0);
2070 err += test_open_acc(O_WRONLY, 0200, 0);
2071 if(!is_root) {
2072 err += test_open_acc(O_RDONLY | O_TRUNC, 0400, EACCES);
2073 err += test_open_acc(O_WRONLY, 0400, EACCES);
2074 err += test_open_acc(O_RDWR, 0400, EACCES);
2075 err += test_open_acc(O_RDONLY, 0200, EACCES);
2076 err += test_open_acc(O_RDWR, 0200, EACCES);
2077 err += test_open_acc(O_RDONLY, 0000, EACCES);
2078 err += test_open_acc(O_WRONLY, 0000, EACCES);
2079 err += test_open_acc(O_RDWR, 0000, EACCES);
2080 }
2081 err += test_create_ro_dir(O_CREAT);
2082 err += test_create_ro_dir(O_CREAT | O_EXCL);
2083 err += test_create_ro_dir(O_CREAT | O_WRONLY);
2084 err += test_create_ro_dir(O_CREAT | O_TRUNC);
2085 err += test_copy_file_range();
2086
2087 unlink(testfile2);
2088 unlink(testsock);
2089 rmdir(testdir);
2090 rmdir(testdir2);
2091
2092 if (err) {
2093 fprintf(stderr, "%i tests failed\n", -err);
2094 return 1;
2095 }
2096
2097 return check_unlinked_testfiles();
2098 }