journal-remote-parse.c revision 09d801a82a46df518dd752e40bf13ac404daa2ce
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering This file is part of systemd.
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering Copyright 2014 Zbigniew Jędrzejewski-Szmek
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 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 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 if (source->fd >= 0 && !source->passive_fd) {
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering log_debug("Closing fd:%d (%s)", source->fd, source->name);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering log_debug("Writer ref count %i", source->writer->n_ref);
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 PoetteringRemoteSource* source_new(int fd, bool passive_fd, char *name, Writer *writer) {
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering log_debug("Creating source for %sfd:%d (%s)",
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poetteringstatic char* realloc_buffer(RemoteSource *source, size_t size) {
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek b = GREEDY_REALLOC(source->buf, source->size, size);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering iovw_rebase(&source->iovw, old, source->buf);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poetteringstatic int get_line(RemoteSource *source, char **line, size_t *size) {
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek assert(source->offset <= source->filled);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering assert(source->buf == NULL || source->size > 0);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering while (true) {
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering size_t start = MAX(source->scanned, source->offset);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering log_error("Entry is bigger than %u bytes.", DATA_SIZE_MAX);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering /* we have to wait for some data to come to us */
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering if (source->size - source->filled < LINE_CHUNK &&
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering MIN(source->filled + LINE_CHUNK, ENTRY_SIZE_MAX)))
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering assert(source->size - source->filled >= LINE_CHUNK ||
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering n = read(source->fd, source->buf + source->filled,
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering if (errno != EAGAIN && errno != EWOULDBLOCK)
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering log_error_errno(errno, "read(%d, ..., %zu): %m", source->fd,
f6422def2c10aa0dea1b872d2f187853e61bd015Michal Schmidt } else if (n == 0)
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering *size = c + 1 - source->buf - source->offset;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poetteringint push_data(RemoteSource *source, const char *data, size_t size) {
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 memcpy(source->buf + source->filled, data, size);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poetteringstatic int fill_fixed_size(RemoteSource *source, void **data, size_t size) {
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering assert(source->state == STATE_DATA_START ||
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering assert(source->offset <= source->filled);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering assert(source->buf != NULL || source->size == 0);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering assert(source->buf == NULL || source->size > 0);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering while (source->filled - source->offset < size) {
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering /* we have to wait for some data to come to us */
2a0e0692565f0435657c93498e09cbb2d3517152Shawn Landden if (!realloc_buffer(source, source->offset + size))
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering n = read(source->fd, source->buf + source->filled,
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering if (errno != EAGAIN && errno != EWOULDBLOCK)
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering log_error_errno(errno, "read(%d, ..., %zu): %m", source->fd,
2a0e0692565f0435657c93498e09cbb2d3517152Shawn Landden } else if (n == 0)
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek *data = source->buf + source->offset;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poetteringstatic int get_data_size(RemoteSource *source) {
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering assert(source->state == STATE_DATA_START);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering r = fill_fixed_size(source, &data, sizeof(uint64_t));
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering source->data_size = le64toh( *(uint64_t *) data );
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering log_error("Stream declares field with size %zu > DATA_SIZE_MAX = %u",
505b6a61c22d5565e9308045c7b9bf79f7d0517eLennart Poettering log_warning("Binary field with zero length");
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poetteringstatic int get_data_data(RemoteSource *source, void **data) {
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering r = fill_fixed_size(source, data, source->data_size);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poetteringstatic int get_data_newline(RemoteSource *source) {
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering assert(source->state == STATE_DATA_FINISH);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering r = fill_fixed_size(source, (void**) &data, 1);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering log_error("expected newline, got '%c'", *data);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poetteringstatic int process_dunder(RemoteSource *source, char *line, size_t n) {
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering /* XXX: is it worth to support timestamps in extended format?
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering * We don't produce them, but who knows... */
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering timestamp = startswith(line, "__CURSOR=");
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering /* ignore __CURSOR */
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering timestamp = startswith(line, "__REALTIME_TIMESTAMP=");
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering long long unsigned x;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering log_warning("Failed to parse __REALTIME_TIMESTAMP: '%s'", timestamp);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering return r < 0 ? r : 1;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering timestamp = startswith(line, "__MONOTONIC_TIMESTAMP=");
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering long long unsigned x;
1dfa7e79a60de680086b1d93fcc3629b463f58bdLennart Poettering log_warning("Failed to parse __MONOTONIC_TIMESTAMP: '%s'", timestamp);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering return r < 0 ? r : 1;
1dfa7e79a60de680086b1d93fcc3629b463f58bdLennart Poettering log_notice("Unknown dunder line %s", line);
1dfa7e79a60de680086b1d93fcc3629b463f58bdLennart Poettering /* no dunder */
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering log_trace("Received empty line, event is ready");
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering return r < 0 ? r : 0;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering /* MESSAGE=xxx\n
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering LLLLLLLL0011223344...\n
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering /* chomp newline */
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering /* replace \n with = */
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering /* we cannot put the field in iovec until we have all data */
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering log_trace("Received: %.*s (%s)", (int) n, line, sep ? "text" : "binary");
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering return 0; /* continue */
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering // log_debug("get_data_size() -> %d", r);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering return 0; /* continue */
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering // log_debug("get_data_data() -> %d", r);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering field = (char*) data - sizeof(uint64_t) - source->field_len;
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering memmove(field + sizeof(uint64_t), field, source->field_len);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering r = iovw_put(&source->iovw, field + sizeof(uint64_t), source->field_len + source->data_size);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering return 0; /* continue */
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering // log_debug("get_data_newline() -> %d", r);
0153028ae379eb7c9a463c548ef73ea392c6cdb0Lennart Poettering return 0; /* continue */
goto freeing;
char *tmp;
if (!tmp)
target);