/* 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); }