From: Michael Tremer Date: Sat, 12 Oct 2024 16:12:29 +0000 (+0000) Subject: log stream: Remove FILE handle X-Git-Tag: 0.9.30~1073 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fe792f2eecca59a0b1c798dde6f63d07fd96afab;p=pakfire.git log stream: Remove FILE handle This is being replaced by our own loop that splits the input by line. Signed-off-by: Michael Tremer --- diff --git a/src/libpakfire/log_stream.c b/src/libpakfire/log_stream.c index a8f20a675..760dcc167 100644 --- a/src/libpakfire/log_stream.c +++ b/src/libpakfire/log_stream.c @@ -33,8 +33,9 @@ struct pakfire_log_stream { // Pipe int pipe[2]; - // FILE Handle - FILE* f; + // Buffer + char buffer[64 * 1024]; + size_t buffered; // Event Source sd_event_source* event; @@ -46,9 +47,7 @@ struct pakfire_log_stream { static void pakfire_log_stream_free(struct pakfire_log_stream* stream) { if (stream->event) - sd_event_source_unref(stream->event); - if (stream->f) - fclose(stream->f); + stream->event = sd_event_source_unref(stream->event); // Close the pipe if (stream->pipe[0] >= 0) @@ -115,39 +114,83 @@ struct pakfire_log_stream* pakfire_log_stream_unref(struct pakfire_log_stream* s return NULL; } +static int pakfire_log_stream_fill_buffer(struct pakfire_log_stream* stream, int fd) { + ssize_t bytes_read; + + // Read into the buffer + bytes_read = read(fd, stream->buffer + stream->buffered, sizeof(stream->buffer) - stream->buffered); + if (bytes_read < 0) + return bytes_read; + + stream->buffered += bytes_read; + + return 0; +} + +static int pakfire_log_stream_drain_buffer(struct pakfire_log_stream* stream) { + const char* eol = NULL; + size_t length; + int r; + + // Log a message if we don't have a callback + if (!stream->callback) { + CTX_ERROR(stream->ctx, "Log stream has no callback set\n"); + return -EINVAL; + } + + for (;;) { + // Find the next line + eol = memchr(stream->buffer, '\n', stream->buffered); + if (!eol) + return 0; + + // Determine the length of the line + length = eol - stream->buffer + 1; + + // Call the callback + r = stream->callback(stream, stream->buffer, length, stream->data); + if (r) + return r; + + memmove(stream->buffer, stream->buffer + length, stream->buffered - length); + stream->buffered -= length; + } +} + static int __pakfire_log_stream(sd_event_source* s, int fd, uint32_t events, void* data) { struct pakfire_log_stream* stream = data; - - char* line = NULL; - size_t l = 0; int r = -EINVAL; - ssize_t bytes_read = 0; - - // Read as many lines as possible if (events & EPOLLIN) { for (;;) { - bytes_read = getline(&line, &l, stream->f); - if (bytes_read < 0) - break; - - // Log a message if we don't have a callback - if (!stream->callback) { - CTX_ERROR(stream->ctx, "Log stream has no callback set\n"); - continue; + // Fill the buffer + r = pakfire_log_stream_fill_buffer(stream, fd); + if (r < 0) { + switch (-r) { + case EAGAIN: + return 0; + + default: + return r; + } } - // Call the callback - r = stream->callback(stream, line, bytes_read, stream->data); - if (r) + // Drain the buffer + r = pakfire_log_stream_drain_buffer(stream); + if (r < 0) return r; } } // Handle if the child process has closed the file descriptor if (events & EPOLLHUP) { - close(stream->pipe[0]); - stream->pipe[0] = -1; + if (stream->event) + stream->event = sd_event_source_unref(stream->event); + + if (stream->pipe[0] >= 0) { + close(stream->pipe[0]); + stream->pipe[0] = -1; + } } return r; @@ -173,13 +216,6 @@ int pakfire_log_stream_in_parent(struct pakfire_log_stream* stream, sd_event* lo return r; } - // Create a file handle for easy line buffering - stream->f = fdopen(stream->pipe[0], "r"); - if (!stream->f) { - CTX_ERROR(stream->ctx, "Could not open a file handle: %m\n"); - return -errno; - } - return 0; }