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 static int test_rename_dir_loop(void)
1286 {
1287 #define PATH(p) (snprintf(path, sizeof path, "%s/%s", testdir, p), path)
1288 #define PATH2(p) (snprintf(path2, sizeof path2, "%s/%s", testdir, p), path2)
1289
1290 char path[1024], path2[1024];
1291 int err = 0;
1292 int res;
1293
1294 start_test("rename dir loop");
1295
1296 res = create_dir(testdir, testdir_files);
1297 if (res == -1)
1298 return -1;
1299
1300 res = mkdir(PATH("a"), 0755);
1301 if (res == -1) {
1302 PERROR("mkdir");
1303 goto fail;
1304 }
1305
1306 res = rename(PATH("a"), PATH2("a"));
1307 if (res == -1) {
1308 PERROR("rename");
1309 goto fail;
1310 }
1311
1312 errno = 0;
1313 res = rename(PATH("a"), PATH2("a/b"));
1314 if (res == 0 || errno != EINVAL) {
1315 PERROR("rename");
1316 goto fail;
1317 }
1318
1319 res = mkdir(PATH("a/b"), 0755);
1320 if (res == -1) {
1321 PERROR("mkdir");
1322 goto fail;
1323 }
1324
1325 res = mkdir(PATH("a/b/c"), 0755);
1326 if (res == -1) {
1327 PERROR("mkdir");
1328 goto fail;
1329 }
1330
1331 errno = 0;
1332 res = rename(PATH("a"), PATH2("a/b/c"));
1333 if (res == 0 || errno != EINVAL) {
1334 PERROR("rename");
1335 goto fail;
1336 }
1337
1338 errno = 0;
1339 res = rename(PATH("a"), PATH2("a/b/c/a"));
1340 if (res == 0 || errno != EINVAL) {
1341 PERROR("rename");
1342 goto fail;
1343 }
1344
1345 errno = 0;
1346 res = rename(PATH("a/b/c"), PATH2("a"));
1347 if (res == 0 || errno != ENOTEMPTY) {
1348 PERROR("rename");
1349 goto fail;
1350 }
1351
1352 res = open(PATH("a/foo"), O_CREAT, 0644);
1353 if (res == -1) {
1354 PERROR("open");
1355 goto fail;
1356 }
1357 close(res);
1358
1359 res = rename(PATH("a/foo"), PATH2("a/bar"));
1360 if (res == -1) {
1361 PERROR("rename");
1362 goto fail;
1363 }
1364
1365 res = rename(PATH("a/bar"), PATH2("a/foo"));
1366 if (res == -1) {
1367 PERROR("rename");
1368 goto fail;
1369 }
1370
1371 res = rename(PATH("a/foo"), PATH2("a/b/bar"));
1372 if (res == -1) {
1373 PERROR("rename");
1374 goto fail;
1375 }
1376
1377 res = rename(PATH("a/b/bar"), PATH2("a/foo"));
1378 if (res == -1) {
1379 PERROR("rename");
1380 goto fail;
1381 }
1382
1383 res = rename(PATH("a/foo"), PATH2("a/b/c/bar"));
1384 if (res == -1) {
1385 PERROR("rename");
1386 goto fail;
1387 }
1388
1389 res = rename(PATH("a/b/c/bar"), PATH2("a/foo"));
1390 if (res == -1) {
1391 PERROR("rename");
1392 goto fail;
1393 }
1394
1395 res = open(PATH("a/bar"), O_CREAT, 0644);
1396 if (res == -1) {
1397 PERROR("open");
1398 goto fail;
1399 }
1400 close(res);
1401
1402 res = rename(PATH("a/foo"), PATH2("a/bar"));
1403 if (res == -1) {
1404 PERROR("rename");
1405 goto fail;
1406 }
1407
1408 unlink(PATH("a/bar"));
1409
1410 res = rename(PATH("a/b"), PATH2("a/d"));
1411 if (res == -1) {
1412 PERROR("rename");
1413 goto fail;
1414 }
1415
1416 res = rename(PATH("a/d"), PATH2("a/b"));
1417 if (res == -1) {
1418 PERROR("rename");
1419 goto fail;
1420 }
1421
1422 res = mkdir(PATH("a/d"), 0755);
1423 if (res == -1) {
1424 PERROR("mkdir");
1425 goto fail;
1426 }
1427
1428 res = rename(PATH("a/b"), PATH2("a/d"));
1429 if (res == -1) {
1430 PERROR("rename");
1431 goto fail;
1432 }
1433
1434 res = rename(PATH("a/d"), PATH2("a/b"));
1435 if (res == -1) {
1436 PERROR("rename");
1437 goto fail;
1438 }
1439
1440 res = mkdir(PATH("a/d"), 0755);
1441 if (res == -1) {
1442 PERROR("mkdir");
1443 goto fail;
1444 }
1445
1446 res = mkdir(PATH("a/d/e"), 0755);
1447 if (res == -1) {
1448 PERROR("mkdir");
1449 goto fail;
1450 }
1451
1452 errno = 0;
1453 res = rename(PATH("a/b"), PATH2("a/d"));
1454 if (res == 0 || errno != ENOTEMPTY) {
1455 PERROR("rename");
1456 goto fail;
1457 }
1458
1459 rmdir(PATH("a/d/e"));
1460 rmdir(PATH("a/d"));
1461
1462 rmdir(PATH("a/b/c"));
1463 rmdir(PATH("a/b"));
1464 rmdir(PATH("a"));
1465
1466 err += cleanup_dir(testdir, testdir_files, 0);
1467 res = rmdir(testdir);
1468 if (res == -1) {
1469 PERROR("rmdir");
1470 goto fail;
1471 }
1472 res = check_nonexist(testdir);
1473 if (res == -1)
1474 return -1;
1475 if (err)
1476 return -1;
1477
1478 success();
1479 return 0;
1480
1481 fail:
1482 unlink(PATH("a/bar"));
1483
1484 rmdir(PATH("a/d/e"));
1485 rmdir(PATH("a/d"));
1486
1487 rmdir(PATH("a/b/c"));
1488 rmdir(PATH("a/b"));
1489 rmdir(PATH("a"));
1490
1491 cleanup_dir(testdir, testdir_files, 1);
1492 rmdir(testdir);
1493
1494 return -1;
1495
1496 #undef PATH2
1497 #undef PATH
1498 }
1499
1500 #ifndef __FreeBSD__
1501 static int test_mkfifo(void)
1502 {
1503 int res;
1504 int err = 0;
1505
1506 start_test("mkfifo");
1507 unlink(testfile);
1508 res = mkfifo(testfile, 0644);
1509 if (res == -1) {
1510 PERROR("mkfifo");
1511 return -1;
1512 }
1513 res = check_type(testfile, S_IFIFO);
1514 if (res == -1)
1515 return -1;
1516 err += check_mode(testfile, 0644);
1517 err += check_nlink(testfile, 1);
1518 res = unlink(testfile);
1519 if (res == -1) {
1520 PERROR("unlink");
1521 return -1;
1522 }
1523 res = check_nonexist(testfile);
1524 if (res == -1)
1525 return -1;
1526 if (err)
1527 return -1;
1528
1529 success();
1530 return 0;
1531 }
1532 #endif
1533
1534 static int test_mkdir(void)
1535 {
1536 int res;
1537 int err = 0;
1538 const char *dir_contents[] = {NULL};
1539
1540 start_test("mkdir");
1541 rmdir(testdir);
1542 res = mkdir(testdir, 0755);
1543 if (res == -1) {
1544 PERROR("mkdir");
1545 return -1;
1546 }
1547 res = check_type(testdir, S_IFDIR);
1548 if (res == -1)
1549 return -1;
1550 err += check_mode(testdir, 0755);
1551 /* Some file systems (like btrfs) don't track link
1552 count for directories */
1553 //err += check_nlink(testdir, 2);
1554 err += check_dir_contents(testdir, dir_contents);
1555 res = rmdir(testdir);
1556 if (res == -1) {
1557 PERROR("rmdir");
1558 return -1;
1559 }
1560 res = check_nonexist(testdir);
1561 if (res == -1)
1562 return -1;
1563 if (err)
1564 return -1;
1565
1566 success();
1567 return 0;
1568 }
1569
1570 #define test_create_ro_dir(flags) \
1571 do_test_create_ro_dir(flags, #flags)
1572
1573 static int do_test_create_ro_dir(int flags, const char *flags_str)
1574 {
1575 int res;
1576 int err = 0;
1577 int fd;
1578
1579 start_test("open(%s) in read-only directory", flags_str);
1580 rmdir(testdir);
1581 res = mkdir(testdir, 0555);
1582 if (res == -1) {
1583 PERROR("mkdir");
1584 return -1;
1585 }
1586 fd = open(subfile, flags, 0644);
1587 if (fd != -1) {
1588 close(fd);
1589 unlink(subfile);
1590 ERROR("open should have failed");
1591 err--;
1592 } else {
1593 res = check_nonexist(subfile);
1594 if (res == -1)
1595 err--;
1596 }
1597 unlink(subfile);
1598 res = rmdir(testdir);
1599 if (res == -1) {
1600 PERROR("rmdir");
1601 return -1;
1602 }
1603 res = check_nonexist(testdir);
1604 if (res == -1)
1605 return -1;
1606 if (err)
1607 return -1;
1608
1609 success();
1610 return 0;
1611 }
1612
1613 int main(int argc, char *argv[])
1614 {
1615 const char *basepath;
1616 const char *realpath;
1617 int err = 0;
1618 int a;
1619 int is_root;
1620
1621 umask(0);
1622 if (argc < 2 || argc > 4) {
1623 fprintf(stderr, "usage: %s testdir [:realdir] [[-]test#]\n", argv[0]);
1624 return 1;
1625 }
1626 basepath = argv[1];
1627 realpath = basepath;
1628 for (a = 2; a < argc; a++) {
1629 char *endptr;
1630 char *arg = argv[a];
1631 if (arg[0] == ':') {
1632 realpath = arg + 1;
1633 } else {
1634 if (arg[0] == '-') {
1635 arg++;
1636 skip_test = strtoul(arg, &endptr, 10);
1637 } else {
1638 select_test = strtoul(arg, &endptr, 10);
1639 }
1640 if (arg[0] == '\0' || *endptr != '\0') {
1641 fprintf(stderr, "invalid number: '%s'\n", arg);
1642 return 1;
1643 }
1644 }
1645 }
1646 assert(strlen(basepath) < 512);
1647 assert(strlen(realpath) < 512);
1648 if (basepath[0] != '/') {
1649 fprintf(stderr, "testdir must be an absolute path\n");
1650 return 1;
1651 }
1652
1653 sprintf(testfile, "%s/testfile", basepath);
1654 sprintf(testfile2, "%s/testfile2", basepath);
1655 sprintf(testdir, "%s/testdir", basepath);
1656 sprintf(testdir2, "%s/testdir2", basepath);
1657 sprintf(subfile, "%s/subfile", testdir2);
1658
1659 sprintf(testfile_r, "%s/testfile", realpath);
1660 sprintf(testfile2_r, "%s/testfile2", realpath);
1661 sprintf(testdir_r, "%s/testdir", realpath);
1662 sprintf(testdir2_r, "%s/testdir2", realpath);
1663 sprintf(subfile_r, "%s/subfile", testdir2_r);
1664
1665 is_root = (geteuid() == 0);
1666
1667 err += test_create();
1668 err += test_create_unlink();
1669 err += test_symlink();
1670 err += test_link();
1671 err += test_link2();
1672 #ifndef __FreeBSD__
1673 err += test_mknod();
1674 err += test_mkfifo();
1675 #endif
1676 err += test_mkdir();
1677 err += test_rename_file();
1678 err += test_rename_dir();
1679 err += test_rename_dir_loop();
1680 err += test_utime();
1681 err += test_truncate(0);
1682 err += test_truncate(testdatalen / 2);
1683 err += test_truncate(testdatalen);
1684 err += test_truncate(testdatalen + 100);
1685 err += test_ftruncate(0, 0600);
1686 err += test_ftruncate(testdatalen / 2, 0600);
1687 err += test_ftruncate(testdatalen, 0600);
1688 err += test_ftruncate(testdatalen + 100, 0600);
1689 err += test_ftruncate(0, 0400);
1690 err += test_ftruncate(0, 0200);
1691 err += test_ftruncate(0, 0000);
1692 err += test_open(0, O_RDONLY, 0);
1693 err += test_open(1, O_RDONLY, 0);
1694 err += test_open(1, O_RDWR, 0);
1695 err += test_open(1, O_WRONLY, 0);
1696 err += test_open(0, O_RDWR | O_CREAT, 0600);
1697 err += test_open(1, O_RDWR | O_CREAT, 0600);
1698 err += test_open(0, O_RDWR | O_CREAT | O_TRUNC, 0600);
1699 err += test_open(1, O_RDWR | O_CREAT | O_TRUNC, 0600);
1700 err += test_open(0, O_RDONLY | O_CREAT, 0600);
1701 err += test_open(0, O_RDONLY | O_CREAT, 0400);
1702 err += test_open(0, O_RDONLY | O_CREAT, 0200);
1703 err += test_open(0, O_RDONLY | O_CREAT, 0000);
1704 err += test_open(0, O_WRONLY | O_CREAT, 0600);
1705 err += test_open(0, O_WRONLY | O_CREAT, 0400);
1706 err += test_open(0, O_WRONLY | O_CREAT, 0200);
1707 err += test_open(0, O_WRONLY | O_CREAT, 0000);
1708 err += test_open(0, O_RDWR | O_CREAT, 0400);
1709 err += test_open(0, O_RDWR | O_CREAT, 0200);
1710 err += test_open(0, O_RDWR | O_CREAT, 0000);
1711 err += test_open(0, O_RDWR | O_CREAT | O_EXCL, 0600);
1712 err += test_open(1, O_RDWR | O_CREAT | O_EXCL, 0600);
1713 err += test_open(0, O_RDWR | O_CREAT | O_EXCL, 0000);
1714 err += test_open(1, O_RDWR | O_CREAT | O_EXCL, 0000);
1715 err += test_open_acc(O_RDONLY, 0600, 0);
1716 err += test_open_acc(O_WRONLY, 0600, 0);
1717 err += test_open_acc(O_RDWR, 0600, 0);
1718 err += test_open_acc(O_RDONLY, 0400, 0);
1719 err += test_open_acc(O_WRONLY, 0200, 0);
1720 if(!is_root) {
1721 err += test_open_acc(O_RDONLY | O_TRUNC, 0400, EACCES);
1722 err += test_open_acc(O_WRONLY, 0400, EACCES);
1723 err += test_open_acc(O_RDWR, 0400, EACCES);
1724 err += test_open_acc(O_RDONLY, 0200, EACCES);
1725 err += test_open_acc(O_RDWR, 0200, EACCES);
1726 err += test_open_acc(O_RDONLY, 0000, EACCES);
1727 err += test_open_acc(O_WRONLY, 0000, EACCES);
1728 err += test_open_acc(O_RDWR, 0000, EACCES);
1729 }
1730 err += test_create_ro_dir(O_CREAT);
1731 err += test_create_ro_dir(O_CREAT | O_EXCL);
1732 err += test_create_ro_dir(O_CREAT | O_WRONLY);
1733 err += test_create_ro_dir(O_CREAT | O_TRUNC);
1734
1735 unlink(testfile);
1736 unlink(testfile2);
1737 rmdir(testdir);
1738 rmdir(testdir2);
1739
1740 if (err) {
1741 fprintf(stderr, "%i tests failed\n", -err);
1742 return 1;
1743 }
1744
1745 return 0;
1746 }