/* See LICENSE file for copyright and license details. */ #include "common.h" #ifndef TEST struct liblog_output * liblog_use_output(struct liblog_context *ctx, const struct liblog_output *output) { void *new; if (!ctx || !output) goto einval; if (output->lowest_verbosity_unlimited && output->highest_verbosity_unlimited) if (output->lowest_verbosity > output->highest_verbosity) goto einval; if (output->sink_type == LIBLOG_STREAM) { if (!output->sink.stream.stream) goto einval; } else if (output->sink_type != LIBLOG_SYSLOG && output->sink_type != LIBLOG_FILE) { /* * We do not want to validate syslog level, * nor do we want to validate file descriptor, * indeed the user may want to output to a negative * file descriptor so that it only visible during * system call tracing */ einval: errno = EINVAL; return NULL; } if (ctx->noutputs > SIZE_MAX / sizeof(*ctx->outputs) - 1) goto enomem; new = realloc(ctx->outputs, (ctx->noutputs + 1) * sizeof(*ctx->outputs)); if (!new) { enomem: errno = ENOMEM; return NULL; } ctx->outputs = new; memcpy(&ctx->outputs[ctx->noutputs], output, sizeof(*output)); if (!ctx->outputs[ctx->noutputs].prefixfmt) ctx->outputs[ctx->noutputs].prefixfmt = DEFAULT_PREFIXFMT; return &ctx->outputs[ctx->noutputs++]; } #else int main(void) { struct liblog_context ctx; struct liblog_output output; struct liblog_output *new_output; ASSERT_ZERO(liblog_init_context(&ctx)); errno = 0; ASSERT_IS_NULL(liblog_use_output(NULL, NULL)); ASSERT_EQ_INT(errno, EINVAL); errno = 0; ASSERT_IS_NULL(liblog_use_output(&ctx, NULL)); ASSERT_EQ_INT(errno, EINVAL); errno = 0; ASSERT_IS_NULL(liblog_use_output(NULL, &output)); ASSERT_EQ_INT(errno, EINVAL); memset(&ctx, 0, sizeof(ctx)); errno = 0; output.lowest_verbosity_unlimited = 1; output.highest_verbosity_unlimited = 1; output.lowest_verbosity = (enum liblog_level)400; output.highest_verbosity = (enum liblog_level)100; ASSERT_IS_NULL(liblog_use_output(&ctx, &output)); ASSERT_EQ_INT(errno, EINVAL); memset(&output, 0, sizeof(output)); errno = 0; output.sink_type = (enum liblog_sink)99; ASSERT_IS_NULL(liblog_use_output(&ctx, &output)); ASSERT_EQ_INT(errno, EINVAL); errno = 0; output.sink_type = (enum liblog_sink)-1; ASSERT_IS_NULL(liblog_use_output(&ctx, &output)); ASSERT_EQ_INT(errno, EINVAL); errno = 0; output.sink_type = LIBLOG_STREAM; output.sink.stream.stream = NULL; ASSERT_IS_NULL(liblog_use_output(&ctx, &output)); ASSERT_EQ_INT(errno, EINVAL); errno = 0; output.sink_type = LIBLOG_FILE; ctx.noutputs = SIZE_MAX / sizeof(*ctx.outputs); ASSERT_IS_NULL(liblog_use_output(&ctx, &output)); ASSERT_EQ_INT(errno, ENOMEM); ctx.noutputs = 0; output.sink_type = LIBLOG_FILE; output.sink.file.fd = 0; output.sink.file.owns_fd = 0; output.prefixfmt = NULL; new_output = liblog_use_output(&ctx, &output); ASSERT_NOT_NULL(new_output); ASSERT_IS_NULL(output.prefixfmt); ASSERT_NOT_NULL(new_output->prefixfmt); ASSERT_EQ_STR(new_output->prefixfmt, DEFAULT_PREFIXFMT); ASSERT_EQ_INT(new_output->sink_type, output.sink_type); ASSERT_EQ_INT(new_output->sink.file.fd, output.sink.file.fd); ASSERT_EQ_INT(new_output->sink.file.owns_fd, output.sink.file.owns_fd); ASSERT_EQ_UINT(ctx.noutputs, 1); ASSERT_NOT_NULL(ctx.outputs); liblog_destroy_context(&ctx); return 0; } #endif