libfuse: remove deprecated fuse_read_cmd(), fuse_process_cmd()
[fuse.git] / test / test.c
blobc421cda923414b65e7ced933e1ccfbffc0a308ba
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>
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 static char testname[256];
21 static char testdata[] = "abcdefghijklmnopqrstuvwxyz";
22 static char testdata2[] = "1234567890-=qwertyuiop[]\asdfghjkl;'zxcvbnm,./";
23 static const char *testdir_files[] = { "f1", "f2", NULL};
24 static char zerodata[4096];
25 static int testdatalen = sizeof(testdata) - 1;
26 static int testdata2len = sizeof(testdata2) - 1;
27 static unsigned int testnum = 1;
28 static unsigned int select_test = 0;
29 static unsigned int skip_test = 0;
31 #define MAX_ENTRIES 1024
33 static void test_perror(const char *func, const char *msg)
35 fprintf(stderr, "%s %s() - %s: %s\n", testname, func, msg,
36 strerror(errno));
39 static void test_error(const char *func, const char *msg, ...)
40 __attribute__ ((format (printf, 2, 3)));
42 static void __start_test(const char *fmt, ...)
43 __attribute__ ((format (printf, 1, 2)));
45 static void test_error(const char *func, const char *msg, ...)
47 va_list ap;
48 fprintf(stderr, "%s %s() - ", testname, func);
49 va_start(ap, msg);
50 vfprintf(stderr, msg, ap);
51 va_end(ap);
52 fprintf(stderr, "\n");
55 static void success(void)
57 fprintf(stderr, "%s OK\n", testname);
60 static void __start_test(const char *fmt, ...)
62 unsigned int n;
63 va_list ap;
64 n = sprintf(testname, "%3i [", testnum++);
65 va_start(ap, fmt);
66 n += vsprintf(testname + n, fmt, ap);
67 va_end(ap);
68 sprintf(testname + n, "]");
71 #define start_test(msg, args...) { \
72 if ((select_test && testnum != select_test) || \
73 (testnum == skip_test)) { \
74 testnum++; \
75 return 0; \
76 } \
77 __start_test(msg, ##args); \
80 #define PERROR(msg) test_perror(__FUNCTION__, msg)
81 #define ERROR(msg, args...) test_error(__FUNCTION__, msg, ##args)
83 static int check_size(const char *path, int len)
85 struct stat stbuf;
86 int res = stat(path, &stbuf);
87 if (res == -1) {
88 PERROR("stat");
89 return -1;
91 if (stbuf.st_size != len) {
92 ERROR("length %u instead of %u", (int) stbuf.st_size,
93 (int) len);
94 return -1;
96 return 0;
99 static int fcheck_size(int fd, int len)
101 struct stat stbuf;
102 int res = fstat(fd, &stbuf);
103 if (res == -1) {
104 PERROR("fstat");
105 return -1;
107 if (stbuf.st_size != len) {
108 ERROR("length %u instead of %u", (int) stbuf.st_size,
109 (int) len);
110 return -1;
112 return 0;
115 static int check_type(const char *path, mode_t type)
117 struct stat stbuf;
118 int res = lstat(path, &stbuf);
119 if (res == -1) {
120 PERROR("lstat");
121 return -1;
123 if ((stbuf.st_mode & S_IFMT) != type) {
124 ERROR("type 0%o instead of 0%o", stbuf.st_mode & S_IFMT, type);
125 return -1;
127 return 0;
130 static int fcheck_type(int fd, mode_t type)
132 struct stat stbuf;
133 int res = fstat(fd, &stbuf);
134 if (res == -1) {
135 PERROR("fstat");
136 return -1;
138 if ((stbuf.st_mode & S_IFMT) != type) {
139 ERROR("type 0%o instead of 0%o", stbuf.st_mode & S_IFMT, type);
140 return -1;
142 return 0;
145 static int check_mode(const char *path, mode_t mode)
147 struct stat stbuf;
148 int res = lstat(path, &stbuf);
149 if (res == -1) {
150 PERROR("lstat");
151 return -1;
153 if ((stbuf.st_mode & 07777) != mode) {
154 ERROR("mode 0%o instead of 0%o", stbuf.st_mode & 07777, mode);
155 return -1;
157 return 0;
160 static int fcheck_mode(int fd, mode_t mode)
162 struct stat stbuf;
163 int res = fstat(fd, &stbuf);
164 if (res == -1) {
165 PERROR("fstat");
166 return -1;
168 if ((stbuf.st_mode & 07777) != mode) {
169 ERROR("mode 0%o instead of 0%o", stbuf.st_mode & 07777, mode);
170 return -1;
172 return 0;
175 static int check_times(const char *path, time_t atime, time_t mtime)
177 int err = 0;
178 struct stat stbuf;
179 int res = lstat(path, &stbuf);
180 if (res == -1) {
181 PERROR("lstat");
182 return -1;
184 if (stbuf.st_atime != atime) {
185 ERROR("atime %li instead of %li", stbuf.st_atime, atime);
186 err--;
188 if (stbuf.st_mtime != mtime) {
189 ERROR("mtime %li instead of %li", stbuf.st_mtime, mtime);
190 err--;
192 if (err)
193 return -1;
195 return 0;
198 #if 0
199 static int fcheck_times(int fd, time_t atime, time_t mtime)
201 int err = 0;
202 struct stat stbuf;
203 int res = fstat(fd, &stbuf);
204 if (res == -1) {
205 PERROR("fstat");
206 return -1;
208 if (stbuf.st_atime != atime) {
209 ERROR("atime %li instead of %li", stbuf.st_atime, atime);
210 err--;
212 if (stbuf.st_mtime != mtime) {
213 ERROR("mtime %li instead of %li", stbuf.st_mtime, mtime);
214 err--;
216 if (err)
217 return -1;
219 return 0;
221 #endif
223 static int check_nlink(const char *path, nlink_t nlink)
225 struct stat stbuf;
226 int res = lstat(path, &stbuf);
227 if (res == -1) {
228 PERROR("lstat");
229 return -1;
231 if (stbuf.st_nlink != nlink) {
232 ERROR("nlink %li instead of %li", (long) stbuf.st_nlink,
233 (long) nlink);
234 return -1;
236 return 0;
239 static int fcheck_nlink(int fd, nlink_t nlink)
241 struct stat stbuf;
242 int res = fstat(fd, &stbuf);
243 if (res == -1) {
244 PERROR("fstat");
245 return -1;
247 if (stbuf.st_nlink != nlink) {
248 ERROR("nlink %li instead of %li", (long) stbuf.st_nlink,
249 (long) nlink);
250 return -1;
252 return 0;
255 static int check_nonexist(const char *path)
257 struct stat stbuf;
258 int res = lstat(path, &stbuf);
259 if (res == 0) {
260 ERROR("file should not exist");
261 return -1;
263 if (errno != ENOENT) {
264 ERROR("file should not exist: %s", strerror(errno));
265 return -1;
267 return 0;
270 static int check_buffer(const char *buf, const char *data, unsigned len)
272 if (memcmp(buf, data, len) != 0) {
273 ERROR("data mismatch");
274 return -1;
276 return 0;
279 static int check_data(const char *path, const char *data, int offset,
280 unsigned len)
282 char buf[4096];
283 int res;
284 int fd = open(path, O_RDONLY);
285 if (fd == -1) {
286 PERROR("open");
287 return -1;
289 if (lseek(fd, offset, SEEK_SET) == (off_t) -1) {
290 PERROR("lseek");
291 close(fd);
292 return -1;
294 while (len) {
295 int rdlen = len < sizeof(buf) ? len : sizeof(buf);
296 res = read(fd, buf, rdlen);
297 if (res == -1) {
298 PERROR("read");
299 close(fd);
300 return -1;
302 if (res != rdlen) {
303 ERROR("short read: %u instead of %u", res, rdlen);
304 close(fd);
305 return -1;
307 if (check_buffer(buf, data, rdlen) != 0) {
308 close(fd);
309 return -1;
311 data += rdlen;
312 len -= rdlen;
314 res = close(fd);
315 if (res == -1) {
316 PERROR("close");
317 return -1;
319 return 0;
322 static int fcheck_data(int fd, const char *data, int offset,
323 unsigned len)
325 char buf[4096];
326 int res;
327 if (lseek(fd, offset, SEEK_SET) == (off_t) -1) {
328 PERROR("lseek");
329 return -1;
331 while (len) {
332 int rdlen = len < sizeof(buf) ? len : sizeof(buf);
333 res = read(fd, buf, rdlen);
334 if (res == -1) {
335 PERROR("read");
336 return -1;
338 if (res != rdlen) {
339 ERROR("short read: %u instead of %u", res, rdlen);
340 return -1;
342 if (check_buffer(buf, data, rdlen) != 0) {
343 return -1;
345 data += rdlen;
346 len -= rdlen;
348 return 0;
351 static int check_dir_contents(const char *path, const char **contents)
353 int i;
354 int res;
355 int err = 0;
356 int found[MAX_ENTRIES];
357 const char *cont[MAX_ENTRIES];
358 DIR *dp;
360 for (i = 0; contents[i]; i++) {
361 assert(i < MAX_ENTRIES - 3);
362 found[i] = 0;
363 cont[i] = contents[i];
365 found[i] = 0;
366 cont[i++] = ".";
367 found[i] = 0;
368 cont[i++] = "..";
369 cont[i] = NULL;
371 dp = opendir(path);
372 if (dp == NULL) {
373 PERROR("opendir");
374 return -1;
376 memset(found, 0, sizeof(found));
377 while(1) {
378 struct dirent *de;
379 errno = 0;
380 de = readdir(dp);
381 if (de == NULL) {
382 if (errno) {
383 PERROR("readdir");
384 closedir(dp);
385 return -1;
387 break;
389 for (i = 0; cont[i] != NULL; i++) {
390 assert(i < MAX_ENTRIES);
391 if (strcmp(cont[i], de->d_name) == 0) {
392 if (found[i]) {
393 ERROR("duplicate entry <%s>",
394 de->d_name);
395 err--;
396 } else
397 found[i] = 1;
398 break;
401 if (!cont[i]) {
402 ERROR("unexpected entry <%s>", de->d_name);
403 err --;
406 for (i = 0; cont[i] != NULL; i++) {
407 if (!found[i]) {
408 ERROR("missing entry <%s>", cont[i]);
409 err--;
412 res = closedir(dp);
413 if (res == -1) {
414 PERROR("closedir");
415 return -1;
417 if (err)
418 return -1;
420 return 0;
423 static int create_file(const char *path, const char *data, int len)
425 int res;
426 int fd;
428 unlink(path);
429 fd = creat(path, 0644);
430 if (fd == -1) {
431 PERROR("creat");
432 return -1;
434 if (len) {
435 res = write(fd, data, len);
436 if (res == -1) {
437 PERROR("write");
438 close(fd);
439 return -1;
441 if (res != len) {
442 ERROR("write is short: %u instead of %u", res, len);
443 close(fd);
444 return -1;
447 res = close(fd);
448 if (res == -1) {
449 PERROR("close");
450 return -1;
452 res = check_type(path, S_IFREG);
453 if (res == -1)
454 return -1;
455 res = check_mode(path, 0644);
456 if (res == -1)
457 return -1;
458 res = check_nlink(path, 1);
459 if (res == -1)
460 return -1;
461 res = check_size(path, len);
462 if (res == -1)
463 return -1;
465 if (len) {
466 res = check_data(path, data, 0, len);
467 if (res == -1)
468 return -1;
471 return 0;
474 static int cleanup_dir(const char *path, const char **dir_files, int quiet)
476 int i;
477 int err = 0;
479 for (i = 0; dir_files[i]; i++) {
480 int res;
481 char fpath[1024];
482 sprintf(fpath, "%s/%s", path, dir_files[i]);
483 res = unlink(fpath);
484 if (res == -1 && !quiet) {
485 PERROR("unlink");
486 err --;
489 if (err)
490 return -1;
492 return 0;
495 static int create_dir(const char *path, const char **dir_files)
497 int res;
498 int i;
500 rmdir(path);
501 res = mkdir(path, 0755);
502 if (res == -1) {
503 PERROR("mkdir");
504 return -1;
506 res = check_type(path, S_IFDIR);
507 if (res == -1)
508 return -1;
509 res = check_mode(path, 0755);
510 if (res == -1)
511 return -1;
513 for (i = 0; dir_files[i]; i++) {
514 char fpath[1024];
515 sprintf(fpath, "%s/%s", path, dir_files[i]);
516 res = create_file(fpath, "", 0);
517 if (res == -1) {
518 cleanup_dir(path, dir_files, 1);
519 return -1;
522 res = check_dir_contents(path, dir_files);
523 if (res == -1) {
524 cleanup_dir(path, dir_files, 1);
525 return -1;
528 return 0;
531 static int test_truncate(int len)
533 const char *data = testdata;
534 int datalen = testdatalen;
535 int res;
537 start_test("truncate(%u)", (int) len);
538 res = create_file(testfile, data, datalen);
539 if (res == -1)
540 return -1;
542 res = truncate(testfile, len);
543 if (res == -1) {
544 PERROR("truncate");
545 return -1;
547 res = check_size(testfile, len);
548 if (res == -1)
549 return -1;
551 if (len > 0) {
552 if (len <= datalen) {
553 res = check_data(testfile, data, 0, len);
554 if (res == -1)
555 return -1;
556 } else {
557 res = check_data(testfile, data, 0, datalen);
558 if (res == -1)
559 return -1;
560 res = check_data(testfile, zerodata, datalen,
561 len - datalen);
562 if (res == -1)
563 return -1;
566 res = unlink(testfile);
567 if (res == -1) {
568 PERROR("unlink");
569 return -1;
571 res = check_nonexist(testfile);
572 if (res == -1)
573 return -1;
575 success();
576 return 0;
579 static int test_ftruncate(int len, int mode)
581 const char *data = testdata;
582 int datalen = testdatalen;
583 int res;
584 int fd;
586 start_test("ftruncate(%u) mode: 0%03o", len, mode);
587 res = create_file(testfile, data, datalen);
588 if (res == -1)
589 return -1;
591 fd = open(testfile, O_WRONLY);
592 if (fd == -1) {
593 PERROR("open");
594 return -1;
597 res = fchmod(fd, mode);
598 if (res == -1) {
599 PERROR("fchmod");
600 close(fd);
601 return -1;
603 res = check_mode(testfile, mode);
604 if (res == -1) {
605 close(fd);
606 return -1;
608 res = ftruncate(fd, len);
609 if (res == -1) {
610 PERROR("ftruncate");
611 close(fd);
612 return -1;
614 close(fd);
615 res = check_size(testfile, len);
616 if (res == -1)
617 return -1;
619 if (len > 0) {
620 if (len <= datalen) {
621 res = check_data(testfile, data, 0, len);
622 if (res == -1)
623 return -1;
624 } else {
625 res = check_data(testfile, data, 0, datalen);
626 if (res == -1)
627 return -1;
628 res = check_data(testfile, zerodata, datalen,
629 len - datalen);
630 if (res == -1)
631 return -1;
634 res = unlink(testfile);
635 if (res == -1) {
636 PERROR("unlink");
637 return -1;
639 res = check_nonexist(testfile);
640 if (res == -1)
641 return -1;
643 success();
644 return 0;
647 static int test_utime(void)
649 struct utimbuf utm;
650 time_t atime = 987631200;
651 time_t mtime = 123116400;
652 int res;
654 start_test("utime");
655 res = create_file(testfile, NULL, 0);
656 if (res == -1)
657 return -1;
659 utm.actime = atime;
660 utm.modtime = mtime;
661 res = utime(testfile, &utm);
662 if (res == -1) {
663 PERROR("utime");
664 return -1;
666 res = check_times(testfile, atime, mtime);
667 if (res == -1) {
668 return -1;
670 res = unlink(testfile);
671 if (res == -1) {
672 PERROR("unlink");
673 return -1;
675 res = check_nonexist(testfile);
676 if (res == -1)
677 return -1;
679 success();
680 return 0;
683 static int test_create(void)
685 const char *data = testdata;
686 int datalen = testdatalen;
687 int err = 0;
688 int res;
689 int fd;
691 start_test("create");
692 unlink(testfile);
693 fd = creat(testfile, 0644);
694 if (fd == -1) {
695 PERROR("creat");
696 return -1;
698 res = write(fd, data, datalen);
699 if (res == -1) {
700 PERROR("write");
701 close(fd);
702 return -1;
704 if (res != datalen) {
705 ERROR("write is short: %u instead of %u", res, datalen);
706 close(fd);
707 return -1;
709 res = close(fd);
710 if (res == -1) {
711 PERROR("close");
712 return -1;
714 res = check_type(testfile, S_IFREG);
715 if (res == -1)
716 return -1;
717 err += check_mode(testfile, 0644);
718 err += check_nlink(testfile, 1);
719 err += check_size(testfile, datalen);
720 err += check_data(testfile, data, 0, datalen);
721 res = unlink(testfile);
722 if (res == -1) {
723 PERROR("unlink");
724 return -1;
726 res = check_nonexist(testfile);
727 if (res == -1)
728 return -1;
729 if (err)
730 return -1;
732 success();
733 return 0;
736 static int test_create_unlink(void)
738 const char *data = testdata;
739 int datalen = testdatalen;
740 int err = 0;
741 int res;
742 int fd;
744 start_test("create+unlink");
745 unlink(testfile);
746 fd = open(testfile, O_CREAT | O_RDWR | O_TRUNC, 0644);
747 if (fd == -1) {
748 PERROR("creat");
749 return -1;
751 res = unlink(testfile);
752 if (res == -1) {
753 PERROR("unlink");
754 close(fd);
755 return -1;
757 res = check_nonexist(testfile);
758 if (res == -1)
759 return -1;
760 res = write(fd, data, datalen);
761 if (res == -1) {
762 PERROR("write");
763 close(fd);
764 return -1;
766 if (res != datalen) {
767 ERROR("write is short: %u instead of %u", res, datalen);
768 close(fd);
769 return -1;
771 err += fcheck_type(fd, S_IFREG);
772 err += fcheck_mode(fd, 0644);
773 err += fcheck_nlink(fd, 0);
774 err += fcheck_size(fd, datalen);
775 err += fcheck_data(fd, data, 0, datalen);
776 res = close(fd);
777 if (res == -1) {
778 PERROR("close");
779 err--;
781 if (err)
782 return -1;
784 success();
785 return 0;
788 static int test_mknod(void)
790 int err = 0;
791 int res;
793 start_test("mknod");
794 unlink(testfile);
795 res = mknod(testfile, 0644, 0);
796 if (res == -1) {
797 PERROR("mknod");
798 return -1;
800 res = check_type(testfile, S_IFREG);
801 if (res == -1)
802 return -1;
803 err += check_mode(testfile, 0644);
804 err += check_nlink(testfile, 1);
805 err += check_size(testfile, 0);
806 res = unlink(testfile);
807 if (res == -1) {
808 PERROR("unlink");
809 return -1;
811 res = check_nonexist(testfile);
812 if (res == -1)
813 return -1;
814 if (err)
815 return -1;
817 success();
818 return 0;
821 #define test_open(exist, flags, mode) do_test_open(exist, flags, #flags, mode)
823 static int do_test_open(int exist, int flags, const char *flags_str, int mode)
825 char buf[4096];
826 const char *data = testdata;
827 int datalen = testdatalen;
828 unsigned currlen = 0;
829 int err = 0;
830 int res;
831 int fd;
832 off_t off;
834 start_test("open(%s, %s, 0%03o)", exist ? "+" : "-", flags_str, mode);
835 unlink(testfile);
836 if (exist) {
837 res = create_file(testfile, testdata2, testdata2len);
838 if (res == -1)
839 return -1;
841 currlen = testdata2len;
844 fd = open(testfile, flags, mode);
845 if ((flags & O_CREAT) && (flags & O_EXCL) && exist) {
846 if (fd != -1) {
847 ERROR("open should have failed");
848 close(fd);
849 return -1;
850 } else if (errno == EEXIST)
851 goto succ;
853 if (!(flags & O_CREAT) && !exist) {
854 if (fd != -1) {
855 ERROR("open should have failed");
856 close(fd);
857 return -1;
858 } else if (errno == ENOENT)
859 goto succ;
861 if (fd == -1) {
862 PERROR("open");
863 return -1;
866 if (flags & O_TRUNC)
867 currlen = 0;
869 err += check_type(testfile, S_IFREG);
870 if (exist)
871 err += check_mode(testfile, 0644);
872 else
873 err += check_mode(testfile, mode);
874 err += check_nlink(testfile, 1);
875 err += check_size(testfile, currlen);
876 if (exist && !(flags & O_TRUNC) && (mode & 0400))
877 err += check_data(testfile, testdata2, 0, testdata2len);
879 res = write(fd, data, datalen);
880 if ((flags & O_ACCMODE) != O_RDONLY) {
881 if (res == -1) {
882 PERROR("write");
883 err --;
884 } else if (res != datalen) {
885 ERROR("write is short: %u instead of %u", res, datalen);
886 err --;
887 } else {
888 if (datalen > (int) currlen)
889 currlen = datalen;
891 err += check_size(testfile, currlen);
893 if (mode & 0400) {
894 err += check_data(testfile, data, 0, datalen);
895 if (exist && !(flags & O_TRUNC) &&
896 testdata2len > datalen)
897 err += check_data(testfile,
898 testdata2 + datalen,
899 datalen,
900 testdata2len - datalen);
903 } else {
904 if (res != -1) {
905 ERROR("write should have failed");
906 err --;
907 } else if (errno != EBADF) {
908 PERROR("write");
909 err --;
912 off = lseek(fd, SEEK_SET, 0);
913 if (off == (off_t) -1) {
914 PERROR("lseek");
915 err--;
916 } else if (off != 0) {
917 ERROR("offset should have returned 0");
918 err --;
920 res = read(fd, buf, sizeof(buf));
921 if ((flags & O_ACCMODE) != O_WRONLY) {
922 if (res == -1) {
923 PERROR("read");
924 err--;
925 } else {
926 int readsize =
927 currlen < sizeof(buf) ? currlen : sizeof(buf);
928 if (res != readsize) {
929 ERROR("read is short: %i instead of %u",
930 res, readsize);
931 err--;
932 } else {
933 if ((flags & O_ACCMODE) != O_RDONLY) {
934 err += check_buffer(buf, data, datalen);
935 if (exist && !(flags & O_TRUNC) &&
936 testdata2len > datalen)
937 err += check_buffer(buf + datalen,
938 testdata2 + datalen,
939 testdata2len - datalen);
940 } else if (exist)
941 err += check_buffer(buf, testdata2,
942 testdata2len);
945 } else {
946 if (res != -1) {
947 ERROR("read should have failed");
948 err --;
949 } else if (errno != EBADF) {
950 PERROR("read");
951 err --;
955 res = close(fd);
956 if (res == -1) {
957 PERROR("close");
958 return -1;
960 res = unlink(testfile);
961 if (res == -1) {
962 PERROR("unlink");
963 return -1;
965 res = check_nonexist(testfile);
966 if (res == -1)
967 return -1;
968 if (err)
969 return -1;
971 succ:
972 success();
973 return 0;
976 #define test_open_acc(flags, mode, err) \
977 do_test_open_acc(flags, #flags, mode, err)
979 static int do_test_open_acc(int flags, const char *flags_str, int mode, int err)
981 const char *data = testdata;
982 int datalen = testdatalen;
983 int res;
984 int fd;
986 start_test("open_acc(%s) mode: 0%03o error: '%s'", flags_str, mode,
987 strerror(err));
988 unlink(testfile);
989 res = create_file(testfile, data, datalen);
990 if (res == -1)
991 return -1;
993 res = chmod(testfile, mode);
994 if (res == -1) {
995 PERROR("chmod");
996 return -1;
999 res = check_mode(testfile, mode);
1000 if (res == -1)
1001 return -1;
1003 fd = open(testfile, flags);
1004 if (fd == -1) {
1005 if (err != errno) {
1006 PERROR("open");
1007 return -1;
1009 } else {
1010 if (err) {
1011 ERROR("open should have failed");
1012 close(fd);
1013 return -1;
1015 close(fd);
1017 success();
1018 return 0;
1021 static int test_symlink(void)
1023 char buf[1024];
1024 const char *data = testdata;
1025 int datalen = testdatalen;
1026 int linklen = strlen(testfile);
1027 int err = 0;
1028 int res;
1030 start_test("symlink");
1031 res = create_file(testfile, data, datalen);
1032 if (res == -1)
1033 return -1;
1035 unlink(testfile2);
1036 res = symlink(testfile, testfile2);
1037 if (res == -1) {
1038 PERROR("symlink");
1039 return -1;
1041 res = check_type(testfile2, S_IFLNK);
1042 if (res == -1)
1043 return -1;
1044 err += check_mode(testfile2, 0777);
1045 err += check_nlink(testfile2, 1);
1046 res = readlink(testfile2, buf, sizeof(buf));
1047 if (res == -1) {
1048 PERROR("readlink");
1049 err--;
1051 if (res != linklen) {
1052 ERROR("short readlink: %u instead of %u", res, linklen);
1053 err--;
1055 if (memcmp(buf, testfile, linklen) != 0) {
1056 ERROR("link mismatch");
1057 err--;
1059 err += check_size(testfile2, datalen);
1060 err += check_data(testfile2, data, 0, datalen);
1061 res = unlink(testfile2);
1062 if (res == -1) {
1063 PERROR("unlink");
1064 return -1;
1066 res = check_nonexist(testfile2);
1067 if (res == -1)
1068 return -1;
1069 if (err)
1070 return -1;
1072 success();
1073 return 0;
1076 static int test_link(void)
1078 const char *data = testdata;
1079 int datalen = testdatalen;
1080 int err = 0;
1081 int res;
1083 start_test("link");
1084 res = create_file(testfile, data, datalen);
1085 if (res == -1)
1086 return -1;
1088 unlink(testfile2);
1089 res = link(testfile, testfile2);
1090 if (res == -1) {
1091 PERROR("link");
1092 return -1;
1094 res = check_type(testfile2, S_IFREG);
1095 if (res == -1)
1096 return -1;
1097 err += check_mode(testfile2, 0644);
1098 err += check_nlink(testfile2, 2);
1099 err += check_size(testfile2, datalen);
1100 err += check_data(testfile2, data, 0, datalen);
1101 res = unlink(testfile);
1102 if (res == -1) {
1103 PERROR("unlink");
1104 return -1;
1106 res = check_nonexist(testfile);
1107 if (res == -1)
1108 return -1;
1110 err += check_nlink(testfile2, 1);
1111 res = unlink(testfile2);
1112 if (res == -1) {
1113 PERROR("unlink");
1114 return -1;
1116 res = check_nonexist(testfile2);
1117 if (res == -1)
1118 return -1;
1119 if (err)
1120 return -1;
1122 success();
1123 return 0;
1126 static int test_link2(void)
1128 const char *data = testdata;
1129 int datalen = testdatalen;
1130 int err = 0;
1131 int res;
1133 start_test("link-unlink-link");
1134 res = create_file(testfile, data, datalen);
1135 if (res == -1)
1136 return -1;
1138 unlink(testfile2);
1139 res = link(testfile, testfile2);
1140 if (res == -1) {
1141 PERROR("link");
1142 return -1;
1144 res = unlink(testfile);
1145 if (res == -1) {
1146 PERROR("unlink");
1147 return -1;
1149 res = check_nonexist(testfile);
1150 if (res == -1)
1151 return -1;
1152 res = link(testfile2, testfile);
1153 if (res == -1) {
1154 PERROR("link");
1156 res = check_type(testfile, S_IFREG);
1157 if (res == -1)
1158 return -1;
1159 err += check_mode(testfile, 0644);
1160 err += check_nlink(testfile, 2);
1161 err += check_size(testfile, datalen);
1162 err += check_data(testfile, data, 0, datalen);
1164 res = unlink(testfile2);
1165 if (res == -1) {
1166 PERROR("unlink");
1167 return -1;
1169 err += check_nlink(testfile, 1);
1170 res = unlink(testfile);
1171 if (res == -1) {
1172 PERROR("unlink");
1173 return -1;
1175 res = check_nonexist(testfile);
1176 if (res == -1)
1177 return -1;
1178 if (err)
1179 return -1;
1181 success();
1182 return 0;
1185 static int test_rename_file(void)
1187 const char *data = testdata;
1188 int datalen = testdatalen;
1189 int err = 0;
1190 int res;
1192 start_test("rename file");
1193 res = create_file(testfile, data, datalen);
1194 if (res == -1)
1195 return -1;
1197 unlink(testfile2);
1198 res = rename(testfile, testfile2);
1199 if (res == -1) {
1200 PERROR("rename");
1201 return -1;
1203 res = check_nonexist(testfile);
1204 if (res == -1)
1205 return -1;
1206 res = check_type(testfile2, S_IFREG);
1207 if (res == -1)
1208 return -1;
1209 err += check_mode(testfile2, 0644);
1210 err += check_nlink(testfile2, 1);
1211 err += check_size(testfile2, datalen);
1212 err += check_data(testfile2, data, 0, datalen);
1213 res = unlink(testfile2);
1214 if (res == -1) {
1215 PERROR("unlink");
1216 return -1;
1218 res = check_nonexist(testfile2);
1219 if (res == -1)
1220 return -1;
1221 if (err)
1222 return -1;
1224 success();
1225 return 0;
1228 static int test_rename_dir(void)
1230 int err = 0;
1231 int res;
1233 start_test("rename dir");
1234 res = create_dir(testdir, testdir_files);
1235 if (res == -1)
1236 return -1;
1238 rmdir(testdir2);
1239 res = rename(testdir, testdir2);
1240 if (res == -1) {
1241 PERROR("rename");
1242 cleanup_dir(testdir, testdir_files, 1);
1243 return -1;
1245 res = check_nonexist(testdir);
1246 if (res == -1) {
1247 cleanup_dir(testdir, testdir_files, 1);
1248 return -1;
1250 res = check_type(testdir2, S_IFDIR);
1251 if (res == -1) {
1252 cleanup_dir(testdir2, testdir_files, 1);
1253 return -1;
1255 err += check_mode(testdir2, 0755);
1256 err += check_dir_contents(testdir2, testdir_files);
1257 err += cleanup_dir(testdir2, testdir_files, 0);
1258 res = rmdir(testdir2);
1259 if (res == -1) {
1260 PERROR("rmdir");
1261 return -1;
1263 res = check_nonexist(testdir2);
1264 if (res == -1)
1265 return -1;
1266 if (err)
1267 return -1;
1269 success();
1270 return 0;
1273 static int test_mkfifo(void)
1275 int res;
1276 int err = 0;
1278 start_test("mkfifo");
1279 unlink(testfile);
1280 res = mkfifo(testfile, 0644);
1281 if (res == -1) {
1282 PERROR("mkfifo");
1283 return -1;
1285 res = check_type(testfile, S_IFIFO);
1286 if (res == -1)
1287 return -1;
1288 err += check_mode(testfile, 0644);
1289 err += check_nlink(testfile, 1);
1290 res = unlink(testfile);
1291 if (res == -1) {
1292 PERROR("unlink");
1293 return -1;
1295 res = check_nonexist(testfile);
1296 if (res == -1)
1297 return -1;
1298 if (err)
1299 return -1;
1301 success();
1302 return 0;
1305 static int test_mkdir(void)
1307 int res;
1308 int err = 0;
1309 const char *dir_contents[] = {NULL};
1311 start_test("mkdir");
1312 rmdir(testdir);
1313 res = mkdir(testdir, 0755);
1314 if (res == -1) {
1315 PERROR("mkdir");
1316 return -1;
1318 res = check_type(testdir, S_IFDIR);
1319 if (res == -1)
1320 return -1;
1321 err += check_mode(testdir, 0755);
1322 err += check_nlink(testdir, 2);
1323 err += check_dir_contents(testdir, dir_contents);
1324 res = rmdir(testdir);
1325 if (res == -1) {
1326 PERROR("rmdir");
1327 return -1;
1329 res = check_nonexist(testdir);
1330 if (res == -1)
1331 return -1;
1332 if (err)
1333 return -1;
1335 success();
1336 return 0;
1339 #define test_create_ro_dir(flags) \
1340 do_test_create_ro_dir(flags, #flags)
1342 static int do_test_create_ro_dir(int flags, const char *flags_str)
1344 int res;
1345 int err = 0;
1346 int fd;
1348 start_test("open(%s) in read-only directory", flags_str);
1349 rmdir(testdir);
1350 res = mkdir(testdir, 0555);
1351 if (res == -1) {
1352 PERROR("mkdir");
1353 return -1;
1355 fd = open(subfile, flags, 0644);
1356 if (fd != -1) {
1357 close(fd);
1358 unlink(subfile);
1359 ERROR("open should have failed");
1360 err--;
1361 } else {
1362 res = check_nonexist(subfile);
1363 if (res == -1)
1364 err--;
1366 unlink(subfile);
1367 res = rmdir(testdir);
1368 if (res == -1) {
1369 PERROR("rmdir");
1370 return -1;
1372 res = check_nonexist(testdir);
1373 if (res == -1)
1374 return -1;
1375 if (err)
1376 return -1;
1378 success();
1379 return 0;
1382 int main(int argc, char *argv[])
1384 const char *basepath;
1385 int err = 0;
1387 umask(0);
1388 if (argc < 2 || argc > 3) {
1389 fprintf(stderr, "usage: %s testdir [test#]\n", argv[0]);
1390 return 1;
1392 basepath = argv[1];
1393 if (argc == 3) {
1394 char *endptr;
1395 char *arg = argv[2];
1396 if (arg[0] == '-') {
1397 arg++;
1398 skip_test = strtoul(arg, &endptr, 10);
1399 } else {
1400 select_test = strtoul(argv[2], &endptr, 10);
1402 if (arg[0] == '\0' || *endptr != '\0') {
1403 fprintf(stderr, "invalid number: '%s'\n", arg);
1404 return 1;
1407 assert(strlen(basepath) < 512);
1408 if (basepath[0] != '/') {
1409 fprintf(stderr, "testdir must be an absolute path\n");
1410 return 1;
1413 sprintf(testfile, "%s/testfile", basepath);
1414 sprintf(testfile2, "%s/testfile2", basepath);
1415 sprintf(testdir, "%s/testdir", basepath);
1416 sprintf(testdir2, "%s/testdir2", basepath);
1417 sprintf(subfile, "%s/subfile", testdir2);
1418 err += test_create();
1419 err += test_create_unlink();
1420 err += test_mknod();
1421 err += test_symlink();
1422 err += test_link();
1423 err += test_link2();
1424 err += test_mkfifo();
1425 err += test_mkdir();
1426 err += test_rename_file();
1427 err += test_rename_dir();
1428 err += test_utime();
1429 err += test_truncate(0);
1430 err += test_truncate(testdatalen / 2);
1431 err += test_truncate(testdatalen);
1432 err += test_truncate(testdatalen + 100);
1433 err += test_ftruncate(0, 0600);
1434 err += test_ftruncate(testdatalen / 2, 0600);
1435 err += test_ftruncate(testdatalen, 0600);
1436 err += test_ftruncate(testdatalen + 100, 0600);
1437 err += test_ftruncate(0, 0400);
1438 err += test_ftruncate(0, 0200);
1439 err += test_ftruncate(0, 0000);
1440 err += test_open(0, O_RDONLY, 0);
1441 err += test_open(1, O_RDONLY, 0);
1442 err += test_open(1, O_RDWR, 0);
1443 err += test_open(1, O_WRONLY, 0);
1444 err += test_open(0, O_RDWR | O_CREAT, 0600);
1445 err += test_open(1, O_RDWR | O_CREAT, 0600);
1446 err += test_open(0, O_RDWR | O_CREAT | O_TRUNC, 0600);
1447 err += test_open(1, O_RDWR | O_CREAT | O_TRUNC, 0600);
1448 err += test_open(0, O_RDONLY | O_CREAT, 0600);
1449 err += test_open(0, O_RDONLY | O_CREAT, 0400);
1450 err += test_open(0, O_RDONLY | O_CREAT, 0200);
1451 err += test_open(0, O_RDONLY | O_CREAT, 0000);
1452 err += test_open(0, O_WRONLY | O_CREAT, 0600);
1453 err += test_open(0, O_WRONLY | O_CREAT, 0400);
1454 err += test_open(0, O_WRONLY | O_CREAT, 0200);
1455 err += test_open(0, O_WRONLY | O_CREAT, 0000);
1456 err += test_open(0, O_RDWR | O_CREAT, 0400);
1457 err += test_open(0, O_RDWR | O_CREAT, 0200);
1458 err += test_open(0, O_RDWR | O_CREAT, 0000);
1459 err += test_open(0, O_RDWR | O_CREAT | O_EXCL, 0600);
1460 err += test_open(1, O_RDWR | O_CREAT | O_EXCL, 0600);
1461 err += test_open(0, O_RDWR | O_CREAT | O_EXCL, 0000);
1462 err += test_open(1, O_RDWR | O_CREAT | O_EXCL, 0000);
1463 err += test_open_acc(O_RDONLY, 0600, 0);
1464 err += test_open_acc(O_WRONLY, 0600, 0);
1465 err += test_open_acc(O_RDWR, 0600, 0);
1466 err += test_open_acc(O_RDONLY, 0400, 0);
1467 err += test_open_acc(O_RDONLY | O_TRUNC, 0400, EACCES);
1468 err += test_open_acc(O_WRONLY, 0400, EACCES);
1469 err += test_open_acc(O_RDWR, 0400, EACCES);
1470 err += test_open_acc(O_RDONLY, 0200, EACCES);
1471 err += test_open_acc(O_WRONLY, 0200, 0);
1472 err += test_open_acc(O_RDWR, 0200, EACCES);
1473 err += test_open_acc(O_RDONLY, 0000, EACCES);
1474 err += test_open_acc(O_WRONLY, 0000, EACCES);
1475 err += test_open_acc(O_RDWR, 0000, EACCES);
1476 err += test_create_ro_dir(O_CREAT);
1477 err += test_create_ro_dir(O_CREAT | O_EXCL);
1478 err += test_create_ro_dir(O_CREAT | O_WRONLY);
1479 err += test_create_ro_dir(O_CREAT | O_TRUNC);
1481 unlink(testfile);
1482 unlink(testfile2);
1483 rmdir(testdir);
1484 rmdir(testdir2);
1486 if (err) {
1487 fprintf(stderr, "%i tests failed\n", -err);
1488 return 1;
1491 return 0;