Home | History | Annotate | Line # | Download | only in detail
fs_test.c revision 1.1.1.3
      1 /*
      2  * Automated Testing Framework (atf)
      3  *
      4  * Copyright (c) 2007 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
     17  * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
     18  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     19  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     20  * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
     21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
     23  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
     25  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     26  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
     27  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     28  */
     29 
     30 #include <sys/types.h>
     31 #include <sys/stat.h>
     32 
     33 #include <errno.h>
     34 #include <fcntl.h>
     35 #include <stdio.h>
     36 #include <stdlib.h>
     37 #include <string.h>
     38 #include <unistd.h>
     39 
     40 #include <atf-c.h>
     41 
     42 #include "fs.h"
     43 #include "test_helpers.h"
     44 #include "user.h"
     45 
     46 /* ---------------------------------------------------------------------
     47  * Auxiliary functions.
     48  * --------------------------------------------------------------------- */
     49 
     50 static
     51 void
     52 create_dir(const char *p, int mode)
     53 {
     54     int ret;
     55 
     56     ret = mkdir(p, mode);
     57     if (ret == -1)
     58         atf_tc_fail("Could not create helper directory %s", p);
     59 }
     60 
     61 static
     62 void
     63 create_file(const char *p, int mode)
     64 {
     65     int fd;
     66 
     67     fd = open(p, O_CREAT | O_WRONLY | O_TRUNC, mode);
     68     if (fd == -1)
     69         atf_tc_fail("Could not create helper file %s", p);
     70     close(fd);
     71 }
     72 
     73 static
     74 bool
     75 exists(const atf_fs_path_t *p)
     76 {
     77     return access(atf_fs_path_cstring(p), F_OK) == 0;
     78 }
     79 
     80 static
     81 atf_error_t
     82 mkstemp_discard_fd(atf_fs_path_t *p)
     83 {
     84     int fd;
     85     atf_error_t err = atf_fs_mkstemp(p, &fd);
     86     if (!atf_is_error(err))
     87         close(fd);
     88     return err;
     89 }
     90 
     91 /* ---------------------------------------------------------------------
     92  * Test cases for the "atf_fs_path" type.
     93  * --------------------------------------------------------------------- */
     94 
     95 ATF_TC(path_normalize);
     96 ATF_TC_HEAD(path_normalize, tc)
     97 {
     98     atf_tc_set_md_var(tc, "descr", "Tests the path's normalization");
     99 }
    100 ATF_TC_BODY(path_normalize, tc)
    101 {
    102     struct test {
    103         const char *in;
    104         const char *out;
    105     } tests[] = {
    106         { ".", ".", },
    107         { "..", "..", },
    108 
    109         { "/", "/", },
    110         { "//", "/", }, /* NO_CHECK_STYLE */
    111         { "///", "/", }, /* NO_CHECK_STYLE */
    112 
    113         { "foo", "foo", },
    114         { "foo/", "foo", },
    115         { "foo/bar", "foo/bar", },
    116         { "foo/bar/", "foo/bar", },
    117 
    118         { "/foo", "/foo", },
    119         { "/foo/bar", "/foo/bar", },
    120         { "/foo/bar/", "/foo/bar", },
    121 
    122         { "///foo", "/foo", }, /* NO_CHECK_STYLE */
    123         { "///foo///bar", "/foo/bar", }, /* NO_CHECK_STYLE */
    124         { "///foo///bar///", "/foo/bar", }, /* NO_CHECK_STYLE */
    125 
    126         { NULL, NULL }
    127     };
    128     struct test *t;
    129 
    130     for (t = &tests[0]; t->in != NULL; t++) {
    131         atf_fs_path_t p;
    132 
    133         printf("Input          : >%s<\n", t->in);
    134         printf("Expected output: >%s<\n", t->out);
    135 
    136         RE(atf_fs_path_init_fmt(&p, "%s", t->in));
    137         printf("Output         : >%s<\n", atf_fs_path_cstring(&p));
    138         ATF_REQUIRE(strcmp(atf_fs_path_cstring(&p), t->out) == 0);
    139         atf_fs_path_fini(&p);
    140 
    141         printf("\n");
    142     }
    143 }
    144 
    145 ATF_TC(path_copy);
    146 ATF_TC_HEAD(path_copy, tc)
    147 {
    148     atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_path_copy constructor");
    149 }
    150 ATF_TC_BODY(path_copy, tc)
    151 {
    152     atf_fs_path_t str, str2;
    153 
    154     RE(atf_fs_path_init_fmt(&str, "foo"));
    155     RE(atf_fs_path_copy(&str2, &str));
    156 
    157     ATF_REQUIRE(atf_equal_fs_path_fs_path(&str, &str2));
    158 
    159     RE(atf_fs_path_append_fmt(&str2, "bar"));
    160 
    161     ATF_REQUIRE(!atf_equal_fs_path_fs_path(&str, &str2));
    162 
    163     atf_fs_path_fini(&str2);
    164     atf_fs_path_fini(&str);
    165 }
    166 
    167 ATF_TC(path_is_absolute);
    168 ATF_TC_HEAD(path_is_absolute, tc)
    169 {
    170     atf_tc_set_md_var(tc, "descr", "Tests the path::is_absolute function");
    171 }
    172 ATF_TC_BODY(path_is_absolute, tc)
    173 {
    174     struct test {
    175         const char *in;
    176         bool abs;
    177     } tests[] = {
    178         { "/", true },
    179         { "////", true }, /* NO_CHECK_STYLE */
    180         { "////a", true }, /* NO_CHECK_STYLE */
    181         { "//a//", true }, /* NO_CHECK_STYLE */
    182         { "a////", false }, /* NO_CHECK_STYLE */
    183         { "../foo", false },
    184         { NULL, false },
    185     };
    186     struct test *t;
    187 
    188     for (t = &tests[0]; t->in != NULL; t++) {
    189         atf_fs_path_t p;
    190 
    191         printf("Input          : %s\n", t->in);
    192         printf("Expected result: %s\n", t->abs ? "true" : "false");
    193 
    194         RE(atf_fs_path_init_fmt(&p, "%s", t->in));
    195         printf("Result         : %s\n",
    196                atf_fs_path_is_absolute(&p) ? "true" : "false");
    197         if (t->abs)
    198             ATF_REQUIRE(atf_fs_path_is_absolute(&p));
    199         else
    200             ATF_REQUIRE(!atf_fs_path_is_absolute(&p));
    201         atf_fs_path_fini(&p);
    202 
    203         printf("\n");
    204     }
    205 }
    206 
    207 ATF_TC(path_is_root);
    208 ATF_TC_HEAD(path_is_root, tc)
    209 {
    210     atf_tc_set_md_var(tc, "descr", "Tests the path::is_root function");
    211 }
    212 ATF_TC_BODY(path_is_root, tc)
    213 {
    214     struct test {
    215         const char *in;
    216         bool root;
    217     } tests[] = {
    218         { "/", true },
    219         { "////", true }, /* NO_CHECK_STYLE */
    220         { "////a", false }, /* NO_CHECK_STYLE */
    221         { "//a//", false }, /* NO_CHECK_STYLE */
    222         { "a////", false }, /* NO_CHECK_STYLE */
    223         { "../foo", false },
    224         { NULL, false },
    225     };
    226     struct test *t;
    227 
    228     for (t = &tests[0]; t->in != NULL; t++) {
    229         atf_fs_path_t p;
    230 
    231         printf("Input          : %s\n", t->in);
    232         printf("Expected result: %s\n", t->root ? "true" : "false");
    233 
    234         RE(atf_fs_path_init_fmt(&p, "%s", t->in));
    235         printf("Result         : %s\n",
    236                atf_fs_path_is_root(&p) ? "true" : "false");
    237         if (t->root)
    238             ATF_REQUIRE(atf_fs_path_is_root(&p));
    239         else
    240             ATF_REQUIRE(!atf_fs_path_is_root(&p));
    241         atf_fs_path_fini(&p);
    242 
    243         printf("\n");
    244     }
    245 }
    246 
    247 ATF_TC(path_branch_path);
    248 ATF_TC_HEAD(path_branch_path, tc)
    249 {
    250     atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_path_branch_path "
    251                       "function");
    252 }
    253 ATF_TC_BODY(path_branch_path, tc)
    254 {
    255     struct test {
    256         const char *in;
    257         const char *branch;
    258     } tests[] = {
    259         { ".", "." },
    260         { "foo", "." },
    261         { "foo/bar", "foo" },
    262         { "/foo", "/" },
    263         { "/foo/bar", "/foo" },
    264         { NULL, NULL },
    265     };
    266     struct test *t;
    267 
    268     for (t = &tests[0]; t->in != NULL; t++) {
    269         atf_fs_path_t p, bp;
    270 
    271         printf("Input          : %s\n", t->in);
    272         printf("Expected output: %s\n", t->branch);
    273 
    274         RE(atf_fs_path_init_fmt(&p, "%s", t->in));
    275         RE(atf_fs_path_branch_path(&p, &bp));
    276         printf("Output         : %s\n", atf_fs_path_cstring(&bp));
    277         ATF_REQUIRE(strcmp(atf_fs_path_cstring(&bp), t->branch) == 0);
    278         atf_fs_path_fini(&bp);
    279         atf_fs_path_fini(&p);
    280 
    281         printf("\n");
    282     }
    283 }
    284 
    285 ATF_TC(path_leaf_name);
    286 ATF_TC_HEAD(path_leaf_name, tc)
    287 {
    288     atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_path_leaf_name "
    289                       "function");
    290 }
    291 ATF_TC_BODY(path_leaf_name, tc)
    292 {
    293     struct test {
    294         const char *in;
    295         const char *leaf;
    296     } tests[] = {
    297         { ".", "." },
    298         { "foo", "foo" },
    299         { "foo/bar", "bar" },
    300         { "/foo", "foo" },
    301         { "/foo/bar", "bar" },
    302         { NULL, NULL },
    303     };
    304     struct test *t;
    305 
    306     for (t = &tests[0]; t->in != NULL; t++) {
    307         atf_fs_path_t p;
    308         atf_dynstr_t ln;
    309 
    310         printf("Input          : %s\n", t->in);
    311         printf("Expected output: %s\n", t->leaf);
    312 
    313         RE(atf_fs_path_init_fmt(&p, "%s", t->in));
    314         RE(atf_fs_path_leaf_name(&p, &ln));
    315         printf("Output         : %s\n", atf_dynstr_cstring(&ln));
    316         ATF_REQUIRE(atf_equal_dynstr_cstring(&ln, t->leaf));
    317         atf_dynstr_fini(&ln);
    318         atf_fs_path_fini(&p);
    319 
    320         printf("\n");
    321     }
    322 }
    323 
    324 ATF_TC(path_append);
    325 ATF_TC_HEAD(path_append, tc)
    326 {
    327     atf_tc_set_md_var(tc, "descr", "Tests the concatenation of multiple "
    328                       "paths");
    329 }
    330 ATF_TC_BODY(path_append, tc)
    331 {
    332     struct test {
    333         const char *in;
    334         const char *ap;
    335         const char *out;
    336     } tests[] = {
    337         { "foo", "bar", "foo/bar" },
    338         { "foo/", "/bar", "foo/bar" },
    339         { "foo/", "/bar/baz", "foo/bar/baz" },
    340         { "foo/", "///bar///baz", "foo/bar/baz" }, /* NO_CHECK_STYLE */
    341 
    342         { NULL, NULL, NULL }
    343     };
    344     struct test *t;
    345 
    346     for (t = &tests[0]; t->in != NULL; t++) {
    347         atf_fs_path_t p;
    348 
    349         printf("Input          : >%s<\n", t->in);
    350         printf("Append         : >%s<\n", t->ap);
    351         printf("Expected output: >%s<\n", t->out);
    352 
    353         RE(atf_fs_path_init_fmt(&p, "%s", t->in));
    354 
    355         RE(atf_fs_path_append_fmt(&p, "%s", t->ap));
    356 
    357         printf("Output         : >%s<\n", atf_fs_path_cstring(&p));
    358         ATF_REQUIRE(strcmp(atf_fs_path_cstring(&p), t->out) == 0);
    359 
    360         atf_fs_path_fini(&p);
    361 
    362         printf("\n");
    363     }
    364 }
    365 
    366 ATF_TC(path_to_absolute);
    367 ATF_TC_HEAD(path_to_absolute, tc)
    368 {
    369     atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_path_to_absolute "
    370                       "function");
    371 }
    372 ATF_TC_BODY(path_to_absolute, tc)
    373 {
    374     const char *names[] = { ".", "dir", NULL };
    375     const char **n;
    376 
    377     ATF_REQUIRE(mkdir("dir", 0755) != -1);
    378 
    379     for (n = names; *n != NULL; n++) {
    380         atf_fs_path_t p, p2;
    381         atf_fs_stat_t st1, st2;
    382 
    383         RE(atf_fs_path_init_fmt(&p, "%s", *n));
    384         RE(atf_fs_stat_init(&st1, &p));
    385         printf("Relative path: %s\n", atf_fs_path_cstring(&p));
    386 
    387         RE(atf_fs_path_to_absolute(&p, &p2));
    388         printf("Absolute path: %s\n", atf_fs_path_cstring(&p2));
    389 
    390         ATF_REQUIRE(atf_fs_path_is_absolute(&p2));
    391         RE(atf_fs_stat_init(&st2, &p2));
    392 
    393         ATF_REQUIRE_EQ(atf_fs_stat_get_device(&st1),
    394                         atf_fs_stat_get_device(&st2));
    395         ATF_REQUIRE_EQ(atf_fs_stat_get_inode(&st1),
    396                         atf_fs_stat_get_inode(&st2));
    397 
    398         atf_fs_stat_fini(&st2);
    399         atf_fs_stat_fini(&st1);
    400         atf_fs_path_fini(&p2);
    401         atf_fs_path_fini(&p);
    402 
    403         printf("\n");
    404     }
    405 }
    406 
    407 ATF_TC(path_equal);
    408 ATF_TC_HEAD(path_equal, tc)
    409 {
    410     atf_tc_set_md_var(tc, "descr", "Tests the equality operators for paths");
    411 }
    412 ATF_TC_BODY(path_equal, tc)
    413 {
    414     atf_fs_path_t p1, p2;
    415 
    416     RE(atf_fs_path_init_fmt(&p1, "foo"));
    417 
    418     RE(atf_fs_path_init_fmt(&p2, "foo"));
    419     ATF_REQUIRE(atf_equal_fs_path_fs_path(&p1, &p2));
    420     atf_fs_path_fini(&p2);
    421 
    422     RE(atf_fs_path_init_fmt(&p2, "bar"));
    423     ATF_REQUIRE(!atf_equal_fs_path_fs_path(&p1, &p2));
    424     atf_fs_path_fini(&p2);
    425 
    426     atf_fs_path_fini(&p1);
    427 }
    428 
    429 /* ---------------------------------------------------------------------
    430  * Test cases for the "atf_fs_stat" type.
    431  * --------------------------------------------------------------------- */
    432 
    433 ATF_TC(stat_mode);
    434 ATF_TC_HEAD(stat_mode, tc)
    435 {
    436     atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_stat_get_mode function "
    437                       "and, indirectly, the constructor");
    438 }
    439 ATF_TC_BODY(stat_mode, tc)
    440 {
    441     atf_fs_path_t p;
    442     atf_fs_stat_t st;
    443 
    444     create_file("f1", 0400);
    445     create_file("f2", 0644);
    446 
    447     RE(atf_fs_path_init_fmt(&p, "f1"));
    448     RE(atf_fs_stat_init(&st, &p));
    449     ATF_CHECK_EQ(0400, atf_fs_stat_get_mode(&st));
    450     atf_fs_stat_fini(&st);
    451     atf_fs_path_fini(&p);
    452 
    453     RE(atf_fs_path_init_fmt(&p, "f2"));
    454     RE(atf_fs_stat_init(&st, &p));
    455     ATF_CHECK_EQ(0644, atf_fs_stat_get_mode(&st));
    456     atf_fs_stat_fini(&st);
    457     atf_fs_path_fini(&p);
    458 }
    459 
    460 ATF_TC(stat_type);
    461 ATF_TC_HEAD(stat_type, tc)
    462 {
    463     atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_stat_get_type function "
    464                       "and, indirectly, the constructor");
    465 }
    466 ATF_TC_BODY(stat_type, tc)
    467 {
    468     atf_fs_path_t p;
    469     atf_fs_stat_t st;
    470 
    471     create_dir("dir", 0755);
    472     create_file("reg", 0644);
    473 
    474     RE(atf_fs_path_init_fmt(&p, "dir"));
    475     RE(atf_fs_stat_init(&st, &p));
    476     ATF_REQUIRE_EQ(atf_fs_stat_get_type(&st), atf_fs_stat_dir_type);
    477     atf_fs_stat_fini(&st);
    478     atf_fs_path_fini(&p);
    479 
    480     RE(atf_fs_path_init_fmt(&p, "reg"));
    481     RE(atf_fs_stat_init(&st, &p));
    482     ATF_REQUIRE_EQ(atf_fs_stat_get_type(&st), atf_fs_stat_reg_type);
    483     atf_fs_stat_fini(&st);
    484     atf_fs_path_fini(&p);
    485 }
    486 
    487 ATF_TC(stat_perms);
    488 ATF_TC_HEAD(stat_perms, tc)
    489 {
    490     atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_stat_is_* functions");
    491 }
    492 ATF_TC_BODY(stat_perms, tc)
    493 {
    494     atf_fs_path_t p;
    495     atf_fs_stat_t st;
    496 
    497     create_file("reg", 0);
    498 
    499     RE(atf_fs_path_init_fmt(&p, "reg"));
    500 
    501 #define perms(ur, uw, ux, gr, gw, gx, othr, othw, othx) \
    502     { \
    503         RE(atf_fs_stat_init(&st, &p)); \
    504         ATF_REQUIRE(atf_fs_stat_is_owner_readable(&st) == ur); \
    505         ATF_REQUIRE(atf_fs_stat_is_owner_writable(&st) == uw); \
    506         ATF_REQUIRE(atf_fs_stat_is_owner_executable(&st) == ux); \
    507         ATF_REQUIRE(atf_fs_stat_is_group_readable(&st) == gr); \
    508         ATF_REQUIRE(atf_fs_stat_is_group_writable(&st) == gw); \
    509         ATF_REQUIRE(atf_fs_stat_is_group_executable(&st) == gx); \
    510         ATF_REQUIRE(atf_fs_stat_is_other_readable(&st) == othr); \
    511         ATF_REQUIRE(atf_fs_stat_is_other_writable(&st) == othw); \
    512         ATF_REQUIRE(atf_fs_stat_is_other_executable(&st) == othx); \
    513         atf_fs_stat_fini(&st); \
    514     }
    515 
    516     chmod("reg", 0000);
    517     perms(false, false, false, false, false, false, false, false, false);
    518 
    519     chmod("reg", 0001);
    520     perms(false, false, false, false, false, false, false, false, true);
    521 
    522     chmod("reg", 0010);
    523     perms(false, false, false, false, false, true, false, false, false);
    524 
    525     chmod("reg", 0100);
    526     perms(false, false, true, false, false, false, false, false, false);
    527 
    528     chmod("reg", 0002);
    529     perms(false, false, false, false, false, false, false, true, false);
    530 
    531     chmod("reg", 0020);
    532     perms(false, false, false, false, true, false, false, false, false);
    533 
    534     chmod("reg", 0200);
    535     perms(false, true, false, false, false, false, false, false, false);
    536 
    537     chmod("reg", 0004);
    538     perms(false, false, false, false, false, false, true, false, false);
    539 
    540     chmod("reg", 0040);
    541     perms(false, false, false, true, false, false, false, false, false);
    542 
    543     chmod("reg", 0400);
    544     perms(true, false, false, false, false, false, false, false, false);
    545 
    546     chmod("reg", 0644);
    547     perms(true, true, false, true, false, false, true, false, false);
    548 
    549     chmod("reg", 0755);
    550     perms(true, true, true, true, false, true, true, false, true);
    551 
    552     chmod("reg", 0777);
    553     perms(true, true, true, true, true, true, true, true, true);
    554 
    555 #undef perms
    556 
    557     atf_fs_path_fini(&p);
    558 }
    559 
    560 /* ---------------------------------------------------------------------
    561  * Test cases for the free functions.
    562  * --------------------------------------------------------------------- */
    563 
    564 ATF_TC(exists);
    565 ATF_TC_HEAD(exists, tc)
    566 {
    567     atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_exists function");
    568 }
    569 ATF_TC_BODY(exists, tc)
    570 {
    571     atf_error_t err;
    572     atf_fs_path_t pdir, pfile;
    573     bool b;
    574 
    575     RE(atf_fs_path_init_fmt(&pdir, "dir"));
    576     RE(atf_fs_path_init_fmt(&pfile, "dir/file"));
    577 
    578     create_dir(atf_fs_path_cstring(&pdir), 0755);
    579     create_file(atf_fs_path_cstring(&pfile), 0644);
    580 
    581     printf("Checking existence of a directory\n");
    582     RE(atf_fs_exists(&pdir, &b));
    583     ATF_REQUIRE(b);
    584 
    585     printf("Checking existence of a file\n");
    586     RE(atf_fs_exists(&pfile, &b));
    587     ATF_REQUIRE(b);
    588 
    589     /* XXX: This should probably be a separate test case to let the user
    590      * be aware that some tests were skipped because privileges were not
    591      * correct. */
    592     if (!atf_user_is_root()) {
    593         printf("Checking existence of a file inside a directory without "
    594                "permissions\n");
    595         ATF_REQUIRE(chmod(atf_fs_path_cstring(&pdir), 0000) != -1);
    596         err = atf_fs_exists(&pfile, &b);
    597         ATF_REQUIRE(atf_is_error(err));
    598         ATF_REQUIRE(atf_error_is(err, "libc"));
    599         ATF_REQUIRE(chmod(atf_fs_path_cstring(&pdir), 0755) != -1);
    600         atf_error_free(err);
    601     }
    602 
    603     printf("Checking existence of a non-existent file\n");
    604     ATF_REQUIRE(unlink(atf_fs_path_cstring(&pfile)) != -1);
    605     RE(atf_fs_exists(&pfile, &b));
    606     ATF_REQUIRE(!b);
    607 
    608     atf_fs_path_fini(&pfile);
    609     atf_fs_path_fini(&pdir);
    610 }
    611 
    612 ATF_TC(eaccess);
    613 ATF_TC_HEAD(eaccess, tc)
    614 {
    615     atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_eaccess function");
    616 }
    617 ATF_TC_BODY(eaccess, tc)
    618 {
    619     const int modes[] = { atf_fs_access_f, atf_fs_access_r, atf_fs_access_w,
    620                           atf_fs_access_x, 0 };
    621     const int *m;
    622     struct tests {
    623         mode_t fmode;
    624         int amode;
    625         int uerror;
    626         int rerror;
    627     } tests[] = {
    628         { 0000, atf_fs_access_r, EACCES, 0 },
    629         { 0000, atf_fs_access_w, EACCES, 0 },
    630         { 0000, atf_fs_access_x, EACCES, EACCES },
    631 
    632         { 0001, atf_fs_access_r, EACCES, 0 },
    633         { 0001, atf_fs_access_w, EACCES, 0 },
    634         { 0001, atf_fs_access_x, EACCES, 0 },
    635         { 0002, atf_fs_access_r, EACCES, 0 },
    636         { 0002, atf_fs_access_w, EACCES, 0 },
    637         { 0002, atf_fs_access_x, EACCES, EACCES },
    638         { 0004, atf_fs_access_r, EACCES, 0 },
    639         { 0004, atf_fs_access_w, EACCES, 0 },
    640         { 0004, atf_fs_access_x, EACCES, EACCES },
    641 
    642         { 0010, atf_fs_access_r, EACCES, 0 },
    643         { 0010, atf_fs_access_w, EACCES, 0 },
    644         { 0010, atf_fs_access_x, 0,      0 },
    645         { 0020, atf_fs_access_r, EACCES, 0 },
    646         { 0020, atf_fs_access_w, 0,      0 },
    647         { 0020, atf_fs_access_x, EACCES, EACCES },
    648         { 0040, atf_fs_access_r, 0,      0 },
    649         { 0040, atf_fs_access_w, EACCES, 0 },
    650         { 0040, atf_fs_access_x, EACCES, EACCES },
    651 
    652         { 0100, atf_fs_access_r, EACCES, 0 },
    653         { 0100, atf_fs_access_w, EACCES, 0 },
    654         { 0100, atf_fs_access_x, 0,      0 },
    655         { 0200, atf_fs_access_r, EACCES, 0 },
    656         { 0200, atf_fs_access_w, 0,      0 },
    657         { 0200, atf_fs_access_x, EACCES, EACCES },
    658         { 0400, atf_fs_access_r, 0,      0 },
    659         { 0400, atf_fs_access_w, EACCES, 0 },
    660         { 0400, atf_fs_access_x, EACCES, EACCES },
    661 
    662         { 0, 0, 0, 0 }
    663     };
    664     struct tests *t;
    665     atf_fs_path_t p;
    666     atf_error_t err;
    667 
    668     RE(atf_fs_path_init_fmt(&p, "the-file"));
    669 
    670     printf("Non-existent file checks\n");
    671     for (m = &modes[0]; *m != 0; m++) {
    672         err = atf_fs_eaccess(&p, *m);
    673         ATF_REQUIRE(atf_is_error(err));
    674         ATF_REQUIRE(atf_error_is(err, "libc"));
    675         ATF_REQUIRE_EQ(atf_libc_error_code(err), ENOENT);
    676         atf_error_free(err);
    677     }
    678 
    679     create_file(atf_fs_path_cstring(&p), 0000);
    680     ATF_REQUIRE(chown(atf_fs_path_cstring(&p), geteuid(), getegid()) != -1);
    681 
    682     for (t = &tests[0]; t->amode != 0; t++) {
    683         const int experr = atf_user_is_root() ? t->rerror : t->uerror;
    684 
    685         printf("\n");
    686         printf("File mode     : %04o\n", (unsigned int)t->fmode);
    687         printf("Access mode   : 0x%02x\n", t->amode);
    688 
    689         ATF_REQUIRE(chmod(atf_fs_path_cstring(&p), t->fmode) != -1);
    690 
    691         /* First, existence check. */
    692         err = atf_fs_eaccess(&p, atf_fs_access_f);
    693         ATF_REQUIRE(!atf_is_error(err));
    694 
    695         /* Now do the specific test case. */
    696         printf("Expected error: %d\n", experr);
    697         err = atf_fs_eaccess(&p, t->amode);
    698         if (atf_is_error(err)) {
    699             if (atf_error_is(err, "libc"))
    700                 printf("Error         : %d\n", atf_libc_error_code(err));
    701             else
    702                 printf("Error         : Non-libc error\n");
    703         } else
    704                 printf("Error         : None\n");
    705         if (experr == 0) {
    706             ATF_REQUIRE(!atf_is_error(err));
    707         } else {
    708             ATF_REQUIRE(atf_is_error(err));
    709             ATF_REQUIRE(atf_error_is(err, "libc"));
    710             ATF_REQUIRE_EQ(atf_libc_error_code(err), experr);
    711             atf_error_free(err);
    712         }
    713     }
    714 
    715     atf_fs_path_fini(&p);
    716 }
    717 
    718 ATF_TC(getcwd);
    719 ATF_TC_HEAD(getcwd, tc)
    720 {
    721     atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_getcwd function");
    722 }
    723 ATF_TC_BODY(getcwd, tc)
    724 {
    725     atf_fs_path_t cwd1, cwd2;
    726 
    727     create_dir ("root", 0755);
    728 
    729     RE(atf_fs_getcwd(&cwd1));
    730     ATF_REQUIRE(chdir("root") != -1);
    731     RE(atf_fs_getcwd(&cwd2));
    732 
    733     RE(atf_fs_path_append_fmt(&cwd1, "root"));
    734 
    735     ATF_REQUIRE(atf_equal_fs_path_fs_path(&cwd1, &cwd2));
    736 
    737     atf_fs_path_fini(&cwd2);
    738     atf_fs_path_fini(&cwd1);
    739 }
    740 
    741 ATF_TC(rmdir_empty);
    742 ATF_TC_HEAD(rmdir_empty, tc)
    743 {
    744     atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_rmdir function");
    745 }
    746 ATF_TC_BODY(rmdir_empty, tc)
    747 {
    748     atf_fs_path_t p;
    749 
    750     RE(atf_fs_path_init_fmt(&p, "test-dir"));
    751 
    752     ATF_REQUIRE(mkdir("test-dir", 0755) != -1);
    753     ATF_REQUIRE(exists(&p));
    754     RE(atf_fs_rmdir(&p));
    755     ATF_REQUIRE(!exists(&p));
    756 
    757     atf_fs_path_fini(&p);
    758 }
    759 
    760 ATF_TC(rmdir_enotempty);
    761 ATF_TC_HEAD(rmdir_enotempty, tc)
    762 {
    763     atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_rmdir function");
    764 }
    765 ATF_TC_BODY(rmdir_enotempty, tc)
    766 {
    767     atf_fs_path_t p;
    768     atf_error_t err;
    769 
    770     RE(atf_fs_path_init_fmt(&p, "test-dir"));
    771 
    772     ATF_REQUIRE(mkdir("test-dir", 0755) != -1);
    773     ATF_REQUIRE(exists(&p));
    774     create_file("test-dir/foo", 0644);
    775 
    776     err = atf_fs_rmdir(&p);
    777     ATF_REQUIRE(atf_is_error(err));
    778     ATF_REQUIRE(atf_error_is(err, "libc"));
    779     ATF_REQUIRE_EQ(atf_libc_error_code(err), ENOTEMPTY);
    780     atf_error_free(err);
    781 
    782     atf_fs_path_fini(&p);
    783 }
    784 
    785 ATF_TC(rmdir_eperm);
    786 ATF_TC_HEAD(rmdir_eperm, tc)
    787 {
    788     atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_rmdir function");
    789 }
    790 ATF_TC_BODY(rmdir_eperm, tc)
    791 {
    792     atf_fs_path_t p;
    793     atf_error_t err;
    794 
    795     RE(atf_fs_path_init_fmt(&p, "test-dir/foo"));
    796 
    797     ATF_REQUIRE(mkdir("test-dir", 0755) != -1);
    798     ATF_REQUIRE(mkdir("test-dir/foo", 0755) != -1);
    799     ATF_REQUIRE(chmod("test-dir", 0555) != -1);
    800     ATF_REQUIRE(exists(&p));
    801 
    802     err = atf_fs_rmdir(&p);
    803     if (atf_user_is_root()) {
    804         ATF_REQUIRE(!atf_is_error(err));
    805     } else {
    806         ATF_REQUIRE(atf_is_error(err));
    807         ATF_REQUIRE(atf_error_is(err, "libc"));
    808         ATF_REQUIRE_EQ(atf_libc_error_code(err), EACCES);
    809         atf_error_free(err);
    810     }
    811 
    812     atf_fs_path_fini(&p);
    813 }
    814 
    815 ATF_TC(mkdtemp_ok);
    816 ATF_TC_HEAD(mkdtemp_ok, tc)
    817 {
    818     atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_mkdtemp function, "
    819                       "successful execution");
    820 }
    821 ATF_TC_BODY(mkdtemp_ok, tc)
    822 {
    823     atf_fs_path_t p1, p2;
    824     atf_fs_stat_t s1, s2;
    825 
    826     RE(atf_fs_path_init_fmt(&p1, "testdir.XXXXXX"));
    827     RE(atf_fs_path_init_fmt(&p2, "testdir.XXXXXX"));
    828     RE(atf_fs_mkdtemp(&p1));
    829     RE(atf_fs_mkdtemp(&p2));
    830     ATF_REQUIRE(!atf_equal_fs_path_fs_path(&p1, &p2));
    831     ATF_REQUIRE(exists(&p1));
    832     ATF_REQUIRE(exists(&p2));
    833 
    834     RE(atf_fs_stat_init(&s1, &p1));
    835     ATF_REQUIRE_EQ(atf_fs_stat_get_type(&s1), atf_fs_stat_dir_type);
    836     ATF_REQUIRE( atf_fs_stat_is_owner_readable(&s1));
    837     ATF_REQUIRE( atf_fs_stat_is_owner_writable(&s1));
    838     ATF_REQUIRE( atf_fs_stat_is_owner_executable(&s1));
    839     ATF_REQUIRE(!atf_fs_stat_is_group_readable(&s1));
    840     ATF_REQUIRE(!atf_fs_stat_is_group_writable(&s1));
    841     ATF_REQUIRE(!atf_fs_stat_is_group_executable(&s1));
    842     ATF_REQUIRE(!atf_fs_stat_is_other_readable(&s1));
    843     ATF_REQUIRE(!atf_fs_stat_is_other_writable(&s1));
    844     ATF_REQUIRE(!atf_fs_stat_is_other_executable(&s1));
    845 
    846     RE(atf_fs_stat_init(&s2, &p2));
    847     ATF_REQUIRE_EQ(atf_fs_stat_get_type(&s2), atf_fs_stat_dir_type);
    848     ATF_REQUIRE( atf_fs_stat_is_owner_readable(&s2));
    849     ATF_REQUIRE( atf_fs_stat_is_owner_writable(&s2));
    850     ATF_REQUIRE( atf_fs_stat_is_owner_executable(&s2));
    851     ATF_REQUIRE(!atf_fs_stat_is_group_readable(&s2));
    852     ATF_REQUIRE(!atf_fs_stat_is_group_writable(&s2));
    853     ATF_REQUIRE(!atf_fs_stat_is_group_executable(&s2));
    854     ATF_REQUIRE(!atf_fs_stat_is_other_readable(&s2));
    855     ATF_REQUIRE(!atf_fs_stat_is_other_writable(&s2));
    856     ATF_REQUIRE(!atf_fs_stat_is_other_executable(&s2));
    857 
    858     atf_fs_stat_fini(&s2);
    859     atf_fs_stat_fini(&s1);
    860     atf_fs_path_fini(&p2);
    861     atf_fs_path_fini(&p1);
    862 }
    863 
    864 ATF_TC(mkdtemp_err);
    865 ATF_TC_HEAD(mkdtemp_err, tc)
    866 {
    867     atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_mkdtemp function, "
    868                       "error conditions");
    869     atf_tc_set_md_var(tc, "require.user", "unprivileged");
    870 }
    871 ATF_TC_BODY(mkdtemp_err, tc)
    872 {
    873     atf_error_t err;
    874     atf_fs_path_t p;
    875 
    876     ATF_REQUIRE(mkdir("dir", 0555) != -1);
    877 
    878     RE(atf_fs_path_init_fmt(&p, "dir/testdir.XXXXXX"));
    879 
    880     err = atf_fs_mkdtemp(&p);
    881     ATF_REQUIRE(atf_is_error(err));
    882     ATF_REQUIRE(atf_error_is(err, "libc"));
    883     ATF_CHECK_EQ(atf_libc_error_code(err), EACCES);
    884     atf_error_free(err);
    885 
    886     ATF_CHECK(!exists(&p));
    887     ATF_CHECK(strcmp(atf_fs_path_cstring(&p), "dir/testdir.XXXXXX") == 0);
    888 
    889     atf_fs_path_fini(&p);
    890 }
    891 
    892 static
    893 void
    894 do_umask_check(atf_error_t (*const mk_func)(atf_fs_path_t *),
    895                atf_fs_path_t *path, const mode_t test_mask,
    896                const char *str_mask, const char *exp_name)
    897 {
    898     char buf[1024];
    899     int old_umask;
    900     atf_error_t err;
    901 
    902     printf("Creating temporary %s with umask %s\n", exp_name, str_mask);
    903 
    904     old_umask = umask(test_mask);
    905     err = mk_func(path);
    906     (void)umask(old_umask);
    907 
    908     ATF_REQUIRE(atf_is_error(err));
    909     ATF_REQUIRE(atf_error_is(err, "invalid_umask"));
    910     atf_error_format(err, buf, sizeof(buf));
    911     ATF_CHECK(strstr(buf, exp_name) != NULL);
    912     ATF_CHECK(strstr(buf, str_mask) != NULL);
    913     atf_error_free(err);
    914 }
    915 
    916 ATF_TC(mkdtemp_umask);
    917 ATF_TC_HEAD(mkdtemp_umask, tc)
    918 {
    919     atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_mkdtemp function "
    920                       "causing an error due to a too strict umask");
    921 }
    922 ATF_TC_BODY(mkdtemp_umask, tc)
    923 {
    924     atf_fs_path_t p;
    925 
    926     RE(atf_fs_path_init_fmt(&p, "testdir.XXXXXX"));
    927 
    928     do_umask_check(atf_fs_mkdtemp, &p, 00100, "00100", "directory");
    929     do_umask_check(atf_fs_mkdtemp, &p, 00200, "00200", "directory");
    930     do_umask_check(atf_fs_mkdtemp, &p, 00400, "00400", "directory");
    931     do_umask_check(atf_fs_mkdtemp, &p, 00500, "00500", "directory");
    932     do_umask_check(atf_fs_mkdtemp, &p, 00600, "00600", "directory");
    933 
    934     atf_fs_path_fini(&p);
    935 }
    936 
    937 ATF_TC(mkstemp_ok);
    938 ATF_TC_HEAD(mkstemp_ok, tc)
    939 {
    940     atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_mkstemp function, "
    941                       "successful execution");
    942 }
    943 ATF_TC_BODY(mkstemp_ok, tc)
    944 {
    945     int fd1, fd2;
    946     atf_fs_path_t p1, p2;
    947     atf_fs_stat_t s1, s2;
    948 
    949     RE(atf_fs_path_init_fmt(&p1, "testfile.XXXXXX"));
    950     RE(atf_fs_path_init_fmt(&p2, "testfile.XXXXXX"));
    951     fd1 = fd2 = -1;
    952     RE(atf_fs_mkstemp(&p1, &fd1));
    953     RE(atf_fs_mkstemp(&p2, &fd2));
    954     ATF_REQUIRE(!atf_equal_fs_path_fs_path(&p1, &p2));
    955     ATF_REQUIRE(exists(&p1));
    956     ATF_REQUIRE(exists(&p2));
    957 
    958     ATF_CHECK(fd1 != -1);
    959     ATF_CHECK(fd2 != -1);
    960     ATF_CHECK(write(fd1, "foo", 3) == 3);
    961     ATF_CHECK(write(fd2, "bar", 3) == 3);
    962     close(fd1);
    963     close(fd2);
    964 
    965     RE(atf_fs_stat_init(&s1, &p1));
    966     ATF_CHECK_EQ(atf_fs_stat_get_type(&s1), atf_fs_stat_reg_type);
    967     ATF_CHECK( atf_fs_stat_is_owner_readable(&s1));
    968     ATF_CHECK( atf_fs_stat_is_owner_writable(&s1));
    969     ATF_CHECK(!atf_fs_stat_is_owner_executable(&s1));
    970     ATF_CHECK(!atf_fs_stat_is_group_readable(&s1));
    971     ATF_CHECK(!atf_fs_stat_is_group_writable(&s1));
    972     ATF_CHECK(!atf_fs_stat_is_group_executable(&s1));
    973     ATF_CHECK(!atf_fs_stat_is_other_readable(&s1));
    974     ATF_CHECK(!atf_fs_stat_is_other_writable(&s1));
    975     ATF_CHECK(!atf_fs_stat_is_other_executable(&s1));
    976 
    977     RE(atf_fs_stat_init(&s2, &p2));
    978     ATF_CHECK_EQ(atf_fs_stat_get_type(&s2), atf_fs_stat_reg_type);
    979     ATF_CHECK( atf_fs_stat_is_owner_readable(&s2));
    980     ATF_CHECK( atf_fs_stat_is_owner_writable(&s2));
    981     ATF_CHECK(!atf_fs_stat_is_owner_executable(&s2));
    982     ATF_CHECK(!atf_fs_stat_is_group_readable(&s2));
    983     ATF_CHECK(!atf_fs_stat_is_group_writable(&s2));
    984     ATF_CHECK(!atf_fs_stat_is_group_executable(&s2));
    985     ATF_CHECK(!atf_fs_stat_is_other_readable(&s2));
    986     ATF_CHECK(!atf_fs_stat_is_other_writable(&s2));
    987     ATF_CHECK(!atf_fs_stat_is_other_executable(&s2));
    988 
    989     atf_fs_stat_fini(&s2);
    990     atf_fs_stat_fini(&s1);
    991     atf_fs_path_fini(&p2);
    992     atf_fs_path_fini(&p1);
    993 }
    994 
    995 ATF_TC(mkstemp_err);
    996 ATF_TC_HEAD(mkstemp_err, tc)
    997 {
    998     atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_mkstemp function, "
    999                       "error conditions");
   1000     atf_tc_set_md_var(tc, "require.user", "unprivileged");
   1001 }
   1002 ATF_TC_BODY(mkstemp_err, tc)
   1003 {
   1004     int fd;
   1005     atf_error_t err;
   1006     atf_fs_path_t p;
   1007 
   1008     ATF_REQUIRE(mkdir("dir", 0555) != -1);
   1009 
   1010     RE(atf_fs_path_init_fmt(&p, "dir/testfile.XXXXXX"));
   1011     fd = 1234;
   1012 
   1013     err = atf_fs_mkstemp(&p, &fd);
   1014     ATF_REQUIRE(atf_is_error(err));
   1015     ATF_REQUIRE(atf_error_is(err, "libc"));
   1016     ATF_CHECK_EQ(atf_libc_error_code(err), EACCES);
   1017     atf_error_free(err);
   1018 
   1019     ATF_CHECK(!exists(&p));
   1020     ATF_CHECK(strcmp(atf_fs_path_cstring(&p), "dir/testfile.XXXXXX") == 0);
   1021     ATF_CHECK_EQ(fd, 1234);
   1022 
   1023     atf_fs_path_fini(&p);
   1024 }
   1025 
   1026 ATF_TC(mkstemp_umask);
   1027 ATF_TC_HEAD(mkstemp_umask, tc)
   1028 {
   1029     atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_mkstemp function "
   1030                       "causing an error due to a too strict umask");
   1031 }
   1032 ATF_TC_BODY(mkstemp_umask, tc)
   1033 {
   1034     atf_fs_path_t p;
   1035 
   1036     RE(atf_fs_path_init_fmt(&p, "testfile.XXXXXX"));
   1037 
   1038     do_umask_check(mkstemp_discard_fd, &p, 00100, "00100", "regular file");
   1039     do_umask_check(mkstemp_discard_fd, &p, 00200, "00200", "regular file");
   1040     do_umask_check(mkstemp_discard_fd, &p, 00400, "00400", "regular file");
   1041 
   1042     atf_fs_path_fini(&p);
   1043 }
   1044 
   1045 /* ---------------------------------------------------------------------
   1046  * Main.
   1047  * --------------------------------------------------------------------- */
   1048 
   1049 ATF_TP_ADD_TCS(tp)
   1050 {
   1051     /* Add the tests for the "atf_fs_path" type. */
   1052     ATF_TP_ADD_TC(tp, path_normalize);
   1053     ATF_TP_ADD_TC(tp, path_copy);
   1054     ATF_TP_ADD_TC(tp, path_is_absolute);
   1055     ATF_TP_ADD_TC(tp, path_is_root);
   1056     ATF_TP_ADD_TC(tp, path_branch_path);
   1057     ATF_TP_ADD_TC(tp, path_leaf_name);
   1058     ATF_TP_ADD_TC(tp, path_append);
   1059     ATF_TP_ADD_TC(tp, path_to_absolute);
   1060     ATF_TP_ADD_TC(tp, path_equal);
   1061 
   1062     /* Add the tests for the "atf_fs_stat" type. */
   1063     ATF_TP_ADD_TC(tp, stat_mode);
   1064     ATF_TP_ADD_TC(tp, stat_type);
   1065     ATF_TP_ADD_TC(tp, stat_perms);
   1066 
   1067     /* Add the tests for the free functions. */
   1068     ATF_TP_ADD_TC(tp, eaccess);
   1069     ATF_TP_ADD_TC(tp, exists);
   1070     ATF_TP_ADD_TC(tp, getcwd);
   1071     ATF_TP_ADD_TC(tp, rmdir_empty);
   1072     ATF_TP_ADD_TC(tp, rmdir_enotempty);
   1073     ATF_TP_ADD_TC(tp, rmdir_eperm);
   1074     ATF_TP_ADD_TC(tp, mkdtemp_ok);
   1075     ATF_TP_ADD_TC(tp, mkdtemp_err);
   1076     ATF_TP_ADD_TC(tp, mkdtemp_umask);
   1077     ATF_TP_ADD_TC(tp, mkstemp_ok);
   1078     ATF_TP_ADD_TC(tp, mkstemp_err);
   1079     ATF_TP_ADD_TC(tp, mkstemp_umask);
   1080 
   1081     return atf_no_error();
   1082 }
   1083