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