bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen#include "lib.h"
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen#include "log-error-buffer.h"
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen#define LOG_ERROR_BUFFER_MAX_LINES 1000
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainenstruct log_error_data {
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen struct log_error_data *next;
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen enum log_type type;
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen time_t timestamp;
30a5cfac4dc13cc89f36b7b54f889fbb149f7e08Timo Sirainen unsigned char prefix_text[FLEXIBLE_ARRAY_MEMBER];
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen};
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainenstruct log_error_buffer {
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen struct log_error_data *head, *tail;
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen unsigned int count;
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen};
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainenstruct log_error_buffer_iter {
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen struct log_error_buffer *buf;
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen struct log_error_data *cur;
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen struct log_error error;
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen};
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainenstruct log_error_buffer *log_error_buffer_init(void)
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen{
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen struct log_error_buffer *buf;
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen buf = i_new(struct log_error_buffer, 1);
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen return buf;
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen}
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainenstatic void log_error_buffer_delete_head(struct log_error_buffer *buf)
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen{
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen struct log_error_data *data;
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen i_assert(buf->head != NULL);
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen buf->count--;
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen data = buf->head;
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen buf->head = data->next;
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen if (buf->tail == data) {
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen /* last one */
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen buf->tail = NULL;
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen }
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen i_free(data);
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen}
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainenvoid log_error_buffer_add(struct log_error_buffer *buf,
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen const struct log_error *error)
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen{
2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74cTimo Sirainen size_t prefix_size = strlen(error->prefix)+1;
2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74cTimo Sirainen size_t text_size = strlen(error->text)+1;
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen struct log_error_data *data;
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen if (buf->count == LOG_ERROR_BUFFER_MAX_LINES)
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen log_error_buffer_delete_head(buf);
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen /* @UNSAFE */
e7d0bea63a08b08c47c4b5c187d2cb7127859657Timo Sirainen data = i_malloc(MALLOC_ADD(sizeof(*data),
e7d0bea63a08b08c47c4b5c187d2cb7127859657Timo Sirainen MALLOC_ADD(prefix_size, text_size)));
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen data->type = error->type;
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen data->timestamp = error->timestamp;
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen memcpy(data->prefix_text, error->prefix, prefix_size);
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen memcpy(data->prefix_text + prefix_size, error->text, text_size);
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen if (buf->tail != NULL)
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen buf->tail->next = data;
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen else
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen buf->head = data;
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen buf->tail = data;
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen buf->count++;
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen}
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainenvoid log_error_buffer_deinit(struct log_error_buffer **_buf)
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen{
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen struct log_error_buffer *buf = *_buf;
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen *_buf = NULL;
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen while (buf->count > 0)
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen log_error_buffer_delete_head(buf);
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen i_free(buf);
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen}
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainenstruct log_error_buffer_iter *
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainenlog_error_buffer_iter_init(struct log_error_buffer *buf)
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen{
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen struct log_error_buffer_iter *iter;
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen iter = i_new(struct log_error_buffer_iter, 1);
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen iter->buf = buf;
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen iter->cur = buf->head;
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen return iter;
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen}
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainenstruct log_error *
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainenlog_error_buffer_iter_next(struct log_error_buffer_iter *iter)
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen{
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen struct log_error_data *data = iter->cur;
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen if (data == NULL)
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen return NULL;
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen iter->cur = iter->cur->next;
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen iter->error.type = data->type;
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen iter->error.timestamp = data->timestamp;
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen iter->error.prefix = (const void *)data->prefix_text;
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen iter->error.text = (const void *)(data->prefix_text +
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen strlen(iter->error.prefix) + 1);
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen return &iter->error;
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen}
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainenvoid log_error_buffer_iter_deinit(struct log_error_buffer_iter **_iter)
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen{
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen struct log_error_buffer_iter *iter = *_iter;
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen *_iter = NULL;
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen i_free(iter);
6a3c23e577be41f7521995c5dae19abb2fb4ffb6Timo Sirainen}