diff --git a/sqfs/squashfs.h b/include/sqfs/squashfs.h similarity index 77% rename from sqfs/squashfs.h rename to include/sqfs/squashfs.h index 0869bee..e8c889f 100644 --- a/sqfs/squashfs.h +++ b/include/sqfs/squashfs.h @@ -2,6 +2,9 @@ #ifndef SQUASHFS_H #define SQUASHFS_H +#include "comp/compressor.h" +#include "pkg/pkgformat.h" + #include #define SQFS_MAGIC 0x73717368 @@ -160,4 +163,36 @@ typedef enum { SQFS_INODE_EXT_SOCKET = 14, } E_SQFS_INODE_TYPE; +typedef struct { + uint8_t data[SQFS_META_BLOCK_SIZE + 2]; + uint8_t scratch[SQFS_META_BLOCK_SIZE]; + size_t offset; + size_t written; + int outfd; + compressor_stream_t *strm; +} meta_writer_t; + +int sqfs_super_init(sqfs_super_t *s, int64_t timestamp, + uint32_t blocksize, E_SQFS_COMPRESSOR comp); + +int sqfs_super_write(const sqfs_super_t *super, int outfd); + +compressor_stream_t *sqfs_get_compressor(sqfs_super_t *s); + +meta_writer_t *meta_writer_create(int fd, compressor_stream_t *strm); + +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); + +int sqfs_write_ids(int outfd, sqfs_super_t *super, + uint32_t *id_tbl, size_t count, + compressor_stream_t *strm); + +int sqfs_write_fragment_table(int outfd, sqfs_super_t *super, + sqfs_fragment_t *fragments, size_t count, + compressor_stream_t *strm); + #endif /* SQUASHFS_H */ diff --git a/lib/Makemodule.am b/lib/Makemodule.am index 9fa19f6..93092d9 100644 --- a/lib/Makemodule.am +++ b/lib/Makemodule.am @@ -33,4 +33,7 @@ libpkg_a_SOURCES += include/pkg/pkgio.h include/pkg/pkgwriter.h libpkg_a_SOURCES += lib/pkg/pkgreader.c lib/pkg/pkgwriter.c libpkg_a_SOURCES += lib/pkg/pkg_unpack.c lib/pkg/pkgio_rd_image_entry.c -noinst_LIBRARIES += libutil.a libfilelist.a libcomp.a libpkg.a +libsqfs_a_SOURCES = include/sqfs/squashfs.h lib/sqfs/super.c +libsqfs_a_SOURCES += lib/sqfs/meta_writer.c lib/sqfs/table.c + +noinst_LIBRARIES += libutil.a libfilelist.a libcomp.a libpkg.a libsqfs.a diff --git a/sqfs/meta_writer.c b/lib/sqfs/meta_writer.c similarity index 93% rename from sqfs/meta_writer.c rename to lib/sqfs/meta_writer.c index 95ae52e..49b3be5 100644 --- a/sqfs/meta_writer.c +++ b/lib/sqfs/meta_writer.c @@ -1,5 +1,10 @@ /* SPDX-License-Identifier: ISC */ -#include "pkg2sqfs.h" +#include "sqfs/squashfs.h" +#include "util/util.h" + +#include +#include +#include meta_writer_t *meta_writer_create(int fd, compressor_stream_t *strm) { diff --git a/sqfs/super.c b/lib/sqfs/super.c similarity index 58% rename from sqfs/super.c rename to lib/sqfs/super.c index 6b6240d..334e887 100644 --- a/sqfs/super.c +++ b/lib/sqfs/super.c @@ -1,10 +1,11 @@ /* SPDX-License-Identifier: ISC */ #include #include +#include #include +#include "sqfs/squashfs.h" #include "util/util.h" -#include "pkg2sqfs.h" int sqfs_super_init(sqfs_super_t *s, int64_t timestamp, uint32_t blocksize, E_SQFS_COMPRESSOR comp) @@ -50,47 +51,47 @@ int sqfs_super_init(sqfs_super_t *s, int64_t timestamp, return 0; } -int sqfs_super_write(sqfs_info_t *info) +int sqfs_super_write(const sqfs_super_t *super, int outfd) { sqfs_super_t copy; ssize_t ret; off_t off; - copy.magic = htole32(info->super.magic); - copy.inode_count = htole32(info->super.inode_count); - copy.modification_time = htole32(info->super.modification_time); - copy.block_size = htole32(info->super.block_size); - copy.fragment_entry_count = htole32(info->super.fragment_entry_count); - copy.compression_id = htole16(info->super.compression_id); - copy.block_log = htole16(info->super.block_log); - copy.flags = htole16(info->super.flags); - copy.id_count = htole16(info->super.id_count); - copy.version_major = htole16(info->super.version_major); - copy.version_minor = htole16(info->super.version_minor); - copy.root_inode_ref = htole64(info->super.root_inode_ref); - copy.bytes_used = htole64(info->super.bytes_used); - copy.id_table_start = htole64(info->super.id_table_start); - copy.xattr_id_table_start = htole64(info->super.xattr_id_table_start); - copy.inode_table_start = htole64(info->super.inode_table_start); - copy.directory_table_start = htole64(info->super.directory_table_start); - copy.fragment_table_start = htole64(info->super.fragment_table_start); - copy.export_table_start = htole64(info->super.export_table_start); + copy.magic = htole32(super->magic); + copy.inode_count = htole32(super->inode_count); + copy.modification_time = htole32(super->modification_time); + copy.block_size = htole32(super->block_size); + copy.fragment_entry_count = htole32(super->fragment_entry_count); + copy.compression_id = htole16(super->compression_id); + copy.block_log = htole16(super->block_log); + copy.flags = htole16(super->flags); + copy.id_count = htole16(super->id_count); + copy.version_major = htole16(super->version_major); + copy.version_minor = htole16(super->version_minor); + copy.root_inode_ref = htole64(super->root_inode_ref); + copy.bytes_used = htole64(super->bytes_used); + copy.id_table_start = htole64(super->id_table_start); + copy.xattr_id_table_start = htole64(super->xattr_id_table_start); + copy.inode_table_start = htole64(super->inode_table_start); + copy.directory_table_start = htole64(super->directory_table_start); + copy.fragment_table_start = htole64(super->fragment_table_start); + copy.export_table_start = htole64(super->export_table_start); - off = lseek(info->outfd, 0, SEEK_SET); + off = lseek(outfd, 0, SEEK_SET); if (off == (off_t)-1) { - perror("seek on output file"); + perror("squashfs writing super block: seek on output file"); return -1; } - ret = write_retry(info->outfd, ©, sizeof(copy)); + ret = write_retry(outfd, ©, sizeof(copy)); if (ret < 0) { - perror("Error writing squashfs super block"); + perror("squashfs writing super block"); return -1; } if (ret == 0) { - fputs("Truncated write trying to write squashfs super block\n", + fputs("squashfs writing super block: truncated write\n", stderr); return -1; } diff --git a/lib/sqfs/table.c b/lib/sqfs/table.c new file mode 100644 index 0000000..20e789d --- /dev/null +++ b/lib/sqfs/table.c @@ -0,0 +1,92 @@ +/* SPDX-License-Identifier: ISC */ +#include "sqfs/squashfs.h" +#include "util/util.h" + +#include +#include + +static int sqfs_write_table(int outfd, sqfs_super_t *super, const void *data, + size_t entsize, size_t count, uint64_t *startblock, + compressor_stream_t *strm) +{ + size_t ent_per_blocks = SQFS_META_BLOCK_SIZE / entsize; + uint64_t blocks[count / ent_per_blocks + 1]; + size_t i, blkidx = 0, tblsize; + meta_writer_t *m; + ssize_t ret; + + /* Write actual data. Whenever we cross a block boundary, remember + the block start offset */ + m = meta_writer_create(outfd, strm); + if (m == NULL) + return -1; + + for (i = 0; i < count; ++i) { + if (blkidx == 0 || m->written > blocks[blkidx - 1]) + blocks[blkidx++] = m->written; + + if (meta_writer_append(m, data, entsize)) + goto fail; + + data = (const char *)data + entsize; + } + + if (meta_writer_flush(m)) + goto fail; + + for (i = 0; i < blkidx; ++i) + blocks[i] = htole64(blocks[i] + super->bytes_used); + + super->bytes_used += m->written; + meta_writer_destroy(m); + + /* write new index table */ + *startblock = super->bytes_used; + tblsize = sizeof(blocks[0]) * blkidx; + + ret = write_retry(outfd, blocks, tblsize); + if (ret < 0) { + perror("writing index table"); + return -1; + } + + if ((size_t)ret < tblsize) { + fputs("index table truncated\n", stderr); + return -1; + } + + super->bytes_used += tblsize; + return 0; +fail: + meta_writer_destroy(m); + return -1; +} + +int sqfs_write_fragment_table(int outfd, sqfs_super_t *super, + sqfs_fragment_t *fragments, size_t count, + compressor_stream_t *strm) +{ + super->fragment_entry_count = count; + + return sqfs_write_table(outfd, super, fragments, sizeof(fragments[0]), + count, &super->fragment_table_start, strm); +} + +int sqfs_write_ids(int outfd, sqfs_super_t *super, + uint32_t *id_tbl, size_t count, + compressor_stream_t *strm) +{ + size_t i; + int ret; + + for (i = 0; i < count; ++i) + id_tbl[i] = htole32(id_tbl[i]); + + ret = sqfs_write_table(outfd, super, id_tbl, sizeof(id_tbl[0]), + count, &super->id_table_start, strm); + + for (i = 0; i < count; ++i) + id_tbl[i] = htole32(id_tbl[i]); + + return ret; +} diff --git a/sqfs/Makemodule.am b/sqfs/Makemodule.am index ce0cbda..fa51f3d 100644 --- a/sqfs/Makemodule.am +++ b/sqfs/Makemodule.am @@ -1,9 +1,9 @@ -pkg2sqfs_SOURCES = sqfs/squashfs.h sqfs/super.c sqfs/pkg2sqfs.c +pkg2sqfs_SOURCES = sqfs/pkg2sqfs.c pkg2sqfs_SOURCES += sqfs/vfs.c sqfs/pkg2sqfs.h sqfs/block.c -pkg2sqfs_SOURCES += sqfs/meta.c sqfs/meta_writer.c sqfs/table.c +pkg2sqfs_SOURCES += sqfs/meta.c pkg2sqfs_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/sqfs pkg2sqfs_CFLAGS = $(AM_CFLAGS) -pkg2sqfs_LDADD = libpkg.a libutil.a libfilelist.a libcomp.a +pkg2sqfs_LDADD = libsqfs.a libpkg.a libutil.a libfilelist.a libcomp.a if WITH_LZMA pkg2sqfs_LDADD += $(XZ_LIBS) diff --git a/sqfs/pkg2sqfs.c b/sqfs/pkg2sqfs.c index 2018d0b..f0d7418 100644 --- a/sqfs/pkg2sqfs.c +++ b/sqfs/pkg2sqfs.c @@ -269,7 +269,7 @@ int main(int argc, char **argv) if (create_vfs_tree(&info)) goto out_buffer; - if (sqfs_super_write(&info)) + if (sqfs_super_write(&info.super, info.outfd)) goto out_tree; if (pkg_data_to_sqfs(&info, cmp)) @@ -281,13 +281,16 @@ int main(int argc, char **argv) if (sqfs_write_inodes(&info, cmp)) goto out_fragments; - if (sqfs_write_fragment_table(&info, cmp)) + if (sqfs_write_fragment_table(info.outfd, &info.super, + info.fragments, info.num_fragments, + cmp)) goto out_fragments; - if (sqfs_write_ids(&info, cmp)) + if (sqfs_write_ids(info.outfd, &info.super, + info.fs.id_tbl, info.fs.num_ids, cmp)) goto out_fragments; - if (sqfs_super_write(&info)) + if (sqfs_super_write(&info.super, info.outfd)) goto out_fragments; if (sqfs_padd_file(&info)) diff --git a/sqfs/pkg2sqfs.h b/sqfs/pkg2sqfs.h index 82ef1ec..33b9981 100644 --- a/sqfs/pkg2sqfs.h +++ b/sqfs/pkg2sqfs.h @@ -23,20 +23,11 @@ #include "filelist/image_entry.h" #include "comp/compressor.h" #include "pkg/pkgreader.h" +#include "sqfs/squashfs.h" #include "pkg/pkgio.h" -#include "squashfs.h" #include "config.h" -typedef struct { - uint8_t data[SQFS_META_BLOCK_SIZE + 2]; - uint8_t scratch[SQFS_META_BLOCK_SIZE]; - size_t offset; - size_t written; - int outfd; - compressor_stream_t *strm; -} meta_writer_t; - typedef struct file_info_t { struct file_info_t *frag_next; uint64_t size; @@ -112,11 +103,6 @@ typedef struct { int pkg_data_to_sqfs(sqfs_info_t *info, compressor_stream_t *strm); -int sqfs_super_init(sqfs_super_t *s, int64_t timestamp, - uint32_t blocksize, E_SQFS_COMPRESSOR comp); - -int sqfs_super_write(sqfs_info_t *info); - int create_vfs_tree(sqfs_info_t *info); void destroy_vfs_tree(vfs_t *fs); @@ -125,18 +111,4 @@ node_t *vfs_node_from_file_id(vfs_t *fs, uint32_t id); int sqfs_write_inodes(sqfs_info_t *info, compressor_stream_t *strm); -int sqfs_write_ids(sqfs_info_t *info, compressor_stream_t *strm); - -int sqfs_write_fragment_table(sqfs_info_t *info, compressor_stream_t *strm); - -meta_writer_t *meta_writer_create(int fd, compressor_stream_t *strm); - -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); - -compressor_stream_t *sqfs_get_compressor(sqfs_super_t *s); - #endif /* PKG2SQFS_H */ diff --git a/sqfs/table.c b/sqfs/table.c deleted file mode 100644 index c3fa2b5..0000000 --- a/sqfs/table.c +++ /dev/null @@ -1,77 +0,0 @@ -/* SPDX-License-Identifier: ISC */ -#include "pkg2sqfs.h" - -static int sqfs_write_table(sqfs_info_t *info, const void *data, - size_t entsize, size_t count, uint64_t *startblock, - compressor_stream_t *strm) -{ - size_t ent_per_blocks = SQFS_META_BLOCK_SIZE / entsize; - uint64_t blocks[count / ent_per_blocks + 1]; - size_t i, blkidx = 0, tblsize; - meta_writer_t *m; - ssize_t ret; - - /* Write actual data. Whenever we cross a block boundary, remember - the block start offset */ - m = meta_writer_create(info->outfd, strm); - if (m == NULL) - return -1; - - for (i = 0; i < count; ++i) { - if (blkidx == 0 || m->written > blocks[blkidx - 1]) - blocks[blkidx++] = m->written; - - if (meta_writer_append(m, data, entsize)) - goto fail; - - data = (const char *)data + entsize; - } - - if (meta_writer_flush(m)) - goto fail; - - for (i = 0; i < blkidx; ++i) - blocks[i] = htole64(blocks[i] + info->super.bytes_used); - - info->super.bytes_used += m->written; - meta_writer_destroy(m); - - /* write new index table */ - *startblock = info->super.bytes_used; - tblsize = sizeof(blocks[0]) * blkidx; - - ret = write_retry(info->outfd, blocks, tblsize); - if (ret < 0) { - perror("writing index table"); - return -1; - } - - if ((size_t)ret < tblsize) { - fputs("index table truncated\n", stderr); - return -1; - } - - info->super.bytes_used += tblsize; - return 0; -fail: - meta_writer_destroy(m); - return -1; -} - -int sqfs_write_fragment_table(sqfs_info_t *info, compressor_stream_t *strm) -{ - info->super.fragment_entry_count = info->num_fragments; - - return sqfs_write_table(info, info->fragments, - sizeof(info->fragments[0]), - info->num_fragments, - &info->super.fragment_table_start, strm); -} - -int sqfs_write_ids(sqfs_info_t *info, compressor_stream_t *strm) -{ - return sqfs_write_table(info, info->fs.id_tbl, - sizeof(info->fs.id_tbl[0]), - info->fs.num_ids, - &info->super.id_table_start, strm); -} diff --git a/sqfs/vfs.c b/sqfs/vfs.c index f3b17c8..581aebf 100644 --- a/sqfs/vfs.c +++ b/sqfs/vfs.c @@ -316,7 +316,6 @@ int create_vfs_tree(sqfs_info_t *info) uint32_t counter = 2; vfs_t *fs = &info->fs; node_t *n; - size_t i; if (image_entry_list_from_package(info->rd, &list)) return -1; @@ -351,10 +350,6 @@ int create_vfs_tree(sqfs_info_t *info) info->super.id_count = fs->num_ids; image_entry_free_list(list); - - for (i = 0; i < fs->num_ids; ++i) - fs->id_tbl[i] = htole32(fs->id_tbl[i]); - return 0; fail_oom: fputs("out of memory\n", stderr);