Beispiel #1
0
ATF_TC_BODY(work_directory__env_tmpdir, tc)
{
    char* tmpdir;
    RE(kyua_fs_make_absolute("worktest", &tmpdir));
    ATF_REQUIRE(mkdir(tmpdir, 0755) != -1);
    RE(kyua_env_set("TMPDIR", tmpdir));

    char* work_directory;
    RE(kyua_run_work_directory_enter("template.XXXXXX", getuid(), getgid(),
                                     &work_directory));

    {
        char* template_test;
        RE(kyua_fs_concat(&template_test, atf_tc_get_config_var(tc, "srcdir"),
                          "worktest", "template.XXXXXX", NULL));
        ATF_REQUIRE(access(template_test, X_OK) == -1);
        free(template_test);
    }

    ATF_REQUIRE(access(work_directory, X_OK) != -1);

    ATF_REQUIRE(rmdir(tmpdir) == -1);  // Not yet empty.
    RE(kyua_run_work_directory_leave(&work_directory));
    ATF_REQUIRE(rmdir(tmpdir) != -1);
    free(tmpdir);
}
Beispiel #2
0
ATF_TC_BODY(make_absolute__absolute, tc)
{
    char* absolute;
    ATF_REQUIRE(!kyua_error_is_set(kyua_fs_make_absolute(
                                       "/this/is/absolute", &absolute)));
    ATF_REQUIRE_STREQ("/this/is/absolute", absolute);
    free(absolute);
}
Beispiel #3
0
/// Looks for a core file for the given program.
///
/// \param name The basename of the binary that generated the core.
/// \param directory The directory from which the program was run.  We expect to
///     find the core file in this directory.
/// \param dead_pid PID of the process that generated the core.  This is needed
///     in some platforms.
///
/// \return The path to the core file if found; otherwise none.
char*
kyua_stacktrace_find_core(const char* name, const char* directory,
                          const pid_t dead_pid)
{
    char* candidate = NULL;

    // TODO(jmmv): Other than checking all these defaults, in NetBSD we should
    // also inspect the value of the kern.defcorename sysctl(2) MIB and use that
    // as the first candidate.
    //
    // In Linux, the way to determine the name is by looking at
    // /proc/sys/kernel/core_{pattern,uses_pid} as described by core(5).
    // Unfortunately, there does not seem to be a standard API to parse these
    // files, which makes checking for core files quite difficult if the
    // defaults have been modified.

    // Default NetBSD naming scheme.
    if (candidate == NULL && MAXCOMLEN > 0) {
        char truncated[MAXCOMLEN + 1];
        candidate = try_core("%s/%s.core", directory,
                             slice(name, truncated, sizeof(truncated)));
    }

    // Common naming scheme without the MAXCOMLEN truncation.
    if (candidate == NULL)
        candidate = try_core("%s/%s.core", directory, name);

    // Common naming scheme found in Linux systems.
    if (candidate == NULL)
        candidate = try_core("%s/core.%d", directory, (int)dead_pid);

    // Default Mac OS X naming scheme.
    if (candidate == NULL)
        candidate = try_core("/cores/core.%d", (int)dead_pid);

    // Common naming scheme found in Linux systems.  Attempted last due to the
    // genericity of the core file name.
    if (candidate == NULL)
        candidate = try_core("%s/core", directory);

    if (candidate != NULL) {
        char* abs_candidate;
        kyua_error_t error = kyua_fs_make_absolute(candidate, &abs_candidate);
        if (kyua_error_is_set(error)) {
            kyua_error_free(error);
            return candidate;  // Return possibly-relative path as a best guess.
        } else {
            free(candidate);
            return abs_candidate;
        }
    } else {
        return candidate;
    }
}
Beispiel #4
0
ATF_TC_BODY(make_absolute__relative, tc)
{
    kyua_error_t error;
    char* absolute;

    DIR* previous = opendir(".");
    ATF_REQUIRE(previous != NULL);
    ATF_REQUIRE(chdir("/usr") != -1);
    error = kyua_fs_make_absolute("bin/foobar", &absolute);
    const int previous_fd = dirfd(previous);
    ATF_REQUIRE(fchdir(previous_fd) != -1);
    close(previous_fd);

    ATF_REQUIRE(!kyua_error_is_set(error));
    ATF_REQUIRE_STREQ("/usr/bin/foobar", absolute);
    free(absolute);
}
Beispiel #5
0
ATF_TC_BODY(work_directory__sanitized, tc)
{
    ATF_REQUIRE(mkdir("foo", 0755) != -1);
    ATF_REQUIRE(mkdir("foo/bar", 0755) != -1);

    char* tmpdir;
    RE(kyua_fs_make_absolute("foo///bar/./", &tmpdir));
    RE(kyua_env_set("TMPDIR", tmpdir));

    char* work_directory;
    RE(kyua_run_work_directory_enter("template.XXXXXX", getuid(), getgid(),
                                     &work_directory));
    ATF_REQUIRE(strstr(work_directory, "/foo/bar/template.") != NULL);

    RE(kyua_run_work_directory_leave(&work_directory));
    free(tmpdir);
}
Beispiel #6
0
ATF_TC_BODY(work_directory__permissions_error, tc)
{
    char* tmpdir;
    RE(kyua_fs_make_absolute("worktest", &tmpdir));
    ATF_REQUIRE(mkdir(tmpdir, 0755) != -1);
    RE(kyua_env_set("TMPDIR", tmpdir));

    char* work_directory;
    const kyua_error_t error = kyua_run_work_directory_enter(
        "template.XXXXXX", getuid() + 1, getgid(), &work_directory);
    ATF_REQUIRE(kyua_error_is_set(error));
    ATF_REQUIRE(kyua_error_is_type(error, "libc"));
    ATF_REQUIRE_EQ(EPERM, kyua_libc_error_errno(error));
    kyua_error_free(error);

    ATF_REQUIRE(rmdir(tmpdir) != -1);  // Empty; subdirectory not created.
    free(tmpdir);
}
Beispiel #7
0
ATF_TC_BODY(sanitize__ok, tc)
{
    ATF_REQUIRE(mkdir("a", 0755) != -1);
    ATF_REQUIRE(mkdir("a/bc", 0755) != -1);
    ATF_REQUIRE(mkdir("a/bc/12-34", 0755) != -1);

    char* sane;
    ATF_REQUIRE(!kyua_error_is_set(kyua_fs_sanitize(
                                       ".//a/bc///12-34", &sane)));

    char *expected;
    ATF_REQUIRE(!kyua_error_is_set(kyua_fs_make_absolute(
                                       "a/bc/12-34", &expected)));

    ATF_REQUIRE_STREQ(expected, sane);

    free(sane);
    free(expected);
}
Beispiel #8
0
/// Performs a signal delivery test to the work directory handling code.
///
/// \param signo The signal to deliver.
static void
work_directory_signal_check(const int signo)
{
    char* tmpdir;
    RE(kyua_fs_make_absolute("worktest", &tmpdir));
    ATF_REQUIRE(mkdir(tmpdir, 0755) != -1);
    RE(kyua_env_set("TMPDIR", tmpdir));

    char* work_directory;
    RE(kyua_run_work_directory_enter("template.XXXXXX", getuid(), getgid(),
                                     &work_directory));

    kyua_run_params_t run_params;
    kyua_run_params_init(&run_params);
    run_params.work_directory = work_directory;

    pid_t pid;
    RE(kyua_run_fork(&run_params, &pid));
    if (pid == 0) {
        sleep(run_params.timeout_seconds * 2);
        abort();
    }

    // This should cause the handled installed by the work_directory management
    // code to terminate the subprocess so that we get a chance to run the
    // cleanup code ourselves.
    kill(getpid(), signo);

    int status; bool timed_out;
    RE(kyua_run_wait(pid, &status, &timed_out));
    ATF_REQUIRE(!timed_out);
    ATF_REQUIRE(WIFSIGNALED(status));
    ATF_REQUIRE_EQ(SIGKILL, WTERMSIG(status));

    ATF_REQUIRE(rmdir(tmpdir) == -1);  // Not yet empty.
    RE(kyua_run_work_directory_leave(&work_directory));
    ATF_REQUIRE(rmdir(tmpdir) != -1);
    free(tmpdir);
}