Add fuse_getgroups (high level lib) and fuse_req_getgroups (low
[fuse.git] / test / test.c
bloba2ce3cdd67daf8b3463f36c59f359529952ec38f
1 #include <stdio.h>
2 #include <stdarg.h>
3 #include <string.h>
4 #include <unistd.h>
5 #include <fcntl.h>
6 #include <dirent.h>
7 #include <utime.h>
8 #include <errno.h>
9 #include <assert.h>
10 #include <sys/types.h>
11 #include <sys/stat.h>
14 static char testfile[1024];
15 static char testfile2[1024];
16 static char testdir[1024];
17 static char testdir2[1024];
18 static char testname[256];
19 static char testdata[] = "abcdefghijklmnopqrstuvwxyz";
20 static char testdata2[] = "1234567890-=qwertyuiop[]\asdfghjkl;'zxcvbnm,./";
21 static const char *testdir_files[] = { "f1", "f2", NULL};
22 static char zerodata[4096];
23 static int testdatalen = sizeof(testdata) - 1;
24 static int testdata2len = sizeof(testdata2) - 1;
26 #define MAX_ENTRIES 1024
28 static void test_perror(const char *func, const char *msg)
30 fprintf(stderr, "[%s] %s() - %s: %s\n", testname, func, msg,
31 strerror(errno));
34 static void test_error(const char *func, const char *msg, ...)
35 __attribute__ ((format (printf, 2, 3)));
37 static void start_test(const char *fmt, ...)
38 __attribute__ ((format (printf, 1, 2)));
40 static void test_error(const char *func, const char *msg, ...)
42 va_list ap;
43 fprintf(stderr, "[%s] %s() - ", testname, func);
44 va_start(ap, msg);
45 vfprintf(stderr, msg, ap);
46 va_end(ap);
47 fprintf(stderr, "\n");
50 static void success(void)
52 fprintf(stderr, "[%s] OK\n", testname);
55 static void start_test(const char *fmt, ...)
57 va_list ap;
58 va_start(ap, fmt);
59 vsprintf(testname, fmt, ap);
60 va_end(ap);
63 #define PERROR(msg) test_perror(__FUNCTION__, msg)
64 #define ERROR(msg, args...) test_error(__FUNCTION__, msg, ##args)
66 static int check_size(const char *path, int len)
68 struct stat stbuf;
69 int res = stat(path, &stbuf);
70 if (res == -1) {
71 PERROR("stat");
72 return -1;
74 if (stbuf.st_size != len) {
75 ERROR("length %u instead of %u", (int) stbuf.st_size,
76 (int) len);
77 return -1;
79 return 0;
82 static int fcheck_size(int fd, int len)
84 struct stat stbuf;
85 int res = fstat(fd, &stbuf);
86 if (res == -1) {
87 PERROR("fstat");
88 return -1;
90 if (stbuf.st_size != len) {
91 ERROR("length %u instead of %u", (int) stbuf.st_size,
92 (int) len);
93 return -1;
95 return 0;
98 static int check_type(const char *path, mode_t type)
100 struct stat stbuf;
101 int res = lstat(path, &stbuf);
102 if (res == -1) {
103 PERROR("lstat");
104 return -1;
106 if ((stbuf.st_mode & S_IFMT) != type) {
107 ERROR("type 0%o instead of 0%o", stbuf.st_mode & S_IFMT, type);
108 return -1;
110 return 0;
113 static int fcheck_type(int fd, mode_t type)
115 struct stat stbuf;
116 int res = fstat(fd, &stbuf);
117 if (res == -1) {
118 PERROR("fstat");
119 return -1;
121 if ((stbuf.st_mode & S_IFMT) != type) {
122 ERROR("type 0%o instead of 0%o", stbuf.st_mode & S_IFMT, type);
123 return -1;
125 return 0;
128 static int check_mode(const char *path, mode_t mode)
130 struct stat stbuf;
131 int res = lstat(path, &stbuf);
132 if (res == -1) {
133 PERROR("lstat");
134 return -1;
136 if ((stbuf.st_mode & 07777) != mode) {
137 ERROR("mode 0%o instead of 0%o", stbuf.st_mode & 07777, mode);
138 return -1;
140 return 0;
143 static int fcheck_mode(int fd, mode_t mode)
145 struct stat stbuf;
146 int res = fstat(fd, &stbuf);
147 if (res == -1) {
148 PERROR("fstat");
149 return -1;
151 if ((stbuf.st_mode & 07777) != mode) {
152 ERROR("mode 0%o instead of 0%o", stbuf.st_mode & 07777, mode);
153 return -1;
155 return 0;
158 static int check_times(const char *path, time_t atime, time_t mtime)
160 int err = 0;
161 struct stat stbuf;
162 int res = lstat(path, &stbuf);
163 if (res == -1) {
164 PERROR("lstat");
165 return -1;
167 if (stbuf.st_atime != atime) {
168 ERROR("atime %li instead of %li", stbuf.st_atime, atime);
169 err--;
171 if (stbuf.st_mtime != mtime) {
172 ERROR("mtime %li instead of %li", stbuf.st_mtime, mtime);
173 err--;
175 if (err)
176 return -1;
178 return 0;
181 static int fcheck_times(int fd, time_t atime, time_t mtime)
183 int err = 0;
184 struct stat stbuf;
185 int res = fstat(fd, &stbuf);
186 if (res == -1) {
187 PERROR("fstat");
188 return -1;
190 if (stbuf.st_atime != atime) {
191 ERROR("atime %li instead of %li", stbuf.st_atime, atime);
192 err--;
194 if (stbuf.st_mtime != mtime) {
195 ERROR("mtime %li instead of %li", stbuf.st_mtime, mtime);
196 err--;
198 if (err)
199 return -1;
201 return 0;
204 static int check_nlink(const char *path, nlink_t nlink)
206 struct stat stbuf;
207 int res = lstat(path, &stbuf);
208 if (res == -1) {
209 PERROR("lstat");
210 return -1;
212 if (stbuf.st_nlink != nlink) {
213 ERROR("nlink %li instead of %li", (long) stbuf.st_nlink,
214 (long) nlink);
215 return -1;
217 return 0;
220 static int fcheck_nlink(int fd, nlink_t nlink)
222 struct stat stbuf;
223 int res = fstat(fd, &stbuf);
224 if (res == -1) {
225 PERROR("fstat");
226 return -1;
228 if (stbuf.st_nlink != nlink) {
229 ERROR("nlink %li instead of %li", (long) stbuf.st_nlink,
230 (long) nlink);
231 return -1;
233 return 0;
236 static int check_nonexist(const char *path)
238 struct stat stbuf;
239 int res = lstat(path, &stbuf);
240 if (res == 0) {
241 ERROR("file should not exist");
242 return -1;
244 if (errno != ENOENT) {
245 ERROR("file should not exist: %s", strerror(errno));
246 return -1;
248 return 0;
251 static int check_buffer(const char *buf, const char *data, unsigned len)
253 if (memcmp(buf, data, len) != 0) {
254 ERROR("data mismatch");
255 return -1;
257 return 0;
260 static int check_data(const char *path, const char *data, int offset,
261 unsigned len)
263 char buf[4096];
264 int res;
265 int fd = open(path, O_RDONLY);
266 if (fd == -1) {
267 PERROR("open");
268 return -1;
270 if (lseek(fd, offset, SEEK_SET) == (off_t) -1) {
271 PERROR("lseek");
272 close(fd);
273 return -1;
275 while (len) {
276 int rdlen = len < sizeof(buf) ? len : sizeof(buf);
277 res = read(fd, buf, rdlen);
278 if (res == -1) {
279 PERROR("read");
280 close(fd);
281 return -1;
283 if (res != rdlen) {
284 ERROR("short read: %u instead of %u", res, rdlen);
285 close(fd);
286 return -1;
288 if (check_buffer(buf, data, rdlen) != 0) {
289 close(fd);
290 return -1;
292 data += rdlen;
293 len -= rdlen;
295 res = close(fd);
296 if (res == -1) {
297 PERROR("close");
298 return -1;
300 return 0;
303 static int fcheck_data(int fd, const char *data, int offset,
304 unsigned len)
306 char buf[4096];
307 int res;
308 if (lseek(fd, offset, SEEK_SET) == (off_t) -1) {
309 PERROR("lseek");
310 return -1;
312 while (len) {
313 int rdlen = len < sizeof(buf) ? len : sizeof(buf);
314 res = read(fd, buf, rdlen);
315 if (res == -1) {
316 PERROR("read");
317 return -1;
319 if (res != rdlen) {
320 ERROR("short read: %u instead of %u", res, rdlen);
321 return -1;
323 if (check_buffer(buf, data, rdlen) != 0) {
324 return -1;
326 data += rdlen;
327 len -= rdlen;
329 return 0;
332 static int check_dir_contents(const char *path, const char **contents)
334 int i;
335 int res;
336 int err = 0;
337 int found[MAX_ENTRIES];
338 const char *cont[MAX_ENTRIES];
339 DIR *dp;
341 for (i = 0; contents[i]; i++) {
342 assert(i < MAX_ENTRIES - 3);
343 found[i] = 0;
344 cont[i] = contents[i];
346 found[i] = 0;
347 cont[i++] = ".";
348 found[i] = 0;
349 cont[i++] = "..";
350 cont[i] = NULL;
352 dp = opendir(path);
353 if (dp == NULL) {
354 PERROR("opendir");
355 return -1;
357 memset(found, 0, sizeof(found));
358 while(1) {
359 struct dirent *de;
360 errno = 0;
361 de = readdir(dp);
362 if (de == NULL) {
363 if (errno) {
364 PERROR("readdir");
365 closedir(dp);
366 return -1;
368 break;
370 for (i = 0; cont[i] != NULL; i++) {
371 assert(i < MAX_ENTRIES);
372 if (strcmp(cont[i], de->d_name) == 0) {
373 if (found[i]) {
374 ERROR("duplicate entry <%s>",
375 de->d_name);
376 err--;
377 } else
378 found[i] = 1;
379 break;
382 if (!cont[i]) {
383 ERROR("unexpected entry <%s>", de->d_name);
384 err --;
387 for (i = 0; cont[i] != NULL; i++) {
388 if (!found[i]) {
389 ERROR("missing entry <%s>", cont[i]);
390 err--;
393 res = closedir(dp);
394 if (res == -1) {
395 PERROR("closedir");
396 return -1;
398 if (err)
399 return -1;
401 return 0;
404 static int create_file(const char *path, const char *data, int len)
406 int res;
407 int fd;
409 unlink(path);
410 fd = creat(path, 0644);
411 if (fd == -1) {
412 PERROR("creat");
413 return -1;
415 if (len) {
416 res = write(fd, data, len);
417 if (res == -1) {
418 PERROR("write");
419 close(fd);
420 return -1;
422 if (res != len) {
423 ERROR("write is short: %u instead of %u", res, len);
424 close(fd);
425 return -1;
428 res = close(fd);
429 if (res == -1) {
430 PERROR("close");
431 return -1;
433 res = check_type(path, S_IFREG);
434 if (res == -1)
435 return -1;
436 res = check_mode(path, 0644);
437 if (res == -1)
438 return -1;
439 res = check_nlink(path, 1);
440 if (res == -1)
441 return -1;
442 res = check_size(path, len);
443 if (res == -1)
444 return -1;
446 if (len) {
447 res = check_data(path, data, 0, len);
448 if (res == -1)
449 return -1;
452 return 0;
455 static int cleanup_dir(const char *path, const char **dir_files, int quiet)
457 int i;
458 int err = 0;
460 for (i = 0; dir_files[i]; i++) {
461 int res;
462 char fpath[1024];
463 sprintf(fpath, "%s/%s", path, dir_files[i]);
464 res = unlink(fpath);
465 if (res == -1 && !quiet) {
466 PERROR("unlink");
467 err --;
470 if (err)
471 return -1;
473 return 0;
476 static int create_dir(const char *path, const char **dir_files)
478 int res;
479 int i;
481 rmdir(path);
482 res = mkdir(path, 0755);
483 if (res == -1) {
484 PERROR("mkdir");
485 return -1;
487 res = check_type(path, S_IFDIR);
488 if (res == -1)
489 return -1;
490 res = check_mode(path, 0755);
491 if (res == -1)
492 return -1;
494 for (i = 0; dir_files[i]; i++) {
495 char fpath[1024];
496 sprintf(fpath, "%s/%s", path, dir_files[i]);
497 res = create_file(fpath, "", 0);
498 if (res == -1) {
499 cleanup_dir(path, dir_files, 1);
500 return -1;
503 res = check_dir_contents(path, dir_files);
504 if (res == -1) {
505 cleanup_dir(path, dir_files, 1);
506 return -1;
509 return 0;
512 static int test_truncate(int len)
514 const char *data = testdata;
515 int datalen = testdatalen;
516 int res;
518 start_test("truncate(%u)", (int) len);
519 res = create_file(testfile, data, datalen);
520 if (res == -1)
521 return -1;
523 res = truncate(testfile, len);
524 if (res == -1) {
525 PERROR("truncate");
526 return -1;
528 res = check_size(testfile, len);
529 if (res == -1)
530 return -1;
532 if (len > 0) {
533 if (len <= datalen) {
534 res = check_data(testfile, data, 0, len);
535 if (res == -1)
536 return -1;
537 } else {
538 res = check_data(testfile, data, 0, datalen);
539 if (res == -1)
540 return -1;
541 res = check_data(testfile, zerodata, datalen,
542 len - datalen);
543 if (res == -1)
544 return -1;
547 res = unlink(testfile);
548 if (res == -1) {
549 PERROR("unlink");
550 return -1;
552 res = check_nonexist(testfile);
553 if (res == -1)
554 return -1;
556 success();
557 return 0;
560 static int test_ftruncate(int len, int mode)
562 const char *data = testdata;
563 int datalen = testdatalen;
564 int res;
565 int fd;
567 start_test("ftruncate(%u) mode: 0%03o", len, mode);
568 res = create_file(testfile, data, datalen);
569 if (res == -1)
570 return -1;
572 fd = open(testfile, O_WRONLY);
573 if (fd == -1) {
574 PERROR("open");
575 return -1;
578 res = fchmod(fd, mode);
579 if (res == -1) {
580 PERROR("fchmod");
581 close(fd);
582 return -1;
584 res = check_mode(testfile, mode);
585 if (res == -1) {
586 close(fd);
587 return -1;
589 res = ftruncate(fd, len);
590 if (res == -1) {
591 PERROR("ftruncate");
592 close(fd);
593 return -1;
595 close(fd);
596 res = check_size(testfile, len);
597 if (res == -1)
598 return -1;
600 if (len > 0) {
601 if (len <= datalen) {
602 res = check_data(testfile, data, 0, len);
603 if (res == -1)
604 return -1;
605 } else {
606 res = check_data(testfile, data, 0, datalen);
607 if (res == -1)
608 return -1;
609 res = check_data(testfile, zerodata, datalen,
610 len - datalen);
611 if (res == -1)
612 return -1;
615 res = unlink(testfile);
616 if (res == -1) {
617 PERROR("unlink");
618 return -1;
620 res = check_nonexist(testfile);
621 if (res == -1)
622 return -1;
624 success();
625 return 0;
628 static int test_utime(void)
630 struct utimbuf utm;
631 time_t atime = 987631200;
632 time_t mtime = 123116400;
633 int res;
635 start_test("utime");
636 res = create_file(testfile, NULL, 0);
637 if (res == -1)
638 return -1;
640 utm.actime = atime;
641 utm.modtime = mtime;
642 res = utime(testfile, &utm);
643 if (res == -1) {
644 PERROR("utime");
645 return -1;
647 res = check_times(testfile, atime, mtime);
648 if (res == -1) {
649 return -1;
651 res = unlink(testfile);
652 if (res == -1) {
653 PERROR("unlink");
654 return -1;
656 res = check_nonexist(testfile);
657 if (res == -1)
658 return -1;
660 success();
661 return 0;
664 static int test_create(void)
666 const char *data = testdata;
667 int datalen = testdatalen;
668 int err = 0;
669 int res;
670 int fd;
672 start_test("create");
673 unlink(testfile);
674 fd = creat(testfile, 0644);
675 if (fd == -1) {
676 PERROR("creat");
677 return -1;
679 res = write(fd, data, datalen);
680 if (res == -1) {
681 PERROR("write");
682 close(fd);
683 return -1;
685 if (res != datalen) {
686 ERROR("write is short: %u instead of %u", res, datalen);
687 close(fd);
688 return -1;
690 res = close(fd);
691 if (res == -1) {
692 PERROR("close");
693 return -1;
695 res = check_type(testfile, S_IFREG);
696 if (res == -1)
697 return -1;
698 err += check_mode(testfile, 0644);
699 err += check_nlink(testfile, 1);
700 err += check_size(testfile, datalen);
701 err += check_data(testfile, data, 0, datalen);
702 res = unlink(testfile);
703 if (res == -1) {
704 PERROR("unlink");
705 return -1;
707 res = check_nonexist(testfile);
708 if (res == -1)
709 return -1;
710 if (err)
711 return -1;
713 success();
714 return 0;
717 static int test_create_unlink(void)
719 const char *data = testdata;
720 int datalen = testdatalen;
721 int err = 0;
722 int res;
723 int fd;
725 start_test("create+unlink");
726 unlink(testfile);
727 fd = open(testfile, O_CREAT | O_RDWR | O_TRUNC, 0644);
728 if (fd == -1) {
729 PERROR("creat");
730 return -1;
732 res = unlink(testfile);
733 if (res == -1) {
734 PERROR("unlink");
735 close(fd);
736 return -1;
738 res = check_nonexist(testfile);
739 if (res == -1)
740 return -1;
741 res = write(fd, data, datalen);
742 if (res == -1) {
743 PERROR("write");
744 close(fd);
745 return -1;
747 if (res != datalen) {
748 ERROR("write is short: %u instead of %u", res, datalen);
749 close(fd);
750 return -1;
752 err += fcheck_type(fd, S_IFREG);
753 err += fcheck_mode(fd, 0644);
754 err += fcheck_nlink(fd, 0);
755 err += fcheck_size(fd, datalen);
756 err += fcheck_data(fd, data, 0, datalen);
757 res = close(fd);
758 if (res == -1) {
759 PERROR("close");
760 err--;
762 if (err)
763 return -1;
765 success();
766 return 0;
769 static int test_mknod(void)
771 int err = 0;
772 int res;
774 start_test("mknod");
775 unlink(testfile);
776 res = mknod(testfile, 0644, 0);
777 if (res == -1) {
778 PERROR("mknod");
779 return -1;
781 res = check_type(testfile, S_IFREG);
782 if (res == -1)
783 return -1;
784 err += check_mode(testfile, 0644);
785 err += check_nlink(testfile, 1);
786 err += check_size(testfile, 0);
787 res = unlink(testfile);
788 if (res == -1) {
789 PERROR("unlink");
790 return -1;
792 res = check_nonexist(testfile);
793 if (res == -1)
794 return -1;
795 if (err)
796 return -1;
798 success();
799 return 0;
802 #define test_open(exist, flags, mode) do_test_open(exist, flags, #flags, mode)
804 static int do_test_open(int exist, int flags, const char *flags_str, int mode)
806 char buf[4096];
807 const char *data = testdata;
808 int datalen = testdatalen;
809 unsigned currlen = 0;
810 int err = 0;
811 int res;
812 int fd;
813 off_t off;
815 start_test("open(%s, %s, 0%03o)", exist ? "+" : "-", flags_str, mode);
816 unlink(testfile);
817 if (exist) {
818 res = create_file(testfile, testdata2, testdata2len);
819 if (res == -1)
820 return -1;
822 currlen = testdata2len;
825 fd = open(testfile, flags, mode);
826 if ((flags & O_CREAT) && (flags & O_EXCL) && exist) {
827 if (fd != -1) {
828 ERROR("open should have failed");
829 close(fd);
830 return -1;
831 } else if (errno == EEXIST)
832 goto succ;
834 if (!(flags & O_CREAT) && !exist) {
835 if (fd != -1) {
836 ERROR("open should have failed");
837 close(fd);
838 return -1;
839 } else if (errno == ENOENT)
840 goto succ;
842 if (fd == -1) {
843 PERROR("open");
844 return -1;
847 if (flags & O_TRUNC)
848 currlen = 0;
850 err += check_type(testfile, S_IFREG);
851 if (exist)
852 err += check_mode(testfile, 0644);
853 else
854 err += check_mode(testfile, mode);
855 err += check_nlink(testfile, 1);
856 err += check_size(testfile, currlen);
857 if (exist && !(flags & O_TRUNC) && (mode & 0400))
858 err += check_data(testfile, testdata2, 0, testdata2len);
860 res = write(fd, data, datalen);
861 if ((flags & O_ACCMODE) != O_RDONLY) {
862 if (res == -1) {
863 PERROR("write");
864 err --;
865 } else if (res != datalen) {
866 ERROR("write is short: %u instead of %u", res, datalen);
867 err --;
868 } else {
869 if (datalen > (int) currlen)
870 currlen = datalen;
872 err += check_size(testfile, currlen);
874 if (mode & 0400) {
875 err += check_data(testfile, data, 0, datalen);
876 if (exist && !(flags & O_TRUNC) &&
877 testdata2len > datalen)
878 err += check_data(testfile,
879 testdata2 + datalen,
880 datalen,
881 testdata2len - datalen);
884 } else {
885 if (res != -1) {
886 ERROR("write should have failed");
887 err --;
888 } else if (errno != EBADF) {
889 PERROR("write");
890 err --;
893 off = lseek(fd, SEEK_SET, 0);
894 if (off == (off_t) -1) {
895 PERROR("lseek");
896 err--;
897 } else if (off != 0) {
898 ERROR("offset should have returned 0");
899 err --;
901 res = read(fd, buf, sizeof(buf));
902 if ((flags & O_ACCMODE) != O_WRONLY) {
903 if (res == -1) {
904 PERROR("read");
905 err--;
906 } else {
907 int readsize =
908 currlen < sizeof(buf) ? currlen : sizeof(buf);
909 if (res != readsize) {
910 ERROR("read is short: %i instead of %u",
911 res, readsize);
912 err--;
913 } else {
914 if ((flags & O_ACCMODE) != O_RDONLY) {
915 err += check_buffer(buf, data, datalen);
916 if (exist && !(flags & O_TRUNC) &&
917 testdata2len > datalen)
918 err += check_buffer(buf + datalen,
919 testdata2 + datalen,
920 testdata2len - datalen);
921 } else if (exist)
922 err += check_buffer(buf, testdata2,
923 testdata2len);
926 } else {
927 if (res != -1) {
928 ERROR("read should have failed");
929 err --;
930 } else if (errno != EBADF) {
931 PERROR("read");
932 err --;
936 res = close(fd);
937 if (res == -1) {
938 PERROR("close");
939 return -1;
941 res = unlink(testfile);
942 if (res == -1) {
943 PERROR("unlink");
944 return -1;
946 res = check_nonexist(testfile);
947 if (res == -1)
948 return -1;
949 if (err)
950 return -1;
952 succ:
953 success();
954 return 0;
957 #define test_open_acc(flags, mode, err) \
958 do_test_open_acc(flags, #flags, mode, err)
960 static int do_test_open_acc(int flags, const char *flags_str, int mode, int err)
962 const char *data = testdata;
963 int datalen = testdatalen;
964 int res;
965 int fd;
967 start_test("open_acc(%s) mode: 0%03o error: '%s'", flags_str, mode,
968 strerror(err));
969 unlink(testfile);
970 res = create_file(testfile, data, datalen);
971 if (res == -1)
972 return -1;
974 res = chmod(testfile, mode);
975 if (res == -1) {
976 PERROR("chmod");
977 return -1;
980 res = check_mode(testfile, mode);
981 if (res == -1)
982 return -1;
984 fd = open(testfile, flags);
985 if (fd == -1) {
986 if (err != errno) {
987 PERROR("open");
988 return -1;
990 } else {
991 if (err) {
992 ERROR("open should have failed");
993 close(fd);
994 return -1;
996 close(fd);
998 success();
999 return 0;
1002 static int test_symlink(void)
1004 char buf[1024];
1005 const char *data = testdata;
1006 int datalen = testdatalen;
1007 int linklen = strlen(testfile);
1008 int err = 0;
1009 int res;
1011 start_test("symlink");
1012 res = create_file(testfile, data, datalen);
1013 if (res == -1)
1014 return -1;
1016 unlink(testfile2);
1017 res = symlink(testfile, testfile2);
1018 if (res == -1) {
1019 PERROR("symlink");
1020 return -1;
1022 res = check_type(testfile2, S_IFLNK);
1023 if (res == -1)
1024 return -1;
1025 err += check_mode(testfile2, 0777);
1026 err += check_nlink(testfile2, 1);
1027 res = readlink(testfile2, buf, sizeof(buf));
1028 if (res == -1) {
1029 PERROR("readlink");
1030 err--;
1032 if (res != linklen) {
1033 ERROR("short readlink: %u instead of %u", res, linklen);
1034 err--;
1036 if (memcmp(buf, testfile, linklen) != 0) {
1037 ERROR("link mismatch");
1038 err--;
1040 err += check_size(testfile2, datalen);
1041 err += check_data(testfile2, data, 0, datalen);
1042 res = unlink(testfile2);
1043 if (res == -1) {
1044 PERROR("unlink");
1045 return -1;
1047 res = check_nonexist(testfile2);
1048 if (res == -1)
1049 return -1;
1050 if (err)
1051 return -1;
1053 success();
1054 return 0;
1057 static int test_link(void)
1059 const char *data = testdata;
1060 int datalen = testdatalen;
1061 int err = 0;
1062 int res;
1064 start_test("link");
1065 res = create_file(testfile, data, datalen);
1066 if (res == -1)
1067 return -1;
1069 unlink(testfile2);
1070 res = link(testfile, testfile2);
1071 if (res == -1) {
1072 PERROR("link");
1073 return -1;
1075 res = check_type(testfile2, S_IFREG);
1076 if (res == -1)
1077 return -1;
1078 err += check_mode(testfile2, 0644);
1079 err += check_nlink(testfile2, 2);
1080 err += check_size(testfile2, datalen);
1081 err += check_data(testfile2, data, 0, datalen);
1082 res = unlink(testfile);
1083 if (res == -1) {
1084 PERROR("unlink");
1085 return -1;
1087 res = check_nonexist(testfile);
1088 if (res == -1)
1089 return -1;
1091 err += check_nlink(testfile2, 1);
1092 res = unlink(testfile2);
1093 if (res == -1) {
1094 PERROR("unlink");
1095 return -1;
1097 res = check_nonexist(testfile2);
1098 if (res == -1)
1099 return -1;
1100 if (err)
1101 return -1;
1103 success();
1104 return 0;
1107 static int test_rename_file(void)
1109 const char *data = testdata;
1110 int datalen = testdatalen;
1111 int err = 0;
1112 int res;
1114 start_test("rename file");
1115 res = create_file(testfile, data, datalen);
1116 if (res == -1)
1117 return -1;
1119 unlink(testfile2);
1120 res = rename(testfile, testfile2);
1121 if (res == -1) {
1122 PERROR("rename");
1123 return -1;
1125 res = check_nonexist(testfile);
1126 if (res == -1)
1127 return -1;
1128 res = check_type(testfile2, S_IFREG);
1129 if (res == -1)
1130 return -1;
1131 err += check_mode(testfile2, 0644);
1132 err += check_nlink(testfile2, 1);
1133 err += check_size(testfile2, datalen);
1134 err += check_data(testfile2, data, 0, datalen);
1135 res = unlink(testfile2);
1136 if (res == -1) {
1137 PERROR("unlink");
1138 return -1;
1140 res = check_nonexist(testfile2);
1141 if (res == -1)
1142 return -1;
1143 if (err)
1144 return -1;
1146 success();
1147 return 0;
1150 static int test_rename_dir(void)
1152 int err = 0;
1153 int res;
1155 start_test("rename dir");
1156 res = create_dir(testdir, testdir_files);
1157 if (res == -1)
1158 return -1;
1160 rmdir(testdir2);
1161 res = rename(testdir, testdir2);
1162 if (res == -1) {
1163 PERROR("rename");
1164 cleanup_dir(testdir, testdir_files, 1);
1165 return -1;
1167 res = check_nonexist(testdir);
1168 if (res == -1) {
1169 cleanup_dir(testdir, testdir_files, 1);
1170 return -1;
1172 res = check_type(testdir2, S_IFDIR);
1173 if (res == -1) {
1174 cleanup_dir(testdir2, testdir_files, 1);
1175 return -1;
1177 err += check_mode(testdir2, 0755);
1178 err += check_dir_contents(testdir2, testdir_files);
1179 err += cleanup_dir(testdir2, testdir_files, 0);
1180 res = rmdir(testdir2);
1181 if (res == -1) {
1182 PERROR("rmdir");
1183 return -1;
1185 res = check_nonexist(testdir2);
1186 if (res == -1)
1187 return -1;
1188 if (err)
1189 return -1;
1191 success();
1192 return 0;
1195 static int test_mkfifo(void)
1197 int res;
1198 int err = 0;
1200 start_test("mkfifo");
1201 unlink(testfile);
1202 res = mkfifo(testfile, 0644);
1203 if (res == -1) {
1204 PERROR("mkfifo");
1205 return -1;
1207 res = check_type(testfile, S_IFIFO);
1208 if (res == -1)
1209 return -1;
1210 err += check_mode(testfile, 0644);
1211 err += check_nlink(testfile, 1);
1212 res = unlink(testfile);
1213 if (res == -1) {
1214 PERROR("unlink");
1215 return -1;
1217 res = check_nonexist(testfile);
1218 if (res == -1)
1219 return -1;
1220 if (err)
1221 return -1;
1223 success();
1224 return 0;
1227 static int test_mkdir(void)
1229 int res;
1230 int err = 0;
1231 const char *dir_contents[] = {NULL};
1233 start_test("mkdir");
1234 rmdir(testdir);
1235 res = mkdir(testdir, 0755);
1236 if (res == -1) {
1237 PERROR("mkdir");
1238 return -1;
1240 res = check_type(testdir, S_IFDIR);
1241 if (res == -1)
1242 return -1;
1243 err += check_mode(testdir, 0755);
1244 err += check_nlink(testdir, 2);
1245 err += check_dir_contents(testdir, dir_contents);
1246 res = rmdir(testdir);
1247 if (res == -1) {
1248 PERROR("rmdir");
1249 return -1;
1251 res = check_nonexist(testdir);
1252 if (res == -1)
1253 return -1;
1254 if (err)
1255 return -1;
1257 success();
1258 return 0;
1261 int main(int argc, char *argv[])
1263 const char *basepath;
1264 int err = 0;
1266 umask(0);
1267 if (argc != 2) {
1268 fprintf(stderr, "usage: %s testdir\n", argv[0]);
1269 return 1;
1271 basepath = argv[1];
1272 assert(strlen(basepath) < 512);
1273 if (basepath[0] != '/') {
1274 fprintf(stderr, "testdir must be an absolute path\n");
1275 return 1;
1278 sprintf(testfile, "%s/testfile", basepath);
1279 sprintf(testfile2, "%s/testfile2", basepath);
1280 sprintf(testdir, "%s/testdir", basepath);
1281 sprintf(testdir2, "%s/testdir2", basepath);
1282 err += test_create();
1283 err += test_create_unlink();
1284 err += test_mknod();
1285 err += test_symlink();
1286 err += test_link();
1287 err += test_mkfifo();
1288 err += test_mkdir();
1289 err += test_rename_file();
1290 err += test_rename_dir();
1291 err += test_utime();
1292 err += test_truncate(0);
1293 err += test_truncate(testdatalen / 2);
1294 err += test_truncate(testdatalen);
1295 err += test_truncate(testdatalen + 100);
1296 err += test_ftruncate(0, 0600);
1297 err += test_ftruncate(testdatalen / 2, 0600);
1298 err += test_ftruncate(testdatalen, 0600);
1299 err += test_ftruncate(testdatalen + 100, 0600);
1300 err += test_ftruncate(0, 0400);
1301 err += test_ftruncate(0, 0200);
1302 err += test_ftruncate(0, 0000);
1303 err += test_open(0, O_RDONLY, 0);
1304 err += test_open(1, O_RDONLY, 0);
1305 err += test_open(1, O_RDWR, 0);
1306 err += test_open(1, O_WRONLY, 0);
1307 err += test_open(0, O_RDWR | O_CREAT, 0600);
1308 err += test_open(1, O_RDWR | O_CREAT, 0600);
1309 err += test_open(0, O_RDWR | O_CREAT | O_TRUNC, 0600);
1310 err += test_open(1, O_RDWR | O_CREAT | O_TRUNC, 0600);
1311 err += test_open(0, O_RDONLY | O_CREAT, 0600);
1312 err += test_open(0, O_RDONLY | O_CREAT, 0400);
1313 err += test_open(0, O_RDONLY | O_CREAT, 0200);
1314 err += test_open(0, O_RDONLY | O_CREAT, 0000);
1315 err += test_open(0, O_WRONLY | O_CREAT, 0600);
1316 err += test_open(0, O_WRONLY | O_CREAT, 0400);
1317 err += test_open(0, O_WRONLY | O_CREAT, 0200);
1318 err += test_open(0, O_WRONLY | O_CREAT, 0000);
1319 err += test_open(0, O_RDWR | O_CREAT, 0400);
1320 err += test_open(0, O_RDWR | O_CREAT, 0200);
1321 err += test_open(0, O_RDWR | O_CREAT, 0000);
1322 err += test_open(0, O_RDWR | O_CREAT | O_EXCL, 0600);
1323 err += test_open(1, O_RDWR | O_CREAT | O_EXCL, 0600);
1324 err += test_open(0, O_RDWR | O_CREAT | O_EXCL, 0000);
1325 err += test_open(1, O_RDWR | O_CREAT | O_EXCL, 0000);
1326 err += test_open_acc(O_RDONLY, 0600, 0);
1327 err += test_open_acc(O_WRONLY, 0600, 0);
1328 err += test_open_acc(O_RDWR, 0600, 0);
1329 err += test_open_acc(O_RDONLY, 0400, 0);
1330 err += test_open_acc(O_RDONLY | O_TRUNC, 0400, EACCES);
1331 err += test_open_acc(O_WRONLY, 0400, EACCES);
1332 err += test_open_acc(O_RDWR, 0400, EACCES);
1333 err += test_open_acc(O_RDONLY, 0200, EACCES);
1334 err += test_open_acc(O_WRONLY, 0200, 0);
1335 err += test_open_acc(O_RDWR, 0200, EACCES);
1336 err += test_open_acc(O_RDONLY, 0000, EACCES);
1337 err += test_open_acc(O_WRONLY, 0000, EACCES);
1338 err += test_open_acc(O_RDWR, 0000, EACCES);
1340 unlink(testfile);
1341 unlink(testfile2);
1342 rmdir(testdir);
1343 rmdir(testdir2);
1345 if (err) {
1346 fprintf(stderr, "%i tests failed\n", -err);
1347 return 1;
1350 return 0;