1 1.1 jmmv /* 2 1.1 jmmv * Automated Testing Framework (atf) 3 1.1 jmmv * 4 1.1.1.7 jmmv * Copyright (c) 2008 The NetBSD Foundation, Inc. 5 1.1 jmmv * All rights reserved. 6 1.1 jmmv * 7 1.1 jmmv * Redistribution and use in source and binary forms, with or without 8 1.1 jmmv * modification, are permitted provided that the following conditions 9 1.1 jmmv * are met: 10 1.1 jmmv * 1. Redistributions of source code must retain the above copyright 11 1.1 jmmv * notice, this list of conditions and the following disclaimer. 12 1.1 jmmv * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 jmmv * notice, this list of conditions and the following disclaimer in the 14 1.1 jmmv * documentation and/or other materials provided with the distribution. 15 1.1 jmmv * 16 1.1 jmmv * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND 17 1.1 jmmv * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 18 1.1 jmmv * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19 1.1 jmmv * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 1.1 jmmv * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY 21 1.1 jmmv * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 1.1 jmmv * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 23 1.1 jmmv * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 1.1 jmmv * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 25 1.1 jmmv * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 26 1.1 jmmv * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 27 1.1 jmmv * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 1.1 jmmv */ 29 1.1 jmmv 30 1.1 jmmv #include <sys/wait.h> 31 1.1 jmmv 32 1.1 jmmv #include <errno.h> 33 1.1.1.2 jmmv #include <fcntl.h> 34 1.1 jmmv #include <stdio.h> 35 1.1 jmmv #include <stdlib.h> 36 1.1 jmmv #include <string.h> 37 1.1 jmmv #include <unistd.h> 38 1.1 jmmv 39 1.1.1.2 jmmv #include "atf-c/build.h" 40 1.1 jmmv #include "atf-c/check.h" 41 1.1 jmmv #include "atf-c/config.h" 42 1.1.1.2 jmmv #include "atf-c/defs.h" 43 1.1 jmmv #include "atf-c/error.h" 44 1.1.1.5 jmmv #include "atf-c/utils.h" 45 1.1.1.5 jmmv 46 1.1.1.5 jmmv #include "detail/dynstr.h" 47 1.1.1.5 jmmv #include "detail/fs.h" 48 1.1.1.5 jmmv #include "detail/list.h" 49 1.1.1.5 jmmv #include "detail/process.h" 50 1.1.1.5 jmmv #include "detail/sanity.h" 51 1.1 jmmv 52 1.1 jmmv /* --------------------------------------------------------------------- 53 1.1 jmmv * Auxiliary functions. 54 1.1 jmmv * --------------------------------------------------------------------- */ 55 1.1 jmmv 56 1.1 jmmv static 57 1.1 jmmv atf_error_t 58 1.1.1.2 jmmv create_tmpdir(atf_fs_path_t *dir) 59 1.1 jmmv { 60 1.1 jmmv atf_error_t err; 61 1.1 jmmv 62 1.1.1.2 jmmv err = atf_fs_path_init_fmt(dir, "%s/check.XXXXXX", 63 1.1.1.2 jmmv atf_config_get("atf_workdir")); 64 1.1 jmmv if (atf_is_error(err)) 65 1.1 jmmv goto out; 66 1.1 jmmv 67 1.1.1.2 jmmv err = atf_fs_mkdtemp(dir); 68 1.1.1.2 jmmv if (atf_is_error(err)) { 69 1.1.1.2 jmmv atf_fs_path_fini(dir); 70 1.1.1.2 jmmv goto out; 71 1.1.1.2 jmmv } 72 1.1 jmmv 73 1.1 jmmv INV(!atf_is_error(err)); 74 1.1 jmmv out: 75 1.1 jmmv return err; 76 1.1 jmmv } 77 1.1 jmmv 78 1.1 jmmv static 79 1.1 jmmv void 80 1.1.1.2 jmmv cleanup_tmpdir(const atf_fs_path_t *dir, const atf_fs_path_t *outfile, 81 1.1.1.2 jmmv const atf_fs_path_t *errfile) 82 1.1.1.2 jmmv { 83 1.1.1.2 jmmv { 84 1.1.1.2 jmmv atf_error_t err = atf_fs_unlink(outfile); 85 1.1.1.2 jmmv if (atf_is_error(err)) { 86 1.1.1.2 jmmv INV(atf_error_is(err, "libc") && 87 1.1.1.2 jmmv atf_libc_error_code(err) == ENOENT); 88 1.1.1.2 jmmv atf_error_free(err); 89 1.1.1.2 jmmv } else 90 1.1.1.2 jmmv INV(!atf_is_error(err)); 91 1.1.1.2 jmmv } 92 1.1.1.2 jmmv 93 1.1.1.2 jmmv { 94 1.1.1.2 jmmv atf_error_t err = atf_fs_unlink(errfile); 95 1.1.1.2 jmmv if (atf_is_error(err)) { 96 1.1.1.2 jmmv INV(atf_error_is(err, "libc") && 97 1.1.1.2 jmmv atf_libc_error_code(err) == ENOENT); 98 1.1.1.2 jmmv atf_error_free(err); 99 1.1.1.2 jmmv } else 100 1.1.1.2 jmmv INV(!atf_is_error(err)); 101 1.1.1.2 jmmv } 102 1.1.1.2 jmmv 103 1.1.1.2 jmmv { 104 1.1.1.2 jmmv atf_error_t err = atf_fs_rmdir(dir); 105 1.1.1.2 jmmv INV(!atf_is_error(err)); 106 1.1.1.2 jmmv } 107 1.1.1.2 jmmv } 108 1.1.1.2 jmmv 109 1.1.1.2 jmmv static 110 1.1.1.2 jmmv int 111 1.1.1.2 jmmv const_execvp(const char *file, const char *const *argv) 112 1.1.1.2 jmmv { 113 1.1.1.2 jmmv #define UNCONST(a) ((void *)(unsigned long)(const void *)(a)) 114 1.1.1.2 jmmv return execvp(file, UNCONST(argv)); 115 1.1.1.2 jmmv #undef UNCONST 116 1.1.1.2 jmmv } 117 1.1.1.2 jmmv 118 1.1.1.2 jmmv static 119 1.1.1.2 jmmv atf_error_t 120 1.1.1.2 jmmv init_sb(const atf_fs_path_t *path, atf_process_stream_t *sb) 121 1.1.1.2 jmmv { 122 1.1.1.2 jmmv atf_error_t err; 123 1.1.1.2 jmmv 124 1.1.1.2 jmmv if (path == NULL) 125 1.1.1.2 jmmv err = atf_process_stream_init_inherit(sb); 126 1.1.1.2 jmmv else 127 1.1.1.2 jmmv err = atf_process_stream_init_redirect_path(sb, path); 128 1.1.1.2 jmmv 129 1.1.1.2 jmmv return err; 130 1.1.1.2 jmmv } 131 1.1.1.2 jmmv 132 1.1.1.2 jmmv static 133 1.1.1.2 jmmv atf_error_t 134 1.1.1.2 jmmv init_sbs(const atf_fs_path_t *outfile, atf_process_stream_t *outsb, 135 1.1.1.2 jmmv const atf_fs_path_t *errfile, atf_process_stream_t *errsb) 136 1.1 jmmv { 137 1.1.1.2 jmmv atf_error_t err; 138 1.1.1.2 jmmv 139 1.1.1.2 jmmv err = init_sb(outfile, outsb); 140 1.1.1.2 jmmv if (atf_is_error(err)) 141 1.1.1.2 jmmv goto out; 142 1.1 jmmv 143 1.1.1.2 jmmv err = init_sb(errfile, errsb); 144 1.1.1.2 jmmv if (atf_is_error(err)) { 145 1.1.1.2 jmmv atf_process_stream_fini(outsb); 146 1.1.1.2 jmmv goto out; 147 1.1.1.2 jmmv } 148 1.1.1.2 jmmv 149 1.1.1.2 jmmv out: 150 1.1.1.2 jmmv return err; 151 1.1.1.2 jmmv } 152 1.1.1.2 jmmv 153 1.1.1.2 jmmv struct exec_data { 154 1.1.1.2 jmmv const char *const *m_argv; 155 1.1.1.2 jmmv }; 156 1.1.1.2 jmmv 157 1.1.1.2 jmmv static void exec_child(void *) ATF_DEFS_ATTRIBUTE_NORETURN; 158 1.1.1.2 jmmv 159 1.1.1.2 jmmv static 160 1.1.1.2 jmmv void 161 1.1.1.2 jmmv exec_child(void *v) 162 1.1.1.2 jmmv { 163 1.1.1.2 jmmv struct exec_data *ea = v; 164 1.1 jmmv 165 1.1.1.2 jmmv const_execvp(ea->m_argv[0], ea->m_argv); 166 1.1.1.2 jmmv fprintf(stderr, "execvp(%s) failed: %s\n", ea->m_argv[0], strerror(errno)); 167 1.1.1.2 jmmv exit(127); 168 1.1 jmmv } 169 1.1 jmmv 170 1.1 jmmv static 171 1.1 jmmv atf_error_t 172 1.1.1.2 jmmv fork_and_wait(const char *const *argv, const atf_fs_path_t *outfile, 173 1.1.1.2 jmmv const atf_fs_path_t *errfile, atf_process_status_t *status) 174 1.1 jmmv { 175 1.1 jmmv atf_error_t err; 176 1.1.1.2 jmmv atf_process_child_t child; 177 1.1.1.2 jmmv atf_process_stream_t outsb, errsb; 178 1.1.1.2 jmmv struct exec_data ea = { argv }; 179 1.1 jmmv 180 1.1.1.2 jmmv err = init_sbs(outfile, &outsb, errfile, &errsb); 181 1.1 jmmv if (atf_is_error(err)) 182 1.1 jmmv goto out; 183 1.1 jmmv 184 1.1.1.2 jmmv err = atf_process_fork(&child, exec_child, &outsb, &errsb, &ea); 185 1.1.1.2 jmmv if (atf_is_error(err)) 186 1.1.1.2 jmmv goto out_sbs; 187 1.1.1.2 jmmv 188 1.1.1.2 jmmv err = atf_process_child_wait(&child, status); 189 1.1.1.2 jmmv 190 1.1.1.2 jmmv out_sbs: 191 1.1.1.2 jmmv atf_process_stream_fini(&errsb); 192 1.1.1.2 jmmv atf_process_stream_fini(&outsb); 193 1.1.1.2 jmmv out: 194 1.1.1.2 jmmv return err; 195 1.1.1.2 jmmv } 196 1.1.1.2 jmmv 197 1.1.1.2 jmmv static 198 1.1.1.2 jmmv void 199 1.1.1.2 jmmv update_success_from_status(const char *progname, 200 1.1.1.2 jmmv const atf_process_status_t *status, bool *success) 201 1.1.1.2 jmmv { 202 1.1.1.2 jmmv bool s = atf_process_status_exited(status) && 203 1.1.1.2 jmmv atf_process_status_exitstatus(status) == EXIT_SUCCESS; 204 1.1.1.2 jmmv 205 1.1.1.2 jmmv if (atf_process_status_exited(status)) { 206 1.1.1.2 jmmv if (atf_process_status_exitstatus(status) == EXIT_SUCCESS) 207 1.1.1.2 jmmv INV(s); 208 1.1.1.2 jmmv else { 209 1.1.1.2 jmmv INV(!s); 210 1.1.1.2 jmmv fprintf(stderr, "%s failed with exit code %d\n", progname, 211 1.1.1.2 jmmv atf_process_status_exitstatus(status)); 212 1.1.1.2 jmmv } 213 1.1.1.2 jmmv } else if (atf_process_status_signaled(status)) { 214 1.1.1.2 jmmv INV(!s); 215 1.1.1.2 jmmv fprintf(stderr, "%s failed due to signal %d%s\n", progname, 216 1.1.1.2 jmmv atf_process_status_termsig(status), 217 1.1.1.2 jmmv atf_process_status_coredump(status) ? " (core dumped)" : ""); 218 1.1 jmmv } else { 219 1.1.1.2 jmmv INV(!s); 220 1.1.1.2 jmmv fprintf(stderr, "%s failed due to unknown reason\n", progname); 221 1.1.1.2 jmmv } 222 1.1.1.2 jmmv 223 1.1.1.2 jmmv *success = s; 224 1.1.1.2 jmmv } 225 1.1.1.2 jmmv 226 1.1.1.2 jmmv static 227 1.1.1.2 jmmv atf_error_t 228 1.1.1.2 jmmv array_to_list(const char *const *a, atf_list_t *l) 229 1.1.1.2 jmmv { 230 1.1.1.2 jmmv atf_error_t err; 231 1.1.1.2 jmmv 232 1.1.1.2 jmmv err = atf_list_init(l); 233 1.1.1.2 jmmv if (atf_is_error(err)) 234 1.1.1.2 jmmv goto out; 235 1.1.1.2 jmmv 236 1.1.1.2 jmmv while (*a != NULL) { 237 1.1.1.2 jmmv char *item = strdup(*a); 238 1.1.1.2 jmmv if (item == NULL) { 239 1.1.1.2 jmmv err = atf_no_memory_error(); 240 1.1.1.2 jmmv goto out; 241 1.1 jmmv } 242 1.1.1.2 jmmv 243 1.1.1.2 jmmv err = atf_list_append(l, item, true); 244 1.1.1.2 jmmv if (atf_is_error(err)) 245 1.1.1.2 jmmv goto out; 246 1.1.1.2 jmmv 247 1.1.1.2 jmmv a++; 248 1.1 jmmv } 249 1.1 jmmv 250 1.1 jmmv out: 251 1.1 jmmv return err; 252 1.1 jmmv } 253 1.1 jmmv 254 1.1.1.5 jmmv static void 255 1.1.1.5 jmmv print_array(const char *const *array, const char *pfx) 256 1.1.1.2 jmmv { 257 1.1.1.5 jmmv const char *const *ptr; 258 1.1.1.2 jmmv 259 1.1.1.2 jmmv printf("%s", pfx); 260 1.1.1.5 jmmv for (ptr = array; *ptr != NULL; ptr++) 261 1.1.1.5 jmmv printf(" %s", *ptr); 262 1.1.1.2 jmmv printf("\n"); 263 1.1.1.2 jmmv } 264 1.1.1.2 jmmv 265 1.1.1.2 jmmv static 266 1.1.1.2 jmmv atf_error_t 267 1.1.1.5 jmmv check_build_run(const char *const *argv, bool *success) 268 1.1.1.2 jmmv { 269 1.1.1.2 jmmv atf_error_t err; 270 1.1.1.2 jmmv atf_process_status_t status; 271 1.1.1.2 jmmv 272 1.1.1.5 jmmv print_array(argv, ">"); 273 1.1.1.2 jmmv 274 1.1.1.5 jmmv err = fork_and_wait(argv, NULL, NULL, &status); 275 1.1.1.2 jmmv if (atf_is_error(err)) 276 1.1.1.2 jmmv goto out; 277 1.1.1.2 jmmv 278 1.1.1.5 jmmv update_success_from_status(argv[0], &status, success); 279 1.1.1.2 jmmv atf_process_status_fini(&status); 280 1.1.1.2 jmmv 281 1.1.1.2 jmmv INV(!atf_is_error(err)); 282 1.1.1.2 jmmv out: 283 1.1.1.2 jmmv return err; 284 1.1.1.2 jmmv } 285 1.1.1.2 jmmv 286 1.1 jmmv /* --------------------------------------------------------------------- 287 1.1 jmmv * The "atf_check_result" type. 288 1.1 jmmv * --------------------------------------------------------------------- */ 289 1.1 jmmv 290 1.1.1.5 jmmv struct atf_check_result_impl { 291 1.1.1.5 jmmv atf_list_t m_argv; 292 1.1.1.5 jmmv atf_fs_path_t m_dir; 293 1.1.1.5 jmmv atf_fs_path_t m_stdout; 294 1.1.1.5 jmmv atf_fs_path_t m_stderr; 295 1.1.1.5 jmmv atf_process_status_t m_status; 296 1.1.1.5 jmmv }; 297 1.1.1.5 jmmv 298 1.1.1.2 jmmv static 299 1.1 jmmv atf_error_t 300 1.1.1.2 jmmv atf_check_result_init(atf_check_result_t *r, const char *const *argv, 301 1.1.1.2 jmmv const atf_fs_path_t *dir) 302 1.1 jmmv { 303 1.1 jmmv atf_error_t err; 304 1.1 jmmv 305 1.1.1.5 jmmv r->pimpl = malloc(sizeof(struct atf_check_result_impl)); 306 1.1.1.5 jmmv if (r->pimpl == NULL) 307 1.1.1.5 jmmv return atf_no_memory_error(); 308 1.1.1.5 jmmv 309 1.1.1.5 jmmv err = array_to_list(argv, &r->pimpl->m_argv); 310 1.1 jmmv if (atf_is_error(err)) 311 1.1 jmmv goto out; 312 1.1 jmmv 313 1.1.1.5 jmmv err = atf_fs_path_copy(&r->pimpl->m_dir, dir); 314 1.1.1.2 jmmv if (atf_is_error(err)) 315 1.1.1.2 jmmv goto err_argv; 316 1.1.1.2 jmmv 317 1.1.1.5 jmmv err = atf_fs_path_init_fmt(&r->pimpl->m_stdout, "%s/stdout", 318 1.1.1.2 jmmv atf_fs_path_cstring(dir)); 319 1.1.1.2 jmmv if (atf_is_error(err)) 320 1.1.1.2 jmmv goto err_dir; 321 1.1.1.2 jmmv 322 1.1.1.5 jmmv err = atf_fs_path_init_fmt(&r->pimpl->m_stderr, "%s/stderr", 323 1.1.1.2 jmmv atf_fs_path_cstring(dir)); 324 1.1 jmmv if (atf_is_error(err)) 325 1.1 jmmv goto err_stdout; 326 1.1 jmmv 327 1.1 jmmv INV(!atf_is_error(err)); 328 1.1 jmmv goto out; 329 1.1 jmmv 330 1.1 jmmv err_stdout: 331 1.1.1.5 jmmv atf_fs_path_fini(&r->pimpl->m_stdout); 332 1.1.1.2 jmmv err_dir: 333 1.1.1.5 jmmv atf_fs_path_fini(&r->pimpl->m_dir); 334 1.1.1.2 jmmv err_argv: 335 1.1.1.5 jmmv atf_list_fini(&r->pimpl->m_argv); 336 1.1 jmmv out: 337 1.1 jmmv return err; 338 1.1 jmmv } 339 1.1 jmmv 340 1.1 jmmv void 341 1.1 jmmv atf_check_result_fini(atf_check_result_t *r) 342 1.1 jmmv { 343 1.1.1.5 jmmv atf_process_status_fini(&r->pimpl->m_status); 344 1.1 jmmv 345 1.1.1.5 jmmv cleanup_tmpdir(&r->pimpl->m_dir, &r->pimpl->m_stdout, 346 1.1.1.5 jmmv &r->pimpl->m_stderr); 347 1.1.1.5 jmmv atf_fs_path_fini(&r->pimpl->m_stdout); 348 1.1.1.5 jmmv atf_fs_path_fini(&r->pimpl->m_stderr); 349 1.1.1.5 jmmv atf_fs_path_fini(&r->pimpl->m_dir); 350 1.1.1.2 jmmv 351 1.1.1.5 jmmv atf_list_fini(&r->pimpl->m_argv); 352 1.1 jmmv 353 1.1.1.5 jmmv free(r->pimpl); 354 1.1.1.2 jmmv } 355 1.1.1.2 jmmv 356 1.1.1.5 jmmv const char * 357 1.1 jmmv atf_check_result_stdout(const atf_check_result_t *r) 358 1.1 jmmv { 359 1.1.1.5 jmmv return atf_fs_path_cstring(&r->pimpl->m_stdout); 360 1.1 jmmv } 361 1.1 jmmv 362 1.1.1.5 jmmv const char * 363 1.1 jmmv atf_check_result_stderr(const atf_check_result_t *r) 364 1.1 jmmv { 365 1.1.1.5 jmmv return atf_fs_path_cstring(&r->pimpl->m_stderr); 366 1.1 jmmv } 367 1.1 jmmv 368 1.1 jmmv bool 369 1.1 jmmv atf_check_result_exited(const atf_check_result_t *r) 370 1.1 jmmv { 371 1.1.1.5 jmmv return atf_process_status_exited(&r->pimpl->m_status); 372 1.1 jmmv } 373 1.1 jmmv 374 1.1 jmmv int 375 1.1 jmmv atf_check_result_exitcode(const atf_check_result_t *r) 376 1.1 jmmv { 377 1.1.1.5 jmmv return atf_process_status_exitstatus(&r->pimpl->m_status); 378 1.1 jmmv } 379 1.1 jmmv 380 1.1.1.4 jmmv bool 381 1.1.1.4 jmmv atf_check_result_signaled(const atf_check_result_t *r) 382 1.1.1.4 jmmv { 383 1.1.1.5 jmmv return atf_process_status_signaled(&r->pimpl->m_status); 384 1.1.1.4 jmmv } 385 1.1.1.4 jmmv 386 1.1.1.4 jmmv int 387 1.1.1.4 jmmv atf_check_result_termsig(const atf_check_result_t *r) 388 1.1.1.4 jmmv { 389 1.1.1.5 jmmv return atf_process_status_termsig(&r->pimpl->m_status); 390 1.1.1.4 jmmv } 391 1.1.1.4 jmmv 392 1.1 jmmv /* --------------------------------------------------------------------- 393 1.1 jmmv * Free functions. 394 1.1 jmmv * --------------------------------------------------------------------- */ 395 1.1 jmmv 396 1.1.1.2 jmmv /* XXX: This function shouldn't be in this module. It messes with stdout 397 1.1.1.2 jmmv * and stderr, and it provides a very high-end interface. This belongs, 398 1.1.1.2 jmmv * probably, somewhere related to test cases (such as in the tc module). */ 399 1.1.1.2 jmmv atf_error_t 400 1.1.1.2 jmmv atf_check_build_c_o(const char *sfile, 401 1.1.1.2 jmmv const char *ofile, 402 1.1.1.2 jmmv const char *const optargs[], 403 1.1.1.2 jmmv bool *success) 404 1.1.1.2 jmmv { 405 1.1.1.2 jmmv atf_error_t err; 406 1.1.1.5 jmmv char **argv; 407 1.1.1.2 jmmv 408 1.1.1.2 jmmv err = atf_build_c_o(sfile, ofile, optargs, &argv); 409 1.1.1.2 jmmv if (atf_is_error(err)) 410 1.1.1.2 jmmv goto out; 411 1.1.1.2 jmmv 412 1.1.1.5 jmmv err = check_build_run((const char *const *)argv, success); 413 1.1.1.2 jmmv 414 1.1.1.5 jmmv atf_utils_free_charpp(argv); 415 1.1.1.2 jmmv out: 416 1.1.1.2 jmmv return err; 417 1.1.1.2 jmmv } 418 1.1.1.2 jmmv 419 1.1 jmmv atf_error_t 420 1.1.1.2 jmmv atf_check_build_cpp(const char *sfile, 421 1.1.1.2 jmmv const char *ofile, 422 1.1.1.2 jmmv const char *const optargs[], 423 1.1.1.2 jmmv bool *success) 424 1.1 jmmv { 425 1.1 jmmv atf_error_t err; 426 1.1.1.5 jmmv char **argv; 427 1.1 jmmv 428 1.1.1.2 jmmv err = atf_build_cpp(sfile, ofile, optargs, &argv); 429 1.1 jmmv if (atf_is_error(err)) 430 1.1 jmmv goto out; 431 1.1 jmmv 432 1.1.1.5 jmmv err = check_build_run((const char *const *)argv, success); 433 1.1.1.2 jmmv 434 1.1.1.5 jmmv atf_utils_free_charpp(argv); 435 1.1.1.2 jmmv out: 436 1.1.1.2 jmmv return err; 437 1.1.1.2 jmmv } 438 1.1.1.2 jmmv 439 1.1.1.2 jmmv atf_error_t 440 1.1.1.2 jmmv atf_check_build_cxx_o(const char *sfile, 441 1.1.1.2 jmmv const char *ofile, 442 1.1.1.2 jmmv const char *const optargs[], 443 1.1.1.2 jmmv bool *success) 444 1.1.1.2 jmmv { 445 1.1.1.2 jmmv atf_error_t err; 446 1.1.1.5 jmmv char **argv; 447 1.1.1.2 jmmv 448 1.1.1.2 jmmv err = atf_build_cxx_o(sfile, ofile, optargs, &argv); 449 1.1 jmmv if (atf_is_error(err)) 450 1.1.1.2 jmmv goto out; 451 1.1.1.2 jmmv 452 1.1.1.5 jmmv err = check_build_run((const char *const *)argv, success); 453 1.1 jmmv 454 1.1.1.5 jmmv atf_utils_free_charpp(argv); 455 1.1.1.2 jmmv out: 456 1.1.1.2 jmmv return err; 457 1.1.1.2 jmmv } 458 1.1.1.2 jmmv 459 1.1.1.2 jmmv atf_error_t 460 1.1.1.2 jmmv atf_check_exec_array(const char *const *argv, atf_check_result_t *r) 461 1.1.1.2 jmmv { 462 1.1.1.2 jmmv atf_error_t err; 463 1.1.1.2 jmmv atf_fs_path_t dir; 464 1.1.1.2 jmmv 465 1.1.1.2 jmmv err = create_tmpdir(&dir); 466 1.1.1.2 jmmv if (atf_is_error(err)) 467 1.1.1.2 jmmv goto out; 468 1.1.1.2 jmmv 469 1.1.1.2 jmmv err = atf_check_result_init(r, argv, &dir); 470 1.1.1.6 jmmv if (atf_is_error(err)) { 471 1.1.1.6 jmmv atf_error_t err2 = atf_fs_rmdir(&dir); 472 1.1.1.6 jmmv INV(!atf_is_error(err2)); 473 1.1.1.6 jmmv goto out; 474 1.1.1.6 jmmv } 475 1.1.1.2 jmmv 476 1.1.1.5 jmmv err = fork_and_wait(argv, &r->pimpl->m_stdout, &r->pimpl->m_stderr, 477 1.1.1.5 jmmv &r->pimpl->m_status); 478 1.1.1.6 jmmv if (atf_is_error(err)) { 479 1.1.1.6 jmmv atf_check_result_fini(r); 480 1.1.1.6 jmmv goto out; 481 1.1.1.6 jmmv } 482 1.1 jmmv 483 1.1 jmmv INV(!atf_is_error(err)); 484 1.1 jmmv 485 1.1.1.2 jmmv atf_fs_path_fini(&dir); 486 1.1.1.2 jmmv out: 487 1.1.1.2 jmmv return err; 488 1.1.1.2 jmmv } 489