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