static int exec_common_fork(int *result) { int pid, rv, status, err; /* * This does not happen in a test context (from the point of * view of report.c) so we have to fiddle a bit. */ pid = fork(); if (pid<0) { err = errno; report_begin("forking for test"); report_result(pid, err); report_aborted(result); return -1; } if (pid==0) { /* child */ return 0; } rv = waitpid(pid, &status, 0); if (rv == -1) { err = errno; report_begin("waiting for test subprocess"); report_result(rv, err); report_failure(result); return -1; } if (WIFEXITED(status) && WEXITSTATUS(status) == MAGIC_STATUS) { *result = SUCCESS; return 1; } /* Oops... */ report_begin("exit code of subprocess; should be %d", MAGIC_STATUS); if (WIFSIGNALED(status)) { report_warnx("signal %d", WTERMSIG(status)); } else { report_warnx("exit %d", WEXITSTATUS(status)); } report_failure(result); return -1; }
/* * Note: unlike everything else this calls skipped/aborted, because * otherwise it has to communicate to the caller which to call and * that's a pain. */ int create_testdir(void) { int rv; rv = mkdir(TESTDIR, 0775); if (rv<0) { if (errno == ENOSYS) { report_saw_enosys(); report_warnx("mkdir unimplemented; cannot run test"); report_skipped(); } else { report_warn("mkdir %s failed", TESTDIR); report_aborted(); } return -1; } return 0; }
static int lseek_file_stdin(void) { int fd, fd2, rv, status; const char slogan[] = "There ain't no such thing as a free lunch"; size_t len = strlen(slogan); pid_t pid; int result = 0; report_begin("lseek stdin when open on file"); /* fork so we don't affect our own stdin */ pid = fork(); if (pid<0) { report_warn("fork failed"); report_aborted(&result); return result; } else if (pid!=0) { /* parent */ rv = waitpid(pid, &status, 0); if (rv<0) { report_warn("waitpid failed"); report_aborted(&result); } if (WIFSIGNALED(status)) { report_warnx("subprocess exited with signal %d", WTERMSIG(status)); report_aborted(&result); } else if (WIFEXITED(status) && WEXITSTATUS(status) != 0) { report_warnx("subprocess exited with code %d", WEXITSTATUS(status)); report_aborted(&result); } return result; } /* child */ fd = open_testfile(NULL); if (fd<0) { _exit(0); } /* * Move file to stdin. * Use stdin (rather than stdout or stderr) to maximize the * chances of detecting any special-case handling of fds 0-2. * (Writing to stdin is fine as long as it's open for write, * and it will be.) */ fd2 = dup2(fd, STDIN_FILENO); if (fd2<0) { report_warn("dup2 to stdin failed"); close(fd); remove(TESTFILE); _exit(1); } if (fd2 != STDIN_FILENO) { report_warn("dup2 returned wrong file handle"); close(fd); remove(TESTFILE); _exit(1); } close(fd); rv = write(STDIN_FILENO, slogan, len); if (rv<0) { report_warn("write to %s (via stdin) failed", TESTFILE); remove(TESTFILE); _exit(1); } if ((unsigned)rv != len) { report_warnx("write to %s (via stdin) got short count", TESTFILE); remove(TESTFILE); _exit(1); } /* blah */ report_skipped(&result); rv = lseek(STDIN_FILENO, 0, SEEK_SET); report_begin("try 1: SEEK_SET"); result = report_check(rv, errno, 0); rv = lseek(STDIN_FILENO, 0, SEEK_END); report_begin("try 2: SEEK_END"); result = report_check(rv, errno, 0); remove(TESTFILE); _exit(0); }
static int lseek_loc_pasteof(void) { const char *message = "blahblah"; int fd; off_t pos; int result; report_begin("seek past/to EOF"); fd = open_testfile(message); if (fd<0) { report_aborted(&result); return result; } pos = lseek(fd, 5340, SEEK_SET); if (pos == -1) { report_warn("lseek past EOF failed"); report_failure(&result); goto out; } if (pos != 5340) { report_warnx("lseek to 5340 got offset %lld", (long long) pos); report_failure(&result); goto out; } pos = lseek(fd, -50, SEEK_CUR); if (pos == -1) { report_warn("small seek beyond EOF failed"); report_failure(&result); goto out; } if (pos != 5290) { report_warnx("SEEK_CUR to 5290 got offset %lld", (long long) pos); report_failure(&result); goto out; } pos = lseek(fd, 0, SEEK_END); if (pos == -1) { report_warn("seek to EOF failed"); report_failure(&result); goto out; } if (pos != (off_t) strlen(message)) { report_warnx("seek to EOF got %lld (should be %zu)", (long long) pos, strlen(message)); report_failure(&result); goto out; } report_passed(&result); out: close(fd); remove(TESTFILE); return result; }
static int wait_siblings(void) { pid_t pids[2]; int rv, fd, semfd, x; int bad = 0; char semname[32]; int result; /* This test may also blow up if FS synchronization is substandard */ report_begin("siblings wait for each other"); report_hassubs(); snprintf(semname, sizeof(semname), "sem:badcall.%d", (int)getpid()); semfd = open(semname, O_WRONLY|O_CREAT|O_TRUNC, 0664); if (semfd < 0) { report_warn("can't make semaphore"); report_aborted(&result); return result; } fd = open_testfile(NULL); if (fd<0) { report_aborted(&result); close(semfd); remove(semname); return result; } pids[0] = fork(); if (pids[0]<0) { report_warn("can't fork"); report_aborted(&result); close(fd); close(semfd); remove(semname); return result; } if (pids[0]==0) { close(fd); close(semfd); wait_siblings_child(semname); _exit(0); } pids[1] = fork(); if (pids[1]<0) { report_warn("can't fork"); report_aborted(&result); /* abandon the other child process :( */ close(fd); close(semfd); remove(semname); return result; } if (pids[1]==0) { close(fd); close(semfd); wait_siblings_child(semname); _exit(0); } rv = write(fd, pids, sizeof(pids)); if (rv < 0) { report_warn("write error on %s", TESTFILE); report_aborted(&result); /* abandon child procs :( */ close(fd); close(semfd); remove(semname); return result; } if (rv != (int)sizeof(pids)) { report_warnx("write error on %s: short count", TESTFILE); report_aborted(&result); /* abandon child procs :( */ close(fd); close(semfd); remove(semname); return result; } /* gate the child procs */ rv = write(semfd, " ", 2); if (rv < 0) { report_warn("%s: write", semname); bad = 1; } report_beginsub("overall"); rv = waitpid(pids[0], &x, 0); if (rv<0) { report_warn("error waiting for child 0 (pid %d)", pids[0]); bad = 1; } rv = waitpid(pids[1], &x, 0); if (rv<0) { report_warn("error waiting for child 1 (pid %d)", pids[1]); bad = 1; } if (bad) { /* XXX: aborted, or failure, or what? */ report_aborted(&result); } else { report_passed(&result); } close(fd); close(semfd); remove(semname); remove(TESTFILE); return result; }