"Fossies" - the Fresh Open Source Software Archive

Member "fuse-3.2.1/test/test_syscalls.c" (14 Nov 2017, 30230 Bytes) of package /linux/misc/fuse-3.2.1.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. See also the last Fossies "Diffs" side-by-side code changes report for "test_syscalls.c": 3.1.1_vs_3.2.0.

    1 #include <stdio.h>
    2 #include <stdlib.h>
    3 #include <stdarg.h>
    4 #include <string.h>
    5 #include <unistd.h>
    6 #include <fcntl.h>
    7 #include <dirent.h>
    8 #include <utime.h>
    9 #include <errno.h>
   10 #include <assert.h>
   11 #include <sys/types.h>
   12 #include <sys/stat.h>
   13 
   14 
   15 static char testfile[1024];
   16 static char testfile2[1024];
   17 static char testdir[1024];
   18 static char testdir2[1024];
   19 static char subfile[1024];
   20 
   21 static char testfile_r[1024];
   22 static char testfile2_r[1024];
   23 static char testdir_r[1024];
   24 static char testdir2_r[1024];
   25 static char subfile_r[1024];
   26 
   27 static char testname[256];
   28 static char testdata[] = "abcdefghijklmnopqrstuvwxyz";
   29 static char testdata2[] = "1234567890-=qwertyuiop[]\asdfghjkl;'zxcvbnm,./";
   30 static const char *testdir_files[] = { "f1", "f2", NULL};
   31 static char zerodata[4096];
   32 static int testdatalen = sizeof(testdata) - 1;
   33 static int testdata2len = sizeof(testdata2) - 1;
   34 static unsigned int testnum = 1;
   35 static unsigned int select_test = 0;
   36 static unsigned int skip_test = 0;
   37 
   38 #define MAX_ENTRIES 1024
   39 
   40 static void test_perror(const char *func, const char *msg)
   41 {
   42     fprintf(stderr, "%s %s() - %s: %s\n", testname, func, msg,
   43         strerror(errno));
   44 }
   45 
   46 static void test_error(const char *func, const char *msg, ...)
   47     __attribute__ ((format (printf, 2, 3)));
   48 
   49 static void __start_test(const char *fmt, ...)
   50     __attribute__ ((format (printf, 1, 2)));
   51 
   52 static void test_error(const char *func, const char *msg, ...)
   53 {
   54     va_list ap;
   55     fprintf(stderr, "%s %s() - ", testname, func);
   56     va_start(ap, msg);
   57     vfprintf(stderr, msg, ap);
   58     va_end(ap);
   59     fprintf(stderr, "\n");
   60 }
   61 
   62 static void success(void)
   63 {
   64     fprintf(stderr, "%s OK\n", testname);
   65 }
   66 
   67 static void __start_test(const char *fmt, ...)
   68 {
   69     unsigned int n;
   70     va_list ap;
   71     n = sprintf(testname, "%3i [", testnum++);
   72     va_start(ap, fmt);
   73     n += vsprintf(testname + n, fmt, ap);
   74     va_end(ap);
   75     sprintf(testname + n, "]");
   76 }
   77 
   78 #define start_test(msg, args...) { \
   79     if ((select_test && testnum != select_test) || \
   80         (testnum == skip_test)) { \
   81         testnum++; \
   82         return 0; \
   83     } \
   84     __start_test(msg, ##args);      \
   85 }
   86 
   87 #define PERROR(msg) test_perror(__FUNCTION__, msg)
   88 #define ERROR(msg, args...) test_error(__FUNCTION__, msg, ##args)
   89 
   90 static int check_size(const char *path, int len)
   91 {
   92     struct stat stbuf;
   93     int res = stat(path, &stbuf);
   94     if (res == -1) {
   95         PERROR("stat");
   96         return -1;
   97     }
   98     if (stbuf.st_size != len) {
   99         ERROR("length %u instead of %u", (int) stbuf.st_size,
  100               (int) len);
  101         return -1;
  102     }
  103     return 0;
  104 }
  105 
  106 static int fcheck_size(int fd, int len)
  107 {
  108     struct stat stbuf;
  109     int res = fstat(fd, &stbuf);
  110     if (res == -1) {
  111         PERROR("fstat");
  112         return -1;
  113     }
  114     if (stbuf.st_size != len) {
  115         ERROR("length %u instead of %u", (int) stbuf.st_size,
  116               (int) len);
  117         return -1;
  118     }
  119     return 0;
  120 }
  121 
  122 static int check_type(const char *path, mode_t type)
  123 {
  124     struct stat stbuf;
  125     int res = lstat(path, &stbuf);
  126     if (res == -1) {
  127         PERROR("lstat");
  128         return -1;
  129     }
  130     if ((stbuf.st_mode & S_IFMT) != type) {
  131         ERROR("type 0%o instead of 0%o", stbuf.st_mode & S_IFMT, type);
  132         return -1;
  133     }
  134     return 0;
  135 }
  136 
  137 static int fcheck_type(int fd, mode_t type)
  138 {
  139     struct stat stbuf;
  140     int res = fstat(fd, &stbuf);
  141     if (res == -1) {
  142         PERROR("fstat");
  143         return -1;
  144     }
  145     if ((stbuf.st_mode & S_IFMT) != type) {
  146         ERROR("type 0%o instead of 0%o", stbuf.st_mode & S_IFMT, type);
  147         return -1;
  148     }
  149     return 0;
  150 }
  151 
  152 static int check_mode(const char *path, mode_t mode)
  153 {
  154     struct stat stbuf;
  155     int res = lstat(path, &stbuf);
  156     if (res == -1) {
  157         PERROR("lstat");
  158         return -1;
  159     }
  160     if ((stbuf.st_mode & 07777) != mode) {
  161         ERROR("mode 0%o instead of 0%o", stbuf.st_mode & 07777, mode);
  162         return -1;
  163     }
  164     return 0;
  165 }
  166 
  167 static int fcheck_mode(int fd, mode_t mode)
  168 {
  169     struct stat stbuf;
  170     int res = fstat(fd, &stbuf);
  171     if (res == -1) {
  172         PERROR("fstat");
  173         return -1;
  174     }
  175     if ((stbuf.st_mode & 07777) != mode) {
  176         ERROR("mode 0%o instead of 0%o", stbuf.st_mode & 07777, mode);
  177         return -1;
  178     }
  179     return 0;
  180 }
  181 
  182 static int check_times(const char *path, time_t atime, time_t mtime)
  183 {
  184     int err = 0;
  185     struct stat stbuf;
  186     int res = lstat(path, &stbuf);
  187     if (res == -1) {
  188         PERROR("lstat");
  189         return -1;
  190     }
  191     if (stbuf.st_atime != atime) {
  192         ERROR("atime %li instead of %li", stbuf.st_atime, atime);
  193         err--;
  194     }
  195     if (stbuf.st_mtime != mtime) {
  196         ERROR("mtime %li instead of %li", stbuf.st_mtime, mtime);
  197         err--;
  198     }
  199     if (err)
  200         return -1;
  201 
  202     return 0;
  203 }
  204 
  205 #if 0
  206 static int fcheck_times(int fd, time_t atime, time_t mtime)
  207 {
  208     int err = 0;
  209     struct stat stbuf;
  210     int res = fstat(fd, &stbuf);
  211     if (res == -1) {
  212         PERROR("fstat");
  213         return -1;
  214     }
  215     if (stbuf.st_atime != atime) {
  216         ERROR("atime %li instead of %li", stbuf.st_atime, atime);
  217         err--;
  218     }
  219     if (stbuf.st_mtime != mtime) {
  220         ERROR("mtime %li instead of %li", stbuf.st_mtime, mtime);
  221         err--;
  222     }
  223     if (err)
  224         return -1;
  225 
  226     return 0;
  227 }
  228 #endif
  229 
  230 static int check_nlink(const char *path, nlink_t nlink)
  231 {
  232     struct stat stbuf;
  233     int res = lstat(path, &stbuf);
  234     if (res == -1) {
  235         PERROR("lstat");
  236         return -1;
  237     }
  238     if (stbuf.st_nlink != nlink) {
  239         ERROR("nlink %li instead of %li", (long) stbuf.st_nlink,
  240               (long) nlink);
  241         return -1;
  242     }
  243     return 0;
  244 }
  245 
  246 static int fcheck_nlink(int fd, nlink_t nlink)
  247 {
  248     struct stat stbuf;
  249     int res = fstat(fd, &stbuf);
  250     if (res == -1) {
  251         PERROR("fstat");
  252         return -1;
  253     }
  254     if (stbuf.st_nlink != nlink) {
  255         ERROR("nlink %li instead of %li", (long) stbuf.st_nlink,
  256               (long) nlink);
  257         return -1;
  258     }
  259     return 0;
  260 }
  261 
  262 static int check_nonexist(const char *path)
  263 {
  264     struct stat stbuf;
  265     int res = lstat(path, &stbuf);
  266     if (res == 0) {
  267         ERROR("file should not exist");
  268         return -1;
  269     }
  270     if (errno != ENOENT) {
  271         ERROR("file should not exist: %s", strerror(errno));
  272         return -1;
  273     }
  274     return 0;
  275 }
  276 
  277 static int check_buffer(const char *buf, const char *data, unsigned len)
  278 {
  279     if (memcmp(buf, data, len) != 0) {
  280         ERROR("data mismatch");
  281         return -1;
  282     }
  283     return 0;
  284 }
  285 
  286 static int check_data(const char *path, const char *data, int offset,
  287               unsigned len)
  288 {
  289     char buf[4096];
  290     int res;
  291     int fd = open(path, O_RDONLY);
  292     if (fd == -1) {
  293         PERROR("open");
  294         return -1;
  295     }
  296     if (lseek(fd, offset, SEEK_SET) == (off_t) -1) {
  297         PERROR("lseek");
  298         close(fd);
  299         return -1;
  300     }
  301     while (len) {
  302         int rdlen = len < sizeof(buf) ? len : sizeof(buf);
  303         res = read(fd, buf, rdlen);
  304         if (res == -1) {
  305             PERROR("read");
  306             close(fd);
  307             return -1;
  308         }
  309         if (res != rdlen) {
  310             ERROR("short read: %u instead of %u", res, rdlen);
  311             close(fd);
  312             return -1;
  313         }
  314         if (check_buffer(buf, data, rdlen) != 0) {
  315             close(fd);
  316             return -1;
  317         }
  318         data += rdlen;
  319         len -= rdlen;
  320     }
  321     res = close(fd);
  322     if (res == -1) {
  323         PERROR("close");
  324         return -1;
  325     }
  326     return 0;
  327 }
  328 
  329 static int fcheck_data(int fd, const char *data, int offset,
  330                unsigned len)
  331 {
  332     char buf[4096];
  333     int res;
  334     if (lseek(fd, offset, SEEK_SET) == (off_t) -1) {
  335         PERROR("lseek");
  336         return -1;
  337     }
  338     while (len) {
  339         int rdlen = len < sizeof(buf) ? len : sizeof(buf);
  340         res = read(fd, buf, rdlen);
  341         if (res == -1) {
  342             PERROR("read");
  343             return -1;
  344         }
  345         if (res != rdlen) {
  346             ERROR("short read: %u instead of %u", res, rdlen);
  347             return -1;
  348         }
  349         if (check_buffer(buf, data, rdlen) != 0) {
  350             return -1;
  351         }
  352         data += rdlen;
  353         len -= rdlen;
  354     }
  355     return 0;
  356 }
  357 
  358 static int check_dir_contents(const char *path, const char **contents)
  359 {
  360     int i;
  361     int res;
  362     int err = 0;
  363     int found[MAX_ENTRIES];
  364     const char *cont[MAX_ENTRIES];
  365     DIR *dp;
  366 
  367     for (i = 0; contents[i]; i++) {
  368         assert(i < MAX_ENTRIES - 3);
  369         found[i] = 0;
  370         cont[i] = contents[i];
  371     }
  372     found[i] = 0;
  373     cont[i++] = ".";
  374     found[i] = 0;
  375     cont[i++] = "..";
  376     cont[i] = NULL;
  377 
  378     dp = opendir(path);
  379     if (dp == NULL) {
  380         PERROR("opendir");
  381         return -1;
  382     }
  383     memset(found, 0, sizeof(found));
  384     while(1) {
  385         struct dirent *de;
  386         errno = 0;
  387         de = readdir(dp);
  388         if (de == NULL) {
  389             if (errno) {
  390                 PERROR("readdir");
  391                 closedir(dp);
  392                 return -1;
  393             }
  394             break;
  395         }
  396         for (i = 0; cont[i] != NULL; i++) {
  397             assert(i < MAX_ENTRIES);
  398             if (strcmp(cont[i], de->d_name) == 0) {
  399                 if (found[i]) {
  400                     ERROR("duplicate entry <%s>",
  401                           de->d_name);
  402                     err--;
  403                 } else
  404                     found[i] = 1;
  405                 break;
  406             }
  407         }
  408         if (!cont[i]) {
  409             ERROR("unexpected entry <%s>", de->d_name);
  410             err --;
  411         }
  412     }
  413     for (i = 0; cont[i] != NULL; i++) {
  414         if (!found[i]) {
  415             ERROR("missing entry <%s>", cont[i]);
  416             err--;
  417         }
  418     }
  419     res = closedir(dp);
  420     if (res == -1) {
  421         PERROR("closedir");
  422         return -1;
  423     }
  424     if (err)
  425         return -1;
  426 
  427     return 0;
  428 }
  429 
  430 static int create_file(const char *path, const char *data, int len)
  431 {
  432     int res;
  433     int fd;
  434 
  435     unlink(path);
  436     fd = creat(path, 0644);
  437     if (fd == -1) {
  438         PERROR("creat");
  439         return -1;
  440     }
  441     if (len) {
  442         res = write(fd, data, len);
  443         if (res == -1) {
  444             PERROR("write");
  445             close(fd);
  446             return -1;
  447         }
  448         if (res != len) {
  449             ERROR("write is short: %u instead of %u", res, len);
  450             close(fd);
  451             return -1;
  452         }
  453     }
  454     res = close(fd);
  455     if (res == -1) {
  456         PERROR("close");
  457         return -1;
  458     }
  459     res = check_type(path, S_IFREG);
  460     if (res == -1)
  461         return -1;
  462     res = check_mode(path, 0644);
  463     if (res == -1)
  464         return -1;
  465     res = check_nlink(path, 1);
  466     if (res == -1)
  467         return -1;
  468     res = check_size(path, len);
  469     if (res == -1)
  470         return -1;
  471 
  472     if (len) {
  473         res = check_data(path, data, 0, len);
  474         if (res == -1)
  475             return -1;
  476     }
  477 
  478     return 0;
  479 }
  480 
  481 static int cleanup_dir(const char *path, const char **dir_files, int quiet)
  482 {
  483     int i;
  484     int err = 0;
  485 
  486     for (i = 0; dir_files[i]; i++) {
  487         int res;
  488         char fpath[1024];
  489         sprintf(fpath, "%s/%s", path, dir_files[i]);
  490         res = unlink(fpath);
  491         if (res == -1 && !quiet) {
  492             PERROR("unlink");
  493             err --;
  494         }
  495     }
  496     if (err)
  497         return -1;
  498 
  499     return 0;
  500 }
  501 
  502 static int create_dir(const char *path, const char **dir_files)
  503 {
  504     int res;
  505     int i;
  506 
  507     rmdir(path);
  508     res = mkdir(path, 0755);
  509     if (res == -1) {
  510         PERROR("mkdir");
  511         return -1;
  512     }
  513     res = check_type(path, S_IFDIR);
  514     if (res == -1)
  515         return -1;
  516     res = check_mode(path, 0755);
  517     if (res == -1)
  518         return -1;
  519 
  520     for (i = 0; dir_files[i]; i++) {
  521         char fpath[1024];
  522         sprintf(fpath, "%s/%s", path, dir_files[i]);
  523         res = create_file(fpath, "", 0);
  524         if (res == -1) {
  525             cleanup_dir(path, dir_files, 1);
  526             return -1;
  527         }
  528     }
  529     res = check_dir_contents(path, dir_files);
  530     if (res == -1) {
  531         cleanup_dir(path, dir_files, 1);
  532         return -1;
  533     }
  534 
  535     return 0;
  536 }
  537 
  538 static int test_truncate(int len)
  539 {
  540     const char *data = testdata;
  541     int datalen = testdatalen;
  542     int res;
  543 
  544     start_test("truncate(%u)", (int) len);
  545     res = create_file(testfile, data, datalen);
  546     if (res == -1)
  547         return -1;
  548 
  549     res = truncate(testfile, len);
  550     if (res == -1) {
  551         PERROR("truncate");
  552         return -1;
  553     }
  554     res = check_size(testfile, len);
  555     if (res == -1)
  556         return -1;
  557 
  558     if (len > 0) {
  559         if (len <= datalen) {
  560             res = check_data(testfile, data, 0, len);
  561             if (res == -1)
  562                 return -1;
  563         } else {
  564             res = check_data(testfile, data, 0, datalen);
  565             if (res == -1)
  566                 return -1;
  567             res = check_data(testfile, zerodata, datalen,
  568                      len - datalen);
  569             if (res == -1)
  570                 return -1;
  571         }
  572     }
  573     res = unlink(testfile);
  574     if (res == -1) {
  575         PERROR("unlink");
  576         return -1;
  577     }
  578     res = check_nonexist(testfile);
  579     if (res == -1)
  580         return -1;
  581 
  582     success();
  583     return 0;
  584 }
  585 
  586 static int test_ftruncate(int len, int mode)
  587 {
  588     const char *data = testdata;
  589     int datalen = testdatalen;
  590     int res;
  591     int fd;
  592 
  593     start_test("ftruncate(%u) mode: 0%03o", len, mode);
  594     res = create_file(testfile, data, datalen);
  595     if (res == -1)
  596         return -1;
  597 
  598     fd = open(testfile, O_WRONLY);
  599     if (fd == -1) {
  600         PERROR("open");
  601         return -1;
  602     }
  603 
  604     res = fchmod(fd, mode);
  605     if (res == -1) {
  606         PERROR("fchmod");
  607         close(fd);
  608         return -1;
  609     }
  610     res = check_mode(testfile, mode);
  611     if (res == -1) {
  612         close(fd);
  613         return -1;
  614     }
  615     res = ftruncate(fd, len);
  616     if (res == -1) {
  617         PERROR("ftruncate");
  618         close(fd);
  619         return -1;
  620     }
  621     close(fd);
  622     res = check_size(testfile, len);
  623     if (res == -1)
  624         return -1;
  625 
  626     if (len > 0) {
  627         if (len <= datalen) {
  628             res = check_data(testfile, data, 0, len);
  629             if (res == -1)
  630                 return -1;
  631         } else {
  632             res = check_data(testfile, data, 0, datalen);
  633             if (res == -1)
  634                 return -1;
  635             res = check_data(testfile, zerodata, datalen,
  636                      len - datalen);
  637             if (res == -1)
  638                 return -1;
  639         }
  640     }
  641     res = unlink(testfile);
  642     if (res == -1) {
  643         PERROR("unlink");
  644         return -1;
  645     }
  646     res = check_nonexist(testfile);
  647     if (res == -1)
  648         return -1;
  649 
  650     success();
  651     return 0;
  652 }
  653 
  654 static int test_utime(void)
  655 {
  656     struct utimbuf utm;
  657     time_t atime = 987631200;
  658     time_t mtime = 123116400;
  659     int res;
  660 
  661     start_test("utime");
  662     res = create_file(testfile, NULL, 0);
  663     if (res == -1)
  664         return -1;
  665 
  666     utm.actime = atime;
  667     utm.modtime = mtime;
  668     res = utime(testfile, &utm);
  669     if (res == -1) {
  670         PERROR("utime");
  671         return -1;
  672     }
  673     res = check_times(testfile, atime, mtime);
  674     if (res == -1) {
  675         return -1;
  676     }
  677     res = unlink(testfile);
  678     if (res == -1) {
  679         PERROR("unlink");
  680         return -1;
  681     }
  682     res = check_nonexist(testfile);
  683     if (res == -1)
  684         return -1;
  685 
  686     success();
  687     return 0;
  688 }
  689 
  690 static int test_create(void)
  691 {
  692     const char *data = testdata;
  693     int datalen = testdatalen;
  694     int err = 0;
  695     int res;
  696     int fd;
  697 
  698     start_test("create");
  699     unlink(testfile);
  700     fd = creat(testfile, 0644);
  701     if (fd == -1) {
  702         PERROR("creat");
  703         return -1;
  704     }
  705     res = write(fd, data, datalen);
  706     if (res == -1) {
  707         PERROR("write");
  708         close(fd);
  709         return -1;
  710     }
  711     if (res != datalen) {
  712         ERROR("write is short: %u instead of %u", res, datalen);
  713         close(fd);
  714         return -1;
  715     }
  716     res = close(fd);
  717     if (res == -1) {
  718         PERROR("close");
  719         return -1;
  720     }
  721     res = check_type(testfile, S_IFREG);
  722     if (res == -1)
  723         return -1;
  724     err += check_mode(testfile, 0644);
  725     err += check_nlink(testfile, 1);
  726     err += check_size(testfile, datalen);
  727     err += check_data(testfile, data, 0, datalen);
  728     res = unlink(testfile);
  729     if (res == -1) {
  730         PERROR("unlink");
  731         return -1;
  732     }
  733     res = check_nonexist(testfile);
  734     if (res == -1)
  735         return -1;
  736     if (err)
  737         return -1;
  738 
  739     success();
  740     return 0;
  741 }
  742 
  743 static int test_create_unlink(void)
  744 {
  745     const char *data = testdata;
  746     int datalen = testdatalen;
  747     int err = 0;
  748     int res;
  749     int fd;
  750 
  751     start_test("create+unlink");
  752     unlink(testfile);
  753     fd = open(testfile, O_CREAT | O_RDWR | O_TRUNC, 0644);
  754     if (fd == -1) {
  755         PERROR("creat");
  756         return -1;
  757     }
  758     res = unlink(testfile);
  759     if (res == -1) {
  760         PERROR("unlink");
  761         close(fd);
  762         return -1;
  763     }
  764     res = check_nonexist(testfile);
  765     if (res == -1)
  766         return -1;
  767     res = write(fd, data, datalen);
  768     if (res == -1) {
  769         PERROR("write");
  770         close(fd);
  771         return -1;
  772     }
  773     if (res != datalen) {
  774         ERROR("write is short: %u instead of %u", res, datalen);
  775         close(fd);
  776         return -1;
  777     }
  778     err += fcheck_type(fd, S_IFREG);
  779     err += fcheck_mode(fd, 0644);
  780     err += fcheck_nlink(fd, 0);
  781     err += fcheck_size(fd, datalen);
  782     err += fcheck_data(fd, data, 0, datalen);
  783     res = close(fd);
  784     if (res == -1) {
  785         PERROR("close");
  786         err--;
  787     }
  788     if (err)
  789         return -1;
  790 
  791     success();
  792     return 0;
  793 }
  794 
  795 #ifndef __FreeBSD__
  796 static int test_mknod(void)
  797 {
  798     int err = 0;
  799     int res;
  800 
  801     start_test("mknod");
  802     unlink(testfile);
  803     res = mknod(testfile, 0644, 0);
  804     if (res == -1) {
  805         PERROR("mknod");
  806         return -1;
  807     }
  808     res = check_type(testfile, S_IFREG);
  809     if (res == -1)
  810         return -1;
  811     err += check_mode(testfile, 0644);
  812     err += check_nlink(testfile, 1);
  813     err += check_size(testfile, 0);
  814     res = unlink(testfile);
  815     if (res == -1) {
  816         PERROR("unlink");
  817         return -1;
  818     }
  819     res = check_nonexist(testfile);
  820     if (res == -1)
  821         return -1;
  822     if (err)
  823         return -1;
  824 
  825     success();
  826     return 0;
  827 }
  828 #endif
  829 
  830 #define test_open(exist, flags, mode)  do_test_open(exist, flags, #flags, mode)
  831 
  832 static int do_test_open(int exist, int flags, const char *flags_str, int mode)
  833 {
  834     char buf[4096];
  835     const char *data = testdata;
  836     int datalen = testdatalen;
  837     unsigned currlen = 0;
  838     int err = 0;
  839     int res;
  840     int fd;
  841     off_t off;
  842 
  843     start_test("open(%s, %s, 0%03o)", exist ? "+" : "-", flags_str, mode);
  844     unlink(testfile);
  845     if (exist) {
  846         res = create_file(testfile_r, testdata2, testdata2len);
  847         if (res == -1)
  848             return -1;
  849 
  850         currlen = testdata2len;
  851     }
  852 
  853     fd = open(testfile, flags, mode);
  854     if ((flags & O_CREAT) && (flags & O_EXCL) && exist) {
  855         if (fd != -1) {
  856             ERROR("open should have failed");
  857             close(fd);
  858             return -1;
  859         } else if (errno == EEXIST)
  860             goto succ;
  861     }
  862     if (!(flags & O_CREAT) && !exist) {
  863         if (fd != -1) {
  864             ERROR("open should have failed");
  865             close(fd);
  866             return -1;
  867         } else if (errno == ENOENT)
  868             goto succ;
  869     }
  870     if (fd == -1) {
  871         PERROR("open");
  872         return -1;
  873     }
  874 
  875     if (flags & O_TRUNC)
  876         currlen = 0;
  877 
  878     err += check_type(testfile, S_IFREG);
  879     if (exist)
  880         err += check_mode(testfile, 0644);
  881     else
  882         err += check_mode(testfile, mode);
  883     err += check_nlink(testfile, 1);
  884     err += check_size(testfile, currlen);
  885     if (exist && !(flags & O_TRUNC) && (mode & 0400))
  886         err += check_data(testfile, testdata2, 0, testdata2len);
  887 
  888     res = write(fd, data, datalen);
  889     if ((flags & O_ACCMODE) != O_RDONLY) {
  890         if (res == -1) {
  891             PERROR("write");
  892             err --;
  893         } else if (res != datalen) {
  894             ERROR("write is short: %u instead of %u", res, datalen);
  895             err --;
  896         } else {
  897             if (datalen > (int) currlen)
  898                 currlen = datalen;
  899 
  900             err += check_size(testfile, currlen);
  901 
  902             if (mode & 0400) {
  903                 err += check_data(testfile, data, 0, datalen);
  904                 if (exist && !(flags & O_TRUNC) &&
  905                     testdata2len > datalen)
  906                     err += check_data(testfile,
  907                               testdata2 + datalen,
  908                               datalen,
  909                               testdata2len - datalen);
  910             }
  911         }
  912     } else {
  913         if (res != -1) {
  914             ERROR("write should have failed");
  915             err --;
  916         } else if (errno != EBADF) {
  917             PERROR("write");
  918             err --;
  919         }
  920     }
  921     off = lseek(fd, SEEK_SET, 0);
  922     if (off == (off_t) -1) {
  923         PERROR("lseek");
  924         err--;
  925     } else if (off != 0) {
  926         ERROR("offset should have returned 0");
  927         err --;
  928     }
  929     res = read(fd, buf, sizeof(buf));
  930     if ((flags & O_ACCMODE) != O_WRONLY) {
  931         if (res == -1) {
  932             PERROR("read");
  933             err--;
  934         } else {
  935             int readsize =
  936                 currlen < sizeof(buf) ? currlen : sizeof(buf);
  937             if (res != readsize) {
  938                 ERROR("read is short: %i instead of %u",
  939                       res, readsize);
  940                 err--;
  941             } else {
  942                 if ((flags & O_ACCMODE) != O_RDONLY) {
  943                     err += check_buffer(buf, data, datalen);
  944                     if (exist && !(flags & O_TRUNC) &&
  945                         testdata2len > datalen)
  946                         err += check_buffer(buf + datalen,
  947                                     testdata2 + datalen,
  948                                     testdata2len - datalen);
  949                 } else if (exist)
  950                     err += check_buffer(buf, testdata2,
  951                                 testdata2len);
  952             }
  953         }
  954     } else {
  955         if (res != -1) {
  956             ERROR("read should have failed");
  957             err --;
  958         } else if (errno != EBADF) {
  959             PERROR("read");
  960             err --;
  961         }
  962     }
  963 
  964     res = close(fd);
  965     if (res == -1) {
  966         PERROR("close");
  967         return -1;
  968     }
  969     res = unlink(testfile);
  970     if (res == -1) {
  971         PERROR("unlink");
  972         return -1;
  973     }
  974     res = check_nonexist(testfile);
  975     if (res == -1)
  976         return -1;
  977     res = check_nonexist(testfile_r);
  978     if (res == -1)
  979         return -1;
  980     if (err)
  981         return -1;
  982 
  983 succ:
  984     success();
  985     return 0;
  986 }
  987 
  988 #define test_open_acc(flags, mode, err)  \
  989     do_test_open_acc(flags, #flags, mode, err)
  990 
  991 static int do_test_open_acc(int flags, const char *flags_str, int mode, int err)
  992 {
  993     const char *data = testdata;
  994     int datalen = testdatalen;
  995     int res;
  996     int fd;
  997 
  998     start_test("open_acc(%s) mode: 0%03o message: '%s'", flags_str, mode,
  999            strerror(err));
 1000     unlink(testfile);
 1001     res = create_file(testfile, data, datalen);
 1002     if (res == -1)
 1003         return -1;
 1004 
 1005     res = chmod(testfile, mode);
 1006     if (res == -1) {
 1007         PERROR("chmod");
 1008         return -1;
 1009     }
 1010 
 1011     res = check_mode(testfile, mode);
 1012     if (res == -1)
 1013         return -1;
 1014 
 1015     fd = open(testfile, flags);
 1016     if (fd == -1) {
 1017         if (err != errno) {
 1018             PERROR("open");
 1019             return -1;
 1020         }
 1021     } else {
 1022         if (err) {
 1023             ERROR("open should have failed");
 1024             close(fd);
 1025             return -1;
 1026         }
 1027         close(fd);
 1028     }
 1029     success();
 1030     return 0;
 1031 }
 1032 
 1033 static int test_symlink(void)
 1034 {
 1035     char buf[1024];
 1036     const char *data = testdata;
 1037     int datalen = testdatalen;
 1038     int linklen = strlen(testfile);
 1039     int err = 0;
 1040     int res;
 1041 
 1042     start_test("symlink");
 1043     res = create_file(testfile, data, datalen);
 1044     if (res == -1)
 1045         return -1;
 1046 
 1047     unlink(testfile2);
 1048     res = symlink(testfile, testfile2);
 1049     if (res == -1) {
 1050         PERROR("symlink");
 1051         return -1;
 1052     }
 1053     res = check_type(testfile2, S_IFLNK);
 1054     if (res == -1)
 1055         return -1;
 1056     err += check_mode(testfile2, 0777);
 1057     err += check_nlink(testfile2, 1);
 1058     res = readlink(testfile2, buf, sizeof(buf));
 1059     if (res == -1) {
 1060         PERROR("readlink");
 1061         err--;
 1062     }
 1063     if (res != linklen) {
 1064         ERROR("short readlink: %u instead of %u", res, linklen);
 1065         err--;
 1066     }
 1067     if (memcmp(buf, testfile, linklen) != 0) {
 1068         ERROR("link mismatch");
 1069         err--;
 1070     }
 1071     err += check_size(testfile2, datalen);
 1072     err += check_data(testfile2, data, 0, datalen);
 1073     res = unlink(testfile2);
 1074     if (res == -1) {
 1075         PERROR("unlink");
 1076         return -1;
 1077     }
 1078     res = check_nonexist(testfile2);
 1079     if (res == -1)
 1080         return -1;
 1081     if (err)
 1082         return -1;
 1083 
 1084     success();
 1085     return 0;
 1086 }
 1087 
 1088 static int test_link(void)
 1089 {
 1090     const char *data = testdata;
 1091     int datalen = testdatalen;
 1092     int err = 0;
 1093     int res;
 1094 
 1095     start_test("link");
 1096     res = create_file(testfile, data, datalen);
 1097     if (res == -1)
 1098         return -1;
 1099 
 1100     unlink(testfile2);
 1101     res = link(testfile, testfile2);
 1102     if (res == -1) {
 1103         PERROR("link");
 1104         return -1;
 1105     }
 1106     res = check_type(testfile2, S_IFREG);
 1107     if (res == -1)
 1108         return -1;
 1109     err += check_mode(testfile2, 0644);
 1110     err += check_nlink(testfile2, 2);
 1111     err += check_size(testfile2, datalen);
 1112     err += check_data(testfile2, data, 0, datalen);
 1113     res = unlink(testfile);
 1114     if (res == -1) {
 1115         PERROR("unlink");
 1116         return -1;
 1117     }
 1118     res = check_nonexist(testfile);
 1119     if (res == -1)
 1120         return -1;
 1121 
 1122     err += check_nlink(testfile2, 1);
 1123     res = unlink(testfile2);
 1124     if (res == -1) {
 1125         PERROR("unlink");
 1126         return -1;
 1127     }
 1128     res = check_nonexist(testfile2);
 1129     if (res == -1)
 1130         return -1;
 1131     if (err)
 1132         return -1;
 1133 
 1134     success();
 1135     return 0;
 1136 }
 1137 
 1138 static int test_link2(void)
 1139 {
 1140     const char *data = testdata;
 1141     int datalen = testdatalen;
 1142     int err = 0;
 1143     int res;
 1144 
 1145     start_test("link-unlink-link");
 1146     res = create_file(testfile, data, datalen);
 1147     if (res == -1)
 1148         return -1;
 1149 
 1150     unlink(testfile2);
 1151     res = link(testfile, testfile2);
 1152     if (res == -1) {
 1153         PERROR("link");
 1154         return -1;
 1155     }
 1156     res = unlink(testfile);
 1157     if (res == -1) {
 1158         PERROR("unlink");
 1159         return -1;
 1160     }
 1161     res = check_nonexist(testfile);
 1162     if (res == -1)
 1163         return -1;
 1164     res = link(testfile2, testfile);
 1165     if (res == -1) {
 1166         PERROR("link");
 1167     }
 1168     res = check_type(testfile, S_IFREG);
 1169     if (res == -1)
 1170         return -1;
 1171     err += check_mode(testfile, 0644);
 1172     err += check_nlink(testfile, 2);
 1173     err += check_size(testfile, datalen);
 1174     err += check_data(testfile, data, 0, datalen);
 1175 
 1176     res = unlink(testfile2);
 1177     if (res == -1) {
 1178         PERROR("unlink");
 1179         return -1;
 1180     }
 1181     err += check_nlink(testfile, 1);
 1182     res = unlink(testfile);
 1183     if (res == -1) {
 1184         PERROR("unlink");
 1185         return -1;
 1186     }
 1187     res = check_nonexist(testfile);
 1188     if (res == -1)
 1189         return -1;
 1190     if (err)
 1191         return -1;
 1192 
 1193     success();
 1194     return 0;
 1195 }
 1196 
 1197 static int test_rename_file(void)
 1198 {
 1199     const char *data = testdata;
 1200     int datalen = testdatalen;
 1201     int err = 0;
 1202     int res;
 1203 
 1204     start_test("rename file");
 1205     res = create_file(testfile, data, datalen);
 1206     if (res == -1)
 1207         return -1;
 1208 
 1209     unlink(testfile2);
 1210     res = rename(testfile, testfile2);
 1211     if (res == -1) {
 1212         PERROR("rename");
 1213         return -1;
 1214     }
 1215     res = check_nonexist(testfile);
 1216     if (res == -1)
 1217         return -1;
 1218     res = check_type(testfile2, S_IFREG);
 1219     if (res == -1)
 1220         return -1;
 1221     err += check_mode(testfile2, 0644);
 1222     err += check_nlink(testfile2, 1);
 1223     err += check_size(testfile2, datalen);
 1224     err += check_data(testfile2, data, 0, datalen);
 1225     res = unlink(testfile2);
 1226     if (res == -1) {
 1227         PERROR("unlink");
 1228         return -1;
 1229     }
 1230     res = check_nonexist(testfile2);
 1231     if (res == -1)
 1232         return -1;
 1233     if (err)
 1234         return -1;
 1235 
 1236     success();
 1237     return 0;
 1238 }
 1239 
 1240 static int test_rename_dir(void)
 1241 {
 1242     int err = 0;
 1243     int res;
 1244 
 1245     start_test("rename dir");
 1246     res = create_dir(testdir, testdir_files);
 1247     if (res == -1)
 1248         return -1;
 1249 
 1250     rmdir(testdir2);
 1251     res = rename(testdir, testdir2);
 1252     if (res == -1) {
 1253         PERROR("rename");
 1254         cleanup_dir(testdir, testdir_files, 1);
 1255         return -1;
 1256     }
 1257     res = check_nonexist(testdir);
 1258     if (res == -1) {
 1259         cleanup_dir(testdir, testdir_files, 1);
 1260         return -1;
 1261     }
 1262     res = check_type(testdir2, S_IFDIR);
 1263     if (res == -1) {
 1264         cleanup_dir(testdir2, testdir_files, 1);
 1265         return -1;
 1266     }
 1267     err += check_mode(testdir2, 0755);
 1268     err += check_dir_contents(testdir2, testdir_files);
 1269     err += cleanup_dir(testdir2, testdir_files, 0);
 1270     res = rmdir(testdir2);
 1271     if (res == -1) {
 1272         PERROR("rmdir");
 1273         return -1;
 1274     }
 1275     res = check_nonexist(testdir2);
 1276     if (res == -1)
 1277         return -1;
 1278     if (err)
 1279         return -1;
 1280 
 1281     success();
 1282     return 0;
 1283 }
 1284 
 1285 #ifndef __FreeBSD__
 1286 static int test_mkfifo(void)
 1287 {
 1288     int res;
 1289     int err = 0;
 1290 
 1291     start_test("mkfifo");
 1292     unlink(testfile);
 1293     res = mkfifo(testfile, 0644);
 1294     if (res == -1) {
 1295         PERROR("mkfifo");
 1296         return -1;
 1297     }
 1298     res = check_type(testfile, S_IFIFO);
 1299     if (res == -1)
 1300         return -1;
 1301     err += check_mode(testfile, 0644);
 1302     err += check_nlink(testfile, 1);
 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     if (err)
 1312         return -1;
 1313 
 1314     success();
 1315     return 0;
 1316 }
 1317 #endif
 1318 
 1319 static int test_mkdir(void)
 1320 {
 1321     int res;
 1322     int err = 0;
 1323     const char *dir_contents[] = {NULL};
 1324 
 1325     start_test("mkdir");
 1326     rmdir(testdir);
 1327     res = mkdir(testdir, 0755);
 1328     if (res == -1) {
 1329         PERROR("mkdir");
 1330         return -1;
 1331     }
 1332     res = check_type(testdir, S_IFDIR);
 1333     if (res == -1)
 1334         return -1;
 1335     err += check_mode(testdir, 0755);
 1336     /* Some file systems (like btrfs) don't track link
 1337        count for directories */
 1338     //err += check_nlink(testdir, 2);
 1339     err += check_dir_contents(testdir, dir_contents);
 1340     res = rmdir(testdir);
 1341     if (res == -1) {
 1342         PERROR("rmdir");
 1343         return -1;
 1344     }
 1345     res = check_nonexist(testdir);
 1346     if (res == -1)
 1347         return -1;
 1348     if (err)
 1349         return -1;
 1350 
 1351     success();
 1352     return 0;
 1353 }
 1354 
 1355 #define test_create_ro_dir(flags)    \
 1356     do_test_create_ro_dir(flags, #flags)
 1357 
 1358 static int do_test_create_ro_dir(int flags, const char *flags_str)
 1359 {
 1360     int res;
 1361     int err = 0;
 1362     int fd;
 1363 
 1364     start_test("open(%s) in read-only directory", flags_str);
 1365     rmdir(testdir);
 1366     res = mkdir(testdir, 0555);
 1367     if (res == -1) {
 1368         PERROR("mkdir");
 1369         return -1;
 1370     }
 1371     fd = open(subfile, flags, 0644);
 1372     if (fd != -1) {
 1373         close(fd);
 1374         unlink(subfile);
 1375         ERROR("open should have failed");
 1376         err--;
 1377     } else {
 1378         res = check_nonexist(subfile);
 1379         if (res == -1)
 1380             err--;
 1381     }
 1382     unlink(subfile);
 1383     res = rmdir(testdir);
 1384     if (res == -1) {
 1385         PERROR("rmdir");
 1386         return -1;
 1387     }
 1388     res = check_nonexist(testdir);
 1389     if (res == -1)
 1390         return -1;
 1391     if (err)
 1392         return -1;
 1393 
 1394     success();
 1395     return 0;
 1396 }
 1397 
 1398 int main(int argc, char *argv[])
 1399 {
 1400     const char *basepath;
 1401     const char *realpath;
 1402     int err = 0;
 1403     int a;
 1404     int is_root;
 1405 
 1406     umask(0);
 1407     if (argc < 2 || argc > 4) {
 1408         fprintf(stderr, "usage: %s testdir [:realdir] [[-]test#]\n", argv[0]);
 1409         return 1;
 1410     }
 1411     basepath = argv[1];
 1412     realpath = basepath;
 1413     for (a = 2; a < argc; a++) {
 1414         char *endptr;
 1415         char *arg = argv[a];
 1416         if (arg[0] == ':') {
 1417             realpath = arg + 1;
 1418         } else {
 1419             if (arg[0] == '-') {
 1420                 arg++;
 1421                 skip_test = strtoul(arg, &endptr, 10);
 1422             } else {
 1423                 select_test = strtoul(arg, &endptr, 10);
 1424             }
 1425             if (arg[0] == '\0' || *endptr != '\0') {
 1426                 fprintf(stderr, "invalid number: '%s'\n", arg);
 1427                 return 1;
 1428             }
 1429         }
 1430     }
 1431     assert(strlen(basepath) < 512);
 1432     assert(strlen(realpath) < 512);
 1433     if (basepath[0] != '/') {
 1434         fprintf(stderr, "testdir must be an absolute path\n");
 1435         return 1;
 1436     }
 1437 
 1438     sprintf(testfile, "%s/testfile", basepath);
 1439     sprintf(testfile2, "%s/testfile2", basepath);
 1440     sprintf(testdir, "%s/testdir", basepath);
 1441     sprintf(testdir2, "%s/testdir2", basepath);
 1442     sprintf(subfile, "%s/subfile", testdir2);
 1443 
 1444     sprintf(testfile_r, "%s/testfile", realpath);
 1445     sprintf(testfile2_r, "%s/testfile2", realpath);
 1446     sprintf(testdir_r, "%s/testdir", realpath);
 1447     sprintf(testdir2_r, "%s/testdir2", realpath);
 1448     sprintf(subfile_r, "%s/subfile", testdir2_r);
 1449 
 1450     is_root = (geteuid() == 0);
 1451 
 1452     err += test_create();
 1453     err += test_create_unlink();
 1454     err += test_symlink();
 1455     err += test_link();
 1456     err += test_link2();
 1457 #ifndef __FreeBSD__ 
 1458     err += test_mknod();
 1459     err += test_mkfifo();
 1460 #endif
 1461     err += test_mkdir();
 1462     err += test_rename_file();
 1463     err += test_rename_dir();
 1464     err += test_utime();
 1465     err += test_truncate(0);
 1466     err += test_truncate(testdatalen / 2);
 1467     err += test_truncate(testdatalen);
 1468     err += test_truncate(testdatalen + 100);
 1469     err += test_ftruncate(0, 0600);
 1470     err += test_ftruncate(testdatalen / 2, 0600);
 1471     err += test_ftruncate(testdatalen, 0600);
 1472     err += test_ftruncate(testdatalen + 100, 0600);
 1473     err += test_ftruncate(0, 0400);
 1474     err += test_ftruncate(0, 0200);
 1475     err += test_ftruncate(0, 0000);
 1476     err += test_open(0, O_RDONLY, 0);
 1477     err += test_open(1, O_RDONLY, 0);
 1478     err += test_open(1, O_RDWR, 0);
 1479     err += test_open(1, O_WRONLY, 0);
 1480     err += test_open(0, O_RDWR | O_CREAT, 0600);
 1481     err += test_open(1, O_RDWR | O_CREAT, 0600);
 1482     err += test_open(0, O_RDWR | O_CREAT | O_TRUNC, 0600);
 1483     err += test_open(1, O_RDWR | O_CREAT | O_TRUNC, 0600);
 1484     err += test_open(0, O_RDONLY | O_CREAT, 0600);
 1485     err += test_open(0, O_RDONLY | O_CREAT, 0400);
 1486     err += test_open(0, O_RDONLY | O_CREAT, 0200);
 1487     err += test_open(0, O_RDONLY | O_CREAT, 0000);
 1488     err += test_open(0, O_WRONLY | O_CREAT, 0600);
 1489     err += test_open(0, O_WRONLY | O_CREAT, 0400);
 1490     err += test_open(0, O_WRONLY | O_CREAT, 0200);
 1491     err += test_open(0, O_WRONLY | O_CREAT, 0000);
 1492     err += test_open(0, O_RDWR | O_CREAT, 0400);
 1493     err += test_open(0, O_RDWR | O_CREAT, 0200);
 1494     err += test_open(0, O_RDWR | O_CREAT, 0000);
 1495     err += test_open(0, O_RDWR | O_CREAT | O_EXCL, 0600);
 1496     err += test_open(1, O_RDWR | O_CREAT | O_EXCL, 0600);
 1497     err += test_open(0, O_RDWR | O_CREAT | O_EXCL, 0000);
 1498     err += test_open(1, O_RDWR | O_CREAT | O_EXCL, 0000);
 1499     err += test_open_acc(O_RDONLY, 0600, 0);
 1500     err += test_open_acc(O_WRONLY, 0600, 0);
 1501     err += test_open_acc(O_RDWR,   0600, 0);
 1502     err += test_open_acc(O_RDONLY, 0400, 0);
 1503     err += test_open_acc(O_WRONLY, 0200, 0);
 1504     if(!is_root) {
 1505         err += test_open_acc(O_RDONLY | O_TRUNC, 0400, EACCES);
 1506         err += test_open_acc(O_WRONLY, 0400, EACCES);
 1507         err += test_open_acc(O_RDWR,   0400, EACCES);
 1508         err += test_open_acc(O_RDONLY, 0200, EACCES);
 1509         err += test_open_acc(O_RDWR,   0200, EACCES);
 1510         err += test_open_acc(O_RDONLY, 0000, EACCES);
 1511         err += test_open_acc(O_WRONLY, 0000, EACCES);
 1512         err += test_open_acc(O_RDWR,   0000, EACCES);
 1513     }
 1514     err += test_create_ro_dir(O_CREAT);
 1515     err += test_create_ro_dir(O_CREAT | O_EXCL);
 1516     err += test_create_ro_dir(O_CREAT | O_WRONLY);
 1517     err += test_create_ro_dir(O_CREAT | O_TRUNC);
 1518 
 1519     unlink(testfile);
 1520     unlink(testfile2);
 1521     rmdir(testdir);
 1522     rmdir(testdir2);
 1523 
 1524     if (err) {
 1525         fprintf(stderr, "%i tests failed\n", -err);
 1526         return 1;
 1527     }
 1528 
 1529     return 0;
 1530 }