journal-remote-parse.c revision 09d801a82a46df518dd752e40bf13ac404daa2ce
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering/***
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering This file is part of systemd.
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering Copyright 2014 Zbigniew Jędrzejewski-Szmek
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering systemd is free software; you can redistribute it and/or modify it
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering under the terms of the GNU Lesser General Public License as published by
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering (at your option) any later version.
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering systemd is distributed in the hope that it will be useful, but
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering Lesser General Public License for more details.
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering You should have received a copy of the GNU Lesser General Public License
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering***/
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering#include "journal-remote-parse.h"
4871690d9e32608bbd9b18505b5326c2079c9690Allin Cottrell#include "journald-native.h"
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering#define LINE_CHUNK 8*1024u
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
1dfa7e79a60de680086b1d93fcc3629b463f58bdLennart Poetteringvoid source_free(RemoteSource *source) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (!source)
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering return;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering if (source->fd >= 0 && !source->passive_fd) {
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering log_debug("Closing fd:%d (%s)", source->fd, source->name);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering safe_close(source->fd);
c4aa09b06f835c91cea9e021df4c3605cff2318dLennart Poettering }
c4aa09b06f835c91cea9e021df4c3605cff2318dLennart Poettering
c4aa09b06f835c91cea9e021df4c3605cff2318dLennart Poettering free(source->name);
c4aa09b06f835c91cea9e021df4c3605cff2318dLennart Poettering free(source->buf);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering iovw_free_contents(&source->iovw);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering log_debug("Writer ref count %i", source->writer->n_ref);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering writer_unref(source->writer);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering sd_event_source_unref(source->event);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering free(source);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering}
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering/**
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering * Initialize zero-filled source with given values. On success, takes
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering * ownerhship of fd and writer, otherwise does not touch them.
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering */
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart PoetteringRemoteSource* source_new(int fd, bool passive_fd, char *name, Writer *writer) {
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering RemoteSource *source;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering log_debug("Creating source for %sfd:%d (%s)",
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering passive_fd ? "passive " : "", fd, name);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering assert(fd >= 0);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering source = new0(RemoteSource, 1);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering if (!source)
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering return NULL;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering source->fd = fd;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering source->passive_fd = passive_fd;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering source->name = name;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering source->writer = writer;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering return source;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering}
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poetteringstatic char* realloc_buffer(RemoteSource *source, size_t size) {
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek char *b, *old = source->buf;
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek b = GREEDY_REALLOC(source->buf, source->size, size);
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek if (!b)
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering return NULL;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering iovw_rebase(&source->iovw, old, source->buf);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering return b;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering}
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poetteringstatic int get_line(RemoteSource *source, char **line, size_t *size) {
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek ssize_t n;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering char *c = NULL;
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering assert(source);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering assert(source->state == STATE_LINE);
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek assert(source->offset <= source->filled);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering assert(source->filled <= source->size);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering assert(source->buf == NULL || source->size > 0);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering assert(source->fd >= 0);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering while (true) {
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering if (source->buf) {
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering size_t start = MAX(source->scanned, source->offset);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering c = memchr(source->buf + start, '\n',
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering source->filled - start);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering if (c != NULL)
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering break;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering }
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering source->scanned = source->filled;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering if (source->scanned >= DATA_SIZE_MAX) {
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering log_error("Entry is bigger than %u bytes.", DATA_SIZE_MAX);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering return -E2BIG;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering }
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek if (source->passive_fd)
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering /* we have to wait for some data to come to us */
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering return -EWOULDBLOCK;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering if (source->size - source->filled < LINE_CHUNK &&
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering !realloc_buffer(source,
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering MIN(source->filled + LINE_CHUNK, ENTRY_SIZE_MAX)))
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering return log_oom();
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering assert(source->size - source->filled >= LINE_CHUNK ||
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering source->size == ENTRY_SIZE_MAX);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering n = read(source->fd, source->buf + source->filled,
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering source->size - source->filled);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering if (n < 0) {
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering if (errno != EAGAIN && errno != EWOULDBLOCK)
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering log_error_errno(errno, "read(%d, ..., %zu): %m", source->fd,
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering source->size - source->filled);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering return -errno;
f6422def2c10aa0dea1b872d2f187853e61bd015Michal Schmidt } else if (n == 0)
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek return 0;
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek source->filled += n;
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek }
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering *line = source->buf + source->offset;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering *size = c + 1 - source->buf - source->offset;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering source->offset += *size;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering return 1;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering}
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poetteringint push_data(RemoteSource *source, const char *data, size_t size) {
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering assert(source);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering assert(source->state != STATE_EOF);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering if (!realloc_buffer(source, source->filled + size)) {
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering log_error("Failed to store received data of size %zu "
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering "(in addition to existing %zu bytes with %zu filled): %s",
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering size, source->size, source->filled, strerror(ENOMEM));
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering return -ENOMEM;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering }
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering memcpy(source->buf + source->filled, data, size);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering source->filled += size;
2a0e0692565f0435657c93498e09cbb2d3517152Shawn Landden
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering return 0;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering}
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poetteringstatic int fill_fixed_size(RemoteSource *source, void **data, size_t size) {
2a0e0692565f0435657c93498e09cbb2d3517152Shawn Landden
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering assert(source);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering assert(source->state == STATE_DATA_START ||
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering source->state == STATE_DATA ||
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering source->state == STATE_DATA_FINISH);
2a0e0692565f0435657c93498e09cbb2d3517152Shawn Landden assert(size <= DATA_SIZE_MAX);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering assert(source->offset <= source->filled);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering assert(source->filled <= source->size);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering assert(source->buf != NULL || source->size == 0);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering assert(source->buf == NULL || source->size > 0);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering assert(source->fd >= 0);
2a0e0692565f0435657c93498e09cbb2d3517152Shawn Landden assert(data);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering while (source->filled - source->offset < size) {
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering int n;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering if (source->passive_fd)
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering /* we have to wait for some data to come to us */
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering return -EWOULDBLOCK;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
2a0e0692565f0435657c93498e09cbb2d3517152Shawn Landden if (!realloc_buffer(source, source->offset + size))
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering return log_oom();
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering n = read(source->fd, source->buf + source->filled,
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering source->size - source->filled);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering if (n < 0) {
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering if (errno != EAGAIN && errno != EWOULDBLOCK)
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering log_error_errno(errno, "read(%d, ..., %zu): %m", source->fd,
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek source->size - source->filled);
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek return -errno;
2a0e0692565f0435657c93498e09cbb2d3517152Shawn Landden } else if (n == 0)
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek return 0;
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek source->filled += n;
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek }
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek *data = source->buf + source->offset;
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek source->offset += size;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering return 1;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering}
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poetteringstatic int get_data_size(RemoteSource *source) {
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering int r;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering void *data;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering assert(source);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering assert(source->state == STATE_DATA_START);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering assert(source->data_size == 0);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering r = fill_fixed_size(source, &data, sizeof(uint64_t));
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering if (r <= 0)
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering return r;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering source->data_size = le64toh( *(uint64_t *) data );
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering if (source->data_size > DATA_SIZE_MAX) {
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering log_error("Stream declares field with size %zu > DATA_SIZE_MAX = %u",
505b6a61c22d5565e9308045c7b9bf79f7d0517eLennart Poettering source->data_size, DATA_SIZE_MAX);
505b6a61c22d5565e9308045c7b9bf79f7d0517eLennart Poettering return -EINVAL;
505b6a61c22d5565e9308045c7b9bf79f7d0517eLennart Poettering }
505b6a61c22d5565e9308045c7b9bf79f7d0517eLennart Poettering if (source->data_size == 0)
505b6a61c22d5565e9308045c7b9bf79f7d0517eLennart Poettering log_warning("Binary field with zero length");
505b6a61c22d5565e9308045c7b9bf79f7d0517eLennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering return 1;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering}
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poetteringstatic int get_data_data(RemoteSource *source, void **data) {
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering int r;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering assert(source);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering assert(data);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering assert(source->state == STATE_DATA);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering r = fill_fixed_size(source, data, source->data_size);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering if (r <= 0)
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering return r;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering return 1;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering}
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poetteringstatic int get_data_newline(RemoteSource *source) {
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering int r;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering char *data;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering assert(source);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering assert(source->state == STATE_DATA_FINISH);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering r = fill_fixed_size(source, (void**) &data, 1);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering if (r <= 0)
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering return r;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering assert(data);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering if (*data != '\n') {
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering log_error("expected newline, got '%c'", *data);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering return -EINVAL;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering }
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering return 1;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering}
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poetteringstatic int process_dunder(RemoteSource *source, char *line, size_t n) {
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering const char *timestamp;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering int r;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering assert(line);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering assert(n > 0);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering assert(line[n-1] == '\n');
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering /* XXX: is it worth to support timestamps in extended format?
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering * We don't produce them, but who knows... */
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering timestamp = startswith(line, "__CURSOR=");
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering if (timestamp)
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering /* ignore __CURSOR */
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering return 1;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering timestamp = startswith(line, "__REALTIME_TIMESTAMP=");
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering if (timestamp) {
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering long long unsigned x;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering line[n-1] = '\0';
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering r = safe_atollu(timestamp, &x);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering if (r < 0)
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering log_warning("Failed to parse __REALTIME_TIMESTAMP: '%s'", timestamp);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering else
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering source->ts.realtime = x;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering return r < 0 ? r : 1;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering }
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering timestamp = startswith(line, "__MONOTONIC_TIMESTAMP=");
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering if (timestamp) {
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering long long unsigned x;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering line[n-1] = '\0';
1dfa7e79a60de680086b1d93fcc3629b463f58bdLennart Poettering r = safe_atollu(timestamp, &x);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering if (r < 0)
1dfa7e79a60de680086b1d93fcc3629b463f58bdLennart Poettering log_warning("Failed to parse __MONOTONIC_TIMESTAMP: '%s'", timestamp);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering else
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering source->ts.monotonic = x;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering return r < 0 ? r : 1;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering }
1dfa7e79a60de680086b1d93fcc3629b463f58bdLennart Poettering
1dfa7e79a60de680086b1d93fcc3629b463f58bdLennart Poettering timestamp = startswith(line, "__");
1dfa7e79a60de680086b1d93fcc3629b463f58bdLennart Poettering if (timestamp) {
1dfa7e79a60de680086b1d93fcc3629b463f58bdLennart Poettering log_notice("Unknown dunder line %s", line);
1dfa7e79a60de680086b1d93fcc3629b463f58bdLennart Poettering return 1;
1dfa7e79a60de680086b1d93fcc3629b463f58bdLennart Poettering }
1dfa7e79a60de680086b1d93fcc3629b463f58bdLennart Poettering
1dfa7e79a60de680086b1d93fcc3629b463f58bdLennart Poettering /* no dunder */
1dfa7e79a60de680086b1d93fcc3629b463f58bdLennart Poettering return 0;
1dfa7e79a60de680086b1d93fcc3629b463f58bdLennart Poettering}
1dfa7e79a60de680086b1d93fcc3629b463f58bdLennart Poettering
1dfa7e79a60de680086b1d93fcc3629b463f58bdLennart Poetteringint process_data(RemoteSource *source) {
1dfa7e79a60de680086b1d93fcc3629b463f58bdLennart Poettering int r;
1dfa7e79a60de680086b1d93fcc3629b463f58bdLennart Poettering
1dfa7e79a60de680086b1d93fcc3629b463f58bdLennart Poettering switch(source->state) {
1dfa7e79a60de680086b1d93fcc3629b463f58bdLennart Poettering case STATE_LINE: {
1dfa7e79a60de680086b1d93fcc3629b463f58bdLennart Poettering char *line, *sep;
1dfa7e79a60de680086b1d93fcc3629b463f58bdLennart Poettering size_t n;
1dfa7e79a60de680086b1d93fcc3629b463f58bdLennart Poettering
1dfa7e79a60de680086b1d93fcc3629b463f58bdLennart Poettering assert(source->data_size == 0);
1dfa7e79a60de680086b1d93fcc3629b463f58bdLennart Poettering
1dfa7e79a60de680086b1d93fcc3629b463f58bdLennart Poettering r = get_line(source, &line, &n);
1dfa7e79a60de680086b1d93fcc3629b463f58bdLennart Poettering if (r < 0)
1dfa7e79a60de680086b1d93fcc3629b463f58bdLennart Poettering return r;
1dfa7e79a60de680086b1d93fcc3629b463f58bdLennart Poettering if (r == 0) {
0b507b17a760b21e33fc52ff377db6aa5086c680Lennart Poettering source->state = STATE_EOF;
1dfa7e79a60de680086b1d93fcc3629b463f58bdLennart Poettering return r;
1dfa7e79a60de680086b1d93fcc3629b463f58bdLennart Poettering }
1dfa7e79a60de680086b1d93fcc3629b463f58bdLennart Poettering assert(n > 0);
1dfa7e79a60de680086b1d93fcc3629b463f58bdLennart Poettering assert(line[n-1] == '\n');
1dfa7e79a60de680086b1d93fcc3629b463f58bdLennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering if (n == 1) {
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering log_trace("Received empty line, event is ready");
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering return 1;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering }
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering r = process_dunder(source, line, n);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering if (r != 0)
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering return r < 0 ? r : 0;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering /* MESSAGE=xxx\n
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering or
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering COREDUMP\n
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering LLLLLLLL0011223344...\n
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering */
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering sep = memchr(line, '=', n);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering if (sep) {
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering /* chomp newline */
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering n--;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering r = iovw_put(&source->iovw, line, n);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering if (r < 0)
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering return r;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering } else {
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering /* replace \n with = */
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering line[n-1] = '=';
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering source->field_len = n;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering source->state = STATE_DATA_START;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering /* we cannot put the field in iovec until we have all data */
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering }
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering log_trace("Received: %.*s (%s)", (int) n, line, sep ? "text" : "binary");
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering return 0; /* continue */
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering }
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering case STATE_DATA_START:
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering assert(source->data_size == 0);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering r = get_data_size(source);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering // log_debug("get_data_size() -> %d", r);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering if (r < 0)
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering return r;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering if (r == 0) {
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering source->state = STATE_EOF;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering return 0;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering }
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering source->state = source->data_size > 0 ?
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering STATE_DATA : STATE_DATA_FINISH;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering return 0; /* continue */
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering case STATE_DATA: {
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering void *data;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering char *field;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering assert(source->data_size > 0);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering r = get_data_data(source, &data);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering // log_debug("get_data_data() -> %d", r);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering if (r < 0)
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering return r;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering if (r == 0) {
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering source->state = STATE_EOF;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering return 0;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering }
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering assert(data);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering field = (char*) data - sizeof(uint64_t) - source->field_len;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering memmove(field + sizeof(uint64_t), field, source->field_len);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering r = iovw_put(&source->iovw, field + sizeof(uint64_t), source->field_len + source->data_size);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering if (r < 0)
be2155ce705c1c1a25fa5b2927e2e02f4b3c7a35Lennart Poettering return r;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering source->state = STATE_DATA_FINISH;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering return 0; /* continue */
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering }
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering case STATE_DATA_FINISH:
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering r = get_data_newline(source);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering // log_debug("get_data_newline() -> %d", r);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering if (r < 0)
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering return r;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering if (r == 0) {
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering source->state = STATE_EOF;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering return 0;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering }
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering source->data_size = 0;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering source->state = STATE_LINE;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering return 0; /* continue */
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering default:
assert_not_reached("wtf?");
}
}
int process_source(RemoteSource *source, bool compress, bool seal) {
size_t remain, target;
int r;
assert(source);
assert(source->writer);
r = process_data(source);
if (r <= 0)
return r;
/* We have a full event */
log_trace("Received a full event from source@%p fd:%d (%s)",
source, source->fd, source->name);
if (!source->iovw.count) {
log_warning("Entry with no payload, skipping");
goto freeing;
}
assert(source->iovw.iovec);
assert(source->iovw.count);
r = writer_write(source->writer, &source->iovw, &source->ts, compress, seal);
if (r < 0)
log_error_errno(r, "Failed to write entry of %zu bytes: %m",
iovw_size(&source->iovw));
else
r = 1;
freeing:
iovw_free_contents(&source->iovw);
/* possibly reset buffer position */
remain = source->filled - source->offset;
if (remain == 0) /* no brainer */
source->offset = source->scanned = source->filled = 0;
else if (source->offset > source->size - source->filled &&
source->offset > remain) {
memcpy(source->buf, source->buf + source->offset, remain);
source->offset = source->scanned = 0;
source->filled = remain;
}
target = source->size;
while (target > 16 * LINE_CHUNK && remain < target / 2)
target /= 2;
if (target < source->size) {
char *tmp;
tmp = realloc(source->buf, target);
if (!tmp)
log_warning("Failed to reallocate buffer to (smaller) size %zu",
target);
else {
log_debug("Reallocated buffer from %zu to %zu bytes",
source->size, target);
source->buf = tmp;
source->size = target;
}
}
return r;
}