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