111be35a1SLionel Sambuc /*
211be35a1SLionel Sambuc * Automated Testing Framework (atf)
311be35a1SLionel Sambuc *
411be35a1SLionel Sambuc * Copyright (c) 2007 The NetBSD Foundation, Inc.
511be35a1SLionel Sambuc * All rights reserved.
611be35a1SLionel Sambuc *
711be35a1SLionel Sambuc * Redistribution and use in source and binary forms, with or without
811be35a1SLionel Sambuc * modification, are permitted provided that the following conditions
911be35a1SLionel Sambuc * are met:
1011be35a1SLionel Sambuc * 1. Redistributions of source code must retain the above copyright
1111be35a1SLionel Sambuc * notice, this list of conditions and the following disclaimer.
1211be35a1SLionel Sambuc * 2. Redistributions in binary form must reproduce the above copyright
1311be35a1SLionel Sambuc * notice, this list of conditions and the following disclaimer in the
1411be35a1SLionel Sambuc * documentation and/or other materials provided with the distribution.
1511be35a1SLionel Sambuc *
1611be35a1SLionel Sambuc * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
1711be35a1SLionel Sambuc * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
1811be35a1SLionel Sambuc * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
1911be35a1SLionel Sambuc * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2011be35a1SLionel Sambuc * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
2111be35a1SLionel Sambuc * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2211be35a1SLionel Sambuc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
2311be35a1SLionel Sambuc * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2411be35a1SLionel Sambuc * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
2511be35a1SLionel Sambuc * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
2611be35a1SLionel Sambuc * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
2711be35a1SLionel Sambuc * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2811be35a1SLionel Sambuc */
2911be35a1SLionel Sambuc
3011be35a1SLionel Sambuc #if defined(HAVE_CONFIG_H)
3111be35a1SLionel Sambuc #include "bconfig.h"
3211be35a1SLionel Sambuc #endif
3311be35a1SLionel Sambuc
3411be35a1SLionel Sambuc #include <sys/types.h>
3511be35a1SLionel Sambuc #include <sys/param.h>
3611be35a1SLionel Sambuc #include <sys/mount.h>
3711be35a1SLionel Sambuc #include <sys/stat.h>
3811be35a1SLionel Sambuc #include <sys/wait.h>
3911be35a1SLionel Sambuc
4011be35a1SLionel Sambuc #include <dirent.h>
4111be35a1SLionel Sambuc #include <errno.h>
4211be35a1SLionel Sambuc #include <libgen.h>
4311be35a1SLionel Sambuc #include <stdarg.h>
4411be35a1SLionel Sambuc #include <stdio.h>
4511be35a1SLionel Sambuc #include <stdlib.h>
4611be35a1SLionel Sambuc #include <string.h>
4711be35a1SLionel Sambuc #include <unistd.h>
4811be35a1SLionel Sambuc
4911be35a1SLionel Sambuc #include "atf-c/defs.h"
5011be35a1SLionel Sambuc #include "atf-c/error.h"
5111be35a1SLionel Sambuc
5211be35a1SLionel Sambuc #include "fs.h"
5311be35a1SLionel Sambuc #include "sanity.h"
5411be35a1SLionel Sambuc #include "text.h"
5511be35a1SLionel Sambuc #include "user.h"
5611be35a1SLionel Sambuc
5711be35a1SLionel Sambuc /* ---------------------------------------------------------------------
5811be35a1SLionel Sambuc * Prototypes for auxiliary functions.
5911be35a1SLionel Sambuc * --------------------------------------------------------------------- */
6011be35a1SLionel Sambuc
6111be35a1SLionel Sambuc static bool check_umask(const mode_t, const mode_t);
6211be35a1SLionel Sambuc static atf_error_t copy_contents(const atf_fs_path_t *, char **);
6311be35a1SLionel Sambuc static mode_t current_umask(void);
6411be35a1SLionel Sambuc static atf_error_t do_mkdtemp(char *);
6511be35a1SLionel Sambuc static atf_error_t normalize(atf_dynstr_t *, char *);
660a6a1f1dSLionel Sambuc static atf_error_t normalize_ap(atf_dynstr_t *, const char *, va_list)
670a6a1f1dSLionel Sambuc ATF_DEFS_ATTRIBUTE_FORMAT_PRINTF(2, 0);
6811be35a1SLionel Sambuc static void replace_contents(atf_fs_path_t *, const char *);
6911be35a1SLionel Sambuc static const char *stat_type_to_string(const int);
7011be35a1SLionel Sambuc
7111be35a1SLionel Sambuc /* ---------------------------------------------------------------------
7211be35a1SLionel Sambuc * The "invalid_umask" error type.
7311be35a1SLionel Sambuc * --------------------------------------------------------------------- */
7411be35a1SLionel Sambuc
7511be35a1SLionel Sambuc struct invalid_umask_error_data {
7611be35a1SLionel Sambuc /* One of atf_fs_stat_*_type. */
7711be35a1SLionel Sambuc int m_type;
7811be35a1SLionel Sambuc
7911be35a1SLionel Sambuc /* The original path causing the error. */
8011be35a1SLionel Sambuc /* XXX: Ideally this would be an atf_fs_path_t, but if we create it
8111be35a1SLionel Sambuc * from the error constructor, we cannot delete the path later on.
8211be35a1SLionel Sambuc * Can't remember why atf_error_new does not take a hook for
8311be35a1SLionel Sambuc * deletion. */
8411be35a1SLionel Sambuc char m_path[1024];
8511be35a1SLionel Sambuc
8611be35a1SLionel Sambuc /* The umask that caused the error. */
8711be35a1SLionel Sambuc mode_t m_umask;
8811be35a1SLionel Sambuc };
8911be35a1SLionel Sambuc typedef struct invalid_umask_error_data invalid_umask_error_data_t;
9011be35a1SLionel Sambuc
9111be35a1SLionel Sambuc static
9211be35a1SLionel Sambuc void
invalid_umask_format(const atf_error_t err,char * buf,size_t buflen)9311be35a1SLionel Sambuc invalid_umask_format(const atf_error_t err, char *buf, size_t buflen)
9411be35a1SLionel Sambuc {
9511be35a1SLionel Sambuc const invalid_umask_error_data_t *data;
9611be35a1SLionel Sambuc
9711be35a1SLionel Sambuc PRE(atf_error_is(err, "invalid_umask"));
9811be35a1SLionel Sambuc
9911be35a1SLionel Sambuc data = atf_error_data(err);
10011be35a1SLionel Sambuc snprintf(buf, buflen, "Could not create the temporary %s %s because "
10111be35a1SLionel Sambuc "it will not have enough access rights due to the current "
10211be35a1SLionel Sambuc "umask %05o", stat_type_to_string(data->m_type),
10311be35a1SLionel Sambuc data->m_path, (unsigned int)data->m_umask);
10411be35a1SLionel Sambuc }
10511be35a1SLionel Sambuc
10611be35a1SLionel Sambuc static
10711be35a1SLionel Sambuc atf_error_t
invalid_umask_error(const atf_fs_path_t * path,const int type,const mode_t failing_mask)10811be35a1SLionel Sambuc invalid_umask_error(const atf_fs_path_t *path, const int type,
10911be35a1SLionel Sambuc const mode_t failing_mask)
11011be35a1SLionel Sambuc {
11111be35a1SLionel Sambuc atf_error_t err;
11211be35a1SLionel Sambuc invalid_umask_error_data_t data;
11311be35a1SLionel Sambuc
11411be35a1SLionel Sambuc data.m_type = type;
11511be35a1SLionel Sambuc
11611be35a1SLionel Sambuc strncpy(data.m_path, atf_fs_path_cstring(path), sizeof(data.m_path));
11711be35a1SLionel Sambuc data.m_path[sizeof(data.m_path) - 1] = '\0';
11811be35a1SLionel Sambuc
11911be35a1SLionel Sambuc data.m_umask = failing_mask;
12011be35a1SLionel Sambuc
12111be35a1SLionel Sambuc err = atf_error_new("invalid_umask", &data, sizeof(data),
12211be35a1SLionel Sambuc invalid_umask_format);
12311be35a1SLionel Sambuc
12411be35a1SLionel Sambuc return err;
12511be35a1SLionel Sambuc }
12611be35a1SLionel Sambuc
12711be35a1SLionel Sambuc /* ---------------------------------------------------------------------
12811be35a1SLionel Sambuc * The "unknown_file_type" error type.
12911be35a1SLionel Sambuc * --------------------------------------------------------------------- */
13011be35a1SLionel Sambuc
13111be35a1SLionel Sambuc struct unknown_type_error_data {
13211be35a1SLionel Sambuc const char *m_path;
13311be35a1SLionel Sambuc int m_type;
13411be35a1SLionel Sambuc };
13511be35a1SLionel Sambuc typedef struct unknown_type_error_data unknown_type_error_data_t;
13611be35a1SLionel Sambuc
13711be35a1SLionel Sambuc static
13811be35a1SLionel Sambuc void
unknown_type_format(const atf_error_t err,char * buf,size_t buflen)13911be35a1SLionel Sambuc unknown_type_format(const atf_error_t err, char *buf, size_t buflen)
14011be35a1SLionel Sambuc {
14111be35a1SLionel Sambuc const unknown_type_error_data_t *data;
14211be35a1SLionel Sambuc
14311be35a1SLionel Sambuc PRE(atf_error_is(err, "unknown_type"));
14411be35a1SLionel Sambuc
14511be35a1SLionel Sambuc data = atf_error_data(err);
14611be35a1SLionel Sambuc snprintf(buf, buflen, "Unknown file type %d of %s", data->m_type,
14711be35a1SLionel Sambuc data->m_path);
14811be35a1SLionel Sambuc }
14911be35a1SLionel Sambuc
15011be35a1SLionel Sambuc static
15111be35a1SLionel Sambuc atf_error_t
unknown_type_error(const char * path,int type)15211be35a1SLionel Sambuc unknown_type_error(const char *path, int type)
15311be35a1SLionel Sambuc {
15411be35a1SLionel Sambuc atf_error_t err;
15511be35a1SLionel Sambuc unknown_type_error_data_t data;
15611be35a1SLionel Sambuc
15711be35a1SLionel Sambuc data.m_path = path;
15811be35a1SLionel Sambuc data.m_type = type;
15911be35a1SLionel Sambuc
16011be35a1SLionel Sambuc err = atf_error_new("unknown_type", &data, sizeof(data),
16111be35a1SLionel Sambuc unknown_type_format);
16211be35a1SLionel Sambuc
16311be35a1SLionel Sambuc return err;
16411be35a1SLionel Sambuc }
16511be35a1SLionel Sambuc
16611be35a1SLionel Sambuc /* ---------------------------------------------------------------------
16711be35a1SLionel Sambuc * Auxiliary functions.
16811be35a1SLionel Sambuc * --------------------------------------------------------------------- */
16911be35a1SLionel Sambuc
17011be35a1SLionel Sambuc static
17111be35a1SLionel Sambuc bool
check_umask(const mode_t exp_mode,const mode_t min_mode)17211be35a1SLionel Sambuc check_umask(const mode_t exp_mode, const mode_t min_mode)
17311be35a1SLionel Sambuc {
17411be35a1SLionel Sambuc const mode_t actual_mode = (~current_umask() & exp_mode);
17511be35a1SLionel Sambuc return (actual_mode & min_mode) == min_mode;
17611be35a1SLionel Sambuc }
17711be35a1SLionel Sambuc
17811be35a1SLionel Sambuc static
17911be35a1SLionel Sambuc atf_error_t
copy_contents(const atf_fs_path_t * p,char ** buf)18011be35a1SLionel Sambuc copy_contents(const atf_fs_path_t *p, char **buf)
18111be35a1SLionel Sambuc {
18211be35a1SLionel Sambuc atf_error_t err;
18311be35a1SLionel Sambuc char *str;
18411be35a1SLionel Sambuc
18511be35a1SLionel Sambuc str = (char *)malloc(atf_dynstr_length(&p->m_data) + 1);
18611be35a1SLionel Sambuc if (str == NULL)
18711be35a1SLionel Sambuc err = atf_no_memory_error();
18811be35a1SLionel Sambuc else {
18911be35a1SLionel Sambuc strcpy(str, atf_dynstr_cstring(&p->m_data));
19011be35a1SLionel Sambuc *buf = str;
19111be35a1SLionel Sambuc err = atf_no_error();
19211be35a1SLionel Sambuc }
19311be35a1SLionel Sambuc
19411be35a1SLionel Sambuc return err;
19511be35a1SLionel Sambuc }
19611be35a1SLionel Sambuc
19711be35a1SLionel Sambuc static
19811be35a1SLionel Sambuc mode_t
current_umask(void)19911be35a1SLionel Sambuc current_umask(void)
20011be35a1SLionel Sambuc {
20111be35a1SLionel Sambuc const mode_t current = umask(0);
20211be35a1SLionel Sambuc (void)umask(current);
20311be35a1SLionel Sambuc return current;
20411be35a1SLionel Sambuc }
20511be35a1SLionel Sambuc
20611be35a1SLionel Sambuc static
20711be35a1SLionel Sambuc atf_error_t
do_mkdtemp(char * tmpl)20811be35a1SLionel Sambuc do_mkdtemp(char *tmpl)
20911be35a1SLionel Sambuc {
21011be35a1SLionel Sambuc atf_error_t err;
21111be35a1SLionel Sambuc
21211be35a1SLionel Sambuc PRE(strstr(tmpl, "XXXXXX") != NULL);
21311be35a1SLionel Sambuc
21411be35a1SLionel Sambuc if (mkdtemp(tmpl) == NULL)
21511be35a1SLionel Sambuc err = atf_libc_error(errno, "Cannot create temporary directory "
21611be35a1SLionel Sambuc "with template '%s'", tmpl);
21711be35a1SLionel Sambuc else
21811be35a1SLionel Sambuc err = atf_no_error();
21911be35a1SLionel Sambuc
22011be35a1SLionel Sambuc return err;
22111be35a1SLionel Sambuc }
22211be35a1SLionel Sambuc
22311be35a1SLionel Sambuc static
22411be35a1SLionel Sambuc atf_error_t
do_mkstemp(char * tmpl,int * fdout)22511be35a1SLionel Sambuc do_mkstemp(char *tmpl, int *fdout)
22611be35a1SLionel Sambuc {
22711be35a1SLionel Sambuc atf_error_t err;
22811be35a1SLionel Sambuc
22911be35a1SLionel Sambuc PRE(strstr(tmpl, "XXXXXX") != NULL);
23011be35a1SLionel Sambuc
23111be35a1SLionel Sambuc *fdout = mkstemp(tmpl);
23211be35a1SLionel Sambuc if (*fdout == -1)
23311be35a1SLionel Sambuc err = atf_libc_error(errno, "Cannot create temporary file "
23411be35a1SLionel Sambuc "with template '%s'", tmpl);
23511be35a1SLionel Sambuc
23611be35a1SLionel Sambuc else
23711be35a1SLionel Sambuc err = atf_no_error();
23811be35a1SLionel Sambuc
23911be35a1SLionel Sambuc return err;
24011be35a1SLionel Sambuc }
24111be35a1SLionel Sambuc
24211be35a1SLionel Sambuc static
24311be35a1SLionel Sambuc atf_error_t
normalize(atf_dynstr_t * d,char * p)24411be35a1SLionel Sambuc normalize(atf_dynstr_t *d, char *p)
24511be35a1SLionel Sambuc {
24611be35a1SLionel Sambuc const char *ptr;
24711be35a1SLionel Sambuc char *last;
24811be35a1SLionel Sambuc atf_error_t err;
24911be35a1SLionel Sambuc bool first;
25011be35a1SLionel Sambuc
25111be35a1SLionel Sambuc PRE(strlen(p) > 0);
25211be35a1SLionel Sambuc PRE(atf_dynstr_length(d) == 0);
25311be35a1SLionel Sambuc
25411be35a1SLionel Sambuc if (p[0] == '/')
25511be35a1SLionel Sambuc err = atf_dynstr_append_fmt(d, "/");
25611be35a1SLionel Sambuc else
25711be35a1SLionel Sambuc err = atf_no_error();
25811be35a1SLionel Sambuc
25911be35a1SLionel Sambuc first = true;
26011be35a1SLionel Sambuc last = NULL; /* Silence GCC warning. */
26111be35a1SLionel Sambuc ptr = strtok_r(p, "/", &last);
26211be35a1SLionel Sambuc while (!atf_is_error(err) && ptr != NULL) {
26311be35a1SLionel Sambuc if (strlen(ptr) > 0) {
26411be35a1SLionel Sambuc err = atf_dynstr_append_fmt(d, "%s%s", first ? "" : "/", ptr);
26511be35a1SLionel Sambuc first = false;
26611be35a1SLionel Sambuc }
26711be35a1SLionel Sambuc
26811be35a1SLionel Sambuc ptr = strtok_r(NULL, "/", &last);
26911be35a1SLionel Sambuc }
27011be35a1SLionel Sambuc
27111be35a1SLionel Sambuc return err;
27211be35a1SLionel Sambuc }
27311be35a1SLionel Sambuc
27411be35a1SLionel Sambuc static
27511be35a1SLionel Sambuc atf_error_t
normalize_ap(atf_dynstr_t * d,const char * p,va_list ap)27611be35a1SLionel Sambuc normalize_ap(atf_dynstr_t *d, const char *p, va_list ap)
27711be35a1SLionel Sambuc {
27811be35a1SLionel Sambuc char *str;
27911be35a1SLionel Sambuc atf_error_t err;
28011be35a1SLionel Sambuc va_list ap2;
28111be35a1SLionel Sambuc
28211be35a1SLionel Sambuc err = atf_dynstr_init(d);
28311be35a1SLionel Sambuc if (atf_is_error(err))
28411be35a1SLionel Sambuc goto out;
28511be35a1SLionel Sambuc
28611be35a1SLionel Sambuc va_copy(ap2, ap);
28711be35a1SLionel Sambuc err = atf_text_format_ap(&str, p, ap2);
28811be35a1SLionel Sambuc va_end(ap2);
28911be35a1SLionel Sambuc if (atf_is_error(err))
29011be35a1SLionel Sambuc atf_dynstr_fini(d);
29111be35a1SLionel Sambuc else {
29211be35a1SLionel Sambuc err = normalize(d, str);
29311be35a1SLionel Sambuc free(str);
29411be35a1SLionel Sambuc }
29511be35a1SLionel Sambuc
29611be35a1SLionel Sambuc out:
29711be35a1SLionel Sambuc return err;
29811be35a1SLionel Sambuc }
29911be35a1SLionel Sambuc
30011be35a1SLionel Sambuc static
30111be35a1SLionel Sambuc void
replace_contents(atf_fs_path_t * p,const char * buf)30211be35a1SLionel Sambuc replace_contents(atf_fs_path_t *p, const char *buf)
30311be35a1SLionel Sambuc {
304*e1cdaee1SLionel Sambuc #if !defined(NDEBUG) && defined(__minix)
30511be35a1SLionel Sambuc atf_error_t err;
30611be35a1SLionel Sambuc
30711be35a1SLionel Sambuc PRE(atf_dynstr_length(&p->m_data) == strlen(buf));
30811be35a1SLionel Sambuc
309*e1cdaee1SLionel Sambuc #endif /* !defined(NDEBUG) && defined(__minix) */
31011be35a1SLionel Sambuc atf_dynstr_clear(&p->m_data);
311*e1cdaee1SLionel Sambuc #if !defined(NDEBUG) && defined(__minix)
312*e1cdaee1SLionel Sambuc err =
313*e1cdaee1SLionel Sambuc #endif /* !defined(NDEBUG) && defined(__minix) */
314*e1cdaee1SLionel Sambuc atf_dynstr_append_fmt(&p->m_data, "%s", buf);
31511be35a1SLionel Sambuc
316*e1cdaee1SLionel Sambuc #if !defined(NDEBUG) && defined(__minix)
31711be35a1SLionel Sambuc INV(!atf_is_error(err));
318*e1cdaee1SLionel Sambuc #endif /* !defined(NDEBUG) && defined(__minix) */
31911be35a1SLionel Sambuc }
32011be35a1SLionel Sambuc
32111be35a1SLionel Sambuc static
32211be35a1SLionel Sambuc const char *
stat_type_to_string(const int type)32311be35a1SLionel Sambuc stat_type_to_string(const int type)
32411be35a1SLionel Sambuc {
32511be35a1SLionel Sambuc const char *str;
32611be35a1SLionel Sambuc
32711be35a1SLionel Sambuc if (type == atf_fs_stat_blk_type)
32811be35a1SLionel Sambuc str = "block device";
32911be35a1SLionel Sambuc else if (type == atf_fs_stat_chr_type)
33011be35a1SLionel Sambuc str = "character device";
33111be35a1SLionel Sambuc else if (type == atf_fs_stat_dir_type)
33211be35a1SLionel Sambuc str = "directory";
33311be35a1SLionel Sambuc else if (type == atf_fs_stat_fifo_type)
33411be35a1SLionel Sambuc str = "named pipe";
33511be35a1SLionel Sambuc else if (type == atf_fs_stat_lnk_type)
33611be35a1SLionel Sambuc str = "symbolic link";
33711be35a1SLionel Sambuc else if (type == atf_fs_stat_reg_type)
33811be35a1SLionel Sambuc str = "regular file";
33911be35a1SLionel Sambuc else if (type == atf_fs_stat_sock_type)
34011be35a1SLionel Sambuc str = "socket";
34111be35a1SLionel Sambuc else if (type == atf_fs_stat_wht_type)
34211be35a1SLionel Sambuc str = "whiteout";
34311be35a1SLionel Sambuc else {
34411be35a1SLionel Sambuc UNREACHABLE;
34511be35a1SLionel Sambuc str = NULL;
34611be35a1SLionel Sambuc }
34711be35a1SLionel Sambuc
34811be35a1SLionel Sambuc return str;
34911be35a1SLionel Sambuc }
35011be35a1SLionel Sambuc
35111be35a1SLionel Sambuc /* ---------------------------------------------------------------------
35211be35a1SLionel Sambuc * The "atf_fs_path" type.
35311be35a1SLionel Sambuc * --------------------------------------------------------------------- */
35411be35a1SLionel Sambuc
35511be35a1SLionel Sambuc /*
35611be35a1SLionel Sambuc * Constructors/destructors.
35711be35a1SLionel Sambuc */
35811be35a1SLionel Sambuc
35911be35a1SLionel Sambuc atf_error_t
atf_fs_path_init_ap(atf_fs_path_t * p,const char * fmt,va_list ap)36011be35a1SLionel Sambuc atf_fs_path_init_ap(atf_fs_path_t *p, const char *fmt, va_list ap)
36111be35a1SLionel Sambuc {
36211be35a1SLionel Sambuc atf_error_t err;
36311be35a1SLionel Sambuc va_list ap2;
36411be35a1SLionel Sambuc
36511be35a1SLionel Sambuc va_copy(ap2, ap);
36611be35a1SLionel Sambuc err = normalize_ap(&p->m_data, fmt, ap2);
36711be35a1SLionel Sambuc va_end(ap2);
36811be35a1SLionel Sambuc
36911be35a1SLionel Sambuc return err;
37011be35a1SLionel Sambuc }
37111be35a1SLionel Sambuc
37211be35a1SLionel Sambuc atf_error_t
atf_fs_path_init_fmt(atf_fs_path_t * p,const char * fmt,...)37311be35a1SLionel Sambuc atf_fs_path_init_fmt(atf_fs_path_t *p, const char *fmt, ...)
37411be35a1SLionel Sambuc {
37511be35a1SLionel Sambuc va_list ap;
37611be35a1SLionel Sambuc atf_error_t err;
37711be35a1SLionel Sambuc
37811be35a1SLionel Sambuc va_start(ap, fmt);
37911be35a1SLionel Sambuc err = atf_fs_path_init_ap(p, fmt, ap);
38011be35a1SLionel Sambuc va_end(ap);
38111be35a1SLionel Sambuc
38211be35a1SLionel Sambuc return err;
38311be35a1SLionel Sambuc }
38411be35a1SLionel Sambuc
38511be35a1SLionel Sambuc atf_error_t
atf_fs_path_copy(atf_fs_path_t * dest,const atf_fs_path_t * src)38611be35a1SLionel Sambuc atf_fs_path_copy(atf_fs_path_t *dest, const atf_fs_path_t *src)
38711be35a1SLionel Sambuc {
38811be35a1SLionel Sambuc return atf_dynstr_copy(&dest->m_data, &src->m_data);
38911be35a1SLionel Sambuc }
39011be35a1SLionel Sambuc
39111be35a1SLionel Sambuc void
atf_fs_path_fini(atf_fs_path_t * p)39211be35a1SLionel Sambuc atf_fs_path_fini(atf_fs_path_t *p)
39311be35a1SLionel Sambuc {
39411be35a1SLionel Sambuc atf_dynstr_fini(&p->m_data);
39511be35a1SLionel Sambuc }
39611be35a1SLionel Sambuc
39711be35a1SLionel Sambuc /*
39811be35a1SLionel Sambuc * Getters.
39911be35a1SLionel Sambuc */
40011be35a1SLionel Sambuc
40111be35a1SLionel Sambuc atf_error_t
atf_fs_path_branch_path(const atf_fs_path_t * p,atf_fs_path_t * bp)40211be35a1SLionel Sambuc atf_fs_path_branch_path(const atf_fs_path_t *p, atf_fs_path_t *bp)
40311be35a1SLionel Sambuc {
40411be35a1SLionel Sambuc const size_t endpos = atf_dynstr_rfind_ch(&p->m_data, '/');
40511be35a1SLionel Sambuc atf_error_t err;
40611be35a1SLionel Sambuc
40711be35a1SLionel Sambuc if (endpos == atf_dynstr_npos)
40811be35a1SLionel Sambuc err = atf_fs_path_init_fmt(bp, ".");
40911be35a1SLionel Sambuc else if (endpos == 0)
41011be35a1SLionel Sambuc err = atf_fs_path_init_fmt(bp, "/");
41111be35a1SLionel Sambuc else
41211be35a1SLionel Sambuc err = atf_dynstr_init_substr(&bp->m_data, &p->m_data, 0, endpos);
41311be35a1SLionel Sambuc
41411be35a1SLionel Sambuc #if defined(HAVE_CONST_DIRNAME)
41511be35a1SLionel Sambuc INV(atf_equal_dynstr_cstring(&bp->m_data,
41611be35a1SLionel Sambuc dirname(atf_dynstr_cstring(&p->m_data))));
41711be35a1SLionel Sambuc #endif /* defined(HAVE_CONST_DIRNAME) */
41811be35a1SLionel Sambuc
41911be35a1SLionel Sambuc return err;
42011be35a1SLionel Sambuc }
42111be35a1SLionel Sambuc
42211be35a1SLionel Sambuc const char *
atf_fs_path_cstring(const atf_fs_path_t * p)42311be35a1SLionel Sambuc atf_fs_path_cstring(const atf_fs_path_t *p)
42411be35a1SLionel Sambuc {
42511be35a1SLionel Sambuc return atf_dynstr_cstring(&p->m_data);
42611be35a1SLionel Sambuc }
42711be35a1SLionel Sambuc
42811be35a1SLionel Sambuc atf_error_t
atf_fs_path_leaf_name(const atf_fs_path_t * p,atf_dynstr_t * ln)42911be35a1SLionel Sambuc atf_fs_path_leaf_name(const atf_fs_path_t *p, atf_dynstr_t *ln)
43011be35a1SLionel Sambuc {
43111be35a1SLionel Sambuc size_t begpos = atf_dynstr_rfind_ch(&p->m_data, '/');
43211be35a1SLionel Sambuc atf_error_t err;
43311be35a1SLionel Sambuc
43411be35a1SLionel Sambuc if (begpos == atf_dynstr_npos)
43511be35a1SLionel Sambuc begpos = 0;
43611be35a1SLionel Sambuc else
43711be35a1SLionel Sambuc begpos++;
43811be35a1SLionel Sambuc
43911be35a1SLionel Sambuc err = atf_dynstr_init_substr(ln, &p->m_data, begpos, atf_dynstr_npos);
44011be35a1SLionel Sambuc
44111be35a1SLionel Sambuc #if defined(HAVE_CONST_BASENAME)
44211be35a1SLionel Sambuc INV(atf_equal_dynstr_cstring(ln,
44311be35a1SLionel Sambuc basename(atf_dynstr_cstring(&p->m_data))));
44411be35a1SLionel Sambuc #endif /* defined(HAVE_CONST_BASENAME) */
44511be35a1SLionel Sambuc
44611be35a1SLionel Sambuc return err;
44711be35a1SLionel Sambuc }
44811be35a1SLionel Sambuc
44911be35a1SLionel Sambuc bool
atf_fs_path_is_absolute(const atf_fs_path_t * p)45011be35a1SLionel Sambuc atf_fs_path_is_absolute(const atf_fs_path_t *p)
45111be35a1SLionel Sambuc {
45211be35a1SLionel Sambuc return atf_dynstr_cstring(&p->m_data)[0] == '/';
45311be35a1SLionel Sambuc }
45411be35a1SLionel Sambuc
45511be35a1SLionel Sambuc bool
atf_fs_path_is_root(const atf_fs_path_t * p)45611be35a1SLionel Sambuc atf_fs_path_is_root(const atf_fs_path_t *p)
45711be35a1SLionel Sambuc {
45811be35a1SLionel Sambuc return atf_equal_dynstr_cstring(&p->m_data, "/");
45911be35a1SLionel Sambuc }
46011be35a1SLionel Sambuc
46111be35a1SLionel Sambuc /*
46211be35a1SLionel Sambuc * Modifiers.
46311be35a1SLionel Sambuc */
46411be35a1SLionel Sambuc
46511be35a1SLionel Sambuc atf_error_t
atf_fs_path_append_ap(atf_fs_path_t * p,const char * fmt,va_list ap)46611be35a1SLionel Sambuc atf_fs_path_append_ap(atf_fs_path_t *p, const char *fmt, va_list ap)
46711be35a1SLionel Sambuc {
46811be35a1SLionel Sambuc atf_dynstr_t aux;
46911be35a1SLionel Sambuc atf_error_t err;
47011be35a1SLionel Sambuc va_list ap2;
47111be35a1SLionel Sambuc
47211be35a1SLionel Sambuc va_copy(ap2, ap);
47311be35a1SLionel Sambuc err = normalize_ap(&aux, fmt, ap2);
47411be35a1SLionel Sambuc va_end(ap2);
47511be35a1SLionel Sambuc if (!atf_is_error(err)) {
47611be35a1SLionel Sambuc const char *auxstr = atf_dynstr_cstring(&aux);
47711be35a1SLionel Sambuc const bool needslash = auxstr[0] != '/';
47811be35a1SLionel Sambuc
47911be35a1SLionel Sambuc err = atf_dynstr_append_fmt(&p->m_data, "%s%s",
48011be35a1SLionel Sambuc needslash ? "/" : "", auxstr);
48111be35a1SLionel Sambuc
48211be35a1SLionel Sambuc atf_dynstr_fini(&aux);
48311be35a1SLionel Sambuc }
48411be35a1SLionel Sambuc
48511be35a1SLionel Sambuc return err;
48611be35a1SLionel Sambuc }
48711be35a1SLionel Sambuc
48811be35a1SLionel Sambuc atf_error_t
atf_fs_path_append_fmt(atf_fs_path_t * p,const char * fmt,...)48911be35a1SLionel Sambuc atf_fs_path_append_fmt(atf_fs_path_t *p, const char *fmt, ...)
49011be35a1SLionel Sambuc {
49111be35a1SLionel Sambuc va_list ap;
49211be35a1SLionel Sambuc atf_error_t err;
49311be35a1SLionel Sambuc
49411be35a1SLionel Sambuc va_start(ap, fmt);
49511be35a1SLionel Sambuc err = atf_fs_path_append_ap(p, fmt, ap);
49611be35a1SLionel Sambuc va_end(ap);
49711be35a1SLionel Sambuc
49811be35a1SLionel Sambuc return err;
49911be35a1SLionel Sambuc }
50011be35a1SLionel Sambuc
50111be35a1SLionel Sambuc atf_error_t
atf_fs_path_append_path(atf_fs_path_t * p,const atf_fs_path_t * p2)50211be35a1SLionel Sambuc atf_fs_path_append_path(atf_fs_path_t *p, const atf_fs_path_t *p2)
50311be35a1SLionel Sambuc {
50411be35a1SLionel Sambuc return atf_fs_path_append_fmt(p, "%s", atf_dynstr_cstring(&p2->m_data));
50511be35a1SLionel Sambuc }
50611be35a1SLionel Sambuc
50711be35a1SLionel Sambuc atf_error_t
atf_fs_path_to_absolute(const atf_fs_path_t * p,atf_fs_path_t * pa)50811be35a1SLionel Sambuc atf_fs_path_to_absolute(const atf_fs_path_t *p, atf_fs_path_t *pa)
50911be35a1SLionel Sambuc {
51011be35a1SLionel Sambuc atf_error_t err;
51111be35a1SLionel Sambuc
51211be35a1SLionel Sambuc PRE(!atf_fs_path_is_absolute(p));
51311be35a1SLionel Sambuc
51411be35a1SLionel Sambuc err = atf_fs_getcwd(pa);
51511be35a1SLionel Sambuc if (atf_is_error(err))
51611be35a1SLionel Sambuc goto out;
51711be35a1SLionel Sambuc
51811be35a1SLionel Sambuc err = atf_fs_path_append_path(pa, p);
51911be35a1SLionel Sambuc if (atf_is_error(err))
52011be35a1SLionel Sambuc atf_fs_path_fini(pa);
52111be35a1SLionel Sambuc
52211be35a1SLionel Sambuc out:
52311be35a1SLionel Sambuc return err;
52411be35a1SLionel Sambuc }
52511be35a1SLionel Sambuc
52611be35a1SLionel Sambuc /*
52711be35a1SLionel Sambuc * Operators.
52811be35a1SLionel Sambuc */
52911be35a1SLionel Sambuc
atf_equal_fs_path_fs_path(const atf_fs_path_t * p1,const atf_fs_path_t * p2)53011be35a1SLionel Sambuc bool atf_equal_fs_path_fs_path(const atf_fs_path_t *p1,
53111be35a1SLionel Sambuc const atf_fs_path_t *p2)
53211be35a1SLionel Sambuc {
53311be35a1SLionel Sambuc return atf_equal_dynstr_dynstr(&p1->m_data, &p2->m_data);
53411be35a1SLionel Sambuc }
53511be35a1SLionel Sambuc
53611be35a1SLionel Sambuc /* ---------------------------------------------------------------------
53711be35a1SLionel Sambuc * The "atf_fs_path" type.
53811be35a1SLionel Sambuc * --------------------------------------------------------------------- */
53911be35a1SLionel Sambuc
54011be35a1SLionel Sambuc /*
54111be35a1SLionel Sambuc * Constants.
54211be35a1SLionel Sambuc */
54311be35a1SLionel Sambuc
54411be35a1SLionel Sambuc const int atf_fs_stat_blk_type = 1;
54511be35a1SLionel Sambuc const int atf_fs_stat_chr_type = 2;
54611be35a1SLionel Sambuc const int atf_fs_stat_dir_type = 3;
54711be35a1SLionel Sambuc const int atf_fs_stat_fifo_type = 4;
54811be35a1SLionel Sambuc const int atf_fs_stat_lnk_type = 5;
54911be35a1SLionel Sambuc const int atf_fs_stat_reg_type = 6;
55011be35a1SLionel Sambuc const int atf_fs_stat_sock_type = 7;
55111be35a1SLionel Sambuc const int atf_fs_stat_wht_type = 8;
55211be35a1SLionel Sambuc
55311be35a1SLionel Sambuc /*
55411be35a1SLionel Sambuc * Constructors/destructors.
55511be35a1SLionel Sambuc */
55611be35a1SLionel Sambuc
55711be35a1SLionel Sambuc atf_error_t
atf_fs_stat_init(atf_fs_stat_t * st,const atf_fs_path_t * p)55811be35a1SLionel Sambuc atf_fs_stat_init(atf_fs_stat_t *st, const atf_fs_path_t *p)
55911be35a1SLionel Sambuc {
56011be35a1SLionel Sambuc atf_error_t err;
56111be35a1SLionel Sambuc const char *pstr = atf_fs_path_cstring(p);
56211be35a1SLionel Sambuc
56311be35a1SLionel Sambuc if (lstat(pstr, &st->m_sb) == -1) {
56411be35a1SLionel Sambuc err = atf_libc_error(errno, "Cannot get information of %s; "
56511be35a1SLionel Sambuc "lstat(2) failed", pstr);
56611be35a1SLionel Sambuc } else {
56711be35a1SLionel Sambuc int type = st->m_sb.st_mode & S_IFMT;
56811be35a1SLionel Sambuc err = atf_no_error();
56911be35a1SLionel Sambuc switch (type) {
57011be35a1SLionel Sambuc case S_IFBLK: st->m_type = atf_fs_stat_blk_type; break;
57111be35a1SLionel Sambuc case S_IFCHR: st->m_type = atf_fs_stat_chr_type; break;
57211be35a1SLionel Sambuc case S_IFDIR: st->m_type = atf_fs_stat_dir_type; break;
57311be35a1SLionel Sambuc case S_IFIFO: st->m_type = atf_fs_stat_fifo_type; break;
57411be35a1SLionel Sambuc case S_IFLNK: st->m_type = atf_fs_stat_lnk_type; break;
57511be35a1SLionel Sambuc case S_IFREG: st->m_type = atf_fs_stat_reg_type; break;
57611be35a1SLionel Sambuc case S_IFSOCK: st->m_type = atf_fs_stat_sock_type; break;
57711be35a1SLionel Sambuc #if defined(S_IFWHT)
57811be35a1SLionel Sambuc case S_IFWHT: st->m_type = atf_fs_stat_wht_type; break;
57911be35a1SLionel Sambuc #endif
58011be35a1SLionel Sambuc default:
58111be35a1SLionel Sambuc err = unknown_type_error(pstr, type);
58211be35a1SLionel Sambuc }
58311be35a1SLionel Sambuc }
58411be35a1SLionel Sambuc
58511be35a1SLionel Sambuc return err;
58611be35a1SLionel Sambuc }
58711be35a1SLionel Sambuc
58811be35a1SLionel Sambuc void
atf_fs_stat_copy(atf_fs_stat_t * dest,const atf_fs_stat_t * src)58911be35a1SLionel Sambuc atf_fs_stat_copy(atf_fs_stat_t *dest, const atf_fs_stat_t *src)
59011be35a1SLionel Sambuc {
59111be35a1SLionel Sambuc dest->m_type = src->m_type;
59211be35a1SLionel Sambuc dest->m_sb = src->m_sb;
59311be35a1SLionel Sambuc }
59411be35a1SLionel Sambuc
59511be35a1SLionel Sambuc void
atf_fs_stat_fini(atf_fs_stat_t * st ATF_DEFS_ATTRIBUTE_UNUSED)59611be35a1SLionel Sambuc atf_fs_stat_fini(atf_fs_stat_t *st ATF_DEFS_ATTRIBUTE_UNUSED)
59711be35a1SLionel Sambuc {
59811be35a1SLionel Sambuc }
59911be35a1SLionel Sambuc
60011be35a1SLionel Sambuc /*
60111be35a1SLionel Sambuc * Getters.
60211be35a1SLionel Sambuc */
60311be35a1SLionel Sambuc
60411be35a1SLionel Sambuc dev_t
atf_fs_stat_get_device(const atf_fs_stat_t * st)60511be35a1SLionel Sambuc atf_fs_stat_get_device(const atf_fs_stat_t *st)
60611be35a1SLionel Sambuc {
60711be35a1SLionel Sambuc return st->m_sb.st_dev;
60811be35a1SLionel Sambuc }
60911be35a1SLionel Sambuc
61011be35a1SLionel Sambuc ino_t
atf_fs_stat_get_inode(const atf_fs_stat_t * st)61111be35a1SLionel Sambuc atf_fs_stat_get_inode(const atf_fs_stat_t *st)
61211be35a1SLionel Sambuc {
61311be35a1SLionel Sambuc return st->m_sb.st_ino;
61411be35a1SLionel Sambuc }
61511be35a1SLionel Sambuc
61611be35a1SLionel Sambuc mode_t
atf_fs_stat_get_mode(const atf_fs_stat_t * st)61711be35a1SLionel Sambuc atf_fs_stat_get_mode(const atf_fs_stat_t *st)
61811be35a1SLionel Sambuc {
61911be35a1SLionel Sambuc return st->m_sb.st_mode & ~S_IFMT;
62011be35a1SLionel Sambuc }
62111be35a1SLionel Sambuc
62211be35a1SLionel Sambuc off_t
atf_fs_stat_get_size(const atf_fs_stat_t * st)62311be35a1SLionel Sambuc atf_fs_stat_get_size(const atf_fs_stat_t *st)
62411be35a1SLionel Sambuc {
62511be35a1SLionel Sambuc return st->m_sb.st_size;
62611be35a1SLionel Sambuc }
62711be35a1SLionel Sambuc
62811be35a1SLionel Sambuc int
atf_fs_stat_get_type(const atf_fs_stat_t * st)62911be35a1SLionel Sambuc atf_fs_stat_get_type(const atf_fs_stat_t *st)
63011be35a1SLionel Sambuc {
63111be35a1SLionel Sambuc return st->m_type;
63211be35a1SLionel Sambuc }
63311be35a1SLionel Sambuc
63411be35a1SLionel Sambuc bool
atf_fs_stat_is_owner_readable(const atf_fs_stat_t * st)63511be35a1SLionel Sambuc atf_fs_stat_is_owner_readable(const atf_fs_stat_t *st)
63611be35a1SLionel Sambuc {
63711be35a1SLionel Sambuc return st->m_sb.st_mode & S_IRUSR;
63811be35a1SLionel Sambuc }
63911be35a1SLionel Sambuc
64011be35a1SLionel Sambuc bool
atf_fs_stat_is_owner_writable(const atf_fs_stat_t * st)64111be35a1SLionel Sambuc atf_fs_stat_is_owner_writable(const atf_fs_stat_t *st)
64211be35a1SLionel Sambuc {
64311be35a1SLionel Sambuc return st->m_sb.st_mode & S_IWUSR;
64411be35a1SLionel Sambuc }
64511be35a1SLionel Sambuc
64611be35a1SLionel Sambuc bool
atf_fs_stat_is_owner_executable(const atf_fs_stat_t * st)64711be35a1SLionel Sambuc atf_fs_stat_is_owner_executable(const atf_fs_stat_t *st)
64811be35a1SLionel Sambuc {
64911be35a1SLionel Sambuc return st->m_sb.st_mode & S_IXUSR;
65011be35a1SLionel Sambuc }
65111be35a1SLionel Sambuc
65211be35a1SLionel Sambuc bool
atf_fs_stat_is_group_readable(const atf_fs_stat_t * st)65311be35a1SLionel Sambuc atf_fs_stat_is_group_readable(const atf_fs_stat_t *st)
65411be35a1SLionel Sambuc {
65511be35a1SLionel Sambuc return st->m_sb.st_mode & S_IRGRP;
65611be35a1SLionel Sambuc }
65711be35a1SLionel Sambuc
65811be35a1SLionel Sambuc bool
atf_fs_stat_is_group_writable(const atf_fs_stat_t * st)65911be35a1SLionel Sambuc atf_fs_stat_is_group_writable(const atf_fs_stat_t *st)
66011be35a1SLionel Sambuc {
66111be35a1SLionel Sambuc return st->m_sb.st_mode & S_IWGRP;
66211be35a1SLionel Sambuc }
66311be35a1SLionel Sambuc
66411be35a1SLionel Sambuc bool
atf_fs_stat_is_group_executable(const atf_fs_stat_t * st)66511be35a1SLionel Sambuc atf_fs_stat_is_group_executable(const atf_fs_stat_t *st)
66611be35a1SLionel Sambuc {
66711be35a1SLionel Sambuc return st->m_sb.st_mode & S_IXGRP;
66811be35a1SLionel Sambuc }
66911be35a1SLionel Sambuc
67011be35a1SLionel Sambuc bool
atf_fs_stat_is_other_readable(const atf_fs_stat_t * st)67111be35a1SLionel Sambuc atf_fs_stat_is_other_readable(const atf_fs_stat_t *st)
67211be35a1SLionel Sambuc {
67311be35a1SLionel Sambuc return st->m_sb.st_mode & S_IROTH;
67411be35a1SLionel Sambuc }
67511be35a1SLionel Sambuc
67611be35a1SLionel Sambuc bool
atf_fs_stat_is_other_writable(const atf_fs_stat_t * st)67711be35a1SLionel Sambuc atf_fs_stat_is_other_writable(const atf_fs_stat_t *st)
67811be35a1SLionel Sambuc {
67911be35a1SLionel Sambuc return st->m_sb.st_mode & S_IWOTH;
68011be35a1SLionel Sambuc }
68111be35a1SLionel Sambuc
68211be35a1SLionel Sambuc bool
atf_fs_stat_is_other_executable(const atf_fs_stat_t * st)68311be35a1SLionel Sambuc atf_fs_stat_is_other_executable(const atf_fs_stat_t *st)
68411be35a1SLionel Sambuc {
68511be35a1SLionel Sambuc return st->m_sb.st_mode & S_IXOTH;
68611be35a1SLionel Sambuc }
68711be35a1SLionel Sambuc
68811be35a1SLionel Sambuc /* ---------------------------------------------------------------------
68911be35a1SLionel Sambuc * Free functions.
69011be35a1SLionel Sambuc * --------------------------------------------------------------------- */
69111be35a1SLionel Sambuc
69211be35a1SLionel Sambuc const int atf_fs_access_f = 1 << 0;
69311be35a1SLionel Sambuc const int atf_fs_access_r = 1 << 1;
69411be35a1SLionel Sambuc const int atf_fs_access_w = 1 << 2;
69511be35a1SLionel Sambuc const int atf_fs_access_x = 1 << 3;
69611be35a1SLionel Sambuc
69711be35a1SLionel Sambuc /*
69811be35a1SLionel Sambuc * An implementation of access(2) but using the effective user value
69911be35a1SLionel Sambuc * instead of the real one. Also avoids false positives for root when
70011be35a1SLionel Sambuc * asking for execute permissions, which appear in SunOS.
70111be35a1SLionel Sambuc */
70211be35a1SLionel Sambuc atf_error_t
atf_fs_eaccess(const atf_fs_path_t * p,int mode)70311be35a1SLionel Sambuc atf_fs_eaccess(const atf_fs_path_t *p, int mode)
70411be35a1SLionel Sambuc {
70511be35a1SLionel Sambuc atf_error_t err;
70611be35a1SLionel Sambuc struct stat st;
70711be35a1SLionel Sambuc bool ok;
70811be35a1SLionel Sambuc
70911be35a1SLionel Sambuc PRE(mode & atf_fs_access_f || mode & atf_fs_access_r ||
71011be35a1SLionel Sambuc mode & atf_fs_access_w || mode & atf_fs_access_x);
71111be35a1SLionel Sambuc
71211be35a1SLionel Sambuc if (lstat(atf_fs_path_cstring(p), &st) == -1) {
71311be35a1SLionel Sambuc err = atf_libc_error(errno, "Cannot get information from file %s",
71411be35a1SLionel Sambuc atf_fs_path_cstring(p));
71511be35a1SLionel Sambuc goto out;
71611be35a1SLionel Sambuc }
71711be35a1SLionel Sambuc
71811be35a1SLionel Sambuc err = atf_no_error();
71911be35a1SLionel Sambuc
72011be35a1SLionel Sambuc /* Early return if we are only checking for existence and the file
72111be35a1SLionel Sambuc * exists (stat call returned). */
72211be35a1SLionel Sambuc if (mode & atf_fs_access_f)
72311be35a1SLionel Sambuc goto out;
72411be35a1SLionel Sambuc
72511be35a1SLionel Sambuc ok = false;
72611be35a1SLionel Sambuc if (atf_user_is_root()) {
72711be35a1SLionel Sambuc if (!ok && !(mode & atf_fs_access_x)) {
72811be35a1SLionel Sambuc /* Allow root to read/write any file. */
72911be35a1SLionel Sambuc ok = true;
73011be35a1SLionel Sambuc }
73111be35a1SLionel Sambuc
73211be35a1SLionel Sambuc if (!ok && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) {
73311be35a1SLionel Sambuc /* Allow root to execute the file if any of its execution bits
73411be35a1SLionel Sambuc * are set. */
73511be35a1SLionel Sambuc ok = true;
73611be35a1SLionel Sambuc }
73711be35a1SLionel Sambuc } else {
73811be35a1SLionel Sambuc if (!ok && (atf_user_euid() == st.st_uid)) {
73911be35a1SLionel Sambuc ok = ((mode & atf_fs_access_r) && (st.st_mode & S_IRUSR)) ||
74011be35a1SLionel Sambuc ((mode & atf_fs_access_w) && (st.st_mode & S_IWUSR)) ||
74111be35a1SLionel Sambuc ((mode & atf_fs_access_x) && (st.st_mode & S_IXUSR));
74211be35a1SLionel Sambuc }
74311be35a1SLionel Sambuc if (!ok && atf_user_is_member_of_group(st.st_gid)) {
74411be35a1SLionel Sambuc ok = ((mode & atf_fs_access_r) && (st.st_mode & S_IRGRP)) ||
74511be35a1SLionel Sambuc ((mode & atf_fs_access_w) && (st.st_mode & S_IWGRP)) ||
74611be35a1SLionel Sambuc ((mode & atf_fs_access_x) && (st.st_mode & S_IXGRP));
74711be35a1SLionel Sambuc }
74811be35a1SLionel Sambuc if (!ok && ((atf_user_euid() != st.st_uid) &&
74911be35a1SLionel Sambuc !atf_user_is_member_of_group(st.st_gid))) {
75011be35a1SLionel Sambuc ok = ((mode & atf_fs_access_r) && (st.st_mode & S_IROTH)) ||
75111be35a1SLionel Sambuc ((mode & atf_fs_access_w) && (st.st_mode & S_IWOTH)) ||
75211be35a1SLionel Sambuc ((mode & atf_fs_access_x) && (st.st_mode & S_IXOTH));
75311be35a1SLionel Sambuc }
75411be35a1SLionel Sambuc }
75511be35a1SLionel Sambuc
75611be35a1SLionel Sambuc if (!ok)
75711be35a1SLionel Sambuc err = atf_libc_error(EACCES, "Access check failed");
75811be35a1SLionel Sambuc
75911be35a1SLionel Sambuc out:
76011be35a1SLionel Sambuc return err;
76111be35a1SLionel Sambuc }
76211be35a1SLionel Sambuc
76311be35a1SLionel Sambuc atf_error_t
atf_fs_exists(const atf_fs_path_t * p,bool * b)76411be35a1SLionel Sambuc atf_fs_exists(const atf_fs_path_t *p, bool *b)
76511be35a1SLionel Sambuc {
76611be35a1SLionel Sambuc atf_error_t err;
76711be35a1SLionel Sambuc
76811be35a1SLionel Sambuc err = atf_fs_eaccess(p, atf_fs_access_f);
76911be35a1SLionel Sambuc if (atf_is_error(err)) {
77011be35a1SLionel Sambuc if (atf_error_is(err, "libc") && atf_libc_error_code(err) == ENOENT) {
77111be35a1SLionel Sambuc atf_error_free(err);
77211be35a1SLionel Sambuc err = atf_no_error();
77311be35a1SLionel Sambuc *b = false;
77411be35a1SLionel Sambuc }
77511be35a1SLionel Sambuc } else
77611be35a1SLionel Sambuc *b = true;
77711be35a1SLionel Sambuc
77811be35a1SLionel Sambuc return err;
77911be35a1SLionel Sambuc }
78011be35a1SLionel Sambuc
78111be35a1SLionel Sambuc atf_error_t
atf_fs_getcwd(atf_fs_path_t * p)78211be35a1SLionel Sambuc atf_fs_getcwd(atf_fs_path_t *p)
78311be35a1SLionel Sambuc {
78411be35a1SLionel Sambuc atf_error_t err;
78511be35a1SLionel Sambuc char *cwd;
78611be35a1SLionel Sambuc
78711be35a1SLionel Sambuc #if defined(HAVE_GETCWD_DYN)
78811be35a1SLionel Sambuc cwd = getcwd(NULL, 0);
78911be35a1SLionel Sambuc #else
79011be35a1SLionel Sambuc cwd = getcwd(NULL, MAXPATHLEN);
79111be35a1SLionel Sambuc #endif
79211be35a1SLionel Sambuc if (cwd == NULL) {
79311be35a1SLionel Sambuc err = atf_libc_error(errno, "Cannot determine current directory");
79411be35a1SLionel Sambuc goto out;
79511be35a1SLionel Sambuc }
79611be35a1SLionel Sambuc
79711be35a1SLionel Sambuc err = atf_fs_path_init_fmt(p, "%s", cwd);
79811be35a1SLionel Sambuc free(cwd);
79911be35a1SLionel Sambuc
80011be35a1SLionel Sambuc out:
80111be35a1SLionel Sambuc return err;
80211be35a1SLionel Sambuc }
80311be35a1SLionel Sambuc
80411be35a1SLionel Sambuc atf_error_t
atf_fs_mkdtemp(atf_fs_path_t * p)80511be35a1SLionel Sambuc atf_fs_mkdtemp(atf_fs_path_t *p)
80611be35a1SLionel Sambuc {
80711be35a1SLionel Sambuc atf_error_t err;
80884d9c625SLionel Sambuc char *buf = NULL; /* MINIX: Complain in -O3 */
80911be35a1SLionel Sambuc
81011be35a1SLionel Sambuc if (!check_umask(S_IRWXU, S_IRWXU)) {
81111be35a1SLionel Sambuc err = invalid_umask_error(p, atf_fs_stat_dir_type, current_umask());
81211be35a1SLionel Sambuc goto out;
81311be35a1SLionel Sambuc }
81411be35a1SLionel Sambuc
81511be35a1SLionel Sambuc err = copy_contents(p, &buf);
81611be35a1SLionel Sambuc if (atf_is_error(err))
81711be35a1SLionel Sambuc goto out;
81811be35a1SLionel Sambuc
81911be35a1SLionel Sambuc err = do_mkdtemp(buf);
82011be35a1SLionel Sambuc if (atf_is_error(err))
82111be35a1SLionel Sambuc goto out_buf;
82211be35a1SLionel Sambuc
82311be35a1SLionel Sambuc replace_contents(p, buf);
82411be35a1SLionel Sambuc
82511be35a1SLionel Sambuc INV(!atf_is_error(err));
82611be35a1SLionel Sambuc out_buf:
82711be35a1SLionel Sambuc free(buf);
82811be35a1SLionel Sambuc out:
82911be35a1SLionel Sambuc return err;
83011be35a1SLionel Sambuc }
83111be35a1SLionel Sambuc
83211be35a1SLionel Sambuc atf_error_t
atf_fs_mkstemp(atf_fs_path_t * p,int * fdout)83311be35a1SLionel Sambuc atf_fs_mkstemp(atf_fs_path_t *p, int *fdout)
83411be35a1SLionel Sambuc {
83511be35a1SLionel Sambuc atf_error_t err;
83684d9c625SLionel Sambuc char *buf = NULL; /* MINIX: Complain in -O3 */
83711be35a1SLionel Sambuc int fd;
83811be35a1SLionel Sambuc
83911be35a1SLionel Sambuc if (!check_umask(S_IRWXU, S_IRWXU)) {
84011be35a1SLionel Sambuc err = invalid_umask_error(p, atf_fs_stat_reg_type, current_umask());
84111be35a1SLionel Sambuc goto out;
84211be35a1SLionel Sambuc }
84311be35a1SLionel Sambuc
84411be35a1SLionel Sambuc err = copy_contents(p, &buf);
84511be35a1SLionel Sambuc if (atf_is_error(err))
84611be35a1SLionel Sambuc goto out;
84711be35a1SLionel Sambuc
84811be35a1SLionel Sambuc err = do_mkstemp(buf, &fd);
84911be35a1SLionel Sambuc if (atf_is_error(err))
85011be35a1SLionel Sambuc goto out_buf;
85111be35a1SLionel Sambuc
85211be35a1SLionel Sambuc replace_contents(p, buf);
85311be35a1SLionel Sambuc *fdout = fd;
85411be35a1SLionel Sambuc
85511be35a1SLionel Sambuc INV(!atf_is_error(err));
85611be35a1SLionel Sambuc out_buf:
85711be35a1SLionel Sambuc free(buf);
85811be35a1SLionel Sambuc out:
85911be35a1SLionel Sambuc return err;
86011be35a1SLionel Sambuc }
86111be35a1SLionel Sambuc
86211be35a1SLionel Sambuc atf_error_t
atf_fs_rmdir(const atf_fs_path_t * p)86311be35a1SLionel Sambuc atf_fs_rmdir(const atf_fs_path_t *p)
86411be35a1SLionel Sambuc {
86511be35a1SLionel Sambuc atf_error_t err;
86611be35a1SLionel Sambuc
86711be35a1SLionel Sambuc if (rmdir(atf_fs_path_cstring(p))) {
86811be35a1SLionel Sambuc if (errno == EEXIST) {
86911be35a1SLionel Sambuc /* Some operating systems (e.g. OpenSolaris 200906) return
87011be35a1SLionel Sambuc * EEXIST instead of ENOTEMPTY for non-empty directories.
87111be35a1SLionel Sambuc * Homogenize the return value so that callers don't need
87211be35a1SLionel Sambuc * to bother about differences in operating systems. */
87311be35a1SLionel Sambuc errno = ENOTEMPTY;
87411be35a1SLionel Sambuc }
87511be35a1SLionel Sambuc err = atf_libc_error(errno, "Cannot remove directory");
87611be35a1SLionel Sambuc } else
87711be35a1SLionel Sambuc err = atf_no_error();
87811be35a1SLionel Sambuc
87911be35a1SLionel Sambuc return err;
88011be35a1SLionel Sambuc }
88111be35a1SLionel Sambuc
88211be35a1SLionel Sambuc atf_error_t
atf_fs_unlink(const atf_fs_path_t * p)88311be35a1SLionel Sambuc atf_fs_unlink(const atf_fs_path_t *p)
88411be35a1SLionel Sambuc {
88511be35a1SLionel Sambuc atf_error_t err;
88611be35a1SLionel Sambuc const char *path;
88711be35a1SLionel Sambuc
88811be35a1SLionel Sambuc path = atf_fs_path_cstring(p);
88911be35a1SLionel Sambuc
89011be35a1SLionel Sambuc if (unlink(path) != 0)
89111be35a1SLionel Sambuc err = atf_libc_error(errno, "Cannot unlink file: '%s'", path);
89211be35a1SLionel Sambuc else
89311be35a1SLionel Sambuc err = atf_no_error();
89411be35a1SLionel Sambuc
89511be35a1SLionel Sambuc return err;
89611be35a1SLionel Sambuc }
897