From 76267654ebd43c1dfa28aa290b0d320df9781b2d Mon Sep 17 00:00:00 2001 From: David Oberhollenzer Date: Tue, 30 Apr 2019 20:24:42 +0200 Subject: Move abstract squashfs I/O code to libsquashfs.a Signed-off-by: David Oberhollenzer --- lib/sqfs/meta_writer.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 lib/sqfs/meta_writer.c (limited to 'lib/sqfs') diff --git a/lib/sqfs/meta_writer.c b/lib/sqfs/meta_writer.c new file mode 100644 index 0000000..95092d5 --- /dev/null +++ b/lib/sqfs/meta_writer.c @@ -0,0 +1,93 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +#include "meta_writer.h" +#include "squashfs.h" +#include "util.h" + +#include +#include +#include +#include + +meta_writer_t *meta_writer_create(int fd, compressor_t *cmp) +{ + meta_writer_t *m = calloc(1, sizeof(*m)); + + if (m == NULL) { + perror("creating meta data writer"); + return NULL; + } + + m->cmp = cmp; + m->outfd = fd; + return m; +} + +void meta_writer_destroy(meta_writer_t *m) +{ + free(m); +} + +int meta_writer_flush(meta_writer_t *m) +{ + ssize_t ret, count; + + if (m->offset == 0) + return 0; + + ret = m->cmp->do_block(m->cmp, m->data + 2, m->offset); + if (ret < 0) + return -1; + + if (ret > 0) { + ((uint16_t *)m->data)[0] = htole16(ret); + count = ret + 2; + } else { + ((uint16_t *)m->data)[0] = htole16(m->offset | 0x8000); + count = m->offset + 2; + } + + ret = write_retry(m->outfd, m->data, count); + + if (ret < 0) { + perror("writing meta data"); + return -1; + } + + if (ret < count) { + fputs("meta data written to file was truncated\n", stderr); + return -1; + } + + memset(m->data, 0, sizeof(m->data)); + m->offset = 0; + m->block_offset += count; + return 0; +} + +int meta_writer_append(meta_writer_t *m, const void *data, size_t size) +{ + size_t diff; + + while (size != 0) { + diff = sizeof(m->data) - 2 - m->offset; + + if (diff == 0) { + if (meta_writer_flush(m)) + return -1; + diff = sizeof(m->data) - 2; + } + + if (diff > size) + diff = size; + + memcpy(m->data + 2 + m->offset, data, diff); + m->offset += diff; + size -= diff; + data = (const char *)data + diff; + } + + if (m->offset == (sizeof(m->data) - 2)) + return meta_writer_flush(m); + + return 0; +} -- cgit v1.2.3