1275988Sngie/* Copyright (c) 2007 The NetBSD Foundation, Inc.
2240116Smarcel * All rights reserved.
3240116Smarcel *
4240116Smarcel * Redistribution and use in source and binary forms, with or without
5240116Smarcel * modification, are permitted provided that the following conditions
6240116Smarcel * are met:
7240116Smarcel * 1. Redistributions of source code must retain the above copyright
8240116Smarcel *    notice, this list of conditions and the following disclaimer.
9240116Smarcel * 2. Redistributions in binary form must reproduce the above copyright
10240116Smarcel *    notice, this list of conditions and the following disclaimer in the
11240116Smarcel *    documentation and/or other materials provided with the distribution.
12240116Smarcel *
13240116Smarcel * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
14240116Smarcel * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
15240116Smarcel * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
16240116Smarcel * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17240116Smarcel * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
18240116Smarcel * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19240116Smarcel * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
20240116Smarcel * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21240116Smarcel * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
22240116Smarcel * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23240116Smarcel * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
24275988Sngie * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  */
25240116Smarcel
26275988Sngie#include "atf-c/detail/fs.h"
27275988Sngie
28240116Smarcel#include <sys/types.h>
29240116Smarcel#include <sys/stat.h>
30240116Smarcel
31240116Smarcel#include <errno.h>
32240116Smarcel#include <fcntl.h>
33240116Smarcel#include <stdio.h>
34240116Smarcel#include <stdlib.h>
35240116Smarcel#include <string.h>
36240116Smarcel#include <unistd.h>
37240116Smarcel
38240116Smarcel#include <atf-c.h>
39240116Smarcel
40275988Sngie#include "atf-c/detail/test_helpers.h"
41275988Sngie#include "atf-c/detail/user.h"
42240116Smarcel
43240116Smarcel/* ---------------------------------------------------------------------
44240116Smarcel * Auxiliary functions.
45240116Smarcel * --------------------------------------------------------------------- */
46240116Smarcel
47240116Smarcelstatic
48240116Smarcelvoid
49240116Smarcelcreate_dir(const char *p, int mode)
50240116Smarcel{
51240116Smarcel    int ret;
52240116Smarcel
53240116Smarcel    ret = mkdir(p, mode);
54240116Smarcel    if (ret == -1)
55240116Smarcel        atf_tc_fail("Could not create helper directory %s", p);
56240116Smarcel}
57240116Smarcel
58240116Smarcelstatic
59240116Smarcelvoid
60240116Smarcelcreate_file(const char *p, int mode)
61240116Smarcel{
62240116Smarcel    int fd;
63240116Smarcel
64240116Smarcel    fd = open(p, O_CREAT | O_WRONLY | O_TRUNC, mode);
65240116Smarcel    if (fd == -1)
66240116Smarcel        atf_tc_fail("Could not create helper file %s", p);
67240116Smarcel    close(fd);
68240116Smarcel}
69240116Smarcel
70240116Smarcelstatic
71240116Smarcelbool
72240116Smarcelexists(const atf_fs_path_t *p)
73240116Smarcel{
74240116Smarcel    return access(atf_fs_path_cstring(p), F_OK) == 0;
75240116Smarcel}
76240116Smarcel
77240116Smarcelstatic
78240116Smarcelatf_error_t
79240116Smarcelmkstemp_discard_fd(atf_fs_path_t *p)
80240116Smarcel{
81240116Smarcel    int fd;
82240116Smarcel    atf_error_t err = atf_fs_mkstemp(p, &fd);
83240116Smarcel    if (!atf_is_error(err))
84240116Smarcel        close(fd);
85240116Smarcel    return err;
86240116Smarcel}
87240116Smarcel
88240116Smarcel/* ---------------------------------------------------------------------
89240116Smarcel * Test cases for the "atf_fs_path" type.
90240116Smarcel * --------------------------------------------------------------------- */
91240116Smarcel
92240116SmarcelATF_TC(path_normalize);
93240116SmarcelATF_TC_HEAD(path_normalize, tc)
94240116Smarcel{
95240116Smarcel    atf_tc_set_md_var(tc, "descr", "Tests the path's normalization");
96240116Smarcel}
97240116SmarcelATF_TC_BODY(path_normalize, tc)
98240116Smarcel{
99240116Smarcel    struct test {
100240116Smarcel        const char *in;
101240116Smarcel        const char *out;
102240116Smarcel    } tests[] = {
103240116Smarcel        { ".", ".", },
104240116Smarcel        { "..", "..", },
105240116Smarcel
106240116Smarcel        { "/", "/", },
107240116Smarcel        { "//", "/", }, /* NO_CHECK_STYLE */
108240116Smarcel        { "///", "/", }, /* NO_CHECK_STYLE */
109240116Smarcel
110240116Smarcel        { "foo", "foo", },
111240116Smarcel        { "foo/", "foo", },
112240116Smarcel        { "foo/bar", "foo/bar", },
113240116Smarcel        { "foo/bar/", "foo/bar", },
114240116Smarcel
115240116Smarcel        { "/foo", "/foo", },
116240116Smarcel        { "/foo/bar", "/foo/bar", },
117240116Smarcel        { "/foo/bar/", "/foo/bar", },
118240116Smarcel
119240116Smarcel        { "///foo", "/foo", }, /* NO_CHECK_STYLE */
120240116Smarcel        { "///foo///bar", "/foo/bar", }, /* NO_CHECK_STYLE */
121240116Smarcel        { "///foo///bar///", "/foo/bar", }, /* NO_CHECK_STYLE */
122240116Smarcel
123240116Smarcel        { NULL, NULL }
124240116Smarcel    };
125240116Smarcel    struct test *t;
126240116Smarcel
127240116Smarcel    for (t = &tests[0]; t->in != NULL; t++) {
128240116Smarcel        atf_fs_path_t p;
129240116Smarcel
130240116Smarcel        printf("Input          : >%s<\n", t->in);
131240116Smarcel        printf("Expected output: >%s<\n", t->out);
132240116Smarcel
133240116Smarcel        RE(atf_fs_path_init_fmt(&p, "%s", t->in));
134240116Smarcel        printf("Output         : >%s<\n", atf_fs_path_cstring(&p));
135240116Smarcel        ATF_REQUIRE(strcmp(atf_fs_path_cstring(&p), t->out) == 0);
136240116Smarcel        atf_fs_path_fini(&p);
137240116Smarcel
138240116Smarcel        printf("\n");
139240116Smarcel    }
140240116Smarcel}
141240116Smarcel
142240116SmarcelATF_TC(path_copy);
143240116SmarcelATF_TC_HEAD(path_copy, tc)
144240116Smarcel{
145240116Smarcel    atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_path_copy constructor");
146240116Smarcel}
147240116SmarcelATF_TC_BODY(path_copy, tc)
148240116Smarcel{
149240116Smarcel    atf_fs_path_t str, str2;
150240116Smarcel
151240116Smarcel    RE(atf_fs_path_init_fmt(&str, "foo"));
152240116Smarcel    RE(atf_fs_path_copy(&str2, &str));
153240116Smarcel
154240116Smarcel    ATF_REQUIRE(atf_equal_fs_path_fs_path(&str, &str2));
155240116Smarcel
156240116Smarcel    RE(atf_fs_path_append_fmt(&str2, "bar"));
157240116Smarcel
158240116Smarcel    ATF_REQUIRE(!atf_equal_fs_path_fs_path(&str, &str2));
159240116Smarcel
160240116Smarcel    atf_fs_path_fini(&str2);
161240116Smarcel    atf_fs_path_fini(&str);
162240116Smarcel}
163240116Smarcel
164240116SmarcelATF_TC(path_is_absolute);
165240116SmarcelATF_TC_HEAD(path_is_absolute, tc)
166240116Smarcel{
167240116Smarcel    atf_tc_set_md_var(tc, "descr", "Tests the path::is_absolute function");
168240116Smarcel}
169240116SmarcelATF_TC_BODY(path_is_absolute, tc)
170240116Smarcel{
171240116Smarcel    struct test {
172240116Smarcel        const char *in;
173240116Smarcel        bool abs;
174240116Smarcel    } tests[] = {
175240116Smarcel        { "/", true },
176240116Smarcel        { "////", true }, /* NO_CHECK_STYLE */
177240116Smarcel        { "////a", true }, /* NO_CHECK_STYLE */
178240116Smarcel        { "//a//", true }, /* NO_CHECK_STYLE */
179240116Smarcel        { "a////", false }, /* NO_CHECK_STYLE */
180240116Smarcel        { "../foo", false },
181240116Smarcel        { NULL, false },
182240116Smarcel    };
183240116Smarcel    struct test *t;
184240116Smarcel
185240116Smarcel    for (t = &tests[0]; t->in != NULL; t++) {
186240116Smarcel        atf_fs_path_t p;
187240116Smarcel
188240116Smarcel        printf("Input          : %s\n", t->in);
189240116Smarcel        printf("Expected result: %s\n", t->abs ? "true" : "false");
190240116Smarcel
191240116Smarcel        RE(atf_fs_path_init_fmt(&p, "%s", t->in));
192240116Smarcel        printf("Result         : %s\n",
193240116Smarcel               atf_fs_path_is_absolute(&p) ? "true" : "false");
194240116Smarcel        if (t->abs)
195240116Smarcel            ATF_REQUIRE(atf_fs_path_is_absolute(&p));
196240116Smarcel        else
197240116Smarcel            ATF_REQUIRE(!atf_fs_path_is_absolute(&p));
198240116Smarcel        atf_fs_path_fini(&p);
199240116Smarcel
200240116Smarcel        printf("\n");
201240116Smarcel    }
202240116Smarcel}
203240116Smarcel
204240116SmarcelATF_TC(path_is_root);
205240116SmarcelATF_TC_HEAD(path_is_root, tc)
206240116Smarcel{
207240116Smarcel    atf_tc_set_md_var(tc, "descr", "Tests the path::is_root function");
208240116Smarcel}
209240116SmarcelATF_TC_BODY(path_is_root, tc)
210240116Smarcel{
211240116Smarcel    struct test {
212240116Smarcel        const char *in;
213240116Smarcel        bool root;
214240116Smarcel    } tests[] = {
215240116Smarcel        { "/", true },
216240116Smarcel        { "////", true }, /* NO_CHECK_STYLE */
217240116Smarcel        { "////a", false }, /* NO_CHECK_STYLE */
218240116Smarcel        { "//a//", false }, /* NO_CHECK_STYLE */
219240116Smarcel        { "a////", false }, /* NO_CHECK_STYLE */
220240116Smarcel        { "../foo", false },
221240116Smarcel        { NULL, false },
222240116Smarcel    };
223240116Smarcel    struct test *t;
224240116Smarcel
225240116Smarcel    for (t = &tests[0]; t->in != NULL; t++) {
226240116Smarcel        atf_fs_path_t p;
227240116Smarcel
228240116Smarcel        printf("Input          : %s\n", t->in);
229240116Smarcel        printf("Expected result: %s\n", t->root ? "true" : "false");
230240116Smarcel
231240116Smarcel        RE(atf_fs_path_init_fmt(&p, "%s", t->in));
232240116Smarcel        printf("Result         : %s\n",
233240116Smarcel               atf_fs_path_is_root(&p) ? "true" : "false");
234240116Smarcel        if (t->root)
235240116Smarcel            ATF_REQUIRE(atf_fs_path_is_root(&p));
236240116Smarcel        else
237240116Smarcel            ATF_REQUIRE(!atf_fs_path_is_root(&p));
238240116Smarcel        atf_fs_path_fini(&p);
239240116Smarcel
240240116Smarcel        printf("\n");
241240116Smarcel    }
242240116Smarcel}
243240116Smarcel
244240116SmarcelATF_TC(path_branch_path);
245240116SmarcelATF_TC_HEAD(path_branch_path, tc)
246240116Smarcel{
247240116Smarcel    atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_path_branch_path "
248240116Smarcel                      "function");
249240116Smarcel}
250240116SmarcelATF_TC_BODY(path_branch_path, tc)
251240116Smarcel{
252240116Smarcel    struct test {
253240116Smarcel        const char *in;
254240116Smarcel        const char *branch;
255240116Smarcel    } tests[] = {
256240116Smarcel        { ".", "." },
257240116Smarcel        { "foo", "." },
258240116Smarcel        { "foo/bar", "foo" },
259240116Smarcel        { "/foo", "/" },
260240116Smarcel        { "/foo/bar", "/foo" },
261240116Smarcel        { NULL, NULL },
262240116Smarcel    };
263240116Smarcel    struct test *t;
264240116Smarcel
265240116Smarcel    for (t = &tests[0]; t->in != NULL; t++) {
266240116Smarcel        atf_fs_path_t p, bp;
267240116Smarcel
268240116Smarcel        printf("Input          : %s\n", t->in);
269240116Smarcel        printf("Expected output: %s\n", t->branch);
270240116Smarcel
271240116Smarcel        RE(atf_fs_path_init_fmt(&p, "%s", t->in));
272240116Smarcel        RE(atf_fs_path_branch_path(&p, &bp));
273240116Smarcel        printf("Output         : %s\n", atf_fs_path_cstring(&bp));
274240116Smarcel        ATF_REQUIRE(strcmp(atf_fs_path_cstring(&bp), t->branch) == 0);
275240116Smarcel        atf_fs_path_fini(&bp);
276240116Smarcel        atf_fs_path_fini(&p);
277240116Smarcel
278240116Smarcel        printf("\n");
279240116Smarcel    }
280240116Smarcel}
281240116Smarcel
282240116SmarcelATF_TC(path_leaf_name);
283240116SmarcelATF_TC_HEAD(path_leaf_name, tc)
284240116Smarcel{
285240116Smarcel    atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_path_leaf_name "
286240116Smarcel                      "function");
287240116Smarcel}
288240116SmarcelATF_TC_BODY(path_leaf_name, tc)
289240116Smarcel{
290240116Smarcel    struct test {
291240116Smarcel        const char *in;
292240116Smarcel        const char *leaf;
293240116Smarcel    } tests[] = {
294240116Smarcel        { ".", "." },
295240116Smarcel        { "foo", "foo" },
296240116Smarcel        { "foo/bar", "bar" },
297240116Smarcel        { "/foo", "foo" },
298240116Smarcel        { "/foo/bar", "bar" },
299240116Smarcel        { NULL, NULL },
300240116Smarcel    };
301240116Smarcel    struct test *t;
302240116Smarcel
303240116Smarcel    for (t = &tests[0]; t->in != NULL; t++) {
304240116Smarcel        atf_fs_path_t p;
305240116Smarcel        atf_dynstr_t ln;
306240116Smarcel
307240116Smarcel        printf("Input          : %s\n", t->in);
308240116Smarcel        printf("Expected output: %s\n", t->leaf);
309240116Smarcel
310240116Smarcel        RE(atf_fs_path_init_fmt(&p, "%s", t->in));
311240116Smarcel        RE(atf_fs_path_leaf_name(&p, &ln));
312240116Smarcel        printf("Output         : %s\n", atf_dynstr_cstring(&ln));
313240116Smarcel        ATF_REQUIRE(atf_equal_dynstr_cstring(&ln, t->leaf));
314240116Smarcel        atf_dynstr_fini(&ln);
315240116Smarcel        atf_fs_path_fini(&p);
316240116Smarcel
317240116Smarcel        printf("\n");
318240116Smarcel    }
319240116Smarcel}
320240116Smarcel
321240116SmarcelATF_TC(path_append);
322240116SmarcelATF_TC_HEAD(path_append, tc)
323240116Smarcel{
324240116Smarcel    atf_tc_set_md_var(tc, "descr", "Tests the concatenation of multiple "
325240116Smarcel                      "paths");
326240116Smarcel}
327240116SmarcelATF_TC_BODY(path_append, tc)
328240116Smarcel{
329240116Smarcel    struct test {
330240116Smarcel        const char *in;
331240116Smarcel        const char *ap;
332240116Smarcel        const char *out;
333240116Smarcel    } tests[] = {
334240116Smarcel        { "foo", "bar", "foo/bar" },
335240116Smarcel        { "foo/", "/bar", "foo/bar" },
336240116Smarcel        { "foo/", "/bar/baz", "foo/bar/baz" },
337240116Smarcel        { "foo/", "///bar///baz", "foo/bar/baz" }, /* NO_CHECK_STYLE */
338240116Smarcel
339240116Smarcel        { NULL, NULL, NULL }
340240116Smarcel    };
341240116Smarcel    struct test *t;
342240116Smarcel
343240116Smarcel    for (t = &tests[0]; t->in != NULL; t++) {
344240116Smarcel        atf_fs_path_t p;
345240116Smarcel
346240116Smarcel        printf("Input          : >%s<\n", t->in);
347240116Smarcel        printf("Append         : >%s<\n", t->ap);
348240116Smarcel        printf("Expected output: >%s<\n", t->out);
349240116Smarcel
350240116Smarcel        RE(atf_fs_path_init_fmt(&p, "%s", t->in));
351240116Smarcel
352240116Smarcel        RE(atf_fs_path_append_fmt(&p, "%s", t->ap));
353240116Smarcel
354240116Smarcel        printf("Output         : >%s<\n", atf_fs_path_cstring(&p));
355240116Smarcel        ATF_REQUIRE(strcmp(atf_fs_path_cstring(&p), t->out) == 0);
356240116Smarcel
357240116Smarcel        atf_fs_path_fini(&p);
358240116Smarcel
359240116Smarcel        printf("\n");
360240116Smarcel    }
361240116Smarcel}
362240116Smarcel
363240116SmarcelATF_TC(path_to_absolute);
364240116SmarcelATF_TC_HEAD(path_to_absolute, tc)
365240116Smarcel{
366240116Smarcel    atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_path_to_absolute "
367240116Smarcel                      "function");
368240116Smarcel}
369240116SmarcelATF_TC_BODY(path_to_absolute, tc)
370240116Smarcel{
371240116Smarcel    const char *names[] = { ".", "dir", NULL };
372240116Smarcel    const char **n;
373240116Smarcel
374240116Smarcel    ATF_REQUIRE(mkdir("dir", 0755) != -1);
375240116Smarcel
376240116Smarcel    for (n = names; *n != NULL; n++) {
377240116Smarcel        atf_fs_path_t p, p2;
378240116Smarcel        atf_fs_stat_t st1, st2;
379240116Smarcel
380240116Smarcel        RE(atf_fs_path_init_fmt(&p, "%s", *n));
381240116Smarcel        RE(atf_fs_stat_init(&st1, &p));
382240116Smarcel        printf("Relative path: %s\n", atf_fs_path_cstring(&p));
383240116Smarcel
384240116Smarcel        RE(atf_fs_path_to_absolute(&p, &p2));
385240116Smarcel        printf("Absolute path: %s\n", atf_fs_path_cstring(&p2));
386240116Smarcel
387240116Smarcel        ATF_REQUIRE(atf_fs_path_is_absolute(&p2));
388240116Smarcel        RE(atf_fs_stat_init(&st2, &p2));
389240116Smarcel
390240116Smarcel        ATF_REQUIRE_EQ(atf_fs_stat_get_device(&st1),
391240116Smarcel                        atf_fs_stat_get_device(&st2));
392240116Smarcel        ATF_REQUIRE_EQ(atf_fs_stat_get_inode(&st1),
393240116Smarcel                        atf_fs_stat_get_inode(&st2));
394240116Smarcel
395240116Smarcel        atf_fs_stat_fini(&st2);
396240116Smarcel        atf_fs_stat_fini(&st1);
397240116Smarcel        atf_fs_path_fini(&p2);
398240116Smarcel        atf_fs_path_fini(&p);
399240116Smarcel
400240116Smarcel        printf("\n");
401240116Smarcel    }
402240116Smarcel}
403240116Smarcel
404240116SmarcelATF_TC(path_equal);
405240116SmarcelATF_TC_HEAD(path_equal, tc)
406240116Smarcel{
407240116Smarcel    atf_tc_set_md_var(tc, "descr", "Tests the equality operators for paths");
408240116Smarcel}
409240116SmarcelATF_TC_BODY(path_equal, tc)
410240116Smarcel{
411240116Smarcel    atf_fs_path_t p1, p2;
412240116Smarcel
413240116Smarcel    RE(atf_fs_path_init_fmt(&p1, "foo"));
414240116Smarcel
415240116Smarcel    RE(atf_fs_path_init_fmt(&p2, "foo"));
416240116Smarcel    ATF_REQUIRE(atf_equal_fs_path_fs_path(&p1, &p2));
417240116Smarcel    atf_fs_path_fini(&p2);
418240116Smarcel
419240116Smarcel    RE(atf_fs_path_init_fmt(&p2, "bar"));
420240116Smarcel    ATF_REQUIRE(!atf_equal_fs_path_fs_path(&p1, &p2));
421240116Smarcel    atf_fs_path_fini(&p2);
422240116Smarcel
423240116Smarcel    atf_fs_path_fini(&p1);
424240116Smarcel}
425240116Smarcel
426240116Smarcel/* ---------------------------------------------------------------------
427240116Smarcel * Test cases for the "atf_fs_stat" type.
428240116Smarcel * --------------------------------------------------------------------- */
429240116Smarcel
430240116SmarcelATF_TC(stat_mode);
431240116SmarcelATF_TC_HEAD(stat_mode, tc)
432240116Smarcel{
433240116Smarcel    atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_stat_get_mode function "
434240116Smarcel                      "and, indirectly, the constructor");
435240116Smarcel}
436240116SmarcelATF_TC_BODY(stat_mode, tc)
437240116Smarcel{
438240116Smarcel    atf_fs_path_t p;
439240116Smarcel    atf_fs_stat_t st;
440240116Smarcel
441240116Smarcel    create_file("f1", 0400);
442240116Smarcel    create_file("f2", 0644);
443240116Smarcel
444240116Smarcel    RE(atf_fs_path_init_fmt(&p, "f1"));
445240116Smarcel    RE(atf_fs_stat_init(&st, &p));
446240116Smarcel    ATF_CHECK_EQ(0400, atf_fs_stat_get_mode(&st));
447240116Smarcel    atf_fs_stat_fini(&st);
448240116Smarcel    atf_fs_path_fini(&p);
449240116Smarcel
450240116Smarcel    RE(atf_fs_path_init_fmt(&p, "f2"));
451240116Smarcel    RE(atf_fs_stat_init(&st, &p));
452240116Smarcel    ATF_CHECK_EQ(0644, atf_fs_stat_get_mode(&st));
453240116Smarcel    atf_fs_stat_fini(&st);
454240116Smarcel    atf_fs_path_fini(&p);
455240116Smarcel}
456240116Smarcel
457240116SmarcelATF_TC(stat_type);
458240116SmarcelATF_TC_HEAD(stat_type, tc)
459240116Smarcel{
460240116Smarcel    atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_stat_get_type function "
461240116Smarcel                      "and, indirectly, the constructor");
462240116Smarcel}
463240116SmarcelATF_TC_BODY(stat_type, tc)
464240116Smarcel{
465240116Smarcel    atf_fs_path_t p;
466240116Smarcel    atf_fs_stat_t st;
467240116Smarcel
468240116Smarcel    create_dir("dir", 0755);
469240116Smarcel    create_file("reg", 0644);
470240116Smarcel
471240116Smarcel    RE(atf_fs_path_init_fmt(&p, "dir"));
472240116Smarcel    RE(atf_fs_stat_init(&st, &p));
473240116Smarcel    ATF_REQUIRE_EQ(atf_fs_stat_get_type(&st), atf_fs_stat_dir_type);
474240116Smarcel    atf_fs_stat_fini(&st);
475240116Smarcel    atf_fs_path_fini(&p);
476240116Smarcel
477240116Smarcel    RE(atf_fs_path_init_fmt(&p, "reg"));
478240116Smarcel    RE(atf_fs_stat_init(&st, &p));
479240116Smarcel    ATF_REQUIRE_EQ(atf_fs_stat_get_type(&st), atf_fs_stat_reg_type);
480240116Smarcel    atf_fs_stat_fini(&st);
481240116Smarcel    atf_fs_path_fini(&p);
482240116Smarcel}
483240116Smarcel
484240116SmarcelATF_TC(stat_perms);
485240116SmarcelATF_TC_HEAD(stat_perms, tc)
486240116Smarcel{
487240116Smarcel    atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_stat_is_* functions");
488240116Smarcel}
489240116SmarcelATF_TC_BODY(stat_perms, tc)
490240116Smarcel{
491240116Smarcel    atf_fs_path_t p;
492240116Smarcel    atf_fs_stat_t st;
493240116Smarcel
494240116Smarcel    create_file("reg", 0);
495240116Smarcel
496240116Smarcel    RE(atf_fs_path_init_fmt(&p, "reg"));
497240116Smarcel
498240116Smarcel#define perms(ur, uw, ux, gr, gw, gx, othr, othw, othx) \
499240116Smarcel    { \
500240116Smarcel        RE(atf_fs_stat_init(&st, &p)); \
501240116Smarcel        ATF_REQUIRE(atf_fs_stat_is_owner_readable(&st) == ur); \
502240116Smarcel        ATF_REQUIRE(atf_fs_stat_is_owner_writable(&st) == uw); \
503240116Smarcel        ATF_REQUIRE(atf_fs_stat_is_owner_executable(&st) == ux); \
504240116Smarcel        ATF_REQUIRE(atf_fs_stat_is_group_readable(&st) == gr); \
505240116Smarcel        ATF_REQUIRE(atf_fs_stat_is_group_writable(&st) == gw); \
506240116Smarcel        ATF_REQUIRE(atf_fs_stat_is_group_executable(&st) == gx); \
507240116Smarcel        ATF_REQUIRE(atf_fs_stat_is_other_readable(&st) == othr); \
508240116Smarcel        ATF_REQUIRE(atf_fs_stat_is_other_writable(&st) == othw); \
509240116Smarcel        ATF_REQUIRE(atf_fs_stat_is_other_executable(&st) == othx); \
510240116Smarcel        atf_fs_stat_fini(&st); \
511240116Smarcel    }
512240116Smarcel
513240116Smarcel    chmod("reg", 0000);
514240116Smarcel    perms(false, false, false, false, false, false, false, false, false);
515240116Smarcel
516240116Smarcel    chmod("reg", 0001);
517240116Smarcel    perms(false, false, false, false, false, false, false, false, true);
518240116Smarcel
519240116Smarcel    chmod("reg", 0010);
520240116Smarcel    perms(false, false, false, false, false, true, false, false, false);
521240116Smarcel
522240116Smarcel    chmod("reg", 0100);
523240116Smarcel    perms(false, false, true, false, false, false, false, false, false);
524240116Smarcel
525240116Smarcel    chmod("reg", 0002);
526240116Smarcel    perms(false, false, false, false, false, false, false, true, false);
527240116Smarcel
528240116Smarcel    chmod("reg", 0020);
529240116Smarcel    perms(false, false, false, false, true, false, false, false, false);
530240116Smarcel
531240116Smarcel    chmod("reg", 0200);
532240116Smarcel    perms(false, true, false, false, false, false, false, false, false);
533240116Smarcel
534240116Smarcel    chmod("reg", 0004);
535240116Smarcel    perms(false, false, false, false, false, false, true, false, false);
536240116Smarcel
537240116Smarcel    chmod("reg", 0040);
538240116Smarcel    perms(false, false, false, true, false, false, false, false, false);
539240116Smarcel
540240116Smarcel    chmod("reg", 0400);
541240116Smarcel    perms(true, false, false, false, false, false, false, false, false);
542240116Smarcel
543240116Smarcel    chmod("reg", 0644);
544240116Smarcel    perms(true, true, false, true, false, false, true, false, false);
545240116Smarcel
546240116Smarcel    chmod("reg", 0755);
547240116Smarcel    perms(true, true, true, true, false, true, true, false, true);
548240116Smarcel
549240116Smarcel    chmod("reg", 0777);
550240116Smarcel    perms(true, true, true, true, true, true, true, true, true);
551240116Smarcel
552240116Smarcel#undef perms
553240116Smarcel
554240116Smarcel    atf_fs_path_fini(&p);
555240116Smarcel}
556240116Smarcel
557240116Smarcel/* ---------------------------------------------------------------------
558240116Smarcel * Test cases for the free functions.
559240116Smarcel * --------------------------------------------------------------------- */
560240116Smarcel
561240116SmarcelATF_TC(exists);
562240116SmarcelATF_TC_HEAD(exists, tc)
563240116Smarcel{
564240116Smarcel    atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_exists function");
565240116Smarcel}
566240116SmarcelATF_TC_BODY(exists, tc)
567240116Smarcel{
568240116Smarcel    atf_error_t err;
569240116Smarcel    atf_fs_path_t pdir, pfile;
570240116Smarcel    bool b;
571240116Smarcel
572240116Smarcel    RE(atf_fs_path_init_fmt(&pdir, "dir"));
573240116Smarcel    RE(atf_fs_path_init_fmt(&pfile, "dir/file"));
574240116Smarcel
575240116Smarcel    create_dir(atf_fs_path_cstring(&pdir), 0755);
576240116Smarcel    create_file(atf_fs_path_cstring(&pfile), 0644);
577240116Smarcel
578240116Smarcel    printf("Checking existence of a directory\n");
579240116Smarcel    RE(atf_fs_exists(&pdir, &b));
580240116Smarcel    ATF_REQUIRE(b);
581240116Smarcel
582240116Smarcel    printf("Checking existence of a file\n");
583240116Smarcel    RE(atf_fs_exists(&pfile, &b));
584240116Smarcel    ATF_REQUIRE(b);
585240116Smarcel
586240116Smarcel    /* XXX: This should probably be a separate test case to let the user
587240116Smarcel     * be aware that some tests were skipped because privileges were not
588240116Smarcel     * correct. */
589240116Smarcel    if (!atf_user_is_root()) {
590240116Smarcel        printf("Checking existence of a file inside a directory without "
591240116Smarcel               "permissions\n");
592240116Smarcel        ATF_REQUIRE(chmod(atf_fs_path_cstring(&pdir), 0000) != -1);
593240116Smarcel        err = atf_fs_exists(&pfile, &b);
594240116Smarcel        ATF_REQUIRE(atf_is_error(err));
595240116Smarcel        ATF_REQUIRE(atf_error_is(err, "libc"));
596240116Smarcel        ATF_REQUIRE(chmod(atf_fs_path_cstring(&pdir), 0755) != -1);
597240116Smarcel        atf_error_free(err);
598240116Smarcel    }
599240116Smarcel
600240116Smarcel    printf("Checking existence of a non-existent file\n");
601240116Smarcel    ATF_REQUIRE(unlink(atf_fs_path_cstring(&pfile)) != -1);
602240116Smarcel    RE(atf_fs_exists(&pfile, &b));
603240116Smarcel    ATF_REQUIRE(!b);
604240116Smarcel
605240116Smarcel    atf_fs_path_fini(&pfile);
606240116Smarcel    atf_fs_path_fini(&pdir);
607240116Smarcel}
608240116Smarcel
609240116SmarcelATF_TC(eaccess);
610240116SmarcelATF_TC_HEAD(eaccess, tc)
611240116Smarcel{
612240116Smarcel    atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_eaccess function");
613240116Smarcel}
614240116SmarcelATF_TC_BODY(eaccess, tc)
615240116Smarcel{
616240116Smarcel    const int modes[] = { atf_fs_access_f, atf_fs_access_r, atf_fs_access_w,
617240116Smarcel                          atf_fs_access_x, 0 };
618240116Smarcel    const int *m;
619240116Smarcel    struct tests {
620240116Smarcel        mode_t fmode;
621240116Smarcel        int amode;
622240116Smarcel        int uerror;
623240116Smarcel        int rerror;
624240116Smarcel    } tests[] = {
625240116Smarcel        { 0000, atf_fs_access_r, EACCES, 0 },
626240116Smarcel        { 0000, atf_fs_access_w, EACCES, 0 },
627240116Smarcel        { 0000, atf_fs_access_x, EACCES, EACCES },
628240116Smarcel
629240116Smarcel        { 0001, atf_fs_access_r, EACCES, 0 },
630240116Smarcel        { 0001, atf_fs_access_w, EACCES, 0 },
631240116Smarcel        { 0001, atf_fs_access_x, EACCES, 0 },
632240116Smarcel        { 0002, atf_fs_access_r, EACCES, 0 },
633240116Smarcel        { 0002, atf_fs_access_w, EACCES, 0 },
634240116Smarcel        { 0002, atf_fs_access_x, EACCES, EACCES },
635240116Smarcel        { 0004, atf_fs_access_r, EACCES, 0 },
636240116Smarcel        { 0004, atf_fs_access_w, EACCES, 0 },
637240116Smarcel        { 0004, atf_fs_access_x, EACCES, EACCES },
638240116Smarcel
639240116Smarcel        { 0010, atf_fs_access_r, EACCES, 0 },
640240116Smarcel        { 0010, atf_fs_access_w, EACCES, 0 },
641240116Smarcel        { 0010, atf_fs_access_x, 0,      0 },
642240116Smarcel        { 0020, atf_fs_access_r, EACCES, 0 },
643240116Smarcel        { 0020, atf_fs_access_w, 0,      0 },
644240116Smarcel        { 0020, atf_fs_access_x, EACCES, EACCES },
645240116Smarcel        { 0040, atf_fs_access_r, 0,      0 },
646240116Smarcel        { 0040, atf_fs_access_w, EACCES, 0 },
647240116Smarcel        { 0040, atf_fs_access_x, EACCES, EACCES },
648240116Smarcel
649240116Smarcel        { 0100, atf_fs_access_r, EACCES, 0 },
650240116Smarcel        { 0100, atf_fs_access_w, EACCES, 0 },
651240116Smarcel        { 0100, atf_fs_access_x, 0,      0 },
652240116Smarcel        { 0200, atf_fs_access_r, EACCES, 0 },
653240116Smarcel        { 0200, atf_fs_access_w, 0,      0 },
654240116Smarcel        { 0200, atf_fs_access_x, EACCES, EACCES },
655240116Smarcel        { 0400, atf_fs_access_r, 0,      0 },
656240116Smarcel        { 0400, atf_fs_access_w, EACCES, 0 },
657240116Smarcel        { 0400, atf_fs_access_x, EACCES, EACCES },
658240116Smarcel
659240116Smarcel        { 0, 0, 0, 0 }
660240116Smarcel    };
661240116Smarcel    struct tests *t;
662240116Smarcel    atf_fs_path_t p;
663240116Smarcel    atf_error_t err;
664240116Smarcel
665240116Smarcel    RE(atf_fs_path_init_fmt(&p, "the-file"));
666240116Smarcel
667240116Smarcel    printf("Non-existent file checks\n");
668240116Smarcel    for (m = &modes[0]; *m != 0; m++) {
669240116Smarcel        err = atf_fs_eaccess(&p, *m);
670240116Smarcel        ATF_REQUIRE(atf_is_error(err));
671240116Smarcel        ATF_REQUIRE(atf_error_is(err, "libc"));
672240116Smarcel        ATF_REQUIRE_EQ(atf_libc_error_code(err), ENOENT);
673240116Smarcel        atf_error_free(err);
674240116Smarcel    }
675240116Smarcel
676240116Smarcel    create_file(atf_fs_path_cstring(&p), 0000);
677240116Smarcel    ATF_REQUIRE(chown(atf_fs_path_cstring(&p), geteuid(), getegid()) != -1);
678240116Smarcel
679240116Smarcel    for (t = &tests[0]; t->amode != 0; t++) {
680240116Smarcel        const int experr = atf_user_is_root() ? t->rerror : t->uerror;
681240116Smarcel
682240116Smarcel        printf("\n");
683240116Smarcel        printf("File mode     : %04o\n", (unsigned int)t->fmode);
684240116Smarcel        printf("Access mode   : 0x%02x\n", t->amode);
685240116Smarcel
686240116Smarcel        ATF_REQUIRE(chmod(atf_fs_path_cstring(&p), t->fmode) != -1);
687240116Smarcel
688240116Smarcel        /* First, existence check. */
689240116Smarcel        err = atf_fs_eaccess(&p, atf_fs_access_f);
690240116Smarcel        ATF_REQUIRE(!atf_is_error(err));
691240116Smarcel
692240116Smarcel        /* Now do the specific test case. */
693240116Smarcel        printf("Expected error: %d\n", experr);
694240116Smarcel        err = atf_fs_eaccess(&p, t->amode);
695240116Smarcel        if (atf_is_error(err)) {
696240116Smarcel            if (atf_error_is(err, "libc"))
697240116Smarcel                printf("Error         : %d\n", atf_libc_error_code(err));
698240116Smarcel            else
699240116Smarcel                printf("Error         : Non-libc error\n");
700240116Smarcel        } else
701240116Smarcel                printf("Error         : None\n");
702240116Smarcel        if (experr == 0) {
703240116Smarcel            ATF_REQUIRE(!atf_is_error(err));
704240116Smarcel        } else {
705240116Smarcel            ATF_REQUIRE(atf_is_error(err));
706240116Smarcel            ATF_REQUIRE(atf_error_is(err, "libc"));
707240116Smarcel            ATF_REQUIRE_EQ(atf_libc_error_code(err), experr);
708240116Smarcel            atf_error_free(err);
709240116Smarcel        }
710240116Smarcel    }
711240116Smarcel
712240116Smarcel    atf_fs_path_fini(&p);
713240116Smarcel}
714240116Smarcel
715240116SmarcelATF_TC(getcwd);
716240116SmarcelATF_TC_HEAD(getcwd, tc)
717240116Smarcel{
718240116Smarcel    atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_getcwd function");
719240116Smarcel}
720240116SmarcelATF_TC_BODY(getcwd, tc)
721240116Smarcel{
722240116Smarcel    atf_fs_path_t cwd1, cwd2;
723240116Smarcel
724240116Smarcel    create_dir ("root", 0755);
725240116Smarcel
726240116Smarcel    RE(atf_fs_getcwd(&cwd1));
727240116Smarcel    ATF_REQUIRE(chdir("root") != -1);
728240116Smarcel    RE(atf_fs_getcwd(&cwd2));
729240116Smarcel
730240116Smarcel    RE(atf_fs_path_append_fmt(&cwd1, "root"));
731240116Smarcel
732240116Smarcel    ATF_REQUIRE(atf_equal_fs_path_fs_path(&cwd1, &cwd2));
733240116Smarcel
734240116Smarcel    atf_fs_path_fini(&cwd2);
735240116Smarcel    atf_fs_path_fini(&cwd1);
736240116Smarcel}
737240116Smarcel
738240116SmarcelATF_TC(rmdir_empty);
739240116SmarcelATF_TC_HEAD(rmdir_empty, tc)
740240116Smarcel{
741240116Smarcel    atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_rmdir function");
742240116Smarcel}
743240116SmarcelATF_TC_BODY(rmdir_empty, tc)
744240116Smarcel{
745240116Smarcel    atf_fs_path_t p;
746240116Smarcel
747240116Smarcel    RE(atf_fs_path_init_fmt(&p, "test-dir"));
748240116Smarcel
749240116Smarcel    ATF_REQUIRE(mkdir("test-dir", 0755) != -1);
750240116Smarcel    ATF_REQUIRE(exists(&p));
751240116Smarcel    RE(atf_fs_rmdir(&p));
752240116Smarcel    ATF_REQUIRE(!exists(&p));
753240116Smarcel
754240116Smarcel    atf_fs_path_fini(&p);
755240116Smarcel}
756240116Smarcel
757240116SmarcelATF_TC(rmdir_enotempty);
758240116SmarcelATF_TC_HEAD(rmdir_enotempty, tc)
759240116Smarcel{
760240116Smarcel    atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_rmdir function");
761240116Smarcel}
762240116SmarcelATF_TC_BODY(rmdir_enotempty, tc)
763240116Smarcel{
764240116Smarcel    atf_fs_path_t p;
765240116Smarcel    atf_error_t err;
766240116Smarcel
767240116Smarcel    RE(atf_fs_path_init_fmt(&p, "test-dir"));
768240116Smarcel
769240116Smarcel    ATF_REQUIRE(mkdir("test-dir", 0755) != -1);
770240116Smarcel    ATF_REQUIRE(exists(&p));
771240116Smarcel    create_file("test-dir/foo", 0644);
772240116Smarcel
773240116Smarcel    err = atf_fs_rmdir(&p);
774240116Smarcel    ATF_REQUIRE(atf_is_error(err));
775240116Smarcel    ATF_REQUIRE(atf_error_is(err, "libc"));
776240116Smarcel    ATF_REQUIRE_EQ(atf_libc_error_code(err), ENOTEMPTY);
777240116Smarcel    atf_error_free(err);
778240116Smarcel
779240116Smarcel    atf_fs_path_fini(&p);
780240116Smarcel}
781240116Smarcel
782240116SmarcelATF_TC(rmdir_eperm);
783240116SmarcelATF_TC_HEAD(rmdir_eperm, tc)
784240116Smarcel{
785240116Smarcel    atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_rmdir function");
786240116Smarcel}
787240116SmarcelATF_TC_BODY(rmdir_eperm, tc)
788240116Smarcel{
789240116Smarcel    atf_fs_path_t p;
790240116Smarcel    atf_error_t err;
791240116Smarcel
792240116Smarcel    RE(atf_fs_path_init_fmt(&p, "test-dir/foo"));
793240116Smarcel
794240116Smarcel    ATF_REQUIRE(mkdir("test-dir", 0755) != -1);
795240116Smarcel    ATF_REQUIRE(mkdir("test-dir/foo", 0755) != -1);
796240116Smarcel    ATF_REQUIRE(chmod("test-dir", 0555) != -1);
797240116Smarcel    ATF_REQUIRE(exists(&p));
798240116Smarcel
799240116Smarcel    err = atf_fs_rmdir(&p);
800240116Smarcel    if (atf_user_is_root()) {
801240116Smarcel        ATF_REQUIRE(!atf_is_error(err));
802240116Smarcel    } else {
803240116Smarcel        ATF_REQUIRE(atf_is_error(err));
804240116Smarcel        ATF_REQUIRE(atf_error_is(err, "libc"));
805240116Smarcel        ATF_REQUIRE_EQ(atf_libc_error_code(err), EACCES);
806240116Smarcel        atf_error_free(err);
807240116Smarcel    }
808240116Smarcel
809240116Smarcel    atf_fs_path_fini(&p);
810240116Smarcel}
811240116Smarcel
812240116SmarcelATF_TC(mkdtemp_ok);
813240116SmarcelATF_TC_HEAD(mkdtemp_ok, tc)
814240116Smarcel{
815240116Smarcel    atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_mkdtemp function, "
816240116Smarcel                      "successful execution");
817240116Smarcel}
818240116SmarcelATF_TC_BODY(mkdtemp_ok, tc)
819240116Smarcel{
820240116Smarcel    atf_fs_path_t p1, p2;
821240116Smarcel    atf_fs_stat_t s1, s2;
822240116Smarcel
823240116Smarcel    RE(atf_fs_path_init_fmt(&p1, "testdir.XXXXXX"));
824240116Smarcel    RE(atf_fs_path_init_fmt(&p2, "testdir.XXXXXX"));
825240116Smarcel    RE(atf_fs_mkdtemp(&p1));
826240116Smarcel    RE(atf_fs_mkdtemp(&p2));
827240116Smarcel    ATF_REQUIRE(!atf_equal_fs_path_fs_path(&p1, &p2));
828240116Smarcel    ATF_REQUIRE(exists(&p1));
829240116Smarcel    ATF_REQUIRE(exists(&p2));
830240116Smarcel
831240116Smarcel    RE(atf_fs_stat_init(&s1, &p1));
832240116Smarcel    ATF_REQUIRE_EQ(atf_fs_stat_get_type(&s1), atf_fs_stat_dir_type);
833240116Smarcel    ATF_REQUIRE( atf_fs_stat_is_owner_readable(&s1));
834240116Smarcel    ATF_REQUIRE( atf_fs_stat_is_owner_writable(&s1));
835240116Smarcel    ATF_REQUIRE( atf_fs_stat_is_owner_executable(&s1));
836240116Smarcel    ATF_REQUIRE(!atf_fs_stat_is_group_readable(&s1));
837240116Smarcel    ATF_REQUIRE(!atf_fs_stat_is_group_writable(&s1));
838240116Smarcel    ATF_REQUIRE(!atf_fs_stat_is_group_executable(&s1));
839240116Smarcel    ATF_REQUIRE(!atf_fs_stat_is_other_readable(&s1));
840240116Smarcel    ATF_REQUIRE(!atf_fs_stat_is_other_writable(&s1));
841240116Smarcel    ATF_REQUIRE(!atf_fs_stat_is_other_executable(&s1));
842240116Smarcel
843240116Smarcel    RE(atf_fs_stat_init(&s2, &p2));
844240116Smarcel    ATF_REQUIRE_EQ(atf_fs_stat_get_type(&s2), atf_fs_stat_dir_type);
845240116Smarcel    ATF_REQUIRE( atf_fs_stat_is_owner_readable(&s2));
846240116Smarcel    ATF_REQUIRE( atf_fs_stat_is_owner_writable(&s2));
847240116Smarcel    ATF_REQUIRE( atf_fs_stat_is_owner_executable(&s2));
848240116Smarcel    ATF_REQUIRE(!atf_fs_stat_is_group_readable(&s2));
849240116Smarcel    ATF_REQUIRE(!atf_fs_stat_is_group_writable(&s2));
850240116Smarcel    ATF_REQUIRE(!atf_fs_stat_is_group_executable(&s2));
851240116Smarcel    ATF_REQUIRE(!atf_fs_stat_is_other_readable(&s2));
852240116Smarcel    ATF_REQUIRE(!atf_fs_stat_is_other_writable(&s2));
853240116Smarcel    ATF_REQUIRE(!atf_fs_stat_is_other_executable(&s2));
854240116Smarcel
855240116Smarcel    atf_fs_stat_fini(&s2);
856240116Smarcel    atf_fs_stat_fini(&s1);
857240116Smarcel    atf_fs_path_fini(&p2);
858240116Smarcel    atf_fs_path_fini(&p1);
859240116Smarcel}
860240116Smarcel
861240116SmarcelATF_TC(mkdtemp_err);
862240116SmarcelATF_TC_HEAD(mkdtemp_err, tc)
863240116Smarcel{
864240116Smarcel    atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_mkdtemp function, "
865240116Smarcel                      "error conditions");
866240116Smarcel    atf_tc_set_md_var(tc, "require.user", "unprivileged");
867240116Smarcel}
868240116SmarcelATF_TC_BODY(mkdtemp_err, tc)
869240116Smarcel{
870240116Smarcel    atf_error_t err;
871240116Smarcel    atf_fs_path_t p;
872240116Smarcel
873240116Smarcel    ATF_REQUIRE(mkdir("dir", 0555) != -1);
874240116Smarcel
875240116Smarcel    RE(atf_fs_path_init_fmt(&p, "dir/testdir.XXXXXX"));
876240116Smarcel
877240116Smarcel    err = atf_fs_mkdtemp(&p);
878240116Smarcel    ATF_REQUIRE(atf_is_error(err));
879240116Smarcel    ATF_REQUIRE(atf_error_is(err, "libc"));
880240116Smarcel    ATF_CHECK_EQ(atf_libc_error_code(err), EACCES);
881240116Smarcel    atf_error_free(err);
882240116Smarcel
883240116Smarcel    ATF_CHECK(!exists(&p));
884240116Smarcel    ATF_CHECK(strcmp(atf_fs_path_cstring(&p), "dir/testdir.XXXXXX") == 0);
885240116Smarcel
886240116Smarcel    atf_fs_path_fini(&p);
887240116Smarcel}
888240116Smarcel
889240116Smarcelstatic
890240116Smarcelvoid
891240116Smarceldo_umask_check(atf_error_t (*const mk_func)(atf_fs_path_t *),
892240116Smarcel               atf_fs_path_t *path, const mode_t test_mask,
893240116Smarcel               const char *str_mask, const char *exp_name)
894240116Smarcel{
895240116Smarcel    char buf[1024];
896240116Smarcel    int old_umask;
897240116Smarcel    atf_error_t err;
898240116Smarcel
899240116Smarcel    printf("Creating temporary %s with umask %s\n", exp_name, str_mask);
900240116Smarcel
901240116Smarcel    old_umask = umask(test_mask);
902240116Smarcel    err = mk_func(path);
903240116Smarcel    (void)umask(old_umask);
904240116Smarcel
905240116Smarcel    ATF_REQUIRE(atf_is_error(err));
906240116Smarcel    ATF_REQUIRE(atf_error_is(err, "invalid_umask"));
907240116Smarcel    atf_error_format(err, buf, sizeof(buf));
908240116Smarcel    ATF_CHECK(strstr(buf, exp_name) != NULL);
909240116Smarcel    ATF_CHECK(strstr(buf, str_mask) != NULL);
910240116Smarcel    atf_error_free(err);
911240116Smarcel}
912240116Smarcel
913240116SmarcelATF_TC(mkdtemp_umask);
914240116SmarcelATF_TC_HEAD(mkdtemp_umask, tc)
915240116Smarcel{
916240116Smarcel    atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_mkdtemp function "
917240116Smarcel                      "causing an error due to a too strict umask");
918240116Smarcel}
919240116SmarcelATF_TC_BODY(mkdtemp_umask, tc)
920240116Smarcel{
921240116Smarcel    atf_fs_path_t p;
922240116Smarcel
923240116Smarcel    RE(atf_fs_path_init_fmt(&p, "testdir.XXXXXX"));
924240116Smarcel
925240116Smarcel    do_umask_check(atf_fs_mkdtemp, &p, 00100, "00100", "directory");
926240116Smarcel    do_umask_check(atf_fs_mkdtemp, &p, 00200, "00200", "directory");
927240116Smarcel    do_umask_check(atf_fs_mkdtemp, &p, 00400, "00400", "directory");
928240116Smarcel    do_umask_check(atf_fs_mkdtemp, &p, 00500, "00500", "directory");
929240116Smarcel    do_umask_check(atf_fs_mkdtemp, &p, 00600, "00600", "directory");
930240116Smarcel
931240116Smarcel    atf_fs_path_fini(&p);
932240116Smarcel}
933240116Smarcel
934240116SmarcelATF_TC(mkstemp_ok);
935240116SmarcelATF_TC_HEAD(mkstemp_ok, tc)
936240116Smarcel{
937240116Smarcel    atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_mkstemp function, "
938240116Smarcel                      "successful execution");
939240116Smarcel}
940240116SmarcelATF_TC_BODY(mkstemp_ok, tc)
941240116Smarcel{
942240116Smarcel    int fd1, fd2;
943240116Smarcel    atf_fs_path_t p1, p2;
944240116Smarcel    atf_fs_stat_t s1, s2;
945240116Smarcel
946240116Smarcel    RE(atf_fs_path_init_fmt(&p1, "testfile.XXXXXX"));
947240116Smarcel    RE(atf_fs_path_init_fmt(&p2, "testfile.XXXXXX"));
948240116Smarcel    fd1 = fd2 = -1;
949240116Smarcel    RE(atf_fs_mkstemp(&p1, &fd1));
950240116Smarcel    RE(atf_fs_mkstemp(&p2, &fd2));
951240116Smarcel    ATF_REQUIRE(!atf_equal_fs_path_fs_path(&p1, &p2));
952240116Smarcel    ATF_REQUIRE(exists(&p1));
953240116Smarcel    ATF_REQUIRE(exists(&p2));
954240116Smarcel
955240116Smarcel    ATF_CHECK(fd1 != -1);
956240116Smarcel    ATF_CHECK(fd2 != -1);
957240116Smarcel    ATF_CHECK(write(fd1, "foo", 3) == 3);
958240116Smarcel    ATF_CHECK(write(fd2, "bar", 3) == 3);
959240116Smarcel    close(fd1);
960240116Smarcel    close(fd2);
961240116Smarcel
962240116Smarcel    RE(atf_fs_stat_init(&s1, &p1));
963240116Smarcel    ATF_CHECK_EQ(atf_fs_stat_get_type(&s1), atf_fs_stat_reg_type);
964240116Smarcel    ATF_CHECK( atf_fs_stat_is_owner_readable(&s1));
965240116Smarcel    ATF_CHECK( atf_fs_stat_is_owner_writable(&s1));
966240116Smarcel    ATF_CHECK(!atf_fs_stat_is_owner_executable(&s1));
967240116Smarcel    ATF_CHECK(!atf_fs_stat_is_group_readable(&s1));
968240116Smarcel    ATF_CHECK(!atf_fs_stat_is_group_writable(&s1));
969240116Smarcel    ATF_CHECK(!atf_fs_stat_is_group_executable(&s1));
970240116Smarcel    ATF_CHECK(!atf_fs_stat_is_other_readable(&s1));
971240116Smarcel    ATF_CHECK(!atf_fs_stat_is_other_writable(&s1));
972240116Smarcel    ATF_CHECK(!atf_fs_stat_is_other_executable(&s1));
973240116Smarcel
974240116Smarcel    RE(atf_fs_stat_init(&s2, &p2));
975240116Smarcel    ATF_CHECK_EQ(atf_fs_stat_get_type(&s2), atf_fs_stat_reg_type);
976240116Smarcel    ATF_CHECK( atf_fs_stat_is_owner_readable(&s2));
977240116Smarcel    ATF_CHECK( atf_fs_stat_is_owner_writable(&s2));
978240116Smarcel    ATF_CHECK(!atf_fs_stat_is_owner_executable(&s2));
979240116Smarcel    ATF_CHECK(!atf_fs_stat_is_group_readable(&s2));
980240116Smarcel    ATF_CHECK(!atf_fs_stat_is_group_writable(&s2));
981240116Smarcel    ATF_CHECK(!atf_fs_stat_is_group_executable(&s2));
982240116Smarcel    ATF_CHECK(!atf_fs_stat_is_other_readable(&s2));
983240116Smarcel    ATF_CHECK(!atf_fs_stat_is_other_writable(&s2));
984240116Smarcel    ATF_CHECK(!atf_fs_stat_is_other_executable(&s2));
985240116Smarcel
986240116Smarcel    atf_fs_stat_fini(&s2);
987240116Smarcel    atf_fs_stat_fini(&s1);
988240116Smarcel    atf_fs_path_fini(&p2);
989240116Smarcel    atf_fs_path_fini(&p1);
990240116Smarcel}
991240116Smarcel
992240116SmarcelATF_TC(mkstemp_err);
993240116SmarcelATF_TC_HEAD(mkstemp_err, tc)
994240116Smarcel{
995240116Smarcel    atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_mkstemp function, "
996240116Smarcel                      "error conditions");
997240116Smarcel    atf_tc_set_md_var(tc, "require.user", "unprivileged");
998240116Smarcel}
999240116SmarcelATF_TC_BODY(mkstemp_err, tc)
1000240116Smarcel{
1001240116Smarcel    int fd;
1002240116Smarcel    atf_error_t err;
1003240116Smarcel    atf_fs_path_t p;
1004240116Smarcel
1005240116Smarcel    ATF_REQUIRE(mkdir("dir", 0555) != -1);
1006240116Smarcel
1007240116Smarcel    RE(atf_fs_path_init_fmt(&p, "dir/testfile.XXXXXX"));
1008240116Smarcel    fd = 1234;
1009240116Smarcel
1010240116Smarcel    err = atf_fs_mkstemp(&p, &fd);
1011240116Smarcel    ATF_REQUIRE(atf_is_error(err));
1012240116Smarcel    ATF_REQUIRE(atf_error_is(err, "libc"));
1013240116Smarcel    ATF_CHECK_EQ(atf_libc_error_code(err), EACCES);
1014240116Smarcel    atf_error_free(err);
1015240116Smarcel
1016240116Smarcel    ATF_CHECK(!exists(&p));
1017240116Smarcel    ATF_CHECK(strcmp(atf_fs_path_cstring(&p), "dir/testfile.XXXXXX") == 0);
1018240116Smarcel    ATF_CHECK_EQ(fd, 1234);
1019240116Smarcel
1020240116Smarcel    atf_fs_path_fini(&p);
1021240116Smarcel}
1022240116Smarcel
1023240116SmarcelATF_TC(mkstemp_umask);
1024240116SmarcelATF_TC_HEAD(mkstemp_umask, tc)
1025240116Smarcel{
1026240116Smarcel    atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_mkstemp function "
1027240116Smarcel                      "causing an error due to a too strict umask");
1028240116Smarcel}
1029240116SmarcelATF_TC_BODY(mkstemp_umask, tc)
1030240116Smarcel{
1031240116Smarcel    atf_fs_path_t p;
1032240116Smarcel
1033240116Smarcel    RE(atf_fs_path_init_fmt(&p, "testfile.XXXXXX"));
1034240116Smarcel
1035240116Smarcel    do_umask_check(mkstemp_discard_fd, &p, 00100, "00100", "regular file");
1036240116Smarcel    do_umask_check(mkstemp_discard_fd, &p, 00200, "00200", "regular file");
1037240116Smarcel    do_umask_check(mkstemp_discard_fd, &p, 00400, "00400", "regular file");
1038240116Smarcel
1039240116Smarcel    atf_fs_path_fini(&p);
1040240116Smarcel}
1041240116Smarcel
1042240116Smarcel/* ---------------------------------------------------------------------
1043240116Smarcel * Main.
1044240116Smarcel * --------------------------------------------------------------------- */
1045240116Smarcel
1046240116SmarcelATF_TP_ADD_TCS(tp)
1047240116Smarcel{
1048240116Smarcel    /* Add the tests for the "atf_fs_path" type. */
1049240116Smarcel    ATF_TP_ADD_TC(tp, path_normalize);
1050240116Smarcel    ATF_TP_ADD_TC(tp, path_copy);
1051240116Smarcel    ATF_TP_ADD_TC(tp, path_is_absolute);
1052240116Smarcel    ATF_TP_ADD_TC(tp, path_is_root);
1053240116Smarcel    ATF_TP_ADD_TC(tp, path_branch_path);
1054240116Smarcel    ATF_TP_ADD_TC(tp, path_leaf_name);
1055240116Smarcel    ATF_TP_ADD_TC(tp, path_append);
1056240116Smarcel    ATF_TP_ADD_TC(tp, path_to_absolute);
1057240116Smarcel    ATF_TP_ADD_TC(tp, path_equal);
1058240116Smarcel
1059240116Smarcel    /* Add the tests for the "atf_fs_stat" type. */
1060240116Smarcel    ATF_TP_ADD_TC(tp, stat_mode);
1061240116Smarcel    ATF_TP_ADD_TC(tp, stat_type);
1062240116Smarcel    ATF_TP_ADD_TC(tp, stat_perms);
1063240116Smarcel
1064240116Smarcel    /* Add the tests for the free functions. */
1065240116Smarcel    ATF_TP_ADD_TC(tp, eaccess);
1066240116Smarcel    ATF_TP_ADD_TC(tp, exists);
1067240116Smarcel    ATF_TP_ADD_TC(tp, getcwd);
1068240116Smarcel    ATF_TP_ADD_TC(tp, rmdir_empty);
1069240116Smarcel    ATF_TP_ADD_TC(tp, rmdir_enotempty);
1070240116Smarcel    ATF_TP_ADD_TC(tp, rmdir_eperm);
1071240116Smarcel    ATF_TP_ADD_TC(tp, mkdtemp_ok);
1072240116Smarcel    ATF_TP_ADD_TC(tp, mkdtemp_err);
1073240116Smarcel    ATF_TP_ADD_TC(tp, mkdtemp_umask);
1074240116Smarcel    ATF_TP_ADD_TC(tp, mkstemp_ok);
1075240116Smarcel    ATF_TP_ADD_TC(tp, mkstemp_err);
1076240116Smarcel    ATF_TP_ADD_TC(tp, mkstemp_umask);
1077240116Smarcel
1078240116Smarcel    return atf_no_error();
1079240116Smarcel}
1080