Module Name: src
Committed By: jmmv
Date: Tue Dec 22 13:36:57 UTC 2009
Modified Files:
src/external/bsd/atf/dist/atf-c: dynstr.c fs.c io.c tc.c
Removed Files:
src/external/bsd/atf/dist: ChangeLog ROADMAP
src/external/bsd/atf/dist/tests/atf/atf-c: h_check.c h_macros.h
src/external/bsd/atf/dist/tests/build: t_include_atf_c++_hpp.cpp
t_include_atf_c_h.cpp
src/external/bsd/atf/dist/tests/build/atf-c: t_include_check_h.c
t_include_config_h.c t_include_dynstr_h.c t_include_env_h.c
t_include_error_fwd_h.c t_include_error_h.c t_include_expand_h.c
t_include_fs_h.c t_include_io_h.c t_include_list_h.c
t_include_macros_h.c t_include_map_h.c t_include_object_h.c
t_include_process_h.c t_include_sanity_h.c t_include_signals_h.c
t_include_tc_h.c t_include_tcr_h.c t_include_text_h.c
t_include_tp_h.c t_include_ui_h.c t_use_macros_h.c
src/external/bsd/atf/dist/tests/build/atf-c++:
t_include_application_hpp.cpp t_include_atffile_hpp.cpp
t_include_check_hpp.cpp t_include_config_hpp.cpp
t_include_env_hpp.cpp t_include_exceptions_hpp.cpp
t_include_expand_hpp.cpp t_include_formats_hpp.cpp
t_include_fs_hpp.cpp t_include_io_hpp.cpp t_include_macros_hpp.cpp
t_include_parser_hpp.cpp t_include_process_hpp.cpp
t_include_sanity_hpp.cpp t_include_signals_hpp.cpp
t_include_tests_hpp.cpp t_include_text_hpp.cpp t_include_ui_hpp.cpp
t_include_user_hpp.cpp t_include_utils_hpp.cpp t_use_macros_hpp.cpp
Log Message:
Merge atf 0.7.
To generate a diff of this commit:
cvs rdiff -u -r1.1.1.1 -r0 src/external/bsd/atf/dist/ChangeLog \
src/external/bsd/atf/dist/ROADMAP
cvs rdiff -u -r1.2 -r1.3 src/external/bsd/atf/dist/atf-c/dynstr.c \
src/external/bsd/atf/dist/atf-c/fs.c src/external/bsd/atf/dist/atf-c/io.c \
src/external/bsd/atf/dist/atf-c/tc.c
cvs rdiff -u -r1.1.1.1 -r0 \
src/external/bsd/atf/dist/tests/atf/atf-c/h_check.c \
src/external/bsd/atf/dist/tests/atf/atf-c/h_macros.h
cvs rdiff -u -r1.1.1.1 -r0 \
src/external/bsd/atf/dist/tests/build/t_include_atf_c++_hpp.cpp \
src/external/bsd/atf/dist/tests/build/t_include_atf_c_h.cpp
cvs rdiff -u -r1.1.1.1 -r0 \
src/external/bsd/atf/dist/tests/build/atf-c/t_include_check_h.c \
src/external/bsd/atf/dist/tests/build/atf-c/t_include_config_h.c \
src/external/bsd/atf/dist/tests/build/atf-c/t_include_dynstr_h.c \
src/external/bsd/atf/dist/tests/build/atf-c/t_include_env_h.c \
src/external/bsd/atf/dist/tests/build/atf-c/t_include_error_fwd_h.c \
src/external/bsd/atf/dist/tests/build/atf-c/t_include_error_h.c \
src/external/bsd/atf/dist/tests/build/atf-c/t_include_expand_h.c \
src/external/bsd/atf/dist/tests/build/atf-c/t_include_fs_h.c \
src/external/bsd/atf/dist/tests/build/atf-c/t_include_io_h.c \
src/external/bsd/atf/dist/tests/build/atf-c/t_include_list_h.c \
src/external/bsd/atf/dist/tests/build/atf-c/t_include_macros_h.c \
src/external/bsd/atf/dist/tests/build/atf-c/t_include_map_h.c \
src/external/bsd/atf/dist/tests/build/atf-c/t_include_object_h.c \
src/external/bsd/atf/dist/tests/build/atf-c/t_include_process_h.c \
src/external/bsd/atf/dist/tests/build/atf-c/t_include_sanity_h.c \
src/external/bsd/atf/dist/tests/build/atf-c/t_include_signals_h.c \
src/external/bsd/atf/dist/tests/build/atf-c/t_include_tc_h.c \
src/external/bsd/atf/dist/tests/build/atf-c/t_include_tcr_h.c \
src/external/bsd/atf/dist/tests/build/atf-c/t_include_text_h.c \
src/external/bsd/atf/dist/tests/build/atf-c/t_include_tp_h.c \
src/external/bsd/atf/dist/tests/build/atf-c/t_include_ui_h.c \
src/external/bsd/atf/dist/tests/build/atf-c/t_use_macros_h.c
cvs rdiff -u -r1.1.1.1 -r0 \
src/external/bsd/atf/dist/tests/build/atf-c++/t_include_application_hpp.cpp
\
src/external/bsd/atf/dist/tests/build/atf-c++/t_include_atffile_hpp.cpp \
src/external/bsd/atf/dist/tests/build/atf-c++/t_include_check_hpp.cpp \
src/external/bsd/atf/dist/tests/build/atf-c++/t_include_config_hpp.cpp \
src/external/bsd/atf/dist/tests/build/atf-c++/t_include_env_hpp.cpp \
src/external/bsd/atf/dist/tests/build/atf-c++/t_include_exceptions_hpp.cpp \
src/external/bsd/atf/dist/tests/build/atf-c++/t_include_expand_hpp.cpp \
src/external/bsd/atf/dist/tests/build/atf-c++/t_include_formats_hpp.cpp \
src/external/bsd/atf/dist/tests/build/atf-c++/t_include_fs_hpp.cpp \
src/external/bsd/atf/dist/tests/build/atf-c++/t_include_io_hpp.cpp \
src/external/bsd/atf/dist/tests/build/atf-c++/t_include_macros_hpp.cpp \
src/external/bsd/atf/dist/tests/build/atf-c++/t_include_parser_hpp.cpp \
src/external/bsd/atf/dist/tests/build/atf-c++/t_include_process_hpp.cpp \
src/external/bsd/atf/dist/tests/build/atf-c++/t_include_sanity_hpp.cpp \
src/external/bsd/atf/dist/tests/build/atf-c++/t_include_signals_hpp.cpp \
src/external/bsd/atf/dist/tests/build/atf-c++/t_include_tests_hpp.cpp \
src/external/bsd/atf/dist/tests/build/atf-c++/t_include_text_hpp.cpp \
src/external/bsd/atf/dist/tests/build/atf-c++/t_include_ui_hpp.cpp \
src/external/bsd/atf/dist/tests/build/atf-c++/t_include_user_hpp.cpp \
src/external/bsd/atf/dist/tests/build/atf-c++/t_include_utils_hpp.cpp \
src/external/bsd/atf/dist/tests/build/atf-c++/t_use_macros_hpp.cpp
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/external/bsd/atf/dist/atf-c/dynstr.c
diff -u src/external/bsd/atf/dist/atf-c/dynstr.c:1.2 src/external/bsd/atf/dist/atf-c/dynstr.c:1.3
--- src/external/bsd/atf/dist/atf-c/dynstr.c:1.2 Thu Feb 12 09:05:13 2009
+++ src/external/bsd/atf/dist/atf-c/dynstr.c Tue Dec 22 13:36:56 2009
@@ -1,7 +1,7 @@
/*
* Automated Testing Framework (atf)
*
- * Copyright (c) 2008 The NetBSD Foundation, Inc.
+ * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -126,13 +126,18 @@
ad->m_data = (char *)malloc(sizeof(char));
if (ad->m_data == NULL) {
err = atf_no_memory_error();
- } else {
- ad->m_data[0] = '\0';
- ad->m_datasize = 1;
- ad->m_length = 0;
- err = atf_no_error();
+ goto err_object;
}
+ ad->m_data[0] = '\0';
+ ad->m_datasize = 1;
+ ad->m_length = 0;
+ err = atf_no_error();
+ goto out;
+
+err_object:
+ atf_object_fini(&ad->m_object);
+out:
return err;
}
@@ -146,31 +151,40 @@
ad->m_datasize = strlen(fmt) + 1;
ad->m_length = 0;
- err = atf_no_error();
do {
+ va_list ap2;
+ int ret;
+
ad->m_datasize *= 2;
ad->m_data = (char *)malloc(ad->m_datasize);
if (ad->m_data == NULL) {
err = atf_no_memory_error();
- } else {
- va_list ap2;
- int ret;
-
- va_copy(ap2, ap);
- ret = vsnprintf(ad->m_data, ad->m_datasize, fmt, ap2);
- va_end(ap2);
- if (ret < 0) {
- err = atf_libc_error(errno, "Cannot format string");
- } else {
- if ((size_t)ret >= ad->m_datasize) {
- free(ad->m_data);
- ad->m_data = NULL;
- }
- ad->m_length = ret;
- }
+ goto err_object;
}
- } while (!atf_is_error(err) && ad->m_length >= ad->m_datasize);
+ va_copy(ap2, ap);
+ ret = vsnprintf(ad->m_data, ad->m_datasize, fmt, ap2);
+ va_end(ap2);
+ if (ret < 0) {
+ free(ad->m_data);
+ err = atf_libc_error(errno, "Cannot format string");
+ goto err_object;
+ }
+
+ INV(ret >= 0);
+ if ((size_t)ret >= ad->m_datasize) {
+ free(ad->m_data);
+ ad->m_data = NULL;
+ }
+ ad->m_length = ret;
+ } while (ad->m_length >= ad->m_datasize);
+
+ err = atf_no_error();
+ goto out;
+
+err_object:
+ atf_object_fini(&ad->m_object);
+out:
POST(atf_is_error(err) || ad->m_data != NULL);
return err;
}
@@ -195,18 +209,28 @@
atf_object_init(&ad->m_object);
+ if (memlen >= SIZE_MAX - 1) {
+ err = atf_no_memory_error();
+ goto err_object;
+ }
+
ad->m_data = (char *)malloc(memlen + 1);
- if (ad->m_data == NULL)
+ if (ad->m_data == NULL) {
err = atf_no_memory_error();
- else {
- ad->m_datasize = memlen + 1;
- memcpy(ad->m_data, mem, memlen);
- ad->m_data[memlen] = '\0';
- ad->m_length = strlen(ad->m_data);
- INV(ad->m_length <= memlen);
- err = atf_no_error();
+ goto err_object;
}
+ ad->m_datasize = memlen + 1;
+ memcpy(ad->m_data, mem, memlen);
+ ad->m_data[memlen] = '\0';
+ ad->m_length = strlen(ad->m_data);
+ INV(ad->m_length <= memlen);
+ err = atf_no_error();
+ goto out;
+
+err_object:
+ atf_object_fini(&ad->m_object);
+out:
return err;
}
@@ -217,21 +241,27 @@
atf_object_init(&ad->m_object);
- if (len == SIZE_MAX)
+ if (len == SIZE_MAX) {
err = atf_no_memory_error();
- else {
- ad->m_datasize = len + sizeof(char);
- ad->m_data = (char *)malloc(ad->m_datasize);
- if (ad->m_data == NULL) {
- err = atf_no_memory_error();
- } else {
- memset(ad->m_data, ch, len);
- ad->m_data[len] = '\0';
- ad->m_length = len;
- err = atf_no_error();
- }
+ goto err_object;
+ }
+
+ ad->m_datasize = (len + 1) * sizeof(char);
+ ad->m_data = (char *)malloc(ad->m_datasize);
+ if (ad->m_data == NULL) {
+ err = atf_no_memory_error();
+ goto err_object;
}
+ memset(ad->m_data, ch, len);
+ ad->m_data[len] = '\0';
+ ad->m_length = len;
+ err = atf_no_error();
+ goto out;
+
+err_object:
+ atf_object_fini(&ad->m_object);
+out:
return err;
}
Index: src/external/bsd/atf/dist/atf-c/fs.c
diff -u src/external/bsd/atf/dist/atf-c/fs.c:1.2 src/external/bsd/atf/dist/atf-c/fs.c:1.3
--- src/external/bsd/atf/dist/atf-c/fs.c:1.2 Thu Feb 12 09:05:13 2009
+++ src/external/bsd/atf/dist/atf-c/fs.c Tue Dec 22 13:36:56 2009
@@ -1,7 +1,7 @@
/*
* Automated Testing Framework (atf)
*
- * Copyright (c) 2007, 2008 The NetBSD Foundation, Inc.
+ * Copyright (c) 2007, 2008, 2009 The NetBSD Foundation, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -54,6 +54,78 @@
#include "atf-c/user.h"
/* ---------------------------------------------------------------------
+ * Prototypes for auxiliary functions.
+ * --------------------------------------------------------------------- */
+
+static bool check_umask(const mode_t, const mode_t);
+static atf_error_t cleanup_aux(const atf_fs_path_t *, dev_t, bool);
+static atf_error_t cleanup_aux_dir(const char *, const atf_fs_stat_t *, bool);
+static atf_error_t copy_contents(const atf_fs_path_t *, char **);
+static mode_t current_umask(void);
+static atf_error_t do_mkdtemp(char *);
+static atf_error_t do_unmount(const atf_fs_path_t *);
+static atf_error_t normalize(atf_dynstr_t *, char *);
+static atf_error_t normalize_ap(atf_dynstr_t *, const char *, va_list);
+static void replace_contents(atf_fs_path_t *, const char *);
+static const char *stat_type_to_string(const int);
+
+/* ---------------------------------------------------------------------
+ * The "invalid_umask" error type.
+ * --------------------------------------------------------------------- */
+
+struct invalid_umask_error_data {
+ /* One of atf_fs_stat_*_type. */
+ int m_type;
+
+ /* The original path causing the error. */
+ /* XXX: Ideally this would be an atf_fs_path_t, but if we create it
+ * from the error constructor, we cannot delete the path later on.
+ * Can't remember why atf_error_new does not take a hook for
+ * deletion. */
+ char m_path[1024];
+
+ /* The umask that caused the error. */
+ mode_t m_umask;
+};
+typedef struct invalid_umask_error_data invalid_umask_error_data_t;
+
+static
+void
+invalid_umask_format(const atf_error_t err, char *buf, size_t buflen)
+{
+ const invalid_umask_error_data_t *data;
+
+ PRE(atf_error_is(err, "invalid_umask"));
+
+ data = atf_error_data(err);
+ snprintf(buf, buflen, "Could not create the temporary %s %s because "
+ "it will not have enough access rights due to the current "
+ "umask %05o", stat_type_to_string(data->m_type),
+ data->m_path, (unsigned int)data->m_umask);
+}
+
+static
+atf_error_t
+invalid_umask_error(const atf_fs_path_t *path, const int type,
+ const mode_t failing_mask)
+{
+ atf_error_t err;
+ invalid_umask_error_data_t data;
+
+ data.m_type = type;
+
+ strncpy(data.m_path, atf_fs_path_cstring(path), sizeof(data.m_path));
+ data.m_path[sizeof(data.m_path) - 1] = '\0';
+
+ data.m_umask = failing_mask;
+
+ err = atf_error_new("invalid_umask", &data, sizeof(data),
+ invalid_umask_format);
+
+ return err;
+}
+
+/* ---------------------------------------------------------------------
* The "unknown_file_type" error type.
* --------------------------------------------------------------------- */
@@ -96,11 +168,13 @@
* Auxiliary functions.
* --------------------------------------------------------------------- */
-static atf_error_t cleanup_aux(const atf_fs_path_t *, dev_t, bool);
-static atf_error_t cleanup_aux_dir(const char *, dev_t, bool);
-static atf_error_t do_unmount(const atf_fs_path_t *);
-static atf_error_t normalize(atf_dynstr_t *, char *);
-static atf_error_t normalize_ap(atf_dynstr_t *, const char *, va_list);
+static
+bool
+check_umask(const mode_t exp_mode, const mode_t min_mode)
+{
+ const mode_t actual_mode = (~current_umask() & exp_mode);
+ return (actual_mode & min_mode) == min_mode;
+}
/* The erase parameter in this routine is to control nested mount points.
* We want to descend into a mount point to unmount anything that is
@@ -120,7 +194,7 @@
goto out;
if (atf_fs_stat_get_type(&st) == atf_fs_stat_dir_type) {
- err = cleanup_aux_dir(pstr, atf_fs_stat_get_device(&st),
+ err = cleanup_aux_dir(pstr, &st,
atf_fs_stat_get_device(&st) == parent_device);
if (atf_is_error(err))
goto out_st;
@@ -134,11 +208,7 @@
if (erase) {
if (atf_fs_stat_get_type(&st) == atf_fs_stat_dir_type) {
- if (rmdir(pstr) == -1)
- err = atf_libc_error(errno, "Cannot remove directory "
- "%s", pstr);
- else
- INV(!atf_is_error(err));
+ err = atf_fs_rmdir(p);
} else {
if (unlink(pstr) == -1)
err = atf_libc_error(errno, "Cannot remove file %s", pstr);
@@ -155,12 +225,20 @@
static
atf_error_t
-cleanup_aux_dir(const char *pstr, dev_t this_device, bool erase)
+cleanup_aux_dir(const char *pstr, const atf_fs_stat_t *st, bool erase)
{
DIR *d;
atf_error_t err;
struct dirent *de;
+ if (erase && !(atf_fs_stat_get_mode(st) & S_IWUSR)) {
+ if (chmod(pstr, atf_fs_stat_get_mode(st) | S_IWUSR) == -1) {
+ err = atf_libc_error(errno, "Cannot grant write permissions "
+ "to %s", pstr);
+ goto out;
+ }
+ }
+
d = opendir(pstr);
if (d == NULL) {
err = atf_libc_error(errno, "Cannot open directory %s", pstr);
@@ -175,7 +253,7 @@
if (!atf_is_error(err)) {
if (strcmp(de->d_name, ".") != 0 &&
strcmp(de->d_name, "..") != 0)
- err = cleanup_aux(&p, this_device, erase);
+ err = cleanup_aux(&p, atf_fs_stat_get_device(st), erase);
atf_fs_path_fini(&p);
}
@@ -207,6 +285,15 @@
}
static
+mode_t
+current_umask(void)
+{
+ const mode_t current = umask(0);
+ (void)umask(current);
+ return current;
+}
+
+static
atf_error_t
do_mkdtemp(char *tmpl)
{
@@ -274,12 +361,28 @@
* also have to update /etc/mtab to match what we did. It is
* simpler to just leave the system-specific umount(8) tool deal
* with it, at least for now. */
- char *cmd;
+ atf_fs_path_t prog;
- err = atf_text_format(&cmd, "umount '%s'", pastr);
+ /* TODO: Should have an atf_fs_find_in_path function or similar to
+ * avoid relying on the automatic path lookup of exec, which I'd
+ * like to get rid of. */
+ err = atf_fs_path_init_fmt(&prog, "umount");
if (!atf_is_error(err)) {
- err = atf_process_system(cmd);
- free(cmd);
+ atf_process_status_t status;
+ const char *argv[3] = { "unmount", pastr, NULL };
+
+ err = atf_process_exec_array(&status, &prog, argv, NULL, NULL);
+ if (!atf_is_error(err)) {
+ if (!atf_process_status_exited(&status) ||
+ atf_process_status_exitstatus(&status) != EXIT_SUCCESS) {
+ /* XXX: This is the wrong error type. */
+ err = atf_libc_error(EINVAL, "Failed to exec unmount");
+ }
+
+ atf_process_status_fini(&status);
+ }
+
+ atf_fs_path_fini(&prog);
}
}
#endif
@@ -361,6 +464,36 @@
INV(!atf_is_error(err));
}
+static
+const char *
+stat_type_to_string(const int type)
+{
+ const char *str;
+
+ if (type == atf_fs_stat_blk_type)
+ str = "block device";
+ else if (type == atf_fs_stat_chr_type)
+ str = "character device";
+ else if (type == atf_fs_stat_dir_type)
+ str = "directory";
+ else if (type == atf_fs_stat_fifo_type)
+ str = "named pipe";
+ else if (type == atf_fs_stat_lnk_type)
+ str = "symbolic link";
+ else if (type == atf_fs_stat_reg_type)
+ str = "regular file";
+ else if (type == atf_fs_stat_sock_type)
+ str = "socket";
+ else if (type == atf_fs_stat_wht_type)
+ str = "whiteout";
+ else {
+ UNREACHABLE;
+ str = NULL;
+ }
+
+ return str;
+}
+
/* ---------------------------------------------------------------------
* The "atf_fs_path" type.
* --------------------------------------------------------------------- */
@@ -420,10 +553,10 @@
atf_error_t
atf_fs_path_branch_path(const atf_fs_path_t *p, atf_fs_path_t *bp)
{
- const ssize_t endpos = atf_dynstr_rfind_ch(&p->m_data, '/');
+ const size_t endpos = atf_dynstr_rfind_ch(&p->m_data, '/');
atf_error_t err;
- if ((size_t)endpos == atf_dynstr_npos)
+ if (endpos == atf_dynstr_npos)
err = atf_fs_path_init_fmt(bp, ".");
else if (endpos == 0)
err = atf_fs_path_init_fmt(bp, "/");
@@ -449,10 +582,10 @@
atf_error_t
atf_fs_path_leaf_name(const atf_fs_path_t *p, atf_dynstr_t *ln)
{
- ssize_t begpos = atf_dynstr_rfind_ch(&p->m_data, '/');
+ size_t begpos = atf_dynstr_rfind_ch(&p->m_data, '/');
atf_error_t err;
- if ((size_t)begpos == atf_dynstr_npos)
+ if (begpos == atf_dynstr_npos)
begpos = 0;
else
begpos++;
@@ -640,6 +773,12 @@
return st->m_sb.st_ino;
}
+mode_t
+atf_fs_stat_get_mode(const atf_fs_stat_t *st)
+{
+ return st->m_sb.st_mode & ~S_IFMT;
+}
+
off_t
atf_fs_stat_get_size(const atf_fs_stat_t *st)
{
@@ -845,6 +984,11 @@
atf_error_t err;
char *buf;
+ if (!check_umask(S_IRWXU, S_IRWXU)) {
+ err = invalid_umask_error(p, atf_fs_stat_dir_type, current_umask());
+ goto out;
+ }
+
err = copy_contents(p, &buf);
if (atf_is_error(err))
goto out;
@@ -869,6 +1013,11 @@
char *buf;
int fd;
+ if (!check_umask(S_IRWXU, S_IRWXU)) {
+ err = invalid_umask_error(p, atf_fs_stat_reg_type, current_umask());
+ goto out;
+ }
+
err = copy_contents(p, &buf);
if (atf_is_error(err))
goto out;
@@ -888,6 +1037,26 @@
}
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;
+}
+
+atf_error_t
atf_fs_unlink(const atf_fs_path_t *p)
{
atf_error_t err;
Index: src/external/bsd/atf/dist/atf-c/io.c
diff -u src/external/bsd/atf/dist/atf-c/io.c:1.2 src/external/bsd/atf/dist/atf-c/io.c:1.3
--- src/external/bsd/atf/dist/atf-c/io.c:1.2 Thu Feb 12 09:05:13 2009
+++ src/external/bsd/atf/dist/atf-c/io.c Tue Dec 22 13:36:56 2009
@@ -1,7 +1,7 @@
/*
* Automated Testing Framework (atf)
*
- * Copyright (c) 2008 The NetBSD Foundation, Inc.
+ * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -43,24 +43,29 @@
#include "atf-c/sanity.h"
atf_error_t
-atf_io_readline(int fd, atf_dynstr_t *dest)
+atf_io_readline(int fd, atf_dynstr_t *dest, bool *eof)
{
- char ch[2];
+ char ch;
ssize_t cnt;
atf_error_t err;
- ch[1] = '\0';
- while ((cnt = read(fd, &ch[0], sizeof(ch[0]))) == sizeof(ch[0]) &&
- ch[0] != '\n') {
- atf_dynstr_append_fmt(dest, ch);
+ while ((cnt = read(fd, &ch, sizeof(ch))) == sizeof(ch) &&
+ ch != '\n') {
+ err = atf_dynstr_append_fmt(dest, "%c", ch);
+ if (atf_is_error(err))
+ goto out;
}
- if (cnt == -1)
+ if (cnt == -1) {
err = atf_libc_error(errno, "Failed to read line from file "
"descriptor %d", fd);
- else
- err = atf_no_error();
+ goto out;
+ }
+
+ *eof = (cnt == 0);
+ err = atf_no_error();
+out:
return err;
}
@@ -80,6 +85,7 @@
"descriptor %d", atf_dynstr_cstring(&str),
fd);
else {
+ INV(cnt >= 0);
INV((size_t)cnt == atf_dynstr_length(&str));
err = atf_no_error();
}
Index: src/external/bsd/atf/dist/atf-c/tc.c
diff -u src/external/bsd/atf/dist/atf-c/tc.c:1.2 src/external/bsd/atf/dist/atf-c/tc.c:1.3
--- src/external/bsd/atf/dist/atf-c/tc.c:1.2 Tue Apr 14 15:41:11 2009
+++ src/external/bsd/atf/dist/atf-c/tc.c Tue Dec 22 13:36:56 2009
@@ -1,7 +1,7 @@
/*
* Automated Testing Framework (atf)
*
- * Copyright (c) 2008 The NetBSD Foundation, Inc.
+ * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -43,6 +43,7 @@
#include <unistd.h>
#include "atf-c/config.h"
+#include "atf-c/defs.h"
#include "atf-c/env.h"
#include "atf-c/error.h"
#include "atf-c/fs.h"
@@ -58,39 +59,46 @@
* Auxiliary types and functions.
* --------------------------------------------------------------------- */
+struct child_data {
+ const atf_tc_t *tc;
+ const atf_fs_path_t *workdir;
+};
+
/* Parent-only stuff. */
struct timeout_data;
static atf_error_t body_parent(const atf_tc_t *, const atf_fs_path_t *,
- pid_t, atf_tcr_t *);
-static atf_error_t cleanup_parent(const atf_tc_t *, pid_t);
-static atf_error_t fork_body(const atf_tc_t *, const atf_fs_path_t *,
- atf_tcr_t *);
-static atf_error_t fork_cleanup(const atf_tc_t *, const atf_fs_path_t *);
+ atf_process_child_t *, atf_tcr_t *);
+static atf_error_t cleanup_parent(const atf_tc_t *, atf_process_child_t *);
+static atf_error_t fork_body(const atf_tc_t *, int, int,
+ const atf_fs_path_t *, atf_tcr_t *);
+static atf_error_t fork_cleanup(const atf_tc_t *, int, int,
+ const atf_fs_path_t *);
static atf_error_t get_tc_result(const atf_fs_path_t *, atf_tcr_t *);
-static atf_error_t program_timeout(pid_t, const atf_tc_t *,
- struct timeout_data *);
+static atf_error_t program_timeout(const atf_process_child_t *,
+ const atf_tc_t *, struct timeout_data *);
static void unprogram_timeout(struct timeout_data *);
static void sigalrm_handler(int);
/* Child-only stuff. */
-static void body_child(const atf_tc_t *, const atf_fs_path_t *)
- ATF_DEFS_ATTRIBUTE_NORETURN;
+static void body_child(void *) ATF_DEFS_ATTRIBUTE_NORETURN;
static atf_error_t check_arch(const char *, void *);
static atf_error_t check_config(const char *, void *);
static atf_error_t check_machine(const char *, void *);
static atf_error_t check_prog(const char *, void *);
static atf_error_t check_prog_in_dir(const char *, void *);
static atf_error_t check_requirements(const atf_tc_t *);
-static void cleanup_child(const atf_tc_t *, const atf_fs_path_t *)
- ATF_DEFS_ATTRIBUTE_NORETURN;
+static void cleanup_child(void *) ATF_DEFS_ATTRIBUTE_NORETURN;
static void fail_internal(const char *, int, const char *, const char *,
const char *, va_list,
+ void (*)(atf_dynstr_t *),
void (*)(const char *, ...));
static void fatal_atf_error(const char *, atf_error_t)
ATF_DEFS_ATTRIBUTE_NORETURN;
static void fatal_libc_error(const char *, int)
ATF_DEFS_ATTRIBUTE_NORETURN;
-static atf_error_t prepare_child(const atf_tc_t *, const atf_fs_path_t *);
+static atf_error_t prepare_child(const struct child_data *);
+static void tc_fail(atf_dynstr_t *) ATF_DEFS_ATTRIBUTE_NORETURN;
+static void tc_fail_nonfatal(atf_dynstr_t *);
static void write_tcr(const atf_tcr_t *);
/* ---------------------------------------------------------------------
@@ -269,7 +277,7 @@
* --------------------------------------------------------------------- */
atf_error_t
-atf_tc_run(const atf_tc_t *tc, atf_tcr_t *tcr,
+atf_tc_run(const atf_tc_t *tc, atf_tcr_t *tcr, int fdout, int fderr,
const atf_fs_path_t *workdirbase)
{
atf_error_t err, cleanuperr;
@@ -287,8 +295,8 @@
if (atf_is_error(err))
goto out_workdir;
- err = fork_body(tc, &workdir, tcr);
- cleanuperr = fork_cleanup(tc, &workdir);
+ err = fork_body(tc, fdout, fderr, &workdir, tcr);
+ cleanuperr = fork_cleanup(tc, fdout, fderr, &workdir);
if (!atf_is_error(cleanuperr))
(void)atf_fs_cleanup(&workdir);
if (!atf_is_error(err))
@@ -328,7 +336,8 @@
static
atf_error_t
-program_timeout(pid_t pid, const atf_tc_t *tc, struct timeout_data *td)
+program_timeout(const atf_process_child_t *child, const atf_tc_t *tc,
+ struct timeout_data *td)
{
atf_error_t err;
long timeout;
@@ -338,7 +347,7 @@
goto out;
if (timeout != 0) {
- sigalrm_pid = pid;
+ sigalrm_pid = atf_process_child_pid(child);
sigalrm_killed = false;
err = atf_signal_programmer_init(&td->m_sigalrm, SIGALRM,
@@ -377,52 +386,62 @@
static
atf_error_t
-body_parent(const atf_tc_t *tc, const atf_fs_path_t *workdir, pid_t pid,
- atf_tcr_t *tcr)
+body_parent(const atf_tc_t *tc, const atf_fs_path_t *workdir,
+ atf_process_child_t *child, atf_tcr_t *tcr)
{
atf_error_t err;
- int state;
+ atf_process_status_t status;
struct timeout_data td;
- err = program_timeout(pid, tc, &td);
+ err = program_timeout(child, tc, &td);
if (atf_is_error(err)) {
char buf[4096];
atf_error_format(err, buf, sizeof(buf));
fprintf(stderr, "Error programming test case's timeout: %s", buf);
atf_error_free(err);
- killpg(pid, SIGKILL);
+ killpg(atf_process_child_pid(child), SIGKILL);
}
- if (waitpid(pid, &state, 0) == -1) {
- if (errno == EINTR && sigalrm_killed)
+again:
+ err = atf_process_child_wait(child, &status);
+ if (atf_is_error(err)) {
+ if (atf_error_is(err, "libc") && atf_libc_error_code(err) == EINTR) {
+ atf_error_free(err);
+ goto again;
+ } else {
+ /* Propagate err */
+ }
+ } else {
+ if (sigalrm_killed)
err = atf_tcr_init_reason_fmt(tcr, atf_tcr_failed_state,
"Test case timed out after %s "
"seconds",
atf_tc_get_md_var(tc, "timeout"));
- else
- err = atf_libc_error(errno, "Error waiting for child process "
- "%d", pid);
- } else {
- if (!WIFEXITED(state) || WEXITSTATUS(state) != EXIT_SUCCESS) {
- if (WIFEXITED(state))
- err = atf_tcr_init_reason_fmt(tcr, atf_tcr_failed_state,
- "Test case did not exit cleanly; "
- "exit status was %d",
- WEXITSTATUS(state));
- else if (WIFSIGNALED(state))
+ else {
+ if (atf_process_status_exited(&status)) {
+ const int exitstatus = atf_process_status_exitstatus(&status);
+ if (exitstatus == EXIT_SUCCESS)
+ err = get_tc_result(workdir, tcr);
+ else
+ err = atf_tcr_init_reason_fmt(tcr, atf_tcr_failed_state,
+ "Test case exited with "
+ "status %d", exitstatus);
+ } else if (atf_process_status_signaled(&status)) {
+ const int sig = atf_process_status_termsig(&status);
+ const bool wcore = atf_process_status_coredump(&status);
err = atf_tcr_init_reason_fmt(tcr, atf_tcr_failed_state,
- "Test case did not exit cleanly: "
- "%s%s",
- strsignal(WTERMSIG(state)),
- WCOREDUMP(state) ?
- " (core dumped)" : "");
- else
+ "Test case was signaled by "
+ "signal %d%s", sig,
+ wcore ? " (core dumped)" : "");
+ } else {
err = atf_tcr_init_reason_fmt(tcr, atf_tcr_failed_state,
- "Test case did not exit cleanly; "
- "state was %d", state);
- } else
- err = get_tc_result(workdir, tcr);
+ "Test case exited due to an "
+ "unexpected condition");
+ }
+ }
+
+ atf_process_status_fini(&status);
}
unprogram_timeout(&td);
@@ -432,71 +451,97 @@
static
atf_error_t
-cleanup_parent(const atf_tc_t *tc, pid_t pid)
+cleanup_parent(const atf_tc_t *tc, atf_process_child_t *child)
{
atf_error_t err;
- int state;
+ atf_process_status_t status;
- if (waitpid(pid, &state, 0) == -1) {
- err = atf_libc_error(errno, "Error waiting for child process "
- "%d", pid);
+ err = atf_process_child_wait(child, &status);
+ if (atf_is_error(err))
goto out;
- }
- if (!WIFEXITED(state) || WEXITSTATUS(state) != EXIT_SUCCESS)
+ if (!atf_process_status_exited(&status) ||
+ atf_process_status_exitstatus(&status) != EXIT_SUCCESS) {
/* XXX Not really a libc error. */
err = atf_libc_error(EINVAL, "Child process did not exit cleanly");
- else
+ } else
err = atf_no_error();
+ atf_process_status_fini(&status);
out:
return err;
}
static
atf_error_t
-fork_body(const atf_tc_t *tc, const atf_fs_path_t *workdir, atf_tcr_t *tcr)
+fork_body(const atf_tc_t *tc, int fdout, int fderr,
+ const atf_fs_path_t *workdir, atf_tcr_t *tcr)
{
atf_error_t err;
- pid_t pid;
+ atf_process_stream_t outsb, errsb;
+ atf_process_child_t child;
+ struct child_data data = {
+ tc,
+ workdir,
+ };
- err = atf_process_fork(&pid);
+ err = atf_process_stream_init_redirect_fd(&outsb, fdout);
if (atf_is_error(err))
goto out;
- if (pid == 0) {
- body_child(tc, workdir);
- UNREACHABLE;
- abort();
- } else {
- err = body_parent(tc, workdir, pid, tcr);
- }
+ err = atf_process_stream_init_redirect_fd(&errsb, fderr);
+ if (atf_is_error(err))
+ goto out_outsb;
+
+ err = atf_process_fork(&child, body_child, &outsb, &errsb, &data);
+ if (atf_is_error(err))
+ goto out_errsb;
+
+ err = body_parent(tc, workdir, &child, tcr);
+out_errsb:
+ atf_process_stream_fini(&errsb);
+out_outsb:
+ atf_process_stream_fini(&outsb);
out:
return err;
}
static
atf_error_t
-fork_cleanup(const atf_tc_t *tc, const atf_fs_path_t *workdir)
+fork_cleanup(const atf_tc_t *tc, int fdout, int fderr,
+ const atf_fs_path_t *workdir)
{
atf_error_t err;
- pid_t pid;
if (tc->m_cleanup == NULL)
err = atf_no_error();
else {
- err = atf_process_fork(&pid);
+ atf_process_stream_t outsb, errsb;
+ atf_process_child_t child;
+ struct child_data data = {
+ tc,
+ workdir,
+ };
+
+ err = atf_process_stream_init_redirect_fd(&outsb, fdout);
if (atf_is_error(err))
goto out;
- if (pid == 0) {
- cleanup_child(tc, workdir);
- UNREACHABLE;
- abort();
- } else {
- err = cleanup_parent(tc, pid);
- }
+ err = atf_process_stream_init_redirect_fd(&errsb, fderr);
+ if (atf_is_error(err))
+ goto out_outsb;
+
+ err = atf_process_fork(&child, cleanup_child, &outsb, &errsb, &data);
+ if (atf_is_error(err))
+ goto out_errsb;
+
+ err = cleanup_parent(tc, &child);
+
+out_errsb:
+ atf_process_stream_fini(&errsb);
+out_outsb:
+ atf_process_stream_fini(&outsb);
}
out:
@@ -544,13 +589,13 @@
static
atf_error_t
-prepare_child(const atf_tc_t *tc, const atf_fs_path_t *workdir)
+prepare_child(const struct child_data *cd)
{
atf_error_t err;
int i, ret;
- current_tc = tc;
- current_workdir = workdir;
+ current_tc = cd->tc;
+ current_workdir = cd->workdir;
current_tc_fail_count = 0;
ret = setpgid(getpid(), 0);
@@ -561,7 +606,7 @@
for (i = 1; i <= atf_signals_last_signo; i++)
atf_signal_reset(i);
- err = atf_env_set("HOME", atf_fs_path_cstring(workdir));
+ err = atf_env_set("HOME", atf_fs_path_cstring(cd->workdir));
if (atf_is_error(err))
goto out;
@@ -601,9 +646,9 @@
if (atf_is_error(err))
goto out;
- if (chdir(atf_fs_path_cstring(workdir)) == -1) {
+ if (chdir(atf_fs_path_cstring(cd->workdir)) == -1) {
err = atf_libc_error(errno, "Cannot enter work directory '%s'",
- atf_fs_path_cstring(workdir));
+ atf_fs_path_cstring(cd->workdir));
goto out;
}
@@ -615,19 +660,21 @@
static
void
-body_child(const atf_tc_t *tc, const atf_fs_path_t *workdir)
+body_child(void *v)
{
+ const struct child_data *cd = v;
atf_error_t err;
- atf_disable_exit_checks();
+ atf_reset_exit_checks();
- err = prepare_child(tc, workdir);
+ err = prepare_child(cd);
if (atf_is_error(err))
goto print_err;
- err = check_requirements(tc);
+ err = check_requirements(cd->tc);
if (atf_is_error(err))
goto print_err;
- tc->m_body(tc);
+
+ cd->tc->m_body(cd->tc);
if (current_tc_fail_count == 0)
atf_tc_pass();
@@ -636,7 +683,6 @@
current_tc_fail_count);
UNREACHABLE;
- abort();
print_err:
INV(atf_is_error(err));
@@ -650,7 +696,6 @@
}
UNREACHABLE;
- abort();
}
static
@@ -704,8 +749,12 @@
goto out;
if (atf_fs_path_is_absolute(&p)) {
- if (atf_is_error(atf_fs_eaccess(&p, atf_fs_access_x)))
+ err = atf_fs_eaccess(&p, atf_fs_access_x);
+ if (atf_is_error(err)) {
+ atf_error_free(err);
+ atf_fs_path_fini(&p);
atf_tc_skip("The required program %s could not be found", prog);
+ }
} else {
const char *path = atf_env_get("PATH");
struct prog_found_pair pf;
@@ -715,9 +764,12 @@
if (atf_is_error(err))
goto out_p;
- if (strcmp(atf_fs_path_cstring(&bp), ".") != 0)
+ if (strcmp(atf_fs_path_cstring(&bp), ".") != 0) {
+ atf_fs_path_fini(&bp);
+ atf_fs_path_fini(&p);
atf_tc_fail("Relative paths are not allowed when searching for "
"a program (%s)", prog);
+ }
pf.prog = prog;
pf.found = false;
@@ -725,9 +777,12 @@
if (atf_is_error(err))
goto out_bp;
- if (!pf.found)
+ if (!pf.found) {
+ atf_fs_path_fini(&bp);
+ atf_fs_path_fini(&p);
atf_tc_skip("The required program %s could not be found in "
"the PATH", prog);
+ }
out_bp:
atf_fs_path_fini(&bp);
@@ -755,8 +810,14 @@
if (atf_is_error(err))
goto out_p;
- if (!atf_is_error(atf_fs_eaccess(&p, atf_fs_access_x)))
+ err = atf_fs_eaccess(&p, atf_fs_access_x);
+ if (!atf_is_error(err))
pf->found = true;
+ else {
+ atf_error_free(err);
+ INV(!pf->found);
+ err = atf_no_error();
+ }
out_p:
atf_fs_path_fini(&p);
@@ -852,22 +913,22 @@
static
void
-cleanup_child(const atf_tc_t *tc, const atf_fs_path_t *workdir)
+cleanup_child(void *v)
{
+ const struct child_data *cd = v;
atf_error_t err;
- atf_disable_exit_checks();
-
- err = prepare_child(tc, workdir);
- if (atf_is_error(err))
+ err = prepare_child(cd);
+ if (atf_is_error(err)) {
+ atf_reset_exit_checks();
exit(EXIT_FAILURE);
- else {
- tc->m_cleanup(tc);
+ } else {
+ atf_reset_exit_checks();
+ cd->tc->m_cleanup(cd->tc);
exit(EXIT_SUCCESS);
}
UNREACHABLE;
- abort();
}
static
@@ -921,6 +982,39 @@
fatal_atf_error("Cannot write test case results", err);
close(fd);
+ atf_fs_path_fini(&tcrfile);
+}
+
+static
+void
+tc_fail(atf_dynstr_t *msg)
+{
+ atf_tcr_t tcr;
+ atf_error_t err;
+
+ PRE(current_tc != NULL);
+
+ err = atf_tcr_init_reason_fmt(&tcr, atf_tcr_failed_state, "%s",
+ atf_dynstr_cstring(msg));
+ if (atf_is_error(err))
+ abort();
+
+ write_tcr(&tcr);
+
+ atf_tcr_fini(&tcr);
+ atf_dynstr_fini(msg);
+
+ exit(EXIT_SUCCESS);
+}
+
+static
+void
+tc_fail_nonfatal(atf_dynstr_t *msg)
+{
+ fprintf(stderr, "%s\n", atf_dynstr_cstring(msg));
+ atf_dynstr_fini(msg);
+
+ current_tc_fail_count++;
}
void
@@ -965,7 +1059,7 @@
va_start(ap, fmt);
fail_internal(file, line, "Check failed", "*** ", fmt, ap,
- atf_tc_fail_nonfatal);
+ tc_fail_nonfatal, atf_tc_fail_nonfatal);
va_end(ap);
}
@@ -974,9 +1068,11 @@
{
va_list ap;
+ atf_reset_exit_checks();
+
va_start(ap, fmt);
fail_internal(file, line, "Requirement failed", "", fmt, ap,
- atf_tc_fail);
+ tc_fail, atf_tc_fail);
va_end(ap);
UNREACHABLE;
@@ -987,7 +1083,8 @@
void
fail_internal(const char *file, int line, const char *reason,
const char *prefix, const char *fmt, va_list ap,
- void (*failfunc)(const char *, ...))
+ void (*failfunc)(atf_dynstr_t *),
+ void (*backupfunc)(const char *, ...))
{
va_list ap2;
atf_error_t err;
@@ -1007,13 +1104,13 @@
}
va_copy(ap2, ap);
- failfunc("%s", atf_dynstr_cstring(&msg));
- atf_dynstr_fini(&msg);
+ failfunc(&msg);
return;
backup:
+ atf_error_free(err);
va_copy(ap2, ap);
- failfunc(fmt, ap2);
+ backupfunc(fmt, ap2);
va_end(ap2);
}
@@ -1042,8 +1139,10 @@
atf_error_t err;
err = check_prog(prog, NULL);
- if (atf_is_error(err))
+ if (atf_is_error(err)) {
+ atf_error_free(err);
atf_tc_fail("atf_tc_require_prog failed"); /* XXX Correct? */
+ }
}
void