journal-remote-parse.c revision dd87b1840c966fd25b81a7aa1071e8488c624db8
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt/***
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt This file is part of systemd.
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
7bd8e95d44977833d0de3fc4e893eb3bc84351d6Patrik Flykt Copyright 2014 Zbigniew Jędrzejewski-Szmek
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt systemd is free software; you can redistribute it and/or modify it
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt under the terms of the GNU Lesser General Public License as published by
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt the Free Software Foundation; either version 2.1 of the License, or
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt (at your option) any later version.
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt systemd is distributed in the hope that it will be useful, but
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt WITHOUT ANY WARRANTY; without even the implied warranty of
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt Lesser General Public License for more details.
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt You should have received a copy of the GNU Lesser General Public License
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt along with systemd; If not, see <http://www.gnu.org/licenses/>.
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt***/
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt#include "journal-remote-parse.h"
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt#include "journald-native.h"
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams#define LINE_CHUNK 8*1024u
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flyktvoid source_free(RemoteSource *source) {
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering if (!source)
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering return;
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (source->fd >= 0 && !source->passive_fd) {
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering log_debug("Closing fd:%d (%s)", source->fd, source->name);
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering safe_close(source->fd);
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering }
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering free(source->name);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt free(source->buf);
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams iovw_free_contents(&source->iovw);
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt log_debug("Writer ref count %u", source->writer->n_ref);
3733eec3e292e4ddb4cba5eb8d3bd8cbee7102d8Lennart Poettering writer_unref(source->writer);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt sd_event_source_unref(source->event);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt free(source);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt}
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams/**
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams * Initialize zero-filled source with given values. On success, takes
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt * ownerhship of fd and writer, otherwise does not touch them.
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt */
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik FlyktRemoteSource* source_new(int fd, bool passive_fd, char *name, Writer *writer) {
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt RemoteSource *source;
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt log_debug("Creating source for %sfd:%d (%s)",
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt passive_fd ? "passive " : "", fd, name);
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt assert(fd >= 0);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt source = new0(RemoteSource, 1);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt if (!source)
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt return NULL;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt source->fd = fd;
764aad6258eec3bd4ae62ea341ea507bd69ce628Tom Gundersen source->passive_fd = passive_fd;
66eac1201a9c1596f5901f8dbbf24bda7e350878Dan Williams source->name = name;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt source->writer = writer;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt return source;
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt}
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flyktstatic char* realloc_buffer(RemoteSource *source, size_t size) {
41e4615d4f4f5c61afa84ba857f23c0ac496687bPatrik Flykt char *b, *old = source->buf;
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt b = GREEDY_REALLOC(source->buf, source->size, size);
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt if (!b)
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt return NULL;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt iovw_rebase(&source->iovw, old, source->buf);
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt return b;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt}
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flyktstatic int get_line(RemoteSource *source, char **line, size_t *size) {
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt ssize_t n;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt char *c = NULL;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt assert(source);
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt assert(source->state == STATE_LINE);
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt assert(source->offset <= source->filled);
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt assert(source->filled <= source->size);
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt assert(source->buf == NULL || source->size > 0);
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt assert(source->fd >= 0);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt while (true) {
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (source->buf) {
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt size_t start = MAX(source->scanned, source->offset);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt c = memchr(source->buf + start, '\n',
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt source->filled - start);
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt if (c != NULL)
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt break;
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt }
631bbe71298ec892f77f44f94feb612646fe6853Patrik Flykt
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flykt source->scanned = source->filled;
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flykt if (source->scanned >= DATA_SIZE_MAX) {
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flykt log_error("Entry is bigger than %u bytes.", DATA_SIZE_MAX);
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flykt return -E2BIG;
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flykt }
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flykt
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt if (source->passive_fd)
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt /* we have to wait for some data to come to us */
0ae0e5cd96813bacad43a39920a043d8d20a67dbLennart Poettering return -EWOULDBLOCK;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt if (source->size - source->filled < LINE_CHUNK &&
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt !realloc_buffer(source,
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt MIN(source->filled + LINE_CHUNK, ENTRY_SIZE_MAX)))
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt return log_oom();
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt assert(source->size - source->filled >= LINE_CHUNK ||
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt source->size == ENTRY_SIZE_MAX);
0ae0e5cd96813bacad43a39920a043d8d20a67dbLennart Poettering
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt n = read(source->fd, source->buf + source->filled,
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt source->size - source->filled);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt if (n < 0) {
d7c9c21f18704580f66a1ce73fb6b506fdf40732Patrik Flykt if (errno != EAGAIN && errno != EWOULDBLOCK)
d7c9c21f18704580f66a1ce73fb6b506fdf40732Patrik Flykt log_error("read(%d, ..., %zd): %m", source->fd,
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt source->size - source->filled);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt return -errno;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt } else if (n == 0)
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt return 0;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
0ae0e5cd96813bacad43a39920a043d8d20a67dbLennart Poettering source->filled += n;
0ae0e5cd96813bacad43a39920a043d8d20a67dbLennart Poettering }
0ae0e5cd96813bacad43a39920a043d8d20a67dbLennart Poettering
0ae0e5cd96813bacad43a39920a043d8d20a67dbLennart Poettering *line = source->buf + source->offset;
0ae0e5cd96813bacad43a39920a043d8d20a67dbLennart Poettering *size = c + 1 - source->buf - source->offset;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt source->offset += *size;
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams return 1;
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams}
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams
d7c9c21f18704580f66a1ce73fb6b506fdf40732Patrik Flyktint push_data(RemoteSource *source, const char *data, size_t size) {
d7c9c21f18704580f66a1ce73fb6b506fdf40732Patrik Flykt assert(source);
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams assert(source->state != STATE_EOF);
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams if (!realloc_buffer(source, source->filled + size)) {
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams log_error("Failed to store received data of size %zu "
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt "(in addition to existing %zu bytes with %zu filled): %s",
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams size, source->size, source->filled, strerror(ENOMEM));
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams return -ENOMEM;
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams }
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams memcpy(source->buf + source->filled, data, size);
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams source->filled += size;
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams return 0;
76253e73f9c9c24fec755e485516f3b55d0707b4Dan Williams}
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flyktstatic int fill_fixed_size(RemoteSource *source, void **data, size_t size) {
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt assert(source);
0ae0e5cd96813bacad43a39920a043d8d20a67dbLennart Poettering assert(source->state == STATE_DATA_START ||
cc22955cfefb4bd6e7a135f1ec95fb5a07ba9ce3Thomas Haller source->state == STATE_DATA ||
cc22955cfefb4bd6e7a135f1ec95fb5a07ba9ce3Thomas Haller source->state == STATE_DATA_FINISH);
0ae0e5cd96813bacad43a39920a043d8d20a67dbLennart Poettering assert(size <= DATA_SIZE_MAX);
cc22955cfefb4bd6e7a135f1ec95fb5a07ba9ce3Thomas Haller assert(source->offset <= source->filled);
cc22955cfefb4bd6e7a135f1ec95fb5a07ba9ce3Thomas Haller assert(source->filled <= source->size);
cc22955cfefb4bd6e7a135f1ec95fb5a07ba9ce3Thomas Haller assert(source->buf != NULL || source->size == 0);
0ae0e5cd96813bacad43a39920a043d8d20a67dbLennart Poettering assert(source->buf == NULL || source->size > 0);
0ae0e5cd96813bacad43a39920a043d8d20a67dbLennart Poettering assert(source->fd >= 0);
0ae0e5cd96813bacad43a39920a043d8d20a67dbLennart Poettering assert(data);
0ae0e5cd96813bacad43a39920a043d8d20a67dbLennart Poettering
66eac1201a9c1596f5901f8dbbf24bda7e350878Dan Williams while (source->filled - source->offset < size) {
66eac1201a9c1596f5901f8dbbf24bda7e350878Dan Williams int n;
66eac1201a9c1596f5901f8dbbf24bda7e350878Dan Williams
66eac1201a9c1596f5901f8dbbf24bda7e350878Dan Williams if (source->passive_fd)
d7c9c21f18704580f66a1ce73fb6b506fdf40732Patrik Flykt /* we have to wait for some data to come to us */
d7c9c21f18704580f66a1ce73fb6b506fdf40732Patrik Flykt return -EWOULDBLOCK;
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen if (!realloc_buffer(source, source->offset + size))
764aad6258eec3bd4ae62ea341ea507bd69ce628Tom Gundersen return log_oom();
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen n = read(source->fd, source->buf + source->filled,
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen source->size - source->filled);
764aad6258eec3bd4ae62ea341ea507bd69ce628Tom Gundersen if (n < 0) {
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen if (errno != EAGAIN && errno != EWOULDBLOCK)
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen log_error("read(%d, ..., %zd): %m", source->fd,
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen source->size - source->filled);
764aad6258eec3bd4ae62ea341ea507bd69ce628Tom Gundersen return -errno;
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen } else if (n == 0)
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen return 0;
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen
764aad6258eec3bd4ae62ea341ea507bd69ce628Tom Gundersen source->filled += n;
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen }
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen *data = source->buf + source->offset;
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen source->offset += size;
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen return 1;
fe4b2156256c5bdf52341576571ce9f095d9f085Tom Gundersen}
764aad6258eec3bd4ae62ea341ea507bd69ce628Tom Gundersen
ebe207d4acf38165adbc45298662982eecdb9e9fTom Gundersenstatic int get_data_size(RemoteSource *source) {
764aad6258eec3bd4ae62ea341ea507bd69ce628Tom Gundersen int r;
66eac1201a9c1596f5901f8dbbf24bda7e350878Dan Williams void *data;
66eac1201a9c1596f5901f8dbbf24bda7e350878Dan Williams
66eac1201a9c1596f5901f8dbbf24bda7e350878Dan Williams assert(source);
66eac1201a9c1596f5901f8dbbf24bda7e350878Dan Williams assert(source->state == STATE_DATA_START);
04c0136989b7eb896bfb0fb176e11233d69e1453Lennart Poettering assert(source->data_size == 0);
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt
d7c9c21f18704580f66a1ce73fb6b506fdf40732Patrik Flykt r = fill_fixed_size(source, &data, sizeof(uint64_t));
d7c9c21f18704580f66a1ce73fb6b506fdf40732Patrik Flykt if (r <= 0)
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt return r;
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt source->data_size = le64toh( *(uint64_t *) data );
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt if (source->data_size > DATA_SIZE_MAX) {
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt log_error("Stream declares field with size %zu > DATA_SIZE_MAX = %u",
04c0136989b7eb896bfb0fb176e11233d69e1453Lennart Poettering source->data_size, DATA_SIZE_MAX);
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt return -EINVAL;
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt }
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt if (source->data_size == 0)
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt log_warning("Binary field with zero length");
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt return 1;
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt}
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt
0ae0e5cd96813bacad43a39920a043d8d20a67dbLennart Poetteringstatic int get_data_data(RemoteSource *source, void **data) {
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt int r;
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt assert(source);
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt assert(data);
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt assert(source->state == STATE_DATA);
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt r = fill_fixed_size(source, data, source->data_size);
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt if (r <= 0)
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt return r;
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt return 1;
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt}
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flyktstatic int get_data_newline(RemoteSource *source) {
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt int r;
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt char *data;
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt assert(source);
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt assert(source->state == STATE_DATA_FINISH);
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt r = fill_fixed_size(source, (void**) &data, 1);
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt if (r <= 0)
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt return r;
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt assert(data);
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt if (*data != '\n') {
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt log_error("expected newline, got '%c'", *data);
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt return -EINVAL;
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt }
ea3b3a75abb3f8b853f7da454b9b8e258a120eeaPatrik Flykt
ea3b3a75abb3f8b853f7da454b9b8e258a120eeaPatrik Flykt return 1;
ea3b3a75abb3f8b853f7da454b9b8e258a120eeaPatrik Flykt}
ea3b3a75abb3f8b853f7da454b9b8e258a120eeaPatrik Flykt
ea3b3a75abb3f8b853f7da454b9b8e258a120eeaPatrik Flyktstatic int process_dunder(RemoteSource *source, char *line, size_t n) {
ea3b3a75abb3f8b853f7da454b9b8e258a120eeaPatrik Flykt const char *timestamp;
ea3b3a75abb3f8b853f7da454b9b8e258a120eeaPatrik Flykt int r;
e6b18ffaea7d557eec3028a37c043da67a78550cDavid Herrmann
ea3b3a75abb3f8b853f7da454b9b8e258a120eeaPatrik Flykt assert(line);
ea3b3a75abb3f8b853f7da454b9b8e258a120eeaPatrik Flykt assert(n > 0);
ea3b3a75abb3f8b853f7da454b9b8e258a120eeaPatrik Flykt assert(line[n-1] == '\n');
ea3b3a75abb3f8b853f7da454b9b8e258a120eeaPatrik Flykt
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flykt /* XXX: is it worth to support timestamps in extended format?
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flykt * We don't produce them, but who knows... */
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt timestamp = startswith(line, "__CURSOR=");
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt if (timestamp)
f89087272b5561c9a3fc9d6a4e2a09f75f688fa7Thomas Haller /* ignore __CURSOR */
4e3e6679e8f73b83d38e4b20d8b025e12991d1cbPatrik Flykt return 1;
4e3e6679e8f73b83d38e4b20d8b025e12991d1cbPatrik Flykt
f89087272b5561c9a3fc9d6a4e2a09f75f688fa7Thomas Haller timestamp = startswith(line, "__REALTIME_TIMESTAMP=");
4e3e6679e8f73b83d38e4b20d8b025e12991d1cbPatrik Flykt if (timestamp) {
f89087272b5561c9a3fc9d6a4e2a09f75f688fa7Thomas Haller long long unsigned x;
f89087272b5561c9a3fc9d6a4e2a09f75f688fa7Thomas Haller line[n-1] = '\0';
f89087272b5561c9a3fc9d6a4e2a09f75f688fa7Thomas Haller r = safe_atollu(timestamp, &x);
f89087272b5561c9a3fc9d6a4e2a09f75f688fa7Thomas Haller if (r < 0)
f89087272b5561c9a3fc9d6a4e2a09f75f688fa7Thomas Haller log_warning("Failed to parse __REALTIME_TIMESTAMP: '%s'", timestamp);
f89087272b5561c9a3fc9d6a4e2a09f75f688fa7Thomas Haller else
f89087272b5561c9a3fc9d6a4e2a09f75f688fa7Thomas Haller source->ts.realtime = x;
4e3e6679e8f73b83d38e4b20d8b025e12991d1cbPatrik Flykt return r < 0 ? r : 1;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt }
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt timestamp = startswith(line, "__MONOTONIC_TIMESTAMP=");
c806ffb9592fa9a2b13a1f9f9be4c77cd5b211aaZbigniew Jędrzejewski-Szmek if (timestamp) {
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt long long unsigned x;
c3e2adeaba8e043caed0ef139eeaea016bd152d0Patrik Flykt line[n-1] = '\0';
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt r = safe_atollu(timestamp, &x);
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt if (r < 0)
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt log_warning("Failed to parse __MONOTONIC_TIMESTAMP: '%s'", timestamp);
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt else
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt source->ts.monotonic = x;
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt return r < 0 ? r : 1;
f12abb48fc510b8b349c05e35ba048134debaf25Patrik Flykt }
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt timestamp = startswith(line, "__");
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt if (timestamp) {
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt log_notice("Unknown dunder line %s", line);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt return 1;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt }
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt /* no dunder */
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt return 0;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt}
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flyktint process_data(RemoteSource *source) {
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flykt int r;
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flykt switch(source->state) {
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt case STATE_LINE: {
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flykt char *line, *sep;
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flykt size_t n;
3f0c075f8ef3344da5a6bda524540201f9204e61Patrik Flykt
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt assert(source->data_size == 0);
139b011ab81ccea1d51f09e0261a1c390115c6ffPatrik Flykt
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt r = get_line(source, &line, &n);
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt if (r < 0)
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt return r;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt if (r == 0) {
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt source->state = STATE_EOF;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt return r;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt }
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt assert(n > 0);
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt assert(line[n-1] == '\n');
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt if (n == 1) {
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt log_debug("Received empty line, event is ready");
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt return 1;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt }
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt r = process_dunder(source, line, n);
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt if (r != 0)
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt return r < 0 ? r : 0;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt /* MESSAGE=xxx\n
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt or
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt COREDUMP\n
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt LLLLLLLL0011223344...\n
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt */
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt sep = memchr(line, '=', n);
bbfa43ca37df0718287c25a8e39ee7477ebf33f6Patrik Flykt if (sep)
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt /* chomp newline */
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt n--;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt else
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt /* replace \n with = */
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt line[n-1] = '=';
926695f1b5f9395eeb416cc2f478a9cf75fdbeb4Thomas Hindoe Paaboel Andersen log_debug("Received: %.*s", (int) n, line);
926695f1b5f9395eeb416cc2f478a9cf75fdbeb4Thomas Hindoe Paaboel Andersen
ed6ee21953dac9c78383da00bc4514ece6b75ab5Patrik Flykt r = iovw_put(&source->iovw, line, n);
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt if (r < 0) {
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt log_error("Failed to put line in iovect");
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt return r;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt }
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt if (!sep)
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt source->state = STATE_DATA_START;
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt return 0; /* continue */
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt }
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt case STATE_DATA_START:
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt assert(source->data_size == 0);
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt r = get_data_size(source);
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt // log_debug("get_data_size() -> %d", r);
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt if (r < 0)
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt return r;
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt if (r == 0) {
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt source->state = STATE_EOF;
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt return 0;
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt }
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt source->state = source->data_size > 0 ?
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt STATE_DATA : STATE_DATA_FINISH;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt return 0; /* continue */
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt case STATE_DATA: {
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt void *data;
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt assert(source->data_size > 0);
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt r = get_data_data(source, &data);
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt // log_debug("get_data_data() -> %d", r);
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt if (r < 0)
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt return r;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt if (r == 0) {
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt source->state = STATE_EOF;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt return 0;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt }
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt assert(data);
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt r = iovw_put(&source->iovw, data, source->data_size);
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt if (r < 0) {
da6fe470e17fa02f3adedc779585caf8669252bdPatrik Flykt log_error("failed to put binary buffer in iovect");
cc22955cfefb4bd6e7a135f1ec95fb5a07ba9ce3Thomas Haller return r;
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt }
66eac1201a9c1596f5901f8dbbf24bda7e350878Dan Williams
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt source->state = STATE_DATA_FINISH;
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt
7246333cb803b03440d3bd0bdaa233564d09b5aePatrik Flykt return 0; /* continue */
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt }
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt case STATE_DATA_FINISH:
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt r = get_data_newline(source);
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt // log_debug("get_data_newline() -> %d", r);
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt if (r < 0)
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt return r;
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt if (r == 0) {
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt source->state = STATE_EOF;
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt return 0;
346e13a25dc6f76d3bc9d8decd40dc4782b02d2aPatrik Flykt }
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt source->data_size = 0;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt source->state = STATE_LINE;
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt return 0; /* continue */
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt default:
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt assert_not_reached("wtf?");
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt }
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt}
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flykt
a9aff3615b430f86bd0a824214d95f634efaf894Patrik Flyktint process_source(RemoteSource *source, bool compress, bool seal) {
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt size_t remain, target;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt int r;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt assert(source);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt assert(source->writer);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt r = process_data(source);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt if (r <= 0)
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt return r;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt /* We have a full event */
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt log_debug("Received a full event from source@%p fd:%d (%s)",
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt source, source->fd, source->name);
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt if (!source->iovw.count) {
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt log_warning("Entry with no payload, skipping");
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt goto freeing;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt }
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt assert(source->iovw.iovec);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt assert(source->iovw.count);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt r = writer_write(source->writer, &source->iovw, &source->ts, compress, seal);
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt if (r < 0)
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt log_error("Failed to write entry of %zu bytes: %s",
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt iovw_size(&source->iovw), strerror(-r));
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt else
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt r = 1;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt freeing:
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt iovw_free_contents(&source->iovw);
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt /* possibly reset buffer position */
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt remain = source->filled - source->offset;
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt
a34b57c0d43b8bf819ccd4f62c314b41b625454dPatrik Flykt if (remain == 0) /* no brainer */
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt source->offset = source->scanned = source->filled = 0;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt else if (source->offset > source->size - source->filled &&
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt source->offset > remain) {
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt memcpy(source->buf, source->buf + source->offset, remain);
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt source->offset = source->scanned = 0;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt source->filled = remain;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt }
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt target = source->size;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt while (target > 16 * LINE_CHUNK && remain < target / 2)
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt target /= 2;
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt if (target < source->size) {
10c9ce615d98e125bc520efa94aebaef250a4061David Herrmann char *tmp;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt tmp = realloc(source->buf, target);
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt if (!tmp)
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt log_warning("Failed to reallocate buffer to (smaller) size %zu",
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt target);
3dc34fcc97b41f8b7b019027225b121dfbb9871dPatrik Flykt else {
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt log_debug("Reallocated buffer from %zu to %zu bytes",
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt source->size, target);
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt source->buf = tmp;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt source->size = target;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt }
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt }
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt return r;
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt}
d1b0afe3653b4316a6361d204169620726d468a0Patrik Flykt