diff options
Diffstat (limited to '')
-rw-r--r-- | src/basic/memstream-util.c | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/src/basic/memstream-util.c b/src/basic/memstream-util.c new file mode 100644 index 0000000..4e147fd --- /dev/null +++ b/src/basic/memstream-util.c @@ -0,0 +1,75 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include "alloc-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "log.h" +#include "memstream-util.h" + +void memstream_done(MemStream *m) { + assert(m); + + /* First, close file stream, as the buffer may be reallocated on close. */ + safe_fclose(m->f); + + /* Then, free buffer. */ + free(m->buf); +} + +FILE* memstream_init(MemStream *m) { + assert(m); + assert(!m->f); + + m->f = open_memstream_unlocked(&m->buf, &m->sz); + return m->f; +} + +int memstream_finalize(MemStream *m, char **ret_buf, size_t *ret_size) { + int r; + + assert(m); + assert(m->f); + assert(ret_buf); + + /* Add terminating NUL, so that the output buffer is a valid string. */ + fputc('\0', m->f); + + r = fflush_and_check(m->f); + if (r < 0) + return r; + + m->f = safe_fclose(m->f); + + /* On fclose(), the buffer may be reallocated, and may trigger OOM. */ + if (!m->buf) + return -ENOMEM; + + assert(m->sz > 0); + + *ret_buf = TAKE_PTR(m->buf); + if (ret_size) + *ret_size = m->sz - 1; + + m->sz = 0; /* For safety when the MemStream object will be reused later. */ + return 0; +} + +int memstream_dump_internal( + int level, + int error, + const char *file, + int line, + const char *func, + MemStream *m) { + + _cleanup_free_ char *buf = NULL; + int r; + + assert(m); + + r = memstream_finalize(m, &buf, NULL); + if (r < 0) + return log_full_errno(level, r, "Failed to flush memstream: %m: %m"); + + return log_dump_internal(level, error, file, line, func, buf); +} |