13b6cf63jmmv/* Copyright (c) 2007 The NetBSD Foundation, Inc.
245147a9marcel * All rights reserved.
345147a9marcel *
445147a9marcel * Redistribution and use in source and binary forms, with or without
545147a9marcel * modification, are permitted provided that the following conditions
645147a9marcel * are met:
745147a9marcel * 1. Redistributions of source code must retain the above copyright
845147a9marcel *    notice, this list of conditions and the following disclaimer.
945147a9marcel * 2. Redistributions in binary form must reproduce the above copyright
1045147a9marcel *    notice, this list of conditions and the following disclaimer in the
1145147a9marcel *    documentation and/or other materials provided with the distribution.
1245147a9marcel *
1345147a9marcel * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
1445147a9marcel * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
1545147a9marcel * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
1645147a9marcel * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1745147a9marcel * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
1845147a9marcel * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1945147a9marcel * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
2045147a9marcel * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2145147a9marcel * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
2245147a9marcel * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
2345147a9marcel * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
243b6cf63jmmv * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  */
253b6cf63jmmv
263b6cf63jmmv#include "atf-c/detail/fs.h"
2745147a9marcel
2845147a9marcel#include <sys/types.h>
2945147a9marcel#include <sys/stat.h>
3045147a9marcel
3145147a9marcel#include <errno.h>
3245147a9marcel#include <fcntl.h>
3345147a9marcel#include <stdio.h>
3445147a9marcel#include <stdlib.h>
3545147a9marcel#include <string.h>
3645147a9marcel#include <unistd.h>
3745147a9marcel
3845147a9marcel#include <atf-c.h>
3945147a9marcel
403b6cf63jmmv#include "atf-c/detail/test_helpers.h"
413b6cf63jmmv#include "atf-c/detail/user.h"
4245147a9marcel
4345147a9marcel/* ---------------------------------------------------------------------
4445147a9marcel * Auxiliary functions.
4545147a9marcel * --------------------------------------------------------------------- */
4645147a9marcel
4745147a9marcelstatic
4845147a9marcelvoid
4945147a9marcelcreate_dir(const char *p, int mode)
5045147a9marcel{
5145147a9marcel    int ret;
5245147a9marcel
5345147a9marcel    ret = mkdir(p, mode);
5445147a9marcel    if (ret == -1)
5545147a9marcel        atf_tc_fail("Could not create helper directory %s", p);
5645147a9marcel}
5745147a9marcel
5845147a9marcelstatic
5945147a9marcelvoid
6045147a9marcelcreate_file(const char *p, int mode)
6145147a9marcel{
6245147a9marcel    int fd;
6345147a9marcel
6445147a9marcel    fd = open(p, O_CREAT | O_WRONLY | O_TRUNC, mode);
6545147a9marcel    if (fd == -1)
6645147a9marcel        atf_tc_fail("Could not create helper file %s", p);
6745147a9marcel    close(fd);
6845147a9marcel}
6945147a9marcel
7045147a9marcelstatic
7145147a9marcelbool
7245147a9marcelexists(const atf_fs_path_t *p)
7345147a9marcel{
7445147a9marcel    return access(atf_fs_path_cstring(p), F_OK) == 0;
7545147a9marcel}
7645147a9marcel
7745147a9marcelstatic
7845147a9marcelatf_error_t
7945147a9marcelmkstemp_discard_fd(atf_fs_path_t *p)
8045147a9marcel{
8145147a9marcel    int fd;
8245147a9marcel    atf_error_t err = atf_fs_mkstemp(p, &fd);
8345147a9marcel    if (!atf_is_error(err))
8445147a9marcel        close(fd);
8545147a9marcel    return err;
8645147a9marcel}
8745147a9marcel
8845147a9marcel/* ---------------------------------------------------------------------
8945147a9marcel * Test cases for the "atf_fs_path" type.
9045147a9marcel * --------------------------------------------------------------------- */
9145147a9marcel
9245147a9marcelATF_TC(path_normalize);
9345147a9marcelATF_TC_HEAD(path_normalize, tc)
9445147a9marcel{
9545147a9marcel    atf_tc_set_md_var(tc, "descr", "Tests the path's normalization");
9645147a9marcel}
9745147a9marcelATF_TC_BODY(path_normalize, tc)
9845147a9marcel{
9945147a9marcel    struct test {
10045147a9marcel        const char *in;
10145147a9marcel        const char *out;
10245147a9marcel    } tests[] = {
10345147a9marcel        { ".", ".", },
10445147a9marcel        { "..", "..", },
10545147a9marcel
10645147a9marcel        { "/", "/", },
10745147a9marcel        { "//", "/", }, /* NO_CHECK_STYLE */
10845147a9marcel        { "///", "/", }, /* NO_CHECK_STYLE */
10945147a9marcel
11045147a9marcel        { "foo", "foo", },
11145147a9marcel        { "foo/", "foo", },
11245147a9marcel        { "foo/bar", "foo/bar", },
11345147a9marcel        { "foo/bar/", "foo/bar", },
11445147a9marcel
11545147a9marcel        { "/foo", "/foo", },
11645147a9marcel        { "/foo/bar", "/foo/bar", },
11745147a9marcel        { "/foo/bar/", "/foo/bar", },
11845147a9marcel
11945147a9marcel        { "///foo", "/foo", }, /* NO_CHECK_STYLE */
12045147a9marcel        { "///foo///bar", "/foo/bar", }, /* NO_CHECK_STYLE */
12145147a9marcel        { "///foo///bar///", "/foo/bar", }, /* NO_CHECK_STYLE */
12245147a9marcel
12345147a9marcel        { NULL, NULL }
12445147a9marcel    };
12545147a9marcel    struct test *t;
12645147a9marcel
12745147a9marcel    for (t = &tests[0]; t->in != NULL; t++) {
12845147a9marcel        atf_fs_path_t p;
12945147a9marcel
13045147a9marcel        printf("Input          : >%s<\n", t->in);
13145147a9marcel        printf("Expected output: >%s<\n", t->out);
13245147a9marcel
13345147a9marcel        RE(atf_fs_path_init_fmt(&p, "%s", t->in));
13445147a9marcel        printf("Output         : >%s<\n", atf_fs_path_cstring(&p));
13545147a9marcel        ATF_REQUIRE(strcmp(atf_fs_path_cstring(&p), t->out) == 0);
13645147a9marcel        atf_fs_path_fini(&p);
13745147a9marcel
13845147a9marcel        printf("\n");
13945147a9marcel    }
14045147a9marcel}
14145147a9marcel
14245147a9marcelATF_TC(path_copy);
14345147a9marcelATF_TC_HEAD(path_copy, tc)
14445147a9marcel{
14545147a9marcel    atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_path_copy constructor");
14645147a9marcel}
14745147a9marcelATF_TC_BODY(path_copy, tc)
14845147a9marcel{
14945147a9marcel    atf_fs_path_t str, str2;
15045147a9marcel
15145147a9marcel    RE(atf_fs_path_init_fmt(&str, "foo"));
15245147a9marcel    RE(atf_fs_path_copy(&str2, &str));
15345147a9marcel
15445147a9marcel    ATF_REQUIRE(atf_equal_fs_path_fs_path(&str, &str2));
15545147a9marcel
15645147a9marcel    RE(atf_fs_path_append_fmt(&str2, "bar"));
15745147a9marcel
15845147a9marcel    ATF_REQUIRE(!atf_equal_fs_path_fs_path(&str, &str2));
15945147a9marcel
16045147a9marcel    atf_fs_path_fini(&str2);
16145147a9marcel    atf_fs_path_fini(&str);
16245147a9marcel}
16345147a9marcel
16445147a9marcelATF_TC(path_is_absolute);
16545147a9marcelATF_TC_HEAD(path_is_absolute, tc)
16645147a9marcel{
16745147a9marcel    atf_tc_set_md_var(tc, "descr", "Tests the path::is_absolute function");
16845147a9marcel}
16945147a9marcelATF_TC_BODY(path_is_absolute, tc)
17045147a9marcel{
17145147a9marcel    struct test {
17245147a9marcel        const char *in;
17345147a9marcel        bool abs;
17445147a9marcel    } tests[] = {
17545147a9marcel        { "/", true },
17645147a9marcel        { "////", true }, /* NO_CHECK_STYLE */
17745147a9marcel        { "////a", true }, /* NO_CHECK_STYLE */
17845147a9marcel        { "//a//", true }, /* NO_CHECK_STYLE */
17945147a9marcel        { "a////", false }, /* NO_CHECK_STYLE */
18045147a9marcel        { "../foo", false },
18145147a9marcel        { NULL, false },
18245147a9marcel    };
18345147a9marcel    struct test *t;
18445147a9marcel
18545147a9marcel    for (t = &tests[0]; t->in != NULL; t++) {
18645147a9marcel        atf_fs_path_t p;
18745147a9marcel
18845147a9marcel        printf("Input          : %s\n", t->in);
18945147a9marcel        printf("Expected result: %s\n", t->abs ? "true" : "false");
19045147a9marcel
19145147a9marcel        RE(atf_fs_path_init_fmt(&p, "%s", t->in));
19245147a9marcel        printf("Result         : %s\n",
19345147a9marcel               atf_fs_path_is_absolute(&p) ? "true" : "false");
19445147a9marcel        if (t->abs)
19545147a9marcel            ATF_REQUIRE(atf_fs_path_is_absolute(&p));
19645147a9marcel        else
19745147a9marcel            ATF_REQUIRE(!atf_fs_path_is_absolute(&p));
19845147a9marcel        atf_fs_path_fini(&p);
19945147a9marcel
20045147a9marcel        printf("\n");
20145147a9marcel    }
20245147a9marcel}
20345147a9marcel
20445147a9marcelATF_TC(path_is_root);
20545147a9marcelATF_TC_HEAD(path_is_root, tc)
20645147a9marcel{
20745147a9marcel    atf_tc_set_md_var(tc, "descr", "Tests the path::is_root function");
20845147a9marcel}
20945147a9marcelATF_TC_BODY(path_is_root, tc)
21045147a9marcel{
21145147a9marcel    struct test {
21245147a9marcel        const char *in;
21345147a9marcel        bool root;
21445147a9marcel    } tests[] = {
21545147a9marcel        { "/", true },
21645147a9marcel        { "////", true }, /* NO_CHECK_STYLE */
21745147a9marcel        { "////a", false }, /* NO_CHECK_STYLE */
21845147a9marcel        { "//a//", false }, /* NO_CHECK_STYLE */
21945147a9marcel        { "a////", false }, /* NO_CHECK_STYLE */
22045147a9marcel        { "../foo", false },
22145147a9marcel        { NULL, false },
22245147a9marcel    };
22345147a9marcel    struct test *t;
22445147a9marcel
22545147a9marcel    for (t = &tests[0]; t->in != NULL; t++) {
22645147a9marcel        atf_fs_path_t p;
22745147a9marcel
22845147a9marcel        printf("Input          : %s\n", t->in);
22945147a9marcel        printf("Expected result: %s\n", t->root ? "true" : "false");
23045147a9marcel
23145147a9marcel        RE(atf_fs_path_init_fmt(&p, "%s", t->in));
23245147a9marcel        printf("Result         : %s\n",
23345147a9marcel               atf_fs_path_is_root(&p) ? "true" : "false");
23445147a9marcel        if (t->root)
23545147a9marcel            ATF_REQUIRE(atf_fs_path_is_root(&p));
23645147a9marcel        else
23745147a9marcel            ATF_REQUIRE(!atf_fs_path_is_root(&p));
23845147a9marcel        atf_fs_path_fini(&p);
23945147a9marcel
24045147a9marcel        printf("\n");
24145147a9marcel    }
24245147a9marcel}
24345147a9marcel
24445147a9marcelATF_TC(path_branch_path);
24545147a9marcelATF_TC_HEAD(path_branch_path, tc)
24645147a9marcel{
24745147a9marcel    atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_path_branch_path "
24845147a9marcel                      "function");
24945147a9marcel}
25045147a9marcelATF_TC_BODY(path_branch_path, tc)
25145147a9marcel{
25245147a9marcel    struct test {
25345147a9marcel        const char *in;
25445147a9marcel        const char *branch;
25545147a9marcel    } tests[] = {
25645147a9marcel        { ".", "." },
25745147a9marcel        { "foo", "." },
25845147a9marcel        { "foo/bar", "foo" },
25945147a9marcel        { "/foo", "/" },
26045147a9marcel        { "/foo/bar", "/foo" },
26145147a9marcel        { NULL, NULL },
26245147a9marcel    };
26345147a9marcel    struct test *t;
26445147a9marcel
26545147a9marcel    for (t = &tests[0]; t->in != NULL; t++) {
26645147a9marcel        atf_fs_path_t p, bp;
26745147a9marcel
26845147a9marcel        printf("Input          : %s\n", t->in);
26945147a9marcel        printf("Expected output: %s\n", t->branch);
27045147a9marcel
27145147a9marcel        RE(atf_fs_path_init_fmt(&p, "%s", t->in));
27245147a9marcel        RE(atf_fs_path_branch_path(&p, &bp));
27345147a9marcel        printf("Output         : %s\n", atf_fs_path_cstring(&bp));
27445147a9marcel        ATF_REQUIRE(strcmp(atf_fs_path_cstring(&bp), t->branch) == 0);
27545147a9marcel        atf_fs_path_fini(&bp);
27645147a9marcel        atf_fs_path_fini(&p);
27745147a9marcel
27845147a9marcel        printf("\n");
27945147a9marcel    }
28045147a9marcel}
28145147a9marcel
28245147a9marcelATF_TC(path_leaf_name);
28345147a9marcelATF_TC_HEAD(path_leaf_name, tc)
28445147a9marcel{
28545147a9marcel    atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_path_leaf_name "
28645147a9marcel                      "function");
28745147a9marcel}
28845147a9marcelATF_TC_BODY(path_leaf_name, tc)
28945147a9marcel{
29045147a9marcel    struct test {
29145147a9marcel        const char *in;
29245147a9marcel        const char *leaf;
29345147a9marcel    } tests[] = {
29445147a9marcel        { ".", "." },
29545147a9marcel        { "foo", "foo" },
29645147a9marcel        { "foo/bar", "bar" },
29745147a9marcel        { "/foo", "foo" },
29845147a9marcel        { "/foo/bar", "bar" },
29945147a9marcel        { NULL, NULL },
30045147a9marcel    };
30145147a9marcel    struct test *t;
30245147a9marcel
30345147a9marcel    for (t = &tests[0]; t->in != NULL; t++) {
30445147a9marcel        atf_fs_path_t p;
30545147a9marcel        atf_dynstr_t ln;
30645147a9marcel
30745147a9marcel        printf("Input          : %s\n", t->in);
30845147a9marcel        printf("Expected output: %s\n", t->leaf);
30945147a9marcel
31045147a9marcel        RE(atf_fs_path_init_fmt(&p, "%s", t->in));
31145147a9marcel        RE(atf_fs_path_leaf_name(&p, &ln));
31245147a9marcel        printf("Output         : %s\n", atf_dynstr_cstring(&ln));
31345147a9marcel        ATF_REQUIRE(atf_equal_dynstr_cstring(&ln, t->leaf));
31445147a9marcel        atf_dynstr_fini(&ln);
31545147a9marcel        atf_fs_path_fini(&p);
31645147a9marcel
31745147a9marcel        printf("\n");
31845147a9marcel    }
31945147a9marcel}
32045147a9marcel
32145147a9marcelATF_TC(path_append);
32245147a9marcelATF_TC_HEAD(path_append, tc)
32345147a9marcel{
32445147a9marcel    atf_tc_set_md_var(tc, "descr", "Tests the concatenation of multiple "
32545147a9marcel                      "paths");
32645147a9marcel}
32745147a9marcelATF_TC_BODY(path_append, tc)
32845147a9marcel{
32945147a9marcel    struct test {
33045147a9marcel        const char *in;
33145147a9marcel        const char *ap;
33245147a9marcel        const char *out;
33345147a9marcel    } tests[] = {
33445147a9marcel        { "foo", "bar", "foo/bar" },
33545147a9marcel        { "foo/", "/bar", "foo/bar" },
33645147a9marcel        { "foo/", "/bar/baz", "foo/bar/baz" },
33745147a9marcel        { "foo/", "///bar///baz", "foo/bar/baz" }, /* NO_CHECK_STYLE */
33845147a9marcel
33945147a9marcel        { NULL, NULL, NULL }
34045147a9marcel    };
34145147a9marcel    struct test *t;
34245147a9marcel
34345147a9marcel    for (t = &tests[0]; t->in != NULL; t++) {
34445147a9marcel        atf_fs_path_t p;
34545147a9marcel
34645147a9marcel        printf("Input          : >%s<\n", t->in);
34745147a9marcel        printf("Append         : >%s<\n", t->ap);
34845147a9marcel        printf("Expected output: >%s<\n", t->out);
34945147a9marcel
35045147a9marcel        RE(atf_fs_path_init_fmt(&p, "%s", t->in));
35145147a9marcel
35245147a9marcel        RE(atf_fs_path_append_fmt(&p, "%s", t->ap));
35345147a9marcel
35445147a9marcel        printf("Output         : >%s<\n", atf_fs_path_cstring(&p));
35545147a9marcel        ATF_REQUIRE(strcmp(atf_fs_path_cstring(&p), t->out) == 0);
35645147a9marcel
35745147a9marcel        atf_fs_path_fini(&p);
35845147a9marcel
35945147a9marcel        printf("\n");
36045147a9marcel    }
36145147a9marcel}
36245147a9marcel
36345147a9marcelATF_TC(path_to_absolute);
36445147a9marcelATF_TC_HEAD(path_to_absolute, tc)
36545147a9marcel{
36645147a9marcel    atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_path_to_absolute "
36745147a9marcel                      "function");
36845147a9marcel}
36945147a9marcelATF_TC_BODY(path_to_absolute, tc)
37045147a9marcel{
37145147a9marcel    const char *names[] = { ".", "dir", NULL };
37245147a9marcel    const char **n;
37345147a9marcel
37445147a9marcel    ATF_REQUIRE(mkdir("dir", 0755) != -1);
37545147a9marcel
37645147a9marcel    for (n = names; *n != NULL; n++) {
37745147a9marcel        atf_fs_path_t p, p2;
37845147a9marcel        atf_fs_stat_t st1, st2;
37945147a9marcel
38045147a9marcel        RE(atf_fs_path_init_fmt(&p, "%s", *n));
38145147a9marcel        RE(atf_fs_stat_init(&st1, &p));
38245147a9marcel        printf("Relative path: %s\n", atf_fs_path_cstring(&p));
38345147a9marcel
38445147a9marcel        RE(atf_fs_path_to_absolute(&p, &p2));
38545147a9marcel        printf("Absolute path: %s\n", atf_fs_path_cstring(&p2));
38645147a9marcel
38745147a9marcel        ATF_REQUIRE(atf_fs_path_is_absolute(&p2));
38845147a9marcel        RE(atf_fs_stat_init(&st2, &p2));
38945147a9marcel
39045147a9marcel        ATF_REQUIRE_EQ(atf_fs_stat_get_device(&st1),
39145147a9marcel                        atf_fs_stat_get_device(&st2));
39245147a9marcel        ATF_REQUIRE_EQ(atf_fs_stat_get_inode(&st1),
39345147a9marcel                        atf_fs_stat_get_inode(&st2));
39445147a9marcel
39545147a9marcel        atf_fs_stat_fini(&st2);
39645147a9marcel        atf_fs_stat_fini(&st1);
39745147a9marcel        atf_fs_path_fini(&p2);
39845147a9marcel        atf_fs_path_fini(&p);
39945147a9marcel
40045147a9marcel        printf("\n");
40145147a9marcel    }
40245147a9marcel}
40345147a9marcel
40445147a9marcelATF_TC(path_equal);
40545147a9marcelATF_TC_HEAD(path_equal, tc)
40645147a9marcel{
40745147a9marcel    atf_tc_set_md_var(tc, "descr", "Tests the equality operators for paths");
40845147a9marcel}
40945147a9marcelATF_TC_BODY(path_equal, tc)
41045147a9marcel{
41145147a9marcel    atf_fs_path_t p1, p2;
41245147a9marcel
41345147a9marcel    RE(atf_fs_path_init_fmt(&p1, "foo"));
41445147a9marcel
41545147a9marcel    RE(atf_fs_path_init_fmt(&p2, "foo"));
41645147a9marcel    ATF_REQUIRE(atf_equal_fs_path_fs_path(&p1, &p2));
41745147a9marcel    atf_fs_path_fini(&p2);
41845147a9marcel
41945147a9marcel    RE(atf_fs_path_init_fmt(&p2, "bar"));
42045147a9marcel    ATF_REQUIRE(!atf_equal_fs_path_fs_path(&p1, &p2));
42145147a9marcel    atf_fs_path_fini(&p2);
42245147a9marcel
42345147a9marcel    atf_fs_path_fini(&p1);
42445147a9marcel}
42545147a9marcel
42645147a9marcel/* ---------------------------------------------------------------------
42745147a9marcel * Test cases for the "atf_fs_stat" type.
42845147a9marcel * --------------------------------------------------------------------- */
42945147a9marcel
43045147a9marcelATF_TC(stat_mode);
43145147a9marcelATF_TC_HEAD(stat_mode, tc)
43245147a9marcel{
43345147a9marcel    atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_stat_get_mode function "
43445147a9marcel                      "and, indirectly, the constructor");
43545147a9marcel}
43645147a9marcelATF_TC_BODY(stat_mode, tc)
43745147a9marcel{
43845147a9marcel    atf_fs_path_t p;
43945147a9marcel    atf_fs_stat_t st;
44045147a9marcel
44145147a9marcel    create_file("f1", 0400);
44245147a9marcel    create_file("f2", 0644);
44345147a9marcel
44445147a9marcel    RE(atf_fs_path_init_fmt(&p, "f1"));
44545147a9marcel    RE(atf_fs_stat_init(&st, &p));
44645147a9marcel    ATF_CHECK_EQ(0400, atf_fs_stat_get_mode(&st));
44745147a9marcel    atf_fs_stat_fini(&st);
44845147a9marcel    atf_fs_path_fini(&p);
44945147a9marcel
45045147a9marcel    RE(atf_fs_path_init_fmt(&p, "f2"));
45145147a9marcel    RE(atf_fs_stat_init(&st, &p));
45245147a9marcel    ATF_CHECK_EQ(0644, atf_fs_stat_get_mode(&st));
45345147a9marcel    atf_fs_stat_fini(&st);
45445147a9marcel    atf_fs_path_fini(&p);
45545147a9marcel}
45645147a9marcel
45745147a9marcelATF_TC(stat_type);
45845147a9marcelATF_TC_HEAD(stat_type, tc)
45945147a9marcel{
46045147a9marcel    atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_stat_get_type function "
46145147a9marcel                      "and, indirectly, the constructor");
46245147a9marcel}
46345147a9marcelATF_TC_BODY(stat_type, tc)
46445147a9marcel{
46545147a9marcel    atf_fs_path_t p;
46645147a9marcel    atf_fs_stat_t st;
46745147a9marcel
46845147a9marcel    create_dir("dir", 0755);
46945147a9marcel    create_file("reg", 0644);
47045147a9marcel
47145147a9marcel    RE(atf_fs_path_init_fmt(&p, "dir"));
47245147a9marcel    RE(atf_fs_stat_init(&st, &p));
47345147a9marcel    ATF_REQUIRE_EQ(atf_fs_stat_get_type(&st), atf_fs_stat_dir_type);
47445147a9marcel    atf_fs_stat_fini(&st);
47545147a9marcel    atf_fs_path_fini(&p);
47645147a9marcel
47745147a9marcel    RE(atf_fs_path_init_fmt(&p, "reg"));
47845147a9marcel    RE(atf_fs_stat_init(&st, &p));
47945147a9marcel    ATF_REQUIRE_EQ(atf_fs_stat_get_type(&st), atf_fs_stat_reg_type);
48045147a9marcel    atf_fs_stat_fini(&st);
48145147a9marcel    atf_fs_path_fini(&p);
48245147a9marcel}
48345147a9marcel
48445147a9marcelATF_TC(stat_perms);
48545147a9marcelATF_TC_HEAD(stat_perms, tc)
48645147a9marcel{
48745147a9marcel    atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_stat_is_* functions");
48845147a9marcel}
48945147a9marcelATF_TC_BODY(stat_perms, tc)
49045147a9marcel{
49145147a9marcel    atf_fs_path_t p;
49245147a9marcel    atf_fs_stat_t st;
49345147a9marcel
49445147a9marcel    create_file("reg", 0);
49545147a9marcel
49645147a9marcel    RE(atf_fs_path_init_fmt(&p, "reg"));
49745147a9marcel
49845147a9marcel#define perms(ur, uw, ux, gr, gw, gx, othr, othw, othx) \
49945147a9marcel    { \
50045147a9marcel        RE(atf_fs_stat_init(&st, &p)); \
50145147a9marcel        ATF_REQUIRE(atf_fs_stat_is_owner_readable(&st) == ur); \
50245147a9marcel        ATF_REQUIRE(atf_fs_stat_is_owner_writable(&st) == uw); \
50345147a9marcel        ATF_REQUIRE(atf_fs_stat_is_owner_executable(&st) == ux); \
50445147a9marcel        ATF_REQUIRE(atf_fs_stat_is_group_readable(&st) == gr); \
50545147a9marcel        ATF_REQUIRE(atf_fs_stat_is_group_writable(&st) == gw); \
50645147a9marcel        ATF_REQUIRE(atf_fs_stat_is_group_executable(&st) == gx); \
50745147a9marcel        ATF_REQUIRE(atf_fs_stat_is_other_readable(&st) == othr); \
50845147a9marcel        ATF_REQUIRE(atf_fs_stat_is_other_writable(&st) == othw); \
50945147a9marcel        ATF_REQUIRE(atf_fs_stat_is_other_executable(&st) == othx); \
51045147a9marcel        atf_fs_stat_fini(&st); \
51145147a9marcel    }
51245147a9marcel
51345147a9marcel    chmod("reg", 0000);
51445147a9marcel    perms(false, false, false, false, false, false, false, false, false);
51545147a9marcel
51645147a9marcel    chmod("reg", 0001);
51745147a9marcel    perms(false, false, false, false, false, false, false, false, true);
51845147a9marcel
51945147a9marcel    chmod("reg", 0010);
52045147a9marcel    perms(false, false, false, false, false, true, false, false, false);
52145147a9marcel
52245147a9marcel    chmod("reg", 0100);
52345147a9marcel    perms(false, false, true, false, false, false, false, false, false);
52445147a9marcel
52545147a9marcel    chmod("reg", 0002);
52645147a9marcel    perms(false, false, false, false, false, false, false, true, false);
52745147a9marcel
52845147a9marcel    chmod("reg", 0020);
52945147a9marcel    perms(false, false, false, false, true, false, false, false, false);
53045147a9marcel
53145147a9marcel    chmod("reg", 0200);
53245147a9marcel    perms(false, true, false, false, false, false, false, false, false);
53345147a9marcel
53445147a9marcel    chmod("reg", 0004);
53545147a9marcel    perms(false, false, false, false, false, false, true, false, false);
53645147a9marcel
53745147a9marcel    chmod("reg", 0040);
53845147a9marcel    perms(false, false, false, true, false, false, false, false, false);
53945147a9marcel
54045147a9marcel    chmod("reg", 0400);
54145147a9marcel    perms(true, false, false, false, false, false, false, false, false);
54245147a9marcel
54345147a9marcel    chmod("reg", 0644);
54445147a9marcel    perms(true, true, false, true, false, false, true, false, false);
54545147a9marcel
54645147a9marcel    chmod("reg", 0755);
54745147a9marcel    perms(true, true, true, true, false, true, true, false, true);
54845147a9marcel
54945147a9marcel    chmod("reg", 0777);
55045147a9marcel    perms(true, true, true, true, true, true, true, true, true);
55145147a9marcel
55245147a9marcel#undef perms
55345147a9marcel
55445147a9marcel    atf_fs_path_fini(&p);
55545147a9marcel}
55645147a9marcel
55745147a9marcel/* ---------------------------------------------------------------------
55845147a9marcel * Test cases for the free functions.
55945147a9marcel * --------------------------------------------------------------------- */
56045147a9marcel
56145147a9marcelATF_TC(exists);
56245147a9marcelATF_TC_HEAD(exists, tc)
56345147a9marcel{
56445147a9marcel    atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_exists function");
56545147a9marcel}
56645147a9marcelATF_TC_BODY(exists, tc)
56745147a9marcel{
56845147a9marcel    atf_error_t err;
56945147a9marcel    atf_fs_path_t pdir, pfile;
57045147a9marcel    bool b;
57145147a9marcel
57245147a9marcel    RE(atf_fs_path_init_fmt(&pdir, "dir"));
57345147a9marcel    RE(atf_fs_path_init_fmt(&pfile, "dir/file"));
57445147a9marcel
57545147a9marcel    create_dir(atf_fs_path_cstring(&pdir), 0755);
57645147a9marcel    create_file(atf_fs_path_cstring(&pfile), 0644);
57745147a9marcel
57845147a9marcel    printf("Checking existence of a directory\n");
57945147a9marcel    RE(atf_fs_exists(&pdir, &b));
58045147a9marcel    ATF_REQUIRE(b);
58145147a9marcel
58245147a9marcel    printf("Checking existence of a file\n");
58345147a9marcel    RE(atf_fs_exists(&pfile, &b));
58445147a9marcel    ATF_REQUIRE(b);
58545147a9marcel
58645147a9marcel    /* XXX: This should probably be a separate test case to let the user
58745147a9marcel     * be aware that some tests were skipped because privileges were not
58845147a9marcel     * correct. */
58945147a9marcel    if (!atf_user_is_root()) {
59045147a9marcel        printf("Checking existence of a file inside a directory without "
59145147a9marcel               "permissions\n");
59245147a9marcel        ATF_REQUIRE(chmod(atf_fs_path_cstring(&pdir), 0000) != -1);
59345147a9marcel        err = atf_fs_exists(&pfile, &b);
59445147a9marcel        ATF_REQUIRE(atf_is_error(err));
59545147a9marcel        ATF_REQUIRE(atf_error_is(err, "libc"));
59645147a9marcel        ATF_REQUIRE(chmod(atf_fs_path_cstring(&pdir), 0755) != -1);
59745147a9marcel        atf_error_free(err);
59845147a9marcel    }
59945147a9marcel
60045147a9marcel    printf("Checking existence of a non-existent file\n");
60145147a9marcel    ATF_REQUIRE(unlink(atf_fs_path_cstring(&pfile)) != -1);
60245147a9marcel    RE(atf_fs_exists(&pfile, &b));
60345147a9marcel    ATF_REQUIRE(!b);
60445147a9marcel
60545147a9marcel    atf_fs_path_fini(&pfile);
60645147a9marcel    atf_fs_path_fini(&pdir);
60745147a9marcel}
60845147a9marcel
60945147a9marcelATF_TC(eaccess);
61045147a9marcelATF_TC_HEAD(eaccess, tc)
61145147a9marcel{
61245147a9marcel    atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_eaccess function");
61345147a9marcel}
61445147a9marcelATF_TC_BODY(eaccess, tc)
61545147a9marcel{
61645147a9marcel    const int modes[] = { atf_fs_access_f, atf_fs_access_r, atf_fs_access_w,
61745147a9marcel                          atf_fs_access_x, 0 };
61845147a9marcel    const int *m;
61945147a9marcel    struct tests {
62045147a9marcel        mode_t fmode;
62145147a9marcel        int amode;
62245147a9marcel        int uerror;
62345147a9marcel        int rerror;
62445147a9marcel    } tests[] = {
62545147a9marcel        { 0000, atf_fs_access_r, EACCES, 0 },
62645147a9marcel        { 0000, atf_fs_access_w, EACCES, 0 },
62745147a9marcel        { 0000, atf_fs_access_x, EACCES, EACCES },
62845147a9marcel
62945147a9marcel        { 0001, atf_fs_access_r, EACCES, 0 },
63045147a9marcel        { 0001, atf_fs_access_w, EACCES, 0 },
63145147a9marcel        { 0001, atf_fs_access_x, EACCES, 0 },
63245147a9marcel        { 0002, atf_fs_access_r, EACCES, 0 },
63345147a9marcel        { 0002, atf_fs_access_w, EACCES, 0 },
63445147a9marcel        { 0002, atf_fs_access_x, EACCES, EACCES },
63545147a9marcel        { 0004, atf_fs_access_r, EACCES, 0 },
63645147a9marcel        { 0004, atf_fs_access_w, EACCES, 0 },
63745147a9marcel        { 0004, atf_fs_access_x, EACCES, EACCES },
63845147a9marcel
63945147a9marcel        { 0010, atf_fs_access_r, EACCES, 0 },
64045147a9marcel        { 0010, atf_fs_access_w, EACCES, 0 },
64145147a9marcel        { 0010, atf_fs_access_x, 0,      0 },
64245147a9marcel        { 0020, atf_fs_access_r, EACCES, 0 },
64345147a9marcel        { 0020, atf_fs_access_w, 0,      0 },
64445147a9marcel        { 0020, atf_fs_access_x, EACCES, EACCES },
64545147a9marcel        { 0040, atf_fs_access_r, 0,      0 },
64645147a9marcel        { 0040, atf_fs_access_w, EACCES, 0 },
64745147a9marcel        { 0040, atf_fs_access_x, EACCES, EACCES },
64845147a9marcel
64945147a9marcel        { 0100, atf_fs_access_r, EACCES, 0 },
65045147a9marcel        { 0100, atf_fs_access_w, EACCES, 0 },
65145147a9marcel        { 0100, atf_fs_access_x, 0,      0 },
65245147a9marcel        { 0200, atf_fs_access_r, EACCES, 0 },
65345147a9marcel        { 0200, atf_fs_access_w, 0,      0 },
65445147a9marcel        { 0200, atf_fs_access_x, EACCES, EACCES },
65545147a9marcel        { 0400, atf_fs_access_r, 0,      0 },
65645147a9marcel        { 0400, atf_fs_access_w, EACCES, 0 },
65745147a9marcel        { 0400, atf_fs_access_x, EACCES, EACCES },
65845147a9marcel
65945147a9marcel        { 0, 0, 0, 0 }
66045147a9marcel    };
66145147a9marcel    struct tests *t;
66245147a9marcel    atf_fs_path_t p;
66345147a9marcel    atf_error_t err;
66445147a9marcel
66545147a9marcel    RE(atf_fs_path_init_fmt(&p, "the-file"));
66645147a9marcel
66745147a9marcel    printf("Non-existent file checks\n");
66845147a9marcel    for (m = &modes[0]; *m != 0; m++) {
66945147a9marcel        err = atf_fs_eaccess(&p, *m);
67045147a9marcel        ATF_REQUIRE(atf_is_error(err));
67145147a9marcel        ATF_REQUIRE(atf_error_is(err, "libc"));
67245147a9marcel        ATF_REQUIRE_EQ(atf_libc_error_code(err), ENOENT);
67345147a9marcel        atf_error_free(err);
67445147a9marcel    }
67545147a9marcel
67645147a9marcel    create_file(atf_fs_path_cstring(&p), 0000);
67745147a9marcel    ATF_REQUIRE(chown(atf_fs_path_cstring(&p), geteuid(), getegid()) != -1);
67845147a9marcel
67945147a9marcel    for (t = &tests[0]; t->amode != 0; t++) {
68045147a9marcel        const int experr = atf_user_is_root() ? t->rerror : t->uerror;
68145147a9marcel
68245147a9marcel        printf("\n");
68345147a9marcel        printf("File mode     : %04o\n", (unsigned int)t->fmode);
68445147a9marcel        printf("Access mode   : 0x%02x\n", t->amode);
68545147a9marcel
68645147a9marcel        ATF_REQUIRE(chmod(atf_fs_path_cstring(&p), t->fmode) != -1);
68745147a9marcel
68845147a9marcel        /* First, existence check. */
68945147a9marcel        err = atf_fs_eaccess(&p, atf_fs_access_f);
69045147a9marcel        ATF_REQUIRE(!atf_is_error(err));
69145147a9marcel
69245147a9marcel        /* Now do the specific test case. */
69345147a9marcel        printf("Expected error: %d\n", experr);
69445147a9marcel        err = atf_fs_eaccess(&p, t->amode);
69545147a9marcel        if (atf_is_error(err)) {
69645147a9marcel            if (atf_error_is(err, "libc"))
69745147a9marcel                printf("Error         : %d\n", atf_libc_error_code(err));
69845147a9marcel            else
69945147a9marcel                printf("Error         : Non-libc error\n");
70045147a9marcel        } else
70145147a9marcel                printf("Error         : None\n");
70245147a9marcel        if (experr == 0) {
70345147a9marcel            ATF_REQUIRE(!atf_is_error(err));
70445147a9marcel        } else {
70545147a9marcel            ATF_REQUIRE(atf_is_error(err));
70645147a9marcel            ATF_REQUIRE(atf_error_is(err, "libc"));
70745147a9marcel            ATF_REQUIRE_EQ(atf_libc_error_code(err), experr);
70845147a9marcel            atf_error_free(err);
70945147a9marcel        }
71045147a9marcel    }
71145147a9marcel
71245147a9marcel    atf_fs_path_fini(&p);
71345147a9marcel}
71445147a9marcel
71545147a9marcelATF_TC(getcwd);
71645147a9marcelATF_TC_HEAD(getcwd, tc)
71745147a9marcel{
71845147a9marcel    atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_getcwd function");
71945147a9marcel}
72045147a9marcelATF_TC_BODY(getcwd, tc)
72145147a9marcel{
72245147a9marcel    atf_fs_path_t cwd1, cwd2;
72345147a9marcel
72445147a9marcel    create_dir ("root", 0755);
72545147a9marcel
72645147a9marcel    RE(atf_fs_getcwd(&cwd1));
72745147a9marcel    ATF_REQUIRE(chdir("root") != -1);
72845147a9marcel    RE(atf_fs_getcwd(&cwd2));
72945147a9marcel
73045147a9marcel    RE(atf_fs_path_append_fmt(&cwd1, "root"));
73145147a9marcel
73245147a9marcel    ATF_REQUIRE(atf_equal_fs_path_fs_path(&cwd1, &cwd2));
73345147a9marcel
73445147a9marcel    atf_fs_path_fini(&cwd2);
73545147a9marcel    atf_fs_path_fini(&cwd1);
73645147a9marcel}
73745147a9marcel
73845147a9marcelATF_TC(rmdir_empty);
73945147a9marcelATF_TC_HEAD(rmdir_empty, tc)
74045147a9marcel{
74145147a9marcel    atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_rmdir function");
74245147a9marcel}
74345147a9marcelATF_TC_BODY(rmdir_empty, tc)
74445147a9marcel{
74545147a9marcel    atf_fs_path_t p;
74645147a9marcel
74745147a9marcel    RE(atf_fs_path_init_fmt(&p, "test-dir"));
74845147a9marcel
74945147a9marcel    ATF_REQUIRE(mkdir("test-dir", 0755) != -1);
75045147a9marcel    ATF_REQUIRE(exists(&p));
75145147a9marcel    RE(atf_fs_rmdir(&p));
75245147a9marcel    ATF_REQUIRE(!exists(&p));
75345147a9marcel
75445147a9marcel    atf_fs_path_fini(&p);
75545147a9marcel}
75645147a9marcel
75745147a9marcelATF_TC(rmdir_enotempty);
75845147a9marcelATF_TC_HEAD(rmdir_enotempty, tc)
75945147a9marcel{
76045147a9marcel    atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_rmdir function");
76145147a9marcel}
76245147a9marcelATF_TC_BODY(rmdir_enotempty, tc)
76345147a9marcel{
76445147a9marcel    atf_fs_path_t p;
76545147a9marcel    atf_error_t err;
76645147a9marcel
76745147a9marcel    RE(atf_fs_path_init_fmt(&p, "test-dir"));
76845147a9marcel
76945147a9marcel    ATF_REQUIRE(mkdir("test-dir", 0755) != -1);
77045147a9marcel    ATF_REQUIRE(exists(&p));
77145147a9marcel    create_file("test-dir/foo", 0644);
77245147a9marcel
77345147a9marcel    err = atf_fs_rmdir(&p);
77445147a9marcel    ATF_REQUIRE(atf_is_error(err));
77545147a9marcel    ATF_REQUIRE(atf_error_is(err, "libc"));
77645147a9marcel    ATF_REQUIRE_EQ(atf_libc_error_code(err), ENOTEMPTY);
77745147a9marcel    atf_error_free(err);
77845147a9marcel
77945147a9marcel    atf_fs_path_fini(&p);
78045147a9marcel}
78145147a9marcel
78245147a9marcelATF_TC(rmdir_eperm);
78345147a9marcelATF_TC_HEAD(rmdir_eperm, tc)
78445147a9marcel{
78545147a9marcel    atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_rmdir function");
78645147a9marcel}
78745147a9marcelATF_TC_BODY(rmdir_eperm, tc)
78845147a9marcel{
78945147a9marcel    atf_fs_path_t p;
79045147a9marcel    atf_error_t err;
79145147a9marcel
79245147a9marcel    RE(atf_fs_path_init_fmt(&p, "test-dir/foo"));
79345147a9marcel
79445147a9marcel    ATF_REQUIRE(mkdir("test-dir", 0755) != -1);
79545147a9marcel    ATF_REQUIRE(mkdir("test-dir/foo", 0755) != -1);
79645147a9marcel    ATF_REQUIRE(chmod("test-dir", 0555) != -1);
79745147a9marcel    ATF_REQUIRE(exists(&p));
79845147a9marcel
79945147a9marcel    err = atf_fs_rmdir(&p);
80045147a9marcel    if (atf_user_is_root()) {
80145147a9marcel        ATF_REQUIRE(!atf_is_error(err));
80245147a9marcel    } else {
80345147a9marcel        ATF_REQUIRE(atf_is_error(err));
80445147a9marcel        ATF_REQUIRE(atf_error_is(err, "libc"));
80545147a9marcel        ATF_REQUIRE_EQ(atf_libc_error_code(err), EACCES);
80645147a9marcel        atf_error_free(err);
80745147a9marcel    }
80845147a9marcel
80945147a9marcel    atf_fs_path_fini(&p);
81045147a9marcel}
81145147a9marcel
81245147a9marcelATF_TC(mkdtemp_ok);
81345147a9marcelATF_TC_HEAD(mkdtemp_ok, tc)
81445147a9marcel{
81545147a9marcel    atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_mkdtemp function, "
81645147a9marcel                      "successful execution");
81745147a9marcel}
81845147a9marcelATF_TC_BODY(mkdtemp_ok, tc)
81945147a9marcel{
82045147a9marcel    atf_fs_path_t p1, p2;
82145147a9marcel    atf_fs_stat_t s1, s2;
82245147a9marcel
82345147a9marcel    RE(atf_fs_path_init_fmt(&p1, "testdir.XXXXXX"));
82445147a9marcel    RE(atf_fs_path_init_fmt(&p2, "testdir.XXXXXX"));
82545147a9marcel    RE(atf_fs_mkdtemp(&p1));
82645147a9marcel    RE(atf_fs_mkdtemp(&p2));
82745147a9marcel    ATF_REQUIRE(!atf_equal_fs_path_fs_path(&p1, &p2));
82845147a9marcel    ATF_REQUIRE(exists(&p1));
82945147a9marcel    ATF_REQUIRE(exists(&p2));
83045147a9marcel
83145147a9marcel    RE(atf_fs_stat_init(&s1, &p1));
83245147a9marcel    ATF_REQUIRE_EQ(atf_fs_stat_get_type(&s1), atf_fs_stat_dir_type);
83345147a9marcel    ATF_REQUIRE( atf_fs_stat_is_owner_readable(&s1));
83445147a9marcel    ATF_REQUIRE( atf_fs_stat_is_owner_writable(&s1));
83545147a9marcel    ATF_REQUIRE( atf_fs_stat_is_owner_executable(&s1));
83645147a9marcel    ATF_REQUIRE(!atf_fs_stat_is_group_readable(&s1));
83745147a9marcel    ATF_REQUIRE(!atf_fs_stat_is_group_writable(&s1));
83845147a9marcel    ATF_REQUIRE(!atf_fs_stat_is_group_executable(&s1));
83945147a9marcel    ATF_REQUIRE(!atf_fs_stat_is_other_readable(&s1));
84045147a9marcel    ATF_REQUIRE(!atf_fs_stat_is_other_writable(&s1));
84145147a9marcel    ATF_REQUIRE(!atf_fs_stat_is_other_executable(&s1));
84245147a9marcel
84345147a9marcel    RE(atf_fs_stat_init(&s2, &p2));
84445147a9marcel    ATF_REQUIRE_EQ(atf_fs_stat_get_type(&s2), atf_fs_stat_dir_type);
84545147a9marcel    ATF_REQUIRE( atf_fs_stat_is_owner_readable(&s2));
84645147a9marcel    ATF_REQUIRE( atf_fs_stat_is_owner_writable(&s2));
84745147a9marcel    ATF_REQUIRE( atf_fs_stat_is_owner_executable(&s2));
84845147a9marcel    ATF_REQUIRE(!atf_fs_stat_is_group_readable(&s2));
84945147a9marcel    ATF_REQUIRE(!atf_fs_stat_is_group_writable(&s2));
85045147a9marcel    ATF_REQUIRE(!atf_fs_stat_is_group_executable(&s2));
85145147a9marcel    ATF_REQUIRE(!atf_fs_stat_is_other_readable(&s2));
85245147a9marcel    ATF_REQUIRE(!atf_fs_stat_is_other_writable(&s2));
85345147a9marcel    ATF_REQUIRE(!atf_fs_stat_is_other_executable(&s2));
85445147a9marcel
85545147a9marcel    atf_fs_stat_fini(&s2);
85645147a9marcel    atf_fs_stat_fini(&s1);
85745147a9marcel    atf_fs_path_fini(&p2);
85845147a9marcel    atf_fs_path_fini(&p1);
85945147a9marcel}
86045147a9marcel
86145147a9marcelATF_TC(mkdtemp_err);
86245147a9marcelATF_TC_HEAD(mkdtemp_err, tc)
86345147a9marcel{
86445147a9marcel    atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_mkdtemp function, "
86545147a9marcel                      "error conditions");
86645147a9marcel    atf_tc_set_md_var(tc, "require.user", "unprivileged");
86745147a9marcel}
86845147a9marcelATF_TC_BODY(mkdtemp_err, tc)
86945147a9marcel{
87045147a9marcel    atf_error_t err;
87145147a9marcel    atf_fs_path_t p;
87245147a9marcel
87345147a9marcel    ATF_REQUIRE(mkdir("dir", 0555) != -1);
87445147a9marcel
87545147a9marcel    RE(atf_fs_path_init_fmt(&p, "dir/testdir.XXXXXX"));
87645147a9marcel
87745147a9marcel    err = atf_fs_mkdtemp(&p);
87845147a9marcel    ATF_REQUIRE(atf_is_error(err));
87945147a9marcel    ATF_REQUIRE(atf_error_is(err, "libc"));
88045147a9marcel    ATF_CHECK_EQ(atf_libc_error_code(err), EACCES);
88145147a9marcel    atf_error_free(err);
88245147a9marcel
88345147a9marcel    ATF_CHECK(!exists(&p));
88445147a9marcel    ATF_CHECK(strcmp(atf_fs_path_cstring(&p), "dir/testdir.XXXXXX") == 0);
88545147a9marcel
88645147a9marcel    atf_fs_path_fini(&p);
88745147a9marcel}
88845147a9marcel
88945147a9marcelstatic
89045147a9marcelvoid
89145147a9marceldo_umask_check(atf_error_t (*const mk_func)(atf_fs_path_t *),
89245147a9marcel               atf_fs_path_t *path, const mode_t test_mask,
89345147a9marcel               const char *str_mask, const char *exp_name)
89445147a9marcel{
89545147a9marcel    char buf[1024];
89645147a9marcel    int old_umask;
89745147a9marcel    atf_error_t err;
89845147a9marcel
89945147a9marcel    printf("Creating temporary %s with umask %s\n", exp_name, str_mask);
90045147a9marcel
90145147a9marcel    old_umask = umask(test_mask);
90245147a9marcel    err = mk_func(path);
90345147a9marcel    (void)umask(old_umask);
90445147a9marcel
90545147a9marcel    ATF_REQUIRE(atf_is_error(err));
90645147a9marcel    ATF_REQUIRE(atf_error_is(err, "invalid_umask"));
90745147a9marcel    atf_error_format(err, buf, sizeof(buf));
90845147a9marcel    ATF_CHECK(strstr(buf, exp_name) != NULL);
90945147a9marcel    ATF_CHECK(strstr(buf, str_mask) != NULL);
91045147a9marcel    atf_error_free(err);
91145147a9marcel}
91245147a9marcel
91345147a9marcelATF_TC(mkdtemp_umask);
91445147a9marcelATF_TC_HEAD(mkdtemp_umask, tc)
91545147a9marcel{
91645147a9marcel    atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_mkdtemp function "
91745147a9marcel                      "causing an error due to a too strict umask");
91845147a9marcel}
91945147a9marcelATF_TC_BODY(mkdtemp_umask, tc)
92045147a9marcel{
92145147a9marcel    atf_fs_path_t p;
92245147a9marcel
92345147a9marcel    RE(atf_fs_path_init_fmt(&p, "testdir.XXXXXX"));
92445147a9marcel
92545147a9marcel    do_umask_check(atf_fs_mkdtemp, &p, 00100, "00100", "directory");
92645147a9marcel    do_umask_check(atf_fs_mkdtemp, &p, 00200, "00200", "directory");
92745147a9marcel    do_umask_check(atf_fs_mkdtemp, &p, 00400, "00400", "directory");
92845147a9marcel    do_umask_check(atf_fs_mkdtemp, &p, 00500, "00500", "directory");
92945147a9marcel    do_umask_check(atf_fs_mkdtemp, &p, 00600, "00600", "directory");
93045147a9marcel
93145147a9marcel    atf_fs_path_fini(&p);
93245147a9marcel}
93345147a9marcel
93445147a9marcelATF_TC(mkstemp_ok);
93545147a9marcelATF_TC_HEAD(mkstemp_ok, tc)
93645147a9marcel{
93745147a9marcel    atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_mkstemp function, "
93845147a9marcel                      "successful execution");
93945147a9marcel}
94045147a9marcelATF_TC_BODY(mkstemp_ok, tc)
94145147a9marcel{
94245147a9marcel    int fd1, fd2;
94345147a9marcel    atf_fs_path_t p1, p2;
94445147a9marcel    atf_fs_stat_t s1, s2;
94545147a9marcel
94645147a9marcel    RE(atf_fs_path_init_fmt(&p1, "testfile.XXXXXX"));
94745147a9marcel    RE(atf_fs_path_init_fmt(&p2, "testfile.XXXXXX"));
94845147a9marcel    fd1 = fd2 = -1;
94945147a9marcel    RE(atf_fs_mkstemp(&p1, &fd1));
95045147a9marcel    RE(atf_fs_mkstemp(&p2, &fd2));
95145147a9marcel    ATF_REQUIRE(!atf_equal_fs_path_fs_path(&p1, &p2));
95245147a9marcel    ATF_REQUIRE(exists(&p1));
95345147a9marcel    ATF_REQUIRE(exists(&p2));
95445147a9marcel
95545147a9marcel    ATF_CHECK(fd1 != -1);
95645147a9marcel    ATF_CHECK(fd2 != -1);
95745147a9marcel    ATF_CHECK(write(fd1, "foo", 3) == 3);
95845147a9marcel    ATF_CHECK(write(fd2, "bar", 3) == 3);
95945147a9marcel    close(fd1);
96045147a9marcel    close(fd2);
96145147a9marcel
96245147a9marcel    RE(atf_fs_stat_init(&s1, &p1));
96345147a9marcel    ATF_CHECK_EQ(atf_fs_stat_get_type(&s1), atf_fs_stat_reg_type);
96445147a9marcel    ATF_CHECK( atf_fs_stat_is_owner_readable(&s1));
96545147a9marcel    ATF_CHECK( atf_fs_stat_is_owner_writable(&s1));
96645147a9marcel    ATF_CHECK(!atf_fs_stat_is_owner_executable(&s1));
96745147a9marcel    ATF_CHECK(!atf_fs_stat_is_group_readable(&s1));
96845147a9marcel    ATF_CHECK(!atf_fs_stat_is_group_writable(&s1));
96945147a9marcel    ATF_CHECK(!atf_fs_stat_is_group_executable(&s1));
97045147a9marcel    ATF_CHECK(!atf_fs_stat_is_other_readable(&s1));
97145147a9marcel    ATF_CHECK(!atf_fs_stat_is_other_writable(&s1));
97245147a9marcel    ATF_CHECK(!atf_fs_stat_is_other_executable(&s1));
97345147a9marcel
97445147a9marcel    RE(atf_fs_stat_init(&s2, &p2));
97545147a9marcel    ATF_CHECK_EQ(atf_fs_stat_get_type(&s2), atf_fs_stat_reg_type);
97645147a9marcel    ATF_CHECK( atf_fs_stat_is_owner_readable(&s2));
97745147a9marcel    ATF_CHECK( atf_fs_stat_is_owner_writable(&s2));
97845147a9marcel    ATF_CHECK(!atf_fs_stat_is_owner_executable(&s2));
97945147a9marcel    ATF_CHECK(!atf_fs_stat_is_group_readable(&s2));
98045147a9marcel    ATF_CHECK(!atf_fs_stat_is_group_writable(&s2));
98145147a9marcel    ATF_CHECK(!atf_fs_stat_is_group_executable(&s2));
98245147a9marcel    ATF_CHECK(!atf_fs_stat_is_other_readable(&s2));
98345147a9marcel    ATF_CHECK(!atf_fs_stat_is_other_writable(&s2));
98445147a9marcel    ATF_CHECK(!atf_fs_stat_is_other_executable(&s2));
98545147a9marcel
98645147a9marcel    atf_fs_stat_fini(&s2);
98745147a9marcel    atf_fs_stat_fini(&s1);
98845147a9marcel    atf_fs_path_fini(&p2);
98945147a9marcel    atf_fs_path_fini(&p1);
99045147a9marcel}
99145147a9marcel
99245147a9marcelATF_TC(mkstemp_err);
99345147a9marcelATF_TC_HEAD(mkstemp_err, tc)
99445147a9marcel{
99545147a9marcel    atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_mkstemp function, "
99645147a9marcel                      "error conditions");
99745147a9marcel    atf_tc_set_md_var(tc, "require.user", "unprivileged");
99845147a9marcel}
99945147a9marcelATF_TC_BODY(mkstemp_err, tc)
100045147a9marcel{
100145147a9marcel    int fd;
100245147a9marcel    atf_error_t err;
100345147a9marcel    atf_fs_path_t p;
100445147a9marcel
100545147a9marcel    ATF_REQUIRE(mkdir("dir", 0555) != -1);
100645147a9marcel
100745147a9marcel    RE(atf_fs_path_init_fmt(&p, "dir/testfile.XXXXXX"));
100845147a9marcel    fd = 1234;
100945147a9marcel
101045147a9marcel    err = atf_fs_mkstemp(&p, &fd);
101145147a9marcel    ATF_REQUIRE(atf_is_error(err));
101245147a9marcel    ATF_REQUIRE(atf_error_is(err, "libc"));
101345147a9marcel    ATF_CHECK_EQ(atf_libc_error_code(err), EACCES);
101445147a9marcel    atf_error_free(err);
101545147a9marcel
101645147a9marcel    ATF_CHECK(!exists(&p));
101745147a9marcel    ATF_CHECK(strcmp(atf_fs_path_cstring(&p), "dir/testfile.XXXXXX") == 0);
101845147a9marcel    ATF_CHECK_EQ(fd, 1234);
101945147a9marcel
102045147a9marcel    atf_fs_path_fini(&p);
102145147a9marcel}
102245147a9marcel
102345147a9marcelATF_TC(mkstemp_umask);
102445147a9marcelATF_TC_HEAD(mkstemp_umask, tc)
102545147a9marcel{
102645147a9marcel    atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_mkstemp function "
102745147a9marcel                      "causing an error due to a too strict umask");
102845147a9marcel}
102945147a9marcelATF_TC_BODY(mkstemp_umask, tc)
103045147a9marcel{
103145147a9marcel    atf_fs_path_t p;
103245147a9marcel
103345147a9marcel    RE(atf_fs_path_init_fmt(&p, "testfile.XXXXXX"));
103445147a9marcel
103545147a9marcel    do_umask_check(mkstemp_discard_fd, &p, 00100, "00100", "regular file");
103645147a9marcel    do_umask_check(mkstemp_discard_fd, &p, 00200, "00200", "regular file");
103745147a9marcel    do_umask_check(mkstemp_discard_fd, &p, 00400, "00400", "regular file");
103845147a9marcel
103945147a9marcel    atf_fs_path_fini(&p);
104045147a9marcel}
104145147a9marcel
104245147a9marcel/* ---------------------------------------------------------------------
104345147a9marcel * Main.
104445147a9marcel * --------------------------------------------------------------------- */
104545147a9marcel
104645147a9marcelATF_TP_ADD_TCS(tp)
104745147a9marcel{
104845147a9marcel    /* Add the tests for the "atf_fs_path" type. */
104945147a9marcel    ATF_TP_ADD_TC(tp, path_normalize);
105045147a9marcel    ATF_TP_ADD_TC(tp, path_copy);
105145147a9marcel    ATF_TP_ADD_TC(tp, path_is_absolute);
105245147a9marcel    ATF_TP_ADD_TC(tp, path_is_root);
105345147a9marcel    ATF_TP_ADD_TC(tp, path_branch_path);
105445147a9marcel    ATF_TP_ADD_TC(tp, path_leaf_name);
105545147a9marcel    ATF_TP_ADD_TC(tp, path_append);
105645147a9marcel    ATF_TP_ADD_TC(tp, path_to_absolute);
105745147a9marcel    ATF_TP_ADD_TC(tp, path_equal);
105845147a9marcel
105945147a9marcel    /* Add the tests for the "atf_fs_stat" type. */
106045147a9marcel    ATF_TP_ADD_TC(tp, stat_mode);
106145147a9marcel    ATF_TP_ADD_TC(tp, stat_type);
106245147a9marcel    ATF_TP_ADD_TC(tp, stat_perms);
106345147a9marcel
106445147a9marcel    /* Add the tests for the free functions. */
106545147a9marcel    ATF_TP_ADD_TC(tp, eaccess);
106645147a9marcel    ATF_TP_ADD_TC(tp, exists);
106745147a9marcel    ATF_TP_ADD_TC(tp, getcwd);
106845147a9marcel    ATF_TP_ADD_TC(tp, rmdir_empty);
106945147a9marcel    ATF_TP_ADD_TC(tp, rmdir_enotempty);
107045147a9marcel    ATF_TP_ADD_TC(tp, rmdir_eperm);
107145147a9marcel    ATF_TP_ADD_TC(tp, mkdtemp_ok);
107245147a9marcel    ATF_TP_ADD_TC(tp, mkdtemp_err);
107345147a9marcel    ATF_TP_ADD_TC(tp, mkdtemp_umask);
107445147a9marcel    ATF_TP_ADD_TC(tp, mkstemp_ok);
107545147a9marcel    ATF_TP_ADD_TC(tp, mkstemp_err);
107645147a9marcel    ATF_TP_ADD_TC(tp, mkstemp_umask);
107745147a9marcel
107845147a9marcel    return atf_no_error();
107945147a9marcel}
1080