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