Example #1
0
atf_error_t
atf_env_set(const char *name, const char *val)
{
    atf_error_t err;

#if defined(HAVE_SETENV)
    if (setenv(name, val, 1) == -1)
        err = atf_libc_error(errno, "Cannot set environment variable "
                             "'%s' to '%s'", name, val);
    else
        err = atf_no_error();
#elif defined(HAVE_PUTENV)
    char *buf;

    err = atf_text_format(&buf, "%s=%s", name, val);
    if (!atf_is_error(err)) {
        if (putenv(buf) == -1)
            err = atf_libc_error(errno, "Cannot set environment variable "
                                 "'%s' to '%s'", name, val);
        free(buf);
    }
#else
#   error "Don't know how to set an environment variable."
#endif

    return err;
}
Example #2
0
/*
 * An implementation of access(2) but using the effective user value
 * instead of the real one.  Also avoids false positives for root when
 * asking for execute permissions, which appear in SunOS.
 */
atf_error_t
atf_fs_eaccess(const atf_fs_path_t *p, int mode)
{
    atf_error_t err;
    struct stat st;
    bool ok;

    PRE(mode & atf_fs_access_f || mode & atf_fs_access_r ||
        mode & atf_fs_access_w || mode & atf_fs_access_x);

    if (lstat(atf_fs_path_cstring(p), &st) == -1) {
        err = atf_libc_error(errno, "Cannot get information from file %s",
                             atf_fs_path_cstring(p));
        goto out;
    }

    err = atf_no_error();

    /* Early return if we are only checking for existence and the file
     * exists (stat call returned). */
    if (mode & atf_fs_access_f)
        goto out;

    ok = false;
    if (atf_user_is_root()) {
        if (!ok && !(mode & atf_fs_access_x)) {
            /* Allow root to read/write any file. */
            ok = true;
        }

        if (!ok && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) {
            /* Allow root to execute the file if any of its execution bits
             * are set. */
            ok = true;
        }
    } else {
        if (!ok && (atf_user_euid() == st.st_uid)) {
            ok = ((mode & atf_fs_access_r) && (st.st_mode & S_IRUSR)) ||
                 ((mode & atf_fs_access_w) && (st.st_mode & S_IWUSR)) ||
                 ((mode & atf_fs_access_x) && (st.st_mode & S_IXUSR));
        }
        if (!ok && atf_user_is_member_of_group(st.st_gid)) {
            ok = ((mode & atf_fs_access_r) && (st.st_mode & S_IRGRP)) ||
                 ((mode & atf_fs_access_w) && (st.st_mode & S_IWGRP)) ||
                 ((mode & atf_fs_access_x) && (st.st_mode & S_IXGRP));
        }
        if (!ok && ((atf_user_euid() != st.st_uid) &&
                    !atf_user_is_member_of_group(st.st_gid))) {
            ok = ((mode & atf_fs_access_r) && (st.st_mode & S_IROTH)) ||
                 ((mode & atf_fs_access_w) && (st.st_mode & S_IWOTH)) ||
                 ((mode & atf_fs_access_x) && (st.st_mode & S_IXOTH));
        }
    }

    if (!ok)
        err = atf_libc_error(EACCES, "Access check failed");

out:
    return err;
}
Example #3
0
atf_error_t
atf_fs_stat_init(atf_fs_stat_t *st, const atf_fs_path_t *p)
{
    atf_error_t err;
    const char *pstr = atf_fs_path_cstring(p);

    if (lstat(pstr, &st->m_sb) == -1) {
        err = atf_libc_error(errno, "Cannot get information of %s; "
                             "lstat(2) failed", pstr);
    } else {
        int type = st->m_sb.st_mode & S_IFMT;
        err = atf_no_error();
        switch (type) {
            case S_IFBLK:  st->m_type = atf_fs_stat_blk_type;  break;
            case S_IFCHR:  st->m_type = atf_fs_stat_chr_type;  break;
            case S_IFDIR:  st->m_type = atf_fs_stat_dir_type;  break;
            case S_IFIFO:  st->m_type = atf_fs_stat_fifo_type; break;
            case S_IFLNK:  st->m_type = atf_fs_stat_lnk_type;  break;
            case S_IFREG:  st->m_type = atf_fs_stat_reg_type;  break;
            case S_IFSOCK: st->m_type = atf_fs_stat_sock_type; break;
#if defined(S_IFWHT)
            case S_IFWHT:  st->m_type = atf_fs_stat_wht_type;  break;
#endif
            default:
                err = unknown_type_error(pstr, type);
        }
    }

    return err;
}
ATF_TC_BODY(libc_new, tc)
{
    atf_error_t err;

    err = atf_libc_error(ENOMEM, "Test message 1");
    ATF_REQUIRE(atf_error_is(err, "libc"));
    ATF_REQUIRE_EQ(atf_libc_error_code(err), ENOMEM);
    ATF_REQUIRE(strcmp(atf_libc_error_msg(err), "Test message 1") == 0);
    atf_error_free(err);

    err = atf_libc_error(EPERM, "%s message %d", "Test", 2);
    ATF_REQUIRE(atf_error_is(err, "libc"));
    ATF_REQUIRE_EQ(atf_libc_error_code(err), EPERM);
    ATF_REQUIRE(strcmp(atf_libc_error_msg(err), "Test message 2") == 0);
    atf_error_free(err);
}
Example #5
0
atf_error_t
atf_text_to_long(const char *str, long *l)
{
    atf_error_t err;
    char *endptr;
    long tmp;

    errno = 0;
    tmp = strtol(str, &endptr, 10);
    if (str[0] == '\0' || *endptr != '\0')
        err = atf_libc_error(EINVAL, "'%s' is not a number", str);
    else if (errno == ERANGE || (tmp == LONG_MAX || tmp == LONG_MIN))
        err = atf_libc_error(ERANGE, "'%s' is out of range", str);
    else {
        *l = tmp;
        err = atf_no_error();
    }

    return err;
}
Example #6
0
static
atf_error_t
child_connect(const stream_prepare_t *sp, int procfd)
{
    atf_error_t err;
    const int type = atf_process_stream_type(sp->m_sb);

    if (type == atf_process_stream_type_capture) {
        close(sp->m_pipefds[0]);
        err = safe_dup(sp->m_pipefds[1], procfd);
    } else if (type == atf_process_stream_type_connect) {
        if (dup2(sp->m_sb->m_tgt_fd, sp->m_sb->m_src_fd) == -1)
            err = atf_libc_error(errno, "Cannot connect descriptor %d to %d",
                                 sp->m_sb->m_tgt_fd, sp->m_sb->m_src_fd);
        else
            err = atf_no_error();
    } else if (type == atf_process_stream_type_inherit) {
        err = atf_no_error();
    } else if (type == atf_process_stream_type_redirect_fd) {
        err = safe_dup(sp->m_sb->m_fd, procfd);
    } else if (type == atf_process_stream_type_redirect_path) {
        int aux = open(atf_fs_path_cstring(sp->m_sb->m_path),
                       O_WRONLY | O_CREAT | O_TRUNC, 0644);
        if (aux == -1)
            err = atf_libc_error(errno, "Could not create %s",
                                 atf_fs_path_cstring(sp->m_sb->m_path));
        else {
            err = safe_dup(aux, procfd);
            if (atf_is_error(err))
                close(aux);
        }
    } else {
        UNREACHABLE;
        err = atf_no_error();
    }

    return err;
}
ATF_TC_BODY(libc_format, tc)
{
    atf_error_t err;
    char buf[1024];

    err = atf_libc_error(ENOMEM, "Test message 1");
    atf_error_format(err, buf, sizeof(buf));
    ATF_REQUIRE(strstr(buf, strerror(ENOMEM)) != NULL);
    ATF_REQUIRE(strstr(buf, "Test message 1") != NULL);
    atf_error_free(err);

    err = atf_libc_error(EPERM, "Test message 2");
    atf_error_format(err, buf, sizeof(buf));
    ATF_REQUIRE(strstr(buf, strerror(EPERM)) != NULL);
    ATF_REQUIRE(strstr(buf, "Test message 2") != NULL);
    atf_error_free(err);

    err = atf_libc_error(EPERM, "%s message %d", "Test", 3);
    atf_error_format(err, buf, sizeof(buf));
    ATF_REQUIRE(strstr(buf, strerror(EPERM)) != NULL);
    ATF_REQUIRE(strstr(buf, "Test message 3") != NULL);
    atf_error_free(err);
}
Example #8
0
atf_error_t
atf_fs_unlink(const atf_fs_path_t *p)
{
    atf_error_t err;
    const char *path;

    path = atf_fs_path_cstring(p);

    if (unlink(path) != 0)
        err = atf_libc_error(errno, "Cannot unlink file: '%s'", path);
    else
        err = atf_no_error();

    return err;
}
Example #9
0
static
atf_error_t
fork_with_streams(atf_process_child_t *c,
                  void (*start)(void *),
                  const atf_process_stream_t *outsb,
                  const atf_process_stream_t *errsb,
                  void *v)
{
    atf_error_t err;
    stream_prepare_t outsp;
    stream_prepare_t errsp;
    pid_t pid;

    err = stream_prepare_init(&outsp, outsb);
    if (atf_is_error(err))
        goto out;

    err = stream_prepare_init(&errsp, errsb);
    if (atf_is_error(err))
        goto err_outpipe;

    pid = fork();
    if (pid == -1) {
        err = atf_libc_error(errno, "Failed to fork");
        goto err_errpipe;
    }

    if (pid == 0) {
        do_child(start, v, &outsp, &errsp);
        UNREACHABLE;
        abort();
        err = atf_no_error();
    } else {
        err = do_parent(c, pid, &outsp, &errsp);
        if (atf_is_error(err))
            goto err_errpipe;
    }

    goto out;

err_errpipe:
    stream_prepare_fini(&errsp);
err_outpipe:
    stream_prepare_fini(&outsp);

out:
    return err;
}
Example #10
0
atf_error_t
atf_process_child_wait(atf_process_child_t *c, atf_process_status_t *s)
{
    atf_error_t err;
    int status;

    if (waitpid(c->m_pid, &status, 0) == -1)
        err = atf_libc_error(errno, "Failed waiting for process %d",
                             c->m_pid);
    else {
        atf_process_child_fini(c);
        err = atf_process_status_init(s, status);
    }

    return err;
}
Example #11
0
static
atf_error_t
do_mkdtemp(char *tmpl)
{
    atf_error_t err;

    PRE(strstr(tmpl, "XXXXXX") != NULL);

    if (mkdtemp(tmpl) == NULL)
        err = atf_libc_error(errno, "Cannot create temporary directory "
                             "with template '%s'", tmpl);
    else
        err = atf_no_error();

    return err;
}
Example #12
0
static
atf_error_t
do_mkstemp(char *tmpl, int *fdout)
{
    atf_error_t err;

    PRE(strstr(tmpl, "XXXXXX") != NULL);

    *fdout = mkstemp(tmpl);
    if (*fdout == -1)
        err = atf_libc_error(errno, "Cannot create temporary file "
                             "with template '%s'", tmpl);

    else
        err = atf_no_error();

    return err;
}
Example #13
0
static
atf_error_t
safe_dup(const int oldfd, const int newfd)
{
    atf_error_t err;

    if (oldfd != newfd) {
        if (dup2(oldfd, newfd) == -1) {
            err = atf_libc_error(errno, "Could not allocate file descriptor");
        } else {
            close(oldfd);
            err = atf_no_error();
        }
    } else
        err = atf_no_error();

    return err;
}
Example #14
0
atf_error_t
atf_fs_rmdir(const atf_fs_path_t *p)
{
    atf_error_t err;

    if (rmdir(atf_fs_path_cstring(p))) {
        if (errno == EEXIST) {
            /* Some operating systems (e.g. OpenSolaris 200906) return
             * EEXIST instead of ENOTEMPTY for non-empty directories.
             * Homogenize the return value so that callers don't need
             * to bother about differences in operating systems. */
            errno = ENOTEMPTY;
        }
        err = atf_libc_error(errno, "Cannot remove directory");
    } else
        err = atf_no_error();

    return err;
}
Example #15
0
atf_error_t
atf_text_to_bool(const char *str, bool *b)
{
    atf_error_t err;

    if (strcasecmp(str, "yes") == 0 ||
            strcasecmp(str, "true") == 0) {
        *b = true;
        err = atf_no_error();
    } else if (strcasecmp(str, "no") == 0 ||
               strcasecmp(str, "false") == 0) {
        *b = false;
        err = atf_no_error();
    } else {
        /* XXX Not really a libc error. */
        err = atf_libc_error(EINVAL, "Cannot convert string '%s' "
                             "to boolean", str);
    }

    return err;
}
Example #16
0
atf_error_t
atf_fs_getcwd(atf_fs_path_t *p)
{
    atf_error_t err;
    char *cwd;

#if defined(HAVE_GETCWD_DYN)
    cwd = getcwd(NULL, 0);
#else
    cwd = getcwd(NULL, MAXPATHLEN);
#endif
    if (cwd == NULL) {
        err = atf_libc_error(errno, "Cannot determine current directory");
        goto out;
    }

    err = atf_fs_path_init_fmt(p, "%s", cwd);
    free(cwd);

out:
    return err;
}
Example #17
0
static
atf_error_t
stream_prepare_init(stream_prepare_t *sp, const atf_process_stream_t *sb)
{
    atf_error_t err;

    const int type = atf_process_stream_type(sb);

    sp->m_sb = sb;
    sp->m_pipefds_ok = false;

    if (type == atf_process_stream_type_capture) {
        if (pipe(sp->m_pipefds) == -1)
            err = atf_libc_error(errno, "Failed to create pipe");
        else {
            err = atf_no_error();
            sp->m_pipefds_ok = true;
        }
    } else
        err = atf_no_error();

    return err;
}
Example #18
0
ATF_TC_BODY(aio_large_read_test, tc)
{
	char pathname[PATH_MAX];
	struct aiocb cb, *cbp;
	ssize_t nread;
	size_t len;
	int fd;
#ifdef __LP64__
	int clamped;
#endif

	ATF_REQUIRE_KERNEL_MODULE("aio");
	ATF_REQUIRE_UNSAFE_AIO();

#ifdef __LP64__
	len = sizeof(clamped);
	if (sysctlbyname("debug.iosize_max_clamp", &clamped, &len, NULL, 0) ==
	    -1)
		atf_libc_error(errno, "Failed to read debug.iosize_max_clamp");
#endif

	/* Determine the maximum supported read(2) size. */
	len = SSIZE_MAX;
#ifdef __LP64__
	if (clamped)
		len = INT_MAX;
#endif

	strcpy(pathname, PATH_TEMPLATE);
	fd = mkstemp(pathname);
	ATF_REQUIRE_MSG(fd != -1, "mkstemp failed: %s", strerror(errno));

	unlink(pathname);

	memset(&cb, 0, sizeof(cb));
	cb.aio_nbytes = len;
	cb.aio_fildes = fd;
	cb.aio_buf = NULL;
	if (aio_read(&cb) == -1)
		atf_tc_fail("aio_read() of maximum read size failed: %s",
		    strerror(errno));

	nread = aio_waitcomplete(&cbp, NULL);
	if (nread == -1)
		atf_tc_fail("aio_waitcomplete() failed: %s", strerror(errno));
	if (nread != 0)
		atf_tc_fail("aio_read() from empty file returned data: %zd",
		    nread);

	memset(&cb, 0, sizeof(cb));
	cb.aio_nbytes = len + 1;
	cb.aio_fildes = fd;
	cb.aio_buf = NULL;
	if (aio_read(&cb) == -1) {
		if (errno == EINVAL)
			goto finished;
		atf_tc_fail("aio_read() of too large read size failed: %s",
		    strerror(errno));
	}

	nread = aio_waitcomplete(&cbp, NULL);
	if (nread == -1) {
		if (errno == EINVAL)
			goto finished;
		atf_tc_fail("aio_waitcomplete() failed: %s", strerror(errno));
	}
	atf_tc_fail("aio_read() of too large read size returned: %zd", nread);

finished:
	close(fd);
}