libfuse: fuse-3.3.2/test/test_syscalls.c Source File

libfuse

test_syscalls.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <stdarg.h>
4 #include <string.h>
5 #include <unistd.h>
6 #include <fcntl.h>
7 #include <dirent.h>
8 #include <utime.h>
9 #include <errno.h>
10 #include <assert.h>
11 #include <sys/types.h>
12 #include <sys/stat.h>
13
14
15 static char testfile[1024];
16 static char testfile2[1024];
17 static char testdir[1024];
18 static char testdir2[1024];
19 static char subfile[1024];
20
21 static char testfile_r[1024];
22 static char testfile2_r[1024];
23 static char testdir_r[1024];
24 static char testdir2_r[1024];
25 static char subfile_r[1024];
26
27 static char testname[256];
28 static char testdata[] = "abcdefghijklmnopqrstuvwxyz";
29 static char testdata2[] = "1234567890-=qwertyuiop[]\asdfghjkl;'zxcvbnm,./";
30 static const char *testdir_files[] = { "f1", "f2", NULL};
31 static char zerodata[4096];
32 static int testdatalen = sizeof(testdata) - 1;
33 static int testdata2len = sizeof(testdata2) - 1;
34 static unsigned int testnum = 1;
35 static unsigned int select_test = 0;
36 static unsigned int skip_test = 0;
37
38 #define MAX_ENTRIES 1024
39
40 static void test_perror(const char *func, const char *msg)
41 {
42 fprintf(stderr, "%s %s() - %s: %s\n", testname, func, msg,
43 strerror(errno));
44 }
45
46 static void test_error(const char *func, const char *msg, ...)
47 __attribute__ ((format (printf, 2, 3)));
48
49 static void __start_test(const char *fmt, ...)
50 __attribute__ ((format (printf, 1, 2)));
51
52 static void test_error(const char *func, const char *msg, ...)
53 {
54 va_list ap;
55 fprintf(stderr, "%s %s() - ", testname, func);
56 va_start(ap, msg);
57 vfprintf(stderr, msg, ap);
58 va_end(ap);
59 fprintf(stderr, "\n");
60 }
61
62 static void success(void)
63 {
64 fprintf(stderr, "%s OK\n", testname);
65 }
66
67 static void __start_test(const char *fmt, ...)
68 {
69 unsigned int n;
70 va_list ap;
71 n = sprintf(testname, "%3i [", testnum++);
72 va_start(ap, fmt);
73 n += vsprintf(testname + n, fmt, ap);
74 va_end(ap);
75 sprintf(testname + n, "]");
76 }
77
78 #define start_test(msg, args...) { \
79 if ((select_test && testnum != select_test) || \
80 (testnum == skip_test)) { \
81 testnum++; \
82 return 0; \
83 } \
84 __start_test(msg, ##args); \
85 }
86
87 #define PERROR(msg) test_perror(__FUNCTION__, msg)
88 #define ERROR(msg, args...) test_error(__FUNCTION__, msg, ##args)
89
90 static int check_size(const char *path, int len)
91 {
92 struct stat stbuf;
93 int res = stat(path, &stbuf);
94 if (res == -1) {
95 PERROR("stat");
96 return -1;
97 }
98 if (stbuf.st_size != len) {
99 ERROR("length %u instead of %u", (int) stbuf.st_size,
100 (int) len);
101 return -1;
102 }
103 return 0;
104 }
105
106 static int fcheck_size(int fd, int len)
107 {
108 struct stat stbuf;
109 int res = fstat(fd, &stbuf);
110 if (res == -1) {
111 PERROR("fstat");
112 return -1;
113 }
114 if (stbuf.st_size != len) {
115 ERROR("length %u instead of %u", (int) stbuf.st_size,
116 (int) len);
117 return -1;
118 }
119 return 0;
120 }
121
122 static int check_type(const char *path, mode_t type)
123 {
124 struct stat stbuf;
125 int res = lstat(path, &stbuf);
126 if (res == -1) {
127 PERROR("lstat");
128 return -1;
129 }
130 if ((stbuf.st_mode & S_IFMT) != type) {
131 ERROR("type 0%o instead of 0%o", stbuf.st_mode & S_IFMT, type);
132 return -1;
133 }
134 return 0;
135 }
136
137 static int fcheck_type(int fd, mode_t type)
138 {
139 struct stat stbuf;
140 int res = fstat(fd, &stbuf);
141 if (res == -1) {
142 PERROR("fstat");
143 return -1;
144 }
145 if ((stbuf.st_mode & S_IFMT) != type) {
146 ERROR("type 0%o instead of 0%o", stbuf.st_mode & S_IFMT, type);
147 return -1;
148 }
149 return 0;
150 }
151
152 static int check_mode(const char *path, mode_t mode)
153 {
154 struct stat stbuf;
155 int res = lstat(path, &stbuf);
156 if (res == -1) {
157 PERROR("lstat");
158 return -1;
159 }
160 if ((stbuf.st_mode & 07777) != mode) {
161 ERROR("mode 0%o instead of 0%o", stbuf.st_mode & 07777, mode);
162 return -1;
163 }
164 return 0;
165 }
166
167 static int fcheck_mode(int fd, mode_t mode)
168 {
169 struct stat stbuf;
170 int res = fstat(fd, &stbuf);
171 if (res == -1) {
172 PERROR("fstat");
173 return -1;
174 }
175 if ((stbuf.st_mode & 07777) != mode) {
176 ERROR("mode 0%o instead of 0%o", stbuf.st_mode & 07777, mode);
177 return -1;
178 }
179 return 0;
180 }
181
182 static int check_times(const char *path, time_t atime, time_t mtime)
183 {
184 int err = 0;
185 struct stat stbuf;
186 int res = lstat(path, &stbuf);
187 if (res == -1) {
188 PERROR("lstat");
189 return -1;
190 }
191 if (stbuf.st_atime != atime) {
192 ERROR("atime %li instead of %li", stbuf.st_atime, atime);
193 err--;
194 }
195 if (stbuf.st_mtime != mtime) {
196 ERROR("mtime %li instead of %li", stbuf.st_mtime, mtime);
197 err--;
198 }
199 if (err)
200 return -1;
201
202 return 0;
203 }
204
205 #if 0
206 static int fcheck_times(int fd, time_t atime, time_t mtime)
207 {
208 int err = 0;
209 struct stat stbuf;
210 int res = fstat(fd, &stbuf);
211 if (res == -1) {
212 PERROR("fstat");
213 return -1;
214 }
215 if (stbuf.st_atime != atime) {
216 ERROR("atime %li instead of %li", stbuf.st_atime, atime);
217 err--;
218 }
219 if (stbuf.st_mtime != mtime) {
220 ERROR("mtime %li instead of %li", stbuf.st_mtime, mtime);
221 err--;
222 }
223 if (err)
224 return -1;
225
226 return 0;
227 }
228 #endif
229
230 static int check_nlink(const char *path, nlink_t nlink)
231 {
232 struct stat stbuf;
233 int res = lstat(path, &stbuf);
234 if (res == -1) {
235 PERROR("lstat");
236 return -1;
237 }
238 if (stbuf.st_nlink != nlink) {
239 ERROR("nlink %li instead of %li", (long) stbuf.st_nlink,
240 (long) nlink);
241 return -1;
242 }
243 return 0;
244 }
245
246 static int fcheck_nlink(int fd, nlink_t nlink)
247 {
248 struct stat stbuf;
249 int res = fstat(fd, &stbuf);
250 if (res == -1) {
251 PERROR("fstat");
252 return -1;
253 }
254 if (stbuf.st_nlink != nlink) {
255 ERROR("nlink %li instead of %li", (long) stbuf.st_nlink,
256 (long) nlink);
257 return -1;
258 }
259 return 0;
260 }
261
262 static int check_nonexist(const char *path)
263 {
264 struct stat stbuf;
265 int res = lstat(path, &stbuf);
266 if (res == 0) {
267 ERROR("file should not exist");
268 return -1;
269 }
270 if (errno != ENOENT) {
271 ERROR("file should not exist: %s", strerror(errno));
272 return -1;
273 }
274 return 0;
275 }
276
277 static int check_buffer(const char *buf, const char *data, unsigned len)
278 {
279 if (memcmp(buf, data, len) != 0) {
280 ERROR("data mismatch");
281 return -1;
282 }
283 return 0;
284 }
285
286 static int check_data(const char *path, const char *data, int offset,
287 unsigned len)
288 {
289 char buf[4096];
290 int res;
291 int fd = open(path, O_RDONLY);
292 if (fd == -1) {
293 PERROR("open");
294 return -1;
295 }
296 if (lseek(fd, offset, SEEK_SET) == (off_t) -1) {
297 PERROR("lseek");
298 close(fd);
299 return -1;
300 }
301 while (len) {
302 int rdlen = len < sizeof(buf) ? len : sizeof(buf);
303 res = read(fd, buf, rdlen);
304 if (res == -1) {
305 PERROR("read");
306 close(fd);
307 return -1;
308 }
309 if (res != rdlen) {
310 ERROR("short read: %u instead of %u", res, rdlen);
311 close(fd);
312 return -1;
313 }
314 if (check_buffer(buf, data, rdlen) != 0) {
315 close(fd);
316 return -1;
317 }
318 data += rdlen;
319 len -= rdlen;
320 }
321 res = close(fd);
322 if (res == -1) {
323 PERROR("close");
324 return -1;
325 }
326 return 0;
327 }
328
329 static int fcheck_data(int fd, const char *data, int offset,
330 unsigned len)
331 {
332 char buf[4096];
333 int res;
334 if (lseek(fd, offset, SEEK_SET) == (off_t) -1) {
335 PERROR("lseek");
336 return -1;
337 }
338 while (len) {
339 int rdlen = len < sizeof(buf) ? len : sizeof(buf);
340 res = read(fd, buf, rdlen);
341 if (res == -1) {
342 PERROR("read");
343 return -1;
344 }
345 if (res != rdlen) {
346 ERROR("short read: %u instead of %u", res, rdlen);
347 return -1;
348 }
349 if (check_buffer(buf, data, rdlen) != 0) {
350 return -1;
351 }
352 data += rdlen;
353 len -= rdlen;
354 }
355 return 0;
356 }
357
358 static int check_dir_contents(const char *path, const char **contents)
359 {
360 int i;
361 int res;
362 int err = 0;
363 int found[MAX_ENTRIES];
364 const char *cont[MAX_ENTRIES];
365 DIR *dp;
366
367 for (i = 0; contents[i]; i++) {
368 assert(i < MAX_ENTRIES - 3);
369 found[i] = 0;
370 cont[i] = contents[i];
371 }
372 found[i] = 0;
373 cont[i++] = ".";
374 found[i] = 0;
375 cont[i++] = "..";
376 cont[i] = NULL;
377
378 dp = opendir(path);
379 if (dp == NULL) {
380 PERROR("opendir");
381 return -1;
382 }
383 memset(found, 0, sizeof(found));
384 while(1) {
385 struct dirent *de;
386 errno = 0;
387 de = readdir(dp);
388 if (de == NULL) {
389 if (errno) {
390 PERROR("readdir");
391 closedir(dp);
392 return -1;
393 }
394 break;
395 }
396 for (i = 0; cont[i] != NULL; i++) {
397 assert(i < MAX_ENTRIES);
398 if (strcmp(cont[i], de->d_name) == 0) {
399 if (found[i]) {
400 ERROR("duplicate entry <%s>",
401 de->d_name);
402 err--;
403 } else
404 found[i] = 1;
405 break;
406 }
407 }
408 if (!cont[i]) {
409 ERROR("unexpected entry <%s>", de->d_name);
410 err --;
411 }
412 }
413 for (i = 0; cont[i] != NULL; i++) {
414 if (!found[i]) {
415 ERROR("missing entry <%s>", cont[i]);
416 err--;
417 }
418 }
419 res = closedir(dp);
420 if (res == -1) {
421 PERROR("closedir");
422 return -1;
423 }
424 if (err)
425 return -1;
426
427 return 0;
428 }
429
430 static int create_file(const char *path, const char *data, int len)
431 {
432 int res;
433 int fd;
434
435 unlink(path);
436 fd = creat(path, 0644);
437 if (fd == -1) {
438 PERROR("creat");
439 return -1;
440 }
441 if (len) {
442 res = write(fd, data, len);
443 if (res == -1) {
444 PERROR("write");
445 close(fd);
446 return -1;
447 }
448 if (res != len) {
449 ERROR("write is short: %u instead of %u", res, len);
450 close(fd);
451 return -1;
452 }
453 }
454 res = close(fd);
455 if (res == -1) {
456 PERROR("close");
457 return -1;
458 }
459 res = check_type(path, S_IFREG);
460 if (res == -1)
461 return -1;
462 res = check_mode(path, 0644);
463 if (res == -1)
464 return -1;
465 res = check_nlink(path, 1);
466 if (res == -1)
467 return -1;
468 res = check_size(path, len);
469 if (res == -1)
470 return -1;
471
472 if (len) {
473 res = check_data(path, data, 0, len);
474 if (res == -1)
475 return -1;
476 }
477
478 return 0;
479 }
480
481 static int cleanup_dir(const char *path, const char **dir_files, int quiet)
482 {
483 int i;
484 int err = 0;
485
486 for (i = 0; dir_files[i]; i++) {
487 int res;
488 char fpath[1024];
489 sprintf(fpath, "%s/%s", path, dir_files[i]);
490 res = unlink(fpath);
491 if (res == -1 && !quiet) {
492 PERROR("unlink");
493 err --;
494 }
495 }
496 if (err)
497 return -1;
498
499 return 0;
500 }
501
502 static int create_dir(const char *path, const char **dir_files)
503 {
504 int res;
505 int i;
506
507 rmdir(path);
508 res = mkdir(path, 0755);
509 if (res == -1) {
510 PERROR("mkdir");
511 return -1;
512 }
513 res = check_type(path, S_IFDIR);
514 if (res == -1)
515 return -1;
516 res = check_mode(path, 0755);
517 if (res == -1)
518 return -1;
519
520 for (i = 0; dir_files[i]; i++) {
521 char fpath[1024];
522 sprintf(fpath, "%s/%s", path, dir_files[i]);
523 res = create_file(fpath, "", 0);
524 if (res == -1) {
525 cleanup_dir(path, dir_files, 1);
526 return -1;
527 }
528 }
529 res = check_dir_contents(path, dir_files);
530 if (res == -1) {
531 cleanup_dir(path, dir_files, 1);
532 return -1;
533 }
534
535 return 0;
536 }
537
538 static int test_truncate(int len)
539 {
540 const char *data = testdata;
541 int datalen = testdatalen;
542 int res;
543
544 start_test("truncate(%u)", (int) len);
545 res = create_file(testfile, data, datalen);
546 if (res == -1)
547 return -1;
548
549 res = truncate(testfile, len);
550 if (res == -1) {
551 PERROR("truncate");
552 return -1;
553 }
554 res = check_size(testfile, len);
555 if (res == -1)
556 return -1;
557
558 if (len > 0) {
559 if (len <= datalen) {
560 res = check_data(testfile, data, 0, len);
561 if (res == -1)
562 return -1;
563 } else {
564 res = check_data(testfile, data, 0, datalen);
565 if (res == -1)
566 return -1;
567 res = check_data(testfile, zerodata, datalen,
568 len - datalen);
569 if (res == -1)
570 return -1;
571 }
572 }
573 res = unlink(testfile);
574 if (res == -1) {
575 PERROR("unlink");
576 return -1;
577 }
578 res = check_nonexist(testfile);
579 if (res == -1)
580 return -1;
581
582 success();
583 return 0;
584 }
585
586 static int test_ftruncate(int len, int mode)
587 {
588 const char *data = testdata;
589 int datalen = testdatalen;
590 int res;
591 int fd;
592
593 start_test("ftruncate(%u) mode: 0%03o", len, mode);
594 res = create_file(testfile, data, datalen);
595 if (res == -1)
596 return -1;
597
598 fd = open(testfile, O_WRONLY);
599 if (fd == -1) {
600 PERROR("open");
601 return -1;
602 }
603
604 res = fchmod(fd, mode);
605 if (res == -1) {
606 PERROR("fchmod");
607 close(fd);
608 return -1;
609 }
610 res = check_mode(testfile, mode);
611 if (res == -1) {
612 close(fd);
613 return -1;
614 }
615 res = ftruncate(fd, len);
616 if (res == -1) {
617 PERROR("ftruncate");
618 close(fd);
619 return -1;
620 }
621 close(fd);
622 res = check_size(testfile, len);
623 if (res == -1)
624 return -1;
625
626 if (len > 0) {
627 if (len <= datalen) {
628 res = check_data(testfile, data, 0, len);
629 if (res == -1)
630 return -1;
631 } else {
632 res = check_data(testfile, data, 0, datalen);
633 if (res == -1)
634 return -1;
635 res = check_data(testfile, zerodata, datalen,
636 len - datalen);
637 if (res == -1)
638 return -1;
639 }
640 }
641 res = unlink(testfile);
642 if (res == -1) {
643 PERROR("unlink");
644 return -1;
645 }
646 res = check_nonexist(testfile);
647 if (res == -1)
648 return -1;
649
650 success();
651 return 0;
652 }
653
654 static int test_utime(void)
655 {
656 struct utimbuf utm;
657 time_t atime = 987631200;
658 time_t mtime = 123116400;
659 int res;
660
661 start_test("utime");
662 res = create_file(testfile, NULL, 0);
663 if (res == -1)
664 return -1;
665
666 utm.actime = atime;
667 utm.modtime = mtime;
668 res = utime(testfile, &utm);
669 if (res == -1) {
670 PERROR("utime");
671 return -1;
672 }
673 res = check_times(testfile, atime, mtime);
674 if (res == -1) {
675 return -1;
676 }
677 res = unlink(testfile);
678 if (res == -1) {
679 PERROR("unlink");
680 return -1;
681 }
682 res = check_nonexist(testfile);
683 if (res == -1)
684 return -1;
685
686 success();
687 return 0;
688 }
689
690 static int test_create(void)
691 {
692 const char *data = testdata;
693 int datalen = testdatalen;
694 int err = 0;
695 int res;
696 int fd;
697
698 start_test("create");
699 unlink(testfile);
700 fd = creat(testfile, 0644);
701 if (fd == -1) {
702 PERROR("creat");
703 return -1;
704 }
705 res = write(fd, data, datalen);
706 if (res == -1) {
707 PERROR("write");
708 close(fd);
709 return -1;
710 }
711 if (res != datalen) {
712 ERROR("write is short: %u instead of %u", res, datalen);
713 close(fd);
714 return -1;
715 }
716 res = close(fd);
717 if (res == -1) {
718 PERROR("close");
719 return -1;
720 }
721 res = check_type(testfile, S_IFREG);
722 if (res == -1)
723 return -1;
724 err += check_mode(testfile, 0644);
725 err += check_nlink(testfile, 1);
726 err += check_size(testfile, datalen);
727 err += check_data(testfile, data, 0, datalen);
728 res = unlink(testfile);
729 if (res == -1) {
730 PERROR("unlink");
731 return -1;
732 }
733 res = check_nonexist(testfile);
734 if (res == -1)
735 return -1;
736 if (err)
737 return -1;
738
739 success();
740 return 0;
741 }
742
743 static int test_create_unlink(void)
744 {
745 const char *data = testdata;
746 int datalen = testdatalen;
747 int err = 0;
748 int res;
749 int fd;
750
751 start_test("create+unlink");
752 unlink(testfile);
753 fd = open(testfile, O_CREAT | O_RDWR | O_TRUNC, 0644);
754 if (fd == -1) {
755 PERROR("creat");
756 return -1;
757 }
758 res = unlink(testfile);
759 if (res == -1) {
760 PERROR("unlink");
761 close(fd);
762 return -1;
763 }
764 res = check_nonexist(testfile);
765 if (res == -1)
766 return -1;
767 res = write(fd, data, datalen);
768 if (res == -1) {
769 PERROR("write");
770 close(fd);
771 return -1;
772 }
773 if (res != datalen) {
774 ERROR("write is short: %u instead of %u", res, datalen);
775 close(fd);
776 return -1;
777 }
778 err += fcheck_type(fd, S_IFREG);
779 err += fcheck_mode(fd, 0644);
780 err += fcheck_nlink(fd, 0);
781 err += fcheck_size(fd, datalen);
782 err += fcheck_data(fd, data, 0, datalen);
783 res = close(fd);
784 if (res == -1) {
785 PERROR("close");
786 err--;
787 }
788 if (err)
789 return -1;
790
791 success();
792 return 0;
793 }
794
795 #ifndef __FreeBSD__
796 static int test_mknod(void)
797 {
798 int err = 0;
799 int res;
800
801 start_test("mknod");
802 unlink(testfile);
803 res = mknod(testfile, 0644, 0);
804 if (res == -1) {
805 PERROR("mknod");
806 return -1;
807 }
808 res = check_type(testfile, S_IFREG);
809 if (res == -1)
810 return -1;
811 err += check_mode(testfile, 0644);
812 err += check_nlink(testfile, 1);
813 err += check_size(testfile, 0);
814 res = unlink(testfile);
815 if (res == -1) {
816 PERROR("unlink");
817 return -1;
818 }
819 res = check_nonexist(testfile);
820 if (res == -1)
821 return -1;
822 if (err)
823 return -1;
824
825 success();
826 return 0;
827 }
828 #endif
829
830 #define test_open(exist, flags, mode) do_test_open(exist, flags, #flags, mode)
831
832 static int do_test_open(int exist, int flags, const char *flags_str, int mode)
833 {
834 char buf[4096];
835 const char *data = testdata;
836 int datalen = testdatalen;
837 unsigned currlen = 0;
838 int err = 0;
839 int res;
840 int fd;
841 off_t off;
842
843 start_test("open(%s, %s, 0%03o)", exist ? "+" : "-", flags_str, mode);
844 unlink(testfile);
845 if (exist) {
846 res = create_file(testfile_r, testdata2, testdata2len);
847 if (res == -1)
848 return -1;
849
850 currlen = testdata2len;
851 }
852
853 fd = open(testfile, flags, mode);
854 if ((flags & O_CREAT) && (flags & O_EXCL) && exist) {
855 if (fd != -1) {
856 ERROR("open should have failed");
857 close(fd);
858 return -1;
859 } else if (errno == EEXIST)
860 goto succ;
861 }
862 if (!(flags & O_CREAT) && !exist) {
863 if (fd != -1) {
864 ERROR("open should have failed");
865 close(fd);
866 return -1;
867 } else if (errno == ENOENT)
868 goto succ;
869 }
870 if (fd == -1) {
871 PERROR("open");
872 return -1;
873 }
874
875 if (flags & O_TRUNC)
876 currlen = 0;
877
878 err += check_type(testfile, S_IFREG);
879 if (exist)
880 err += check_mode(testfile, 0644);
881 else
882 err += check_mode(testfile, mode);
883 err += check_nlink(testfile, 1);
884 err += check_size(testfile, currlen);
885 if (exist && !(flags & O_TRUNC) && (mode & 0400))
886 err += check_data(testfile, testdata2, 0, testdata2len);
887
888 res = write(fd, data, datalen);
889 if ((flags & O_ACCMODE) != O_RDONLY) {
890 if (res == -1) {
891 PERROR("write");
892 err --;
893 } else if (res != datalen) {
894 ERROR("write is short: %u instead of %u", res, datalen);
895 err --;
896 } else {
897 if (datalen > (int) currlen)
898 currlen = datalen;
899
900 err += check_size(testfile, currlen);
901
902 if (mode & 0400) {
903 err += check_data(testfile, data, 0, datalen);
904 if (exist && !(flags & O_TRUNC) &&
905 testdata2len > datalen)
906 err += check_data(testfile,
907 testdata2 + datalen,
908 datalen,
909 testdata2len - datalen);
910 }
911 }
912 } else {
913 if (res != -1) {
914 ERROR("write should have failed");
915 err --;
916 } else if (errno != EBADF) {
917 PERROR("write");
918 err --;
919 }
920 }
921 off = lseek(fd, SEEK_SET, 0);
922 if (off == (off_t) -1) {
923 PERROR("lseek");
924 err--;
925 } else if (off != 0) {
926 ERROR("offset should have returned 0");
927 err --;
928 }
929 res = read(fd, buf, sizeof(buf));
930 if ((flags & O_ACCMODE) != O_WRONLY) {
931 if (res == -1) {
932 PERROR("read");
933 err--;
934 } else {
935 int readsize =
936 currlen < sizeof(buf) ? currlen : sizeof(buf);
937 if (res != readsize) {
938 ERROR("read is short: %i instead of %u",
939 res, readsize);
940 err--;
941 } else {
942 if ((flags & O_ACCMODE) != O_RDONLY) {
943 err += check_buffer(buf, data, datalen);
944 if (exist && !(flags & O_TRUNC) &&
945 testdata2len > datalen)
946 err += check_buffer(buf + datalen,
947 testdata2 + datalen,
948 testdata2len - datalen);
949 } else if (exist)
950 err += check_buffer(buf, testdata2,
951 testdata2len);
952 }
953 }
954 } else {
955 if (res != -1) {
956 ERROR("read should have failed");
957 err --;
958 } else if (errno != EBADF) {
959 PERROR("read");
960 err --;
961 }
962 }
963
964 res = close(fd);
965 if (res == -1) {
966 PERROR("close");
967 return -1;
968 }
969 res = unlink(testfile);
970 if (res == -1) {
971 PERROR("unlink");
972 return -1;
973 }
974 res = check_nonexist(testfile);
975 if (res == -1)
976 return -1;
977 res = check_nonexist(testfile_r);
978 if (res == -1)
979 return -1;
980 if (err)
981 return -1;
982
983 succ:
984 success();
985 return 0;
986 }
987
988 #define test_open_acc(flags, mode, err) \
989 do_test_open_acc(flags, #flags, mode, err)
990
991 static int do_test_open_acc(int flags, const char *flags_str, int mode, int err)
992 {
993 const char *data = testdata;
994 int datalen = testdatalen;
995 int res;
996 int fd;
997
998 start_test("open_acc(%s) mode: 0%03o message: '%s'", flags_str, mode,
999 strerror(err));
1000 unlink(testfile);
1001 res = create_file(testfile, data, datalen);
1002 if (res == -1)
1003 return -1;
1004
1005 res = chmod(testfile, mode);
1006 if (res == -1) {
1007 PERROR("chmod");
1008 return -1;
1009 }
1010
1011 res = check_mode(testfile, mode);
1012 if (res == -1)
1013 return -1;
1014
1015 fd = open(testfile, flags);
1016 if (fd == -1) {
1017 if (err != errno) {
1018 PERROR("open");
1019 return -1;
1020 }
1021 } else {
1022 if (err) {
1023 ERROR("open should have failed");
1024 close(fd);
1025 return -1;
1026 }
1027 close(fd);
1028 }
1029 success();
1030 return 0;
1031 }
1032
1033 static int test_symlink(void)
1034 {
1035 char buf[1024];
1036 const char *data = testdata;
1037 int datalen = testdatalen;
1038 int linklen = strlen(testfile);
1039 int err = 0;
1040 int res;
1041
1042 start_test("symlink");
1043 res = create_file(testfile, data, datalen);
1044 if (res == -1)
1045 return -1;
1046
1047 unlink(testfile2);
1048 res = symlink(testfile, testfile2);
1049 if (res == -1) {
1050 PERROR("symlink");
1051 return -1;
1052 }
1053 res = check_type(testfile2, S_IFLNK);
1054 if (res == -1)
1055 return -1;
1056 err += check_mode(testfile2, 0777);
1057 err += check_nlink(testfile2, 1);
1058 res = readlink(testfile2, buf, sizeof(buf));
1059 if (res == -1) {
1060 PERROR("readlink");
1061 err--;
1062 }
1063 if (res != linklen) {
1064 ERROR("short readlink: %u instead of %u", res, linklen);
1065 err--;
1066 }
1067 if (memcmp(buf, testfile, linklen) != 0) {
1068 ERROR("link mismatch");
1069 err--;
1070 }
1071 err += check_size(testfile2, datalen);
1072 err += check_data(testfile2, data, 0, datalen);
1073 res = unlink(testfile2);
1074 if (res == -1) {
1075 PERROR("unlink");
1076 return -1;
1077 }
1078 res = check_nonexist(testfile2);
1079 if (res == -1)
1080 return -1;
1081 if (err)
1082 return -1;
1083
1084 success();
1085 return 0;
1086 }
1087
1088 static int test_link(void)
1089 {
1090 const char *data = testdata;
1091 int datalen = testdatalen;
1092 int err = 0;
1093 int res;
1094
1095 start_test("link");
1096 res = create_file(testfile, data, datalen);
1097 if (res == -1)
1098 return -1;
1099
1100 unlink(testfile2);
1101 res = link(testfile, testfile2);
1102 if (res == -1) {
1103 PERROR("link");
1104 return -1;
1105 }
1106 res = check_type(testfile2, S_IFREG);
1107 if (res == -1)
1108 return -1;
1109 err += check_mode(testfile2, 0644);
1110 err += check_nlink(testfile2, 2);
1111 err += check_size(testfile2, datalen);
1112 err += check_data(testfile2, data, 0, datalen);
1113 res = unlink(testfile);
1114 if (res == -1) {
1115 PERROR("unlink");
1116 return -1;
1117 }
1118 res = check_nonexist(testfile);
1119 if (res == -1)
1120 return -1;
1121
1122 err += check_nlink(testfile2, 1);
1123 res = unlink(testfile2);
1124 if (res == -1) {
1125 PERROR("unlink");
1126 return -1;
1127 }
1128 res = check_nonexist(testfile2);
1129 if (res == -1)
1130 return -1;
1131 if (err)
1132 return -1;
1133
1134 success();
1135 return 0;
1136 }
1137
1138 static int test_link2(void)
1139 {
1140 const char *data = testdata;
1141 int datalen = testdatalen;
1142 int err = 0;
1143 int res;
1144
1145 start_test("link-unlink-link");
1146 res = create_file(testfile, data, datalen);
1147 if (res == -1)
1148 return -1;
1149
1150 unlink(testfile2);
1151 res = link(testfile, testfile2);
1152 if (res == -1) {
1153 PERROR("link");
1154 return -1;
1155 }
1156 res = unlink(testfile);
1157 if (res == -1) {
1158 PERROR("unlink");
1159 return -1;
1160 }
1161 res = check_nonexist(testfile);
1162 if (res == -1)
1163 return -1;
1164 res = link(testfile2, testfile);
1165 if (res == -1) {
1166 PERROR("link");
1167 }
1168 res = check_type(testfile, S_IFREG);
1169 if (res == -1)
1170 return -1;
1171 err += check_mode(testfile, 0644);
1172 err += check_nlink(testfile, 2);
1173 err += check_size(testfile, datalen);
1174 err += check_data(testfile, data, 0, datalen);
1175
1176 res = unlink(testfile2);
1177 if (res == -1) {
1178 PERROR("unlink");
1179 return -1;
1180 }
1181 err += check_nlink(testfile, 1);
1182 res = unlink(testfile);
1183 if (res == -1) {
1184 PERROR("unlink");
1185 return -1;
1186 }
1187 res = check_nonexist(testfile);
1188 if (res == -1)
1189 return -1;
1190 if (err)
1191 return -1;
1192
1193 success();
1194 return 0;
1195 }
1196
1197 static int test_rename_file(void)
1198 {
1199 const char *data = testdata;
1200 int datalen = testdatalen;
1201 int err = 0;
1202 int res;
1203
1204 start_test("rename file");
1205 res = create_file(testfile, data, datalen);
1206 if (res == -1)
1207 return -1;
1208
1209 unlink(testfile2);
1210 res = rename(testfile, testfile2);
1211 if (res == -1) {
1212 PERROR("rename");
1213 return -1;
1214 }
1215 res = check_nonexist(testfile);
1216 if (res == -1)
1217 return -1;
1218 res = check_type(testfile2, S_IFREG);
1219 if (res == -1)
1220 return -1;
1221 err += check_mode(testfile2, 0644);
1222 err += check_nlink(testfile2, 1);
1223 err += check_size(testfile2, datalen);
1224 err += check_data(testfile2, data, 0, datalen);
1225 res = unlink(testfile2);
1226 if (res == -1) {
1227 PERROR("unlink");
1228 return -1;
1229 }
1230 res = check_nonexist(testfile2);
1231 if (res == -1)
1232 return -1;
1233 if (err)
1234 return -1;
1235
1236 success();
1237 return 0;
1238 }
1239
1240 static int test_rename_dir(void)
1241 {
1242 int err = 0;
1243 int res;
1244
1245 start_test("rename dir");
1246 res = create_dir(testdir, testdir_files);
1247 if (res == -1)
1248 return -1;
1249
1250 rmdir(testdir2);
1251 res = rename(testdir, testdir2);
1252 if (res == -1) {
1253 PERROR("rename");
1254 cleanup_dir(testdir, testdir_files, 1);
1255 return -1;
1256 }
1257 res = check_nonexist(testdir);
1258 if (res == -1) {
1259 cleanup_dir(testdir, testdir_files, 1);
1260 return -1;
1261 }
1262 res = check_type(testdir2, S_IFDIR);
1263 if (res == -1) {
1264 cleanup_dir(testdir2, testdir_files, 1);
1265 return -1;
1266 }
1267 err += check_mode(testdir2, 0755);
1268 err += check_dir_contents(testdir2, testdir_files);
1269 err += cleanup_dir(testdir2, testdir_files, 0);
1270 res = rmdir(testdir2);
1271 if (res == -1) {
1272 PERROR("rmdir");
1273 return -1;
1274 }
1275 res = check_nonexist(testdir2);
1276 if (res == -1)
1277 return -1;
1278 if (err)
1279 return -1;
1280
1281 success();
1282 return 0;
1283 }
1284
1285 #ifndef __FreeBSD__
1286 static int test_mkfifo(void)
1287 {
1288 int res;
1289 int err = 0;
1290
1291 start_test("mkfifo");
1292 unlink(testfile);
1293 res = mkfifo(testfile, 0644);
1294 if (res == -1) {
1295 PERROR("mkfifo");
1296 return -1;
1297 }
1298 res = check_type(testfile, S_IFIFO);
1299 if (res == -1)
1300 return -1;
1301 err += check_mode(testfile, 0644);
1302 err += check_nlink(testfile, 1);
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 if (err)
1312 return -1;
1313
1314 success();
1315 return 0;
1316 }
1317 #endif
1318
1319 static int test_mkdir(void)
1320 {
1321 int res;
1322 int err = 0;
1323 const char *dir_contents[] = {NULL};
1324
1325 start_test("mkdir");
1326 rmdir(testdir);
1327 res = mkdir(testdir, 0755);
1328 if (res == -1) {
1329 PERROR("mkdir");
1330 return -1;
1331 }
1332 res = check_type(testdir, S_IFDIR);
1333 if (res == -1)
1334 return -1;
1335 err += check_mode(testdir, 0755);
1336 /* Some file systems (like btrfs) don't track link
1337 count for directories */
1338 //err += check_nlink(testdir, 2);
1339 err += check_dir_contents(testdir, dir_contents);
1340 res = rmdir(testdir);
1341 if (res == -1) {
1342 PERROR("rmdir");
1343 return -1;
1344 }
1345 res = check_nonexist(testdir);
1346 if (res == -1)
1347 return -1;
1348 if (err)
1349 return -1;
1350
1351 success();
1352 return 0;
1353 }
1354
1355 #define test_create_ro_dir(flags) \
1356 do_test_create_ro_dir(flags, #flags)
1357
1358 static int do_test_create_ro_dir(int flags, const char *flags_str)
1359 {
1360 int res;
1361 int err = 0;
1362 int fd;
1363
1364 start_test("open(%s) in read-only directory", flags_str);
1365 rmdir(testdir);
1366 res = mkdir(testdir, 0555);
1367 if (res == -1) {
1368 PERROR("mkdir");
1369 return -1;
1370 }
1371 fd = open(subfile, flags, 0644);
1372 if (fd != -1) {
1373 close(fd);
1374 unlink(subfile);
1375 ERROR("open should have failed");
1376 err--;
1377 } else {
1378 res = check_nonexist(subfile);
1379 if (res == -1)
1380 err--;
1381 }
1382 unlink(subfile);
1383 res = rmdir(testdir);
1384 if (res == -1) {
1385 PERROR("rmdir");
1386 return -1;
1387 }
1388 res = check_nonexist(testdir);
1389 if (res == -1)
1390 return -1;
1391 if (err)
1392 return -1;
1393
1394 success();
1395 return 0;
1396 }
1397
1398 int main(int argc, char *argv[])
1399 {
1400 const char *basepath;
1401 const char *realpath;
1402 int err = 0;
1403 int a;
1404 int is_root;
1405
1406 umask(0);
1407 if (argc < 2 || argc > 4) {
1408 fprintf(stderr, "usage: %s testdir [:realdir] [[-]test#]\n", argv[0]);
1409 return 1;
1410 }
1411 basepath = argv[1];
1412 realpath = basepath;
1413 for (a = 2; a < argc; a++) {
1414 char *endptr;
1415 char *arg = argv[a];
1416 if (arg[0] == ':') {
1417 realpath = arg + 1;
1418 } else {
1419 if (arg[0] == '-') {
1420 arg++;
1421 skip_test = strtoul(arg, &endptr, 10);
1422 } else {
1423 select_test = strtoul(arg, &endptr, 10);
1424 }
1425 if (arg[0] == '\0' || *endptr != '\0') {
1426 fprintf(stderr, "invalid number: '%s'\n", arg);
1427 return 1;
1428 }
1429 }
1430 }
1431 assert(strlen(basepath) < 512);
1432 assert(strlen(realpath) < 512);
1433 if (basepath[0] != '/') {
1434 fprintf(stderr, "testdir must be an absolute path\n");
1435 return 1;
1436 }
1437
1438 sprintf(testfile, "%s/testfile", basepath);
1439 sprintf(testfile2, "%s/testfile2", basepath);
1440 sprintf(testdir, "%s/testdir", basepath);
1441 sprintf(testdir2, "%s/testdir2", basepath);
1442 sprintf(subfile, "%s/subfile", testdir2);
1443
1444 sprintf(testfile_r, "%s/testfile", realpath);
1445 sprintf(testfile2_r, "%s/testfile2", realpath);
1446 sprintf(testdir_r, "%s/testdir", realpath);
1447 sprintf(testdir2_r, "%s/testdir2", realpath);
1448 sprintf(subfile_r, "%s/subfile", testdir2_r);
1449
1450 is_root = (geteuid() == 0);
1451
1452 err += test_create();
1453 err += test_create_unlink();
1454 err += test_symlink();
1455 err += test_link();
1456 err += test_link2();
1457 #ifndef __FreeBSD__
1458 err += test_mknod();
1459 err += test_mkfifo();
1460 #endif
1461 err += test_mkdir();
1462 err += test_rename_file();
1463 err += test_rename_dir();
1464 err += test_utime();
1465 err += test_truncate(0);
1466 err += test_truncate(testdatalen / 2);
1467 err += test_truncate(testdatalen);
1468 err += test_truncate(testdatalen + 100);
1469 err += test_ftruncate(0, 0600);
1470 err += test_ftruncate(testdatalen / 2, 0600);
1471 err += test_ftruncate(testdatalen, 0600);
1472 err += test_ftruncate(testdatalen + 100, 0600);
1473 err += test_ftruncate(0, 0400);
1474 err += test_ftruncate(0, 0200);
1475 err += test_ftruncate(0, 0000);
1476 err += test_open(0, O_RDONLY, 0);
1477 err += test_open(1, O_RDONLY, 0);
1478 err += test_open(1, O_RDWR, 0);
1479 err += test_open(1, O_WRONLY, 0);
1480 err += test_open(0, O_RDWR | O_CREAT, 0600);
1481 err += test_open(1, O_RDWR | O_CREAT, 0600);
1482 err += test_open(0, O_RDWR | O_CREAT | O_TRUNC, 0600);
1483 err += test_open(1, O_RDWR | O_CREAT | O_TRUNC, 0600);
1484 err += test_open(0, O_RDONLY | O_CREAT, 0600);
1485 err += test_open(0, O_RDONLY | O_CREAT, 0400);
1486 err += test_open(0, O_RDONLY | O_CREAT, 0200);
1487 err += test_open(0, O_RDONLY | O_CREAT, 0000);
1488 err += test_open(0, O_WRONLY | O_CREAT, 0600);
1489 err += test_open(0, O_WRONLY | O_CREAT, 0400);
1490 err += test_open(0, O_WRONLY | O_CREAT, 0200);
1491 err += test_open(0, O_WRONLY | O_CREAT, 0000);
1492 err += test_open(0, O_RDWR | O_CREAT, 0400);
1493 err += test_open(0, O_RDWR | O_CREAT, 0200);
1494 err += test_open(0, O_RDWR | O_CREAT, 0000);
1495 err += test_open(0, O_RDWR | O_CREAT | O_EXCL, 0600);
1496 err += test_open(1, O_RDWR | O_CREAT | O_EXCL, 0600);
1497 err += test_open(0, O_RDWR | O_CREAT | O_EXCL, 0000);
1498 err += test_open(1, O_RDWR | O_CREAT | O_EXCL, 0000);
1499 err += test_open_acc(O_RDONLY, 0600, 0);
1500 err += test_open_acc(O_WRONLY, 0600, 0);
1501 err += test_open_acc(O_RDWR, 0600, 0);
1502 err += test_open_acc(O_RDONLY, 0400, 0);
1503 err += test_open_acc(O_WRONLY, 0200, 0);
1504 if(!is_root) {
1505 err += test_open_acc(O_RDONLY | O_TRUNC, 0400, EACCES);
1506 err += test_open_acc(O_WRONLY, 0400, EACCES);
1507 err += test_open_acc(O_RDWR, 0400, EACCES);
1508 err += test_open_acc(O_RDONLY, 0200, EACCES);
1509 err += test_open_acc(O_RDWR, 0200, EACCES);
1510 err += test_open_acc(O_RDONLY, 0000, EACCES);
1511 err += test_open_acc(O_WRONLY, 0000, EACCES);
1512 err += test_open_acc(O_RDWR, 0000, EACCES);
1513 }
1514 err += test_create_ro_dir(O_CREAT);
1515 err += test_create_ro_dir(O_CREAT | O_EXCL);
1516 err += test_create_ro_dir(O_CREAT | O_WRONLY);
1517 err += test_create_ro_dir(O_CREAT | O_TRUNC);
1518
1519 unlink(testfile);
1520 unlink(testfile2);
1521 rmdir(testdir);
1522 rmdir(testdir2);
1523
1524 if (err) {
1525 fprintf(stderr, "%i tests failed\n", -err);
1526 return 1;
1527 }
1528
1529 return 0;
1530 }