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  close(fd_out);
783  return -1;
784  }
785  res = close(fd_out);
786  if (res == -1) {
787  PERROR("close");
788  return -1;
789  }
790 
791  err = check_data(testfile2, data, 0, datalen);
792 
793  res = unlink(testfile);
794  if (res == -1) {
795  PERROR("unlink");
796  return -1;
797  }
798  res = check_nonexist(testfile);
799  if (res == -1)
800  return -1;
801  if (err)
802  return -1;
803 
804  res = unlink(testfile2);
805  if (res == -1) {
806  PERROR("unlink");
807  return -1;
808  }
809  res = check_nonexist(testfile2);
810  if (res == -1)
811  return -1;
812  if (err)
813  return -1;
814 
815  success();
816  return 0;
817 }
818 #else
819 static int test_copy_file_range(void)
820 {
821  return 0;
822 }
823 #endif
824 
825 static int test_utime(void)
826 {
827  struct utimbuf utm;
828  time_t atime = 987631200;
829  time_t mtime = 123116400;
830  int res;
831 
832  start_test("utime");
833  res = create_file(testfile, NULL, 0);
834  if (res == -1)
835  return -1;
836 
837  utm.actime = atime;
838  utm.modtime = mtime;
839  res = utime(testfile, &utm);
840  if (res == -1) {
841  PERROR("utime");
842  return -1;
843  }
844  res = check_times(testfile, atime, mtime);
845  if (res == -1) {
846  return -1;
847  }
848  res = unlink(testfile);
849  if (res == -1) {
850  PERROR("unlink");
851  return -1;
852  }
853  res = check_nonexist(testfile);
854  if (res == -1)
855  return -1;
856 
857  success();
858  return 0;
859 }
860 
861 static int test_create(void)
862 {
863  const char *data = testdata;
864  int datalen = testdatalen;
865  int err = 0;
866  int res;
867  int fd;
868 
869  start_test("create");
870  unlink(testfile);
871  fd = creat(testfile, 0644);
872  if (fd == -1) {
873  PERROR("creat");
874  return -1;
875  }
876  res = write(fd, data, datalen);
877  if (res == -1) {
878  PERROR("write");
879  close(fd);
880  return -1;
881  }
882  if (res != datalen) {
883  ERROR("write is short: %u instead of %u", res, datalen);
884  close(fd);
885  return -1;
886  }
887  res = close(fd);
888  if (res == -1) {
889  PERROR("close");
890  return -1;
891  }
892  res = check_type(testfile, S_IFREG);
893  if (res == -1)
894  return -1;
895  err += check_mode(testfile, 0644);
896  err += check_nlink(testfile, 1);
897  err += check_size(testfile, datalen);
898  err += check_data(testfile, data, 0, datalen);
899  res = unlink(testfile);
900  if (res == -1) {
901  PERROR("unlink");
902  return -1;
903  }
904  res = check_nonexist(testfile);
905  if (res == -1)
906  return -1;
907  if (err)
908  return -1;
909 
910  success();
911  return 0;
912 }
913 
914 static int test_create_unlink(void)
915 {
916  const char *data = testdata;
917  int datalen = testdatalen;
918  int err = 0;
919  int res;
920  int fd;
921 
922  start_test("create+unlink");
923  unlink(testfile);
924  fd = open(testfile, O_CREAT | O_RDWR | O_TRUNC, 0644);
925  if (fd == -1) {
926  PERROR("creat");
927  return -1;
928  }
929  res = unlink(testfile);
930  if (res == -1) {
931  PERROR("unlink");
932  close(fd);
933  return -1;
934  }
935  res = check_nonexist(testfile);
936  if (res == -1) {
937  close(fd);
938  return -1;
939  }
940  res = write(fd, data, datalen);
941  if (res == -1) {
942  PERROR("write");
943  close(fd);
944  return -1;
945  }
946  if (res != datalen) {
947  ERROR("write is short: %u instead of %u", res, datalen);
948  close(fd);
949  return -1;
950  }
951  err += fcheck_type(fd, S_IFREG);
952  err += fcheck_mode(fd, 0644);
953  err += fcheck_nlink(fd, 0);
954  err += fcheck_size(fd, datalen);
955  err += fcheck_data(fd, data, 0, datalen);
956  res = close(fd);
957  if (res == -1) {
958  PERROR("close");
959  err--;
960  }
961  if (err)
962  return -1;
963 
964  success();
965  return 0;
966 }
967 
968 #ifndef __FreeBSD__
969 static int test_mknod(void)
970 {
971  int err = 0;
972  int res;
973 
974  start_test("mknod");
975  unlink(testfile);
976  res = mknod(testfile, 0644, 0);
977  if (res == -1) {
978  PERROR("mknod");
979  return -1;
980  }
981  res = check_type(testfile, S_IFREG);
982  if (res == -1)
983  return -1;
984  err += check_mode(testfile, 0644);
985  err += check_nlink(testfile, 1);
986  err += check_size(testfile, 0);
987  res = unlink(testfile);
988  if (res == -1) {
989  PERROR("unlink");
990  return -1;
991  }
992  res = check_nonexist(testfile);
993  if (res == -1)
994  return -1;
995  if (err)
996  return -1;
997 
998  success();
999  return 0;
1000 }
1001 #endif
1002 
1003 #define test_open(exist, flags, mode) do_test_open(exist, flags, #flags, mode)
1004 
1005 static int do_test_open(int exist, int flags, const char *flags_str, int mode)
1006 {
1007  char buf[4096];
1008  const char *data = testdata;
1009  int datalen = testdatalen;
1010  unsigned currlen = 0;
1011  int err = 0;
1012  int res;
1013  int fd;
1014  off_t off;
1015 
1016  start_test("open(%s, %s, 0%03o)", exist ? "+" : "-", flags_str, mode);
1017  unlink(testfile);
1018  if (exist) {
1019  res = create_file(testfile_r, testdata2, testdata2len);
1020  if (res == -1)
1021  return -1;
1022 
1023  currlen = testdata2len;
1024  }
1025 
1026  fd = open(testfile, flags, mode);
1027  if ((flags & O_CREAT) && (flags & O_EXCL) && exist) {
1028  if (fd != -1) {
1029  ERROR("open should have failed");
1030  close(fd);
1031  return -1;
1032  } else if (errno == EEXIST)
1033  goto succ;
1034  }
1035  if (!(flags & O_CREAT) && !exist) {
1036  if (fd != -1) {
1037  ERROR("open should have failed");
1038  close(fd);
1039  return -1;
1040  } else if (errno == ENOENT)
1041  goto succ;
1042  }
1043  if (fd == -1) {
1044  PERROR("open");
1045  return -1;
1046  }
1047 
1048  if (flags & O_TRUNC)
1049  currlen = 0;
1050 
1051  err += check_type(testfile, S_IFREG);
1052  if (exist)
1053  err += check_mode(testfile, 0644);
1054  else
1055  err += check_mode(testfile, mode);
1056  err += check_nlink(testfile, 1);
1057  err += check_size(testfile, currlen);
1058  if (exist && !(flags & O_TRUNC) && (mode & S_IRUSR))
1059  err += check_data(testfile, testdata2, 0, testdata2len);
1060 
1061  res = write(fd, data, datalen);
1062  if ((flags & O_ACCMODE) != O_RDONLY) {
1063  if (res == -1) {
1064  PERROR("write");
1065  err --;
1066  } else if (res != datalen) {
1067  ERROR("write is short: %u instead of %u", res, datalen);
1068  err --;
1069  } else {
1070  if (datalen > (int) currlen)
1071  currlen = datalen;
1072 
1073  err += check_size(testfile, currlen);
1074 
1075  if (mode & S_IRUSR) {
1076  err += check_data(testfile, data, 0, datalen);
1077  if (exist && !(flags & O_TRUNC) &&
1078  testdata2len > datalen)
1079  err += check_data(testfile,
1080  testdata2 + datalen,
1081  datalen,
1082  testdata2len - datalen);
1083  }
1084  }
1085  } else {
1086  if (res != -1) {
1087  ERROR("write should have failed");
1088  err --;
1089  } else if (errno != EBADF) {
1090  PERROR("write");
1091  err --;
1092  }
1093  }
1094  off = lseek(fd, SEEK_SET, 0);
1095  if (off == (off_t) -1) {
1096  PERROR("lseek");
1097  err--;
1098  } else if (off != 0) {
1099  ERROR("offset should have returned 0");
1100  err --;
1101  }
1102  res = read(fd, buf, sizeof(buf));
1103  if ((flags & O_ACCMODE) != O_WRONLY) {
1104  if (res == -1) {
1105  PERROR("read");
1106  err--;
1107  } else {
1108  int readsize =
1109  currlen < sizeof(buf) ? currlen : sizeof(buf);
1110  if (res != readsize) {
1111  ERROR("read is short: %i instead of %u",
1112  res, readsize);
1113  err--;
1114  } else {
1115  if ((flags & O_ACCMODE) != O_RDONLY) {
1116  err += check_buffer(buf, data, datalen);
1117  if (exist && !(flags & O_TRUNC) &&
1118  testdata2len > datalen)
1119  err += check_buffer(buf + datalen,
1120  testdata2 + datalen,
1121  testdata2len - datalen);
1122  } else if (exist)
1123  err += check_buffer(buf, testdata2,
1124  testdata2len);
1125  }
1126  }
1127  } else {
1128  if (res != -1) {
1129  ERROR("read should have failed");
1130  err --;
1131  } else if (errno != EBADF) {
1132  PERROR("read");
1133  err --;
1134  }
1135  }
1136 
1137  res = close(fd);
1138  if (res == -1) {
1139  PERROR("close");
1140  return -1;
1141  }
1142  res = unlink(testfile);
1143  if (res == -1) {
1144  PERROR("unlink");
1145  return -1;
1146  }
1147  res = check_nonexist(testfile);
1148  if (res == -1)
1149  return -1;
1150  res = check_nonexist(testfile_r);
1151  if (res == -1)
1152  return -1;
1153  if (err)
1154  return -1;
1155 
1156 succ:
1157  success();
1158  return 0;
1159 }
1160 
1161 #define test_open_acc(flags, mode, err) \
1162  do_test_open_acc(flags, #flags, mode, err)
1163 
1164 static int do_test_open_acc(int flags, const char *flags_str, int mode, int err)
1165 {
1166  const char *data = testdata;
1167  int datalen = testdatalen;
1168  int res;
1169  int fd;
1170 
1171  start_test("open_acc(%s) mode: 0%03o message: '%s'", flags_str, mode,
1172  strerror(err));
1173  unlink(testfile);
1174  res = create_file(testfile, data, datalen);
1175  if (res == -1)
1176  return -1;
1177 
1178  res = chmod(testfile, mode);
1179  if (res == -1) {
1180  PERROR("chmod");
1181  return -1;
1182  }
1183 
1184  res = check_mode(testfile, mode);
1185  if (res == -1)
1186  return -1;
1187 
1188  fd = open(testfile, flags);
1189  if (fd == -1) {
1190  if (err != errno) {
1191  PERROR("open");
1192  return -1;
1193  }
1194  } else {
1195  if (err) {
1196  ERROR("open should have failed");
1197  close(fd);
1198  return -1;
1199  }
1200  close(fd);
1201  }
1202  success();
1203  return 0;
1204 }
1205 
1206 static int test_symlink(void)
1207 {
1208  char buf[1024];
1209  const char *data = testdata;
1210  int datalen = testdatalen;
1211  int linklen = strlen(testfile);
1212  int err = 0;
1213  int res;
1214 
1215  start_test("symlink");
1216  res = create_file(testfile, data, datalen);
1217  if (res == -1)
1218  return -1;
1219 
1220  unlink(testfile2);
1221  res = symlink(testfile, testfile2);
1222  if (res == -1) {
1223  PERROR("symlink");
1224  return -1;
1225  }
1226  res = check_type(testfile2, S_IFLNK);
1227  if (res == -1)
1228  return -1;
1229  err += check_mode(testfile2, 0777);
1230  err += check_nlink(testfile2, 1);
1231  res = readlink(testfile2, buf, sizeof(buf));
1232  if (res == -1) {
1233  PERROR("readlink");
1234  err--;
1235  }
1236  if (res != linklen) {
1237  ERROR("short readlink: %u instead of %u", res, linklen);
1238  err--;
1239  }
1240  if (memcmp(buf, testfile, linklen) != 0) {
1241  ERROR("link mismatch");
1242  err--;
1243  }
1244  err += check_size(testfile2, datalen);
1245  err += check_data(testfile2, data, 0, datalen);
1246  res = unlink(testfile2);
1247  if (res == -1) {
1248  PERROR("unlink");
1249  return -1;
1250  }
1251  res = check_nonexist(testfile2);
1252  if (res == -1)
1253  return -1;
1254  if (err)
1255  return -1;
1256 
1257  success();
1258  return 0;
1259 }
1260 
1261 static int test_link(void)
1262 {
1263  const char *data = testdata;
1264  int datalen = testdatalen;
1265  int err = 0;
1266  int res;
1267 
1268  start_test("link");
1269  res = create_file(testfile, data, datalen);
1270  if (res == -1)
1271  return -1;
1272 
1273  unlink(testfile2);
1274  res = link(testfile, testfile2);
1275  if (res == -1) {
1276  PERROR("link");
1277  return -1;
1278  }
1279  res = check_type(testfile2, S_IFREG);
1280  if (res == -1)
1281  return -1;
1282  err += check_mode(testfile2, 0644);
1283  err += check_nlink(testfile2, 2);
1284  err += check_size(testfile2, datalen);
1285  err += check_data(testfile2, data, 0, datalen);
1286  res = unlink(testfile);
1287  if (res == -1) {
1288  PERROR("unlink");
1289  return -1;
1290  }
1291  res = check_nonexist(testfile);
1292  if (res == -1)
1293  return -1;
1294 
1295  err += check_nlink(testfile2, 1);
1296  res = unlink(testfile2);
1297  if (res == -1) {
1298  PERROR("unlink");
1299  return -1;
1300  }
1301  res = check_nonexist(testfile2);
1302  if (res == -1)
1303  return -1;
1304  if (err)
1305  return -1;
1306 
1307  success();
1308  return 0;
1309 }
1310 
1311 static int test_link2(void)
1312 {
1313  const char *data = testdata;
1314  int datalen = testdatalen;
1315  int err = 0;
1316  int res;
1317 
1318  start_test("link-unlink-link");
1319  res = create_file(testfile, data, datalen);
1320  if (res == -1)
1321  return -1;
1322 
1323  unlink(testfile2);
1324  res = link(testfile, testfile2);
1325  if (res == -1) {
1326  PERROR("link");
1327  return -1;
1328  }
1329  res = unlink(testfile);
1330  if (res == -1) {
1331  PERROR("unlink");
1332  return -1;
1333  }
1334  res = check_nonexist(testfile);
1335  if (res == -1)
1336  return -1;
1337  res = link(testfile2, testfile);
1338  if (res == -1) {
1339  PERROR("link");
1340  }
1341  res = check_type(testfile, S_IFREG);
1342  if (res == -1)
1343  return -1;
1344  err += check_mode(testfile, 0644);
1345  err += check_nlink(testfile, 2);
1346  err += check_size(testfile, datalen);
1347  err += check_data(testfile, data, 0, datalen);
1348 
1349  res = unlink(testfile2);
1350  if (res == -1) {
1351  PERROR("unlink");
1352  return -1;
1353  }
1354  err += check_nlink(testfile, 1);
1355  res = unlink(testfile);
1356  if (res == -1) {
1357  PERROR("unlink");
1358  return -1;
1359  }
1360  res = check_nonexist(testfile);
1361  if (res == -1)
1362  return -1;
1363  if (err)
1364  return -1;
1365 
1366  success();
1367  return 0;
1368 }
1369 
1370 static int test_rename_file(void)
1371 {
1372  const char *data = testdata;
1373  int datalen = testdatalen;
1374  int err = 0;
1375  int res;
1376 
1377  start_test("rename file");
1378  res = create_file(testfile, data, datalen);
1379  if (res == -1)
1380  return -1;
1381 
1382  unlink(testfile2);
1383  res = rename(testfile, testfile2);
1384  if (res == -1) {
1385  PERROR("rename");
1386  return -1;
1387  }
1388  res = check_nonexist(testfile);
1389  if (res == -1)
1390  return -1;
1391  res = check_type(testfile2, S_IFREG);
1392  if (res == -1)
1393  return -1;
1394  err += check_mode(testfile2, 0644);
1395  err += check_nlink(testfile2, 1);
1396  err += check_size(testfile2, datalen);
1397  err += check_data(testfile2, data, 0, datalen);
1398  res = unlink(testfile2);
1399  if (res == -1) {
1400  PERROR("unlink");
1401  return -1;
1402  }
1403  res = check_nonexist(testfile2);
1404  if (res == -1)
1405  return -1;
1406  if (err)
1407  return -1;
1408 
1409  success();
1410  return 0;
1411 }
1412 
1413 static int test_rename_dir(void)
1414 {
1415  int err = 0;
1416  int res;
1417 
1418  start_test("rename dir");
1419  res = create_dir(testdir, testdir_files);
1420  if (res == -1)
1421  return -1;
1422 
1423  rmdir(testdir2);
1424  res = rename(testdir, testdir2);
1425  if (res == -1) {
1426  PERROR("rename");
1427  cleanup_dir(testdir, testdir_files, 1);
1428  return -1;
1429  }
1430  res = check_nonexist(testdir);
1431  if (res == -1) {
1432  cleanup_dir(testdir, testdir_files, 1);
1433  return -1;
1434  }
1435  res = check_type(testdir2, S_IFDIR);
1436  if (res == -1) {
1437  cleanup_dir(testdir2, testdir_files, 1);
1438  return -1;
1439  }
1440  err += check_mode(testdir2, 0755);
1441  err += check_dir_contents(testdir2, testdir_files);
1442  err += cleanup_dir(testdir2, testdir_files, 0);
1443  res = rmdir(testdir2);
1444  if (res == -1) {
1445  PERROR("rmdir");
1446  return -1;
1447  }
1448  res = check_nonexist(testdir2);
1449  if (res == -1)
1450  return -1;
1451  if (err)
1452  return -1;
1453 
1454  success();
1455  return 0;
1456 }
1457 
1458 static int test_rename_dir_loop(void)
1459 {
1460 #define PATH(p) (snprintf(path, sizeof path, "%s/%s", testdir, p), path)
1461 #define PATH2(p) (snprintf(path2, sizeof path2, "%s/%s", testdir, p), path2)
1462 
1463  char path[1280], path2[1280];
1464  int err = 0;
1465  int res;
1466 
1467  start_test("rename dir loop");
1468 
1469  res = create_dir(testdir, testdir_files);
1470  if (res == -1)
1471  return -1;
1472 
1473  res = mkdir(PATH("a"), 0755);
1474  if (res == -1) {
1475  PERROR("mkdir");
1476  goto fail;
1477  }
1478 
1479  res = rename(PATH("a"), PATH2("a"));
1480  if (res == -1) {
1481  PERROR("rename");
1482  goto fail;
1483  }
1484 
1485  errno = 0;
1486  res = rename(PATH("a"), PATH2("a/b"));
1487  if (res == 0 || errno != EINVAL) {
1488  PERROR("rename");
1489  goto fail;
1490  }
1491 
1492  res = mkdir(PATH("a/b"), 0755);
1493  if (res == -1) {
1494  PERROR("mkdir");
1495  goto fail;
1496  }
1497 
1498  res = mkdir(PATH("a/b/c"), 0755);
1499  if (res == -1) {
1500  PERROR("mkdir");
1501  goto fail;
1502  }
1503 
1504  errno = 0;
1505  res = rename(PATH("a"), PATH2("a/b/c"));
1506  if (res == 0 || errno != EINVAL) {
1507  PERROR("rename");
1508  goto fail;
1509  }
1510 
1511  errno = 0;
1512  res = rename(PATH("a"), PATH2("a/b/c/a"));
1513  if (res == 0 || errno != EINVAL) {
1514  PERROR("rename");
1515  goto fail;
1516  }
1517 
1518  errno = 0;
1519  res = rename(PATH("a/b/c"), PATH2("a"));
1520  if (res == 0 || errno != ENOTEMPTY) {
1521  PERROR("rename");
1522  goto fail;
1523  }
1524 
1525  res = open(PATH("a/foo"), O_CREAT, 0644);
1526  if (res == -1) {
1527  PERROR("open");
1528  goto fail;
1529  }
1530  close(res);
1531 
1532  res = rename(PATH("a/foo"), PATH2("a/bar"));
1533  if (res == -1) {
1534  PERROR("rename");
1535  goto fail;
1536  }
1537 
1538  res = rename(PATH("a/bar"), PATH2("a/foo"));
1539  if (res == -1) {
1540  PERROR("rename");
1541  goto fail;
1542  }
1543 
1544  res = rename(PATH("a/foo"), PATH2("a/b/bar"));
1545  if (res == -1) {
1546  PERROR("rename");
1547  goto fail;
1548  }
1549 
1550  res = rename(PATH("a/b/bar"), PATH2("a/foo"));
1551  if (res == -1) {
1552  PERROR("rename");
1553  goto fail;
1554  }
1555 
1556  res = rename(PATH("a/foo"), PATH2("a/b/c/bar"));
1557  if (res == -1) {
1558  PERROR("rename");
1559  goto fail;
1560  }
1561 
1562  res = rename(PATH("a/b/c/bar"), PATH2("a/foo"));
1563  if (res == -1) {
1564  PERROR("rename");
1565  goto fail;
1566  }
1567 
1568  res = open(PATH("a/bar"), O_CREAT, 0644);
1569  if (res == -1) {
1570  PERROR("open");
1571  goto fail;
1572  }
1573  close(res);
1574 
1575  res = rename(PATH("a/foo"), PATH2("a/bar"));
1576  if (res == -1) {
1577  PERROR("rename");
1578  goto fail;
1579  }
1580 
1581  unlink(PATH("a/bar"));
1582 
1583  res = rename(PATH("a/b"), PATH2("a/d"));
1584  if (res == -1) {
1585  PERROR("rename");
1586  goto fail;
1587  }
1588 
1589  res = rename(PATH("a/d"), PATH2("a/b"));
1590  if (res == -1) {
1591  PERROR("rename");
1592  goto fail;
1593  }
1594 
1595  res = mkdir(PATH("a/d"), 0755);
1596  if (res == -1) {
1597  PERROR("mkdir");
1598  goto fail;
1599  }
1600 
1601  res = rename(PATH("a/b"), PATH2("a/d"));
1602  if (res == -1) {
1603  PERROR("rename");
1604  goto fail;
1605  }
1606 
1607  res = rename(PATH("a/d"), PATH2("a/b"));
1608  if (res == -1) {
1609  PERROR("rename");
1610  goto fail;
1611  }
1612 
1613  res = mkdir(PATH("a/d"), 0755);
1614  if (res == -1) {
1615  PERROR("mkdir");
1616  goto fail;
1617  }
1618 
1619  res = mkdir(PATH("a/d/e"), 0755);
1620  if (res == -1) {
1621  PERROR("mkdir");
1622  goto fail;
1623  }
1624 
1625  errno = 0;
1626  res = rename(PATH("a/b"), PATH2("a/d"));
1627  if (res == 0 || errno != ENOTEMPTY) {
1628  PERROR("rename");
1629  goto fail;
1630  }
1631 
1632  rmdir(PATH("a/d/e"));
1633  rmdir(PATH("a/d"));
1634 
1635  rmdir(PATH("a/b/c"));
1636  rmdir(PATH("a/b"));
1637  rmdir(PATH("a"));
1638 
1639  err += cleanup_dir(testdir, testdir_files, 0);
1640  res = rmdir(testdir);
1641  if (res == -1) {
1642  PERROR("rmdir");
1643  goto fail;
1644  }
1645  res = check_nonexist(testdir);
1646  if (res == -1)
1647  return -1;
1648  if (err)
1649  return -1;
1650 
1651  success();
1652  return 0;
1653 
1654 fail:
1655  unlink(PATH("a/bar"));
1656 
1657  rmdir(PATH("a/d/e"));
1658  rmdir(PATH("a/d"));
1659 
1660  rmdir(PATH("a/b/c"));
1661  rmdir(PATH("a/b"));
1662  rmdir(PATH("a"));
1663 
1664  cleanup_dir(testdir, testdir_files, 1);
1665  rmdir(testdir);
1666 
1667  return -1;
1668 
1669 #undef PATH2
1670 #undef PATH
1671 }
1672 
1673 #ifndef __FreeBSD__
1674 static int test_mkfifo(void)
1675 {
1676  int res;
1677  int err = 0;
1678 
1679  start_test("mkfifo");
1680  unlink(testfile);
1681  res = mkfifo(testfile, 0644);
1682  if (res == -1) {
1683  PERROR("mkfifo");
1684  return -1;
1685  }
1686  res = check_type(testfile, S_IFIFO);
1687  if (res == -1)
1688  return -1;
1689  err += check_mode(testfile, 0644);
1690  err += check_nlink(testfile, 1);
1691  res = unlink(testfile);
1692  if (res == -1) {
1693  PERROR("unlink");
1694  return -1;
1695  }
1696  res = check_nonexist(testfile);
1697  if (res == -1)
1698  return -1;
1699  if (err)
1700  return -1;
1701 
1702  success();
1703  return 0;
1704 }
1705 #endif
1706 
1707 static int test_mkdir(void)
1708 {
1709  int res;
1710  int err = 0;
1711  const char *dir_contents[] = {NULL};
1712 
1713  start_test("mkdir");
1714  rmdir(testdir);
1715  res = mkdir(testdir, 0755);
1716  if (res == -1) {
1717  PERROR("mkdir");
1718  return -1;
1719  }
1720  res = check_type(testdir, S_IFDIR);
1721  if (res == -1)
1722  return -1;
1723  err += check_mode(testdir, 0755);
1724  /* Some file systems (like btrfs) don't track link
1725  count for directories */
1726  //err += check_nlink(testdir, 2);
1727  err += check_dir_contents(testdir, dir_contents);
1728  res = rmdir(testdir);
1729  if (res == -1) {
1730  PERROR("rmdir");
1731  return -1;
1732  }
1733  res = check_nonexist(testdir);
1734  if (res == -1)
1735  return -1;
1736  if (err)
1737  return -1;
1738 
1739  success();
1740  return 0;
1741 }
1742 
1743 static int test_socket(void)
1744 {
1745  struct sockaddr_un su;
1746  int fd;
1747  int res;
1748  int err = 0;
1749 
1750  start_test("socket");
1751  if (strlen(testsock) + 1 > sizeof(su.sun_path)) {
1752  fprintf(stderr, "Need to shorten mount point by %zu chars\n",
1753  strlen(testsock) + 1 - sizeof(su.sun_path));
1754  return -1;
1755  }
1756  unlink(testsock);
1757  fd = socket(AF_UNIX, SOCK_STREAM, 0);
1758  if (fd < 0) {
1759  PERROR("socket");
1760  return -1;
1761  }
1762  su.sun_family = AF_UNIX;
1763  strncpy(su.sun_path, testsock, sizeof(su.sun_path) - 1);
1764  su.sun_path[sizeof(su.sun_path) - 1] = '\0';
1765  res = bind(fd, (struct sockaddr*)&su, sizeof(su));
1766  if (res == -1) {
1767  PERROR("bind");
1768  return -1;
1769  }
1770 
1771  res = check_type(testsock, S_IFSOCK);
1772  if (res == -1) {
1773  close(fd);
1774  return -1;
1775  }
1776  err += check_nlink(testsock, 1);
1777  close(fd);
1778  res = unlink(testsock);
1779  if (res == -1) {
1780  PERROR("unlink");
1781  return -1;
1782  }
1783  res = check_nonexist(testsock);
1784  if (res == -1)
1785  return -1;
1786  if (err)
1787  return -1;
1788 
1789  success();
1790  return 0;
1791 }
1792 
1793 #define test_create_ro_dir(flags) \
1794  do_test_create_ro_dir(flags, #flags)
1795 
1796 static int do_test_create_ro_dir(int flags, const char *flags_str)
1797 {
1798  int res;
1799  int err = 0;
1800  int fd;
1801 
1802  start_test("open(%s) in read-only directory", flags_str);
1803  rmdir(testdir);
1804  res = mkdir(testdir, 0555);
1805  if (res == -1) {
1806  PERROR("mkdir");
1807  return -1;
1808  }
1809  fd = open(subfile, flags, 0644);
1810  if (fd != -1) {
1811  close(fd);
1812  unlink(subfile);
1813  ERROR("open should have failed");
1814  err--;
1815  } else {
1816  res = check_nonexist(subfile);
1817  if (res == -1)
1818  err--;
1819  }
1820  unlink(subfile);
1821  res = rmdir(testdir);
1822  if (res == -1) {
1823  PERROR("rmdir");
1824  return -1;
1825  }
1826  res = check_nonexist(testdir);
1827  if (res == -1)
1828  return -1;
1829  if (err)
1830  return -1;
1831 
1832  success();
1833  return 0;
1834 }
1835 
1836 int main(int argc, char *argv[])
1837 {
1838  const char *basepath;
1839  const char *realpath;
1840  int err = 0;
1841  int a;
1842  int is_root;
1843 
1844  umask(0);
1845  if (argc < 2 || argc > 4) {
1846  fprintf(stderr, "usage: %s testdir [:realdir] [[-]test#]\n", argv[0]);
1847  return 1;
1848  }
1849  basepath = argv[1];
1850  realpath = basepath;
1851  for (a = 2; a < argc; a++) {
1852  char *endptr;
1853  char *arg = argv[a];
1854  if (arg[0] == ':') {
1855  realpath = arg + 1;
1856  } else {
1857  if (arg[0] == '-') {
1858  arg++;
1859  skip_test = strtoul(arg, &endptr, 10);
1860  } else {
1861  select_test = strtoul(arg, &endptr, 10);
1862  }
1863  if (arg[0] == '\0' || *endptr != '\0') {
1864  fprintf(stderr, "invalid number: '%s'\n", arg);
1865  return 1;
1866  }
1867  }
1868  }
1869  assert(strlen(basepath) < 512);
1870  assert(strlen(realpath) < 512);
1871  if (basepath[0] != '/') {
1872  fprintf(stderr, "testdir must be an absolute path\n");
1873  return 1;
1874  }
1875 
1876  sprintf(testfile, "%s/testfile", basepath);
1877  sprintf(testfile2, "%s/testfile2", basepath);
1878  sprintf(testdir, "%s/testdir", basepath);
1879  sprintf(testdir2, "%s/testdir2", basepath);
1880  sprintf(subfile, "%s/subfile", testdir2);
1881  sprintf(testsock, "%s/testsock", basepath);
1882 
1883  sprintf(testfile_r, "%s/testfile", realpath);
1884  sprintf(testfile2_r, "%s/testfile2", realpath);
1885  sprintf(testdir_r, "%s/testdir", realpath);
1886  sprintf(testdir2_r, "%s/testdir2", realpath);
1887  sprintf(subfile_r, "%s/subfile", testdir2_r);
1888 
1889  is_root = (geteuid() == 0);
1890 
1891  err += test_create();
1892  err += test_create_unlink();
1893  err += test_symlink();
1894  err += test_link();
1895  err += test_link2();
1896 #ifndef __FreeBSD__
1897  err += test_mknod();
1898  err += test_mkfifo();
1899 #endif
1900  err += test_mkdir();
1901  err += test_rename_file();
1902  err += test_rename_dir();
1903  err += test_rename_dir_loop();
1904  err += test_seekdir();
1905  err += test_socket();
1906  err += test_utime();
1907  err += test_truncate(0);
1908  err += test_truncate(testdatalen / 2);
1909  err += test_truncate(testdatalen);
1910  err += test_truncate(testdatalen + 100);
1911  err += test_ftruncate(0, 0600);
1912  err += test_ftruncate(testdatalen / 2, 0600);
1913  err += test_ftruncate(testdatalen, 0600);
1914  err += test_ftruncate(testdatalen + 100, 0600);
1915  err += test_ftruncate(0, 0400);
1916  err += test_ftruncate(0, 0200);
1917  err += test_ftruncate(0, 0000);
1918  err += test_open(0, O_RDONLY, 0);
1919  err += test_open(1, O_RDONLY, 0);
1920  err += test_open(1, O_RDWR, 0);
1921  err += test_open(1, O_WRONLY, 0);
1922  err += test_open(0, O_RDWR | O_CREAT, 0600);
1923  err += test_open(1, O_RDWR | O_CREAT, 0600);
1924  err += test_open(0, O_RDWR | O_CREAT | O_TRUNC, 0600);
1925  err += test_open(1, O_RDWR | O_CREAT | O_TRUNC, 0600);
1926  err += test_open(0, O_RDONLY | O_CREAT, 0600);
1927  err += test_open(0, O_RDONLY | O_CREAT, 0400);
1928  err += test_open(0, O_RDONLY | O_CREAT, 0200);
1929  err += test_open(0, O_RDONLY | O_CREAT, 0000);
1930  err += test_open(0, O_WRONLY | O_CREAT, 0600);
1931  err += test_open(0, O_WRONLY | O_CREAT, 0400);
1932  err += test_open(0, O_WRONLY | O_CREAT, 0200);
1933  err += test_open(0, O_WRONLY | O_CREAT, 0000);
1934  err += test_open(0, O_RDWR | O_CREAT, 0400);
1935  err += test_open(0, O_RDWR | O_CREAT, 0200);
1936  err += test_open(0, O_RDWR | O_CREAT, 0000);
1937  err += test_open(0, O_RDWR | O_CREAT | O_EXCL, 0600);
1938  err += test_open(1, O_RDWR | O_CREAT | O_EXCL, 0600);
1939  err += test_open(0, O_RDWR | O_CREAT | O_EXCL, 0000);
1940  err += test_open(1, O_RDWR | O_CREAT | O_EXCL, 0000);
1941  err += test_open_acc(O_RDONLY, 0600, 0);
1942  err += test_open_acc(O_WRONLY, 0600, 0);
1943  err += test_open_acc(O_RDWR, 0600, 0);
1944  err += test_open_acc(O_RDONLY, 0400, 0);
1945  err += test_open_acc(O_WRONLY, 0200, 0);
1946  if(!is_root) {
1947  err += test_open_acc(O_RDONLY | O_TRUNC, 0400, EACCES);
1948  err += test_open_acc(O_WRONLY, 0400, EACCES);
1949  err += test_open_acc(O_RDWR, 0400, EACCES);
1950  err += test_open_acc(O_RDONLY, 0200, EACCES);
1951  err += test_open_acc(O_RDWR, 0200, EACCES);
1952  err += test_open_acc(O_RDONLY, 0000, EACCES);
1953  err += test_open_acc(O_WRONLY, 0000, EACCES);
1954  err += test_open_acc(O_RDWR, 0000, EACCES);
1955  }
1956  err += test_create_ro_dir(O_CREAT);
1957  err += test_create_ro_dir(O_CREAT | O_EXCL);
1958  err += test_create_ro_dir(O_CREAT | O_WRONLY);
1959  err += test_create_ro_dir(O_CREAT | O_TRUNC);
1960  err += test_copy_file_range();
1961 
1962  unlink(testfile);
1963  unlink(testfile2);
1964  unlink(testsock);
1965  rmdir(testdir);
1966  rmdir(testdir2);
1967 
1968  if (err) {
1969  fprintf(stderr, "%i tests failed\n", -err);
1970  return 1;
1971  }
1972 
1973  return 0;
1974 }