#include <stdio.h>
#include <stdarg.h>
#include <ctype.h>
-#include <err.h>
#include <unistd.h>
#include <poll.h>
#include <errno.h>
#include <sys/resource.h>
#include <signal.h>
#include <assert.h>
+#include <ccan/err/err.h>
#include <ccan/time/time.h>
#include <ccan/read_write_all/read_write_all.h>
#include <ccan/failtest/failtest_proto.h>
/* If we're a child, this is the first call we did ourselves. */
static struct failtest_call *our_history_start = NULL;
/* For printing runtime with --trace. */
-static struct timeval start;
+static struct timeabs start;
/* Set when failtest_hook returns FAIL_PROBE */
static bool probing = false;
/* Table to track duplicates. */
call->line = line;
call->cleanup = NULL;
call->backtrace = get_backtrace(&call->backtrace_num);
- memcpy(&call->u, elem, elem_size);
+ if (elem_size != 0)
+ memcpy(&call->u, elem, elem_size);
tlist_add_tail(&history, call, list);
return call;
}
/* But their program shouldn't leak, even on failure. */
if (!forced_cleanup && i->can_leak) {
+ char *p = failpath_string();
printf("Leak at %s:%u: --failpath=%s\n",
- i->file, i->line, failpath_string());
+ i->file, i->line, p);
+ free(p);
status = 1;
}
}
if (child == 0) {
traceindent++;
if (tracef) {
- struct timeval diff;
+ struct timerel diff;
const char *p;
char *failpath;
struct failtest_call *c;
c = tlist_tail(&history, list);
- diff = time_sub(time_now(), start);
+ diff = time_between(time_now(), start);
failpath = failpath_string();
p = strrchr(c->file, '/');
if (p)
p = c->file;
trace("%u->%u (%u.%02u): %s (%s:%u)\n",
getppid(), getpid(),
- (int)diff.tv_sec, (int)diff.tv_usec / 10000,
+ (int)diff.ts.tv_sec, (int)diff.ts.tv_nsec / 10000000,
failpath, p, c->line);
free(failpath);
}
call.closed = false;
if (call.flags & O_CREAT) {
call.mode = va_arg(ap, int);
- va_end(ap);
}
+ va_end(ap);
p = add_history(FAILTEST_OPEN, true, file, line, &call);
/* Avoid memory leak! */
if (p == &unrecorded_call)
return p->u.mmap.ret;
}
+/* Since OpenBSD can't handle adding args, we use this file and line.
+ * This will make all mmaps look the same, reducing coverage. */
+void *failtest_mmap_noloc(void *addr, size_t length, int prot, int flags,
+ int fd, off_t offset)
+{
+ return failtest_mmap(addr, length, prot, flags, fd, offset,
+ __FILE__, __LINE__);
+}
+
static void cleanup_pipe(struct pipe_call *call, bool restore)
{
trace("cleaning up pipe fd=%i%s,%i%s\n",
int failtest_pipe(int pipefd[2], const char *file, unsigned line)
{
struct failtest_call *p;
- struct pipe_call call;
- p = add_history(FAILTEST_PIPE, true, file, line, &call);
+ p = add_history_(FAILTEST_PIPE, true, file, line, NULL, 0);
if (should_fail(p)) {
p->u.open.ret = -1;
/* FIXME: Play with error codes? */
set_cleanup(p, cleanup_read, struct read_call);
}
}
- trace("%sread %s:%u fd %i %zu@%llu -> %i\n",
+ trace("%sread %s:%u fd %i %zu@%llu -> %zi\n",
is_pread ? "p" : "", file, line, fd, count, (long long)off,
p->u.read.ret);
errno = p->error;
else
p->u.write.ret = write(fd, buf, count);
}
- trace("%swrite %s:%i %zu@%llu on fd %i -> %i\n",
+ trace("%swrite %s:%i %zu@%llu on fd %i -> %zi\n",
p->u.write.is_pwrite ? "p" : "",
file, line, count, (long long)off, fd, p->u.write.ret);
errno = p->error;