diff options
-rw-r--r-- | mkfs/Makemodule.am | 3 | ||||
-rw-r--r-- | mkfs/meta_writer.c | 92 | ||||
-rw-r--r-- | mkfs/meta_writer.h | 24 | ||||
-rw-r--r-- | mkfs/options.c | 3 |
4 files changed, 120 insertions, 2 deletions
diff --git a/mkfs/Makemodule.am b/mkfs/Makemodule.am index ad3f166..7b0b353 100644 --- a/mkfs/Makemodule.am +++ b/mkfs/Makemodule.am @@ -1,6 +1,7 @@ mksquashfs_SOURCES = mkfs/mksquashfs.c mkfs/options.c mkfs/options.h +mksquashfs_SOURCES += mkfs/meta_writer.c mkfs/meta_writer.h mksquashfs_SOURCES += include/squashfs.h -mksquashfs_LDADD = libfstree.a libcompress.a +mksquashfs_LDADD = libutil.a libfstree.a libcompress.a if WITH_LZMA mksquashfs_LDADD += $(XZ_LIBS) diff --git a/mkfs/meta_writer.c b/mkfs/meta_writer.c new file mode 100644 index 0000000..97db1c1 --- /dev/null +++ b/mkfs/meta_writer.c @@ -0,0 +1,92 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +#include "meta_writer.h" +#include "util.h" + +#include <string.h> +#include <stdlib.h> +#include <unistd.h> +#include <stdio.h> + +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; +} diff --git a/mkfs/meta_writer.h b/mkfs/meta_writer.h new file mode 100644 index 0000000..bfa4160 --- /dev/null +++ b/mkfs/meta_writer.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +#ifndef META_WRITER_H +#define META_WRITER_H + +#include "squashfs.h" +#include "compress.h" + +typedef struct { + uint8_t data[SQFS_META_BLOCK_SIZE + 2]; + size_t offset; + size_t block_offset; + int outfd; + compressor_t *cmp; +} meta_writer_t; + +meta_writer_t *meta_writer_create(int fd, compressor_t *cmp); + +void meta_writer_destroy(meta_writer_t *m); + +int meta_writer_flush(meta_writer_t *m); + +int meta_writer_append(meta_writer_t *m, const void *data, size_t size); + +#endif /* META_WRITER_H */ diff --git a/mkfs/options.c b/mkfs/options.c index e3371aa..fedf404 100644 --- a/mkfs/options.c +++ b/mkfs/options.c @@ -263,7 +263,8 @@ void process_command_line(options_t *opt, int argc, char **argv) break; case 'b': opt->blksz = read_number("Block size", optarg, - 1024, 0xFFFFFFFF); + SQFS_META_BLOCK_SIZE, + 0xFFFFFFFF); break; case 'B': opt->devblksz = read_number("Device block size", optarg, |