diff options
author | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2019-09-08 14:53:30 +0200 |
---|---|---|
committer | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2019-09-08 14:53:30 +0200 |
commit | 3a851dfe87c88ac1d4dddc2a26cc48b037f852f9 (patch) | |
tree | a8a8f34291aa58b25737088d247a91a7f60b4fec | |
parent | 60064dd0412a149fe00cfc4e2f2361c22656db57 (diff) |
Replace direct file I/O with abstraction layer
This should make it easier to use libsquashfs with custom setups that
embedd a squashfs image inside something else. Also, it should make
it easier to port to non unix-like platforms.
Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
42 files changed, 451 insertions, 219 deletions
diff --git a/include/data_reader.h b/include/data_reader.h index a45c3e2..846ffd1 100644 --- a/include/data_reader.h +++ b/include/data_reader.h @@ -23,7 +23,7 @@ typedef struct data_reader_t data_reader_t; Prints error messsages to stderr on failure. */ -data_reader_t *data_reader_create(int fd, sqfs_super_t *super, +data_reader_t *data_reader_create(sqfs_file_t *file, sqfs_super_t *super, sqfs_compressor_t *cmp); void data_reader_destroy(data_reader_t *data); diff --git a/include/data_writer.h b/include/data_writer.h index 89eb2c8..4d86bbf 100644 --- a/include/data_writer.h +++ b/include/data_writer.h @@ -36,7 +36,7 @@ enum { Returns NULL on failure and prints errors to stderr. */ data_writer_t *data_writer_create(sqfs_super_t *super, sqfs_compressor_t *cmp, - int outfd, size_t devblksize, + sqfs_file_t *file, size_t devblksize, unsigned int num_jobs); void data_writer_destroy(data_writer_t *data); diff --git a/include/highlevel.h b/include/highlevel.h index ffcc44c..4c560f7 100644 --- a/include/highlevel.h +++ b/include/highlevel.h @@ -17,6 +17,7 @@ #include "sqfs/meta_writer.h" #include "sqfs/xattr.h" #include "sqfs/dir.h" +#include "sqfs/io.h" #include "data_reader.h" #include "fstree.h" @@ -26,9 +27,9 @@ typedef struct { sqfs_compressor_t *cmp; data_reader_t *data; + sqfs_file_t *file; sqfs_super_t super; fstree_t fs; - int sqfsfd; } sqfs_reader_t; enum RDTREE_FLAGS { @@ -52,7 +53,7 @@ enum RDTREE_FLAGS { Returns 0 on success. Prints error messages to stderr on failure. */ -int sqfs_serialize_fstree(int outfd, sqfs_super_t *super, fstree_t *fs, +int sqfs_serialize_fstree(sqfs_file_t *file, sqfs_super_t *super, fstree_t *fs, sqfs_compressor_t *cmp, sqfs_id_table_t *idtbl); /* @@ -72,14 +73,14 @@ tree_node_t *tree_node_from_inode(sqfs_inode_generic_t *inode, Returns 0 on success. Prints error messages to stderr on failure. */ int deserialize_fstree(fstree_t *out, sqfs_super_t *super, - sqfs_compressor_t *cmp, int fd, int flags); + sqfs_compressor_t *cmp, sqfs_file_t *file, int flags); /* Generate a squahfs xattr table from a file system tree. Returns 0 on success. Prints error messages to stderr on failure. */ -int write_xattr(int outfd, fstree_t *fs, sqfs_super_t *super, +int write_xattr(sqfs_file_t *file, fstree_t *fs, sqfs_super_t *super, sqfs_compressor_t *cmp); /* @@ -87,7 +88,7 @@ int write_xattr(int outfd, fstree_t *fs, sqfs_super_t *super, Returns 0 on success. Prints error messages to stderr on failure. */ -int write_export_table(int outfd, fstree_t *fs, sqfs_super_t *super, +int write_export_table(sqfs_file_t *file, fstree_t *fs, sqfs_super_t *super, sqfs_compressor_t *cmp); /* Print out fancy statistics for squashfs packing tools */ diff --git a/include/sqfs/compress.h b/include/sqfs/compress.h index f0e3b76..e781e02 100644 --- a/include/sqfs/compress.h +++ b/include/sqfs/compress.h @@ -18,12 +18,12 @@ struct sqfs_compressor_t { /* Write compressor options to the output file if necessary. Returns the number of bytes written or -1 on failure. Internally prints error messages to stderr. */ - int (*write_options)(sqfs_compressor_t *cmp, int fd); + int (*write_options)(sqfs_compressor_t *cmp, sqfs_file_t *file); /* Read compressor options to the input file. Returns zero on success, -1 on failure. Internally prints error messages to stderr. */ - int (*read_options)(sqfs_compressor_t *cmp, int fd); + int (*read_options)(sqfs_compressor_t *cmp, sqfs_file_t *file); /* Compress or uncompress a chunk of data. diff --git a/include/sqfs/id_table.h b/include/sqfs/id_table.h index 3610640..6b058ae 100644 --- a/include/sqfs/id_table.h +++ b/include/sqfs/id_table.h @@ -25,12 +25,12 @@ SQFS_API int sqfs_id_table_id_to_index(sqfs_id_table_t *tbl, uint32_t id, /* Write an ID table to a SquashFS image. Returns 0 on success. Internally prints error message to stderr. */ -SQFS_API int sqfs_id_table_write(sqfs_id_table_t *tbl, int outfd, +SQFS_API int sqfs_id_table_write(sqfs_id_table_t *tbl, sqfs_file_t *file, sqfs_super_t *super, sqfs_compressor_t *cmp); /* Read an ID table from a SquashFS image. Returns 0 on success. Internally prints error messages to stderr. */ -SQFS_API int sqfs_id_table_read(sqfs_id_table_t *tbl, int fd, +SQFS_API int sqfs_id_table_read(sqfs_id_table_t *tbl, sqfs_file_t *file, sqfs_super_t *super, sqfs_compressor_t *cmp); SQFS_API int sqfs_id_table_index_to_id(const sqfs_id_table_t *tbl, diff --git a/include/sqfs/io.h b/include/sqfs/io.h new file mode 100644 index 0000000..f290c2d --- /dev/null +++ b/include/sqfs/io.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * io.h + * + * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at> + */ +#ifndef SQFS_IO_H +#define SQFS_IO_H + +#include "sqfs/predef.h" + +typedef enum { + SQFS_FILE_OPEN_READ_ONLY = 0x01, + + SQFS_FILE_OPEN_OVERWRITE = 0x02, + + SQFS_FILE_OPEN_ALL_FLAGS = 0x03, +} E_SQFS_FILE_OPEN_FLAGS; + +struct sqfs_file_t { + void (*destroy)(sqfs_file_t *file); + + int (*read_at)(sqfs_file_t *file, uint64_t offset, + void *buffer, size_t size); + + int (*write_at)(sqfs_file_t *file, uint64_t offset, + const void *buffer, size_t size); + + uint64_t (*get_size)(sqfs_file_t *file); + + int (*truncate)(sqfs_file_t *file, uint64_t size); +}; + +#ifdef __cplusplus +extern "C" { +#endif + +SQFS_API sqfs_file_t *sqfs_open_file(const char *filename, int flags); + +#ifdef __cplusplus +} +#endif + +#endif /* SQFS_IO_H */ diff --git a/include/sqfs/meta_reader.h b/include/sqfs/meta_reader.h index f5008d4..00a6d65 100644 --- a/include/sqfs/meta_reader.h +++ b/include/sqfs/meta_reader.h @@ -19,7 +19,7 @@ extern "C" { Start offset and limit can be specified to do bounds checking against a subregion of the filesystem image. */ -SQFS_API sqfs_meta_reader_t *sqfs_meta_reader_create(int fd, +SQFS_API sqfs_meta_reader_t *sqfs_meta_reader_create(sqfs_file_t *file, sqfs_compressor_t *cmp, uint64_t start, uint64_t limit); diff --git a/include/sqfs/meta_writer.h b/include/sqfs/meta_writer.h index 9cd1598..3b255f2 100644 --- a/include/sqfs/meta_writer.h +++ b/include/sqfs/meta_writer.h @@ -18,7 +18,7 @@ extern "C" { If keep_in_mem is true, the blocks are collected in memory and must be explicitly flushed to disk using meta_write_write_to_file. */ -SQFS_API sqfs_meta_writer_t *sqfs_meta_writer_create(int fd, +SQFS_API sqfs_meta_writer_t *sqfs_meta_writer_create(sqfs_file_t *file, sqfs_compressor_t *cmp, bool keep_in_mem); diff --git a/include/sqfs/predef.h b/include/sqfs/predef.h index 6df257c..df08b1b 100644 --- a/include/sqfs/predef.h +++ b/include/sqfs/predef.h @@ -47,6 +47,7 @@ typedef struct sqfs_id_table_t sqfs_id_table_t; typedef struct sqfs_meta_reader_t sqfs_meta_reader_t; typedef struct sqfs_meta_writer_t sqfs_meta_writer_t; typedef struct sqfs_xattr_reader_t sqfs_xattr_reader_t; +typedef struct sqfs_file_t sqfs_file_t; typedef struct sqfs_fragment_t sqfs_fragment_t; typedef struct sqfs_dir_header_t sqfs_dir_header_t; diff --git a/include/sqfs/super.h b/include/sqfs/super.h index b1ce82b..a8697a1 100644 --- a/include/sqfs/super.h +++ b/include/sqfs/super.h @@ -73,10 +73,10 @@ SQFS_API int sqfs_super_init(sqfs_super_t *super, size_t block_size, E_SQFS_COMPRESSOR compressor); /* Returns 0 on success. Prints error messages to stderr on failure. */ -SQFS_API int sqfs_super_write(sqfs_super_t *super, int fd); +SQFS_API int sqfs_super_write(sqfs_super_t *super, sqfs_file_t *file); /* Returns 0 on success. Prints error messages to stderr on failure. */ -SQFS_API int sqfs_super_read(sqfs_super_t *super, int fd); +SQFS_API int sqfs_super_read(sqfs_super_t *super, sqfs_file_t *file); #ifdef __cplusplus } diff --git a/include/sqfs/table.h b/include/sqfs/table.h index f837f6b..7767b9a 100644 --- a/include/sqfs/table.h +++ b/include/sqfs/table.h @@ -24,12 +24,12 @@ extern "C" { Returns 0 on success. Internally prints error messages to stderr. */ -SQFS_API int sqfs_write_table(int outfd, sqfs_super_t *super, +SQFS_API int sqfs_write_table(sqfs_file_t *file, sqfs_super_t *super, sqfs_compressor_t *cmp, const void *data, size_t table_size, uint64_t *start); -SQFS_API int sqfs_read_table(int fd, sqfs_compressor_t *cmp, +SQFS_API int sqfs_read_table(sqfs_file_t *file, sqfs_compressor_t *cmp, size_t table_size, uint64_t location, uint64_t lower_limit, uint64_t upper_limit, void **out); diff --git a/include/sqfs/xattr.h b/include/sqfs/xattr.h index 0f9cf32..23587d1 100644 --- a/include/sqfs/xattr.h +++ b/include/sqfs/xattr.h @@ -58,7 +58,7 @@ SQFS_API int sqfs_xattr_reader_load_locations(sqfs_xattr_reader_t *xr); SQFS_API void sqfs_xattr_reader_destroy(sqfs_xattr_reader_t *xr); -SQFS_API sqfs_xattr_reader_t *sqfs_xattr_reader_create(int sqfsfd, +SQFS_API sqfs_xattr_reader_t *sqfs_xattr_reader_create(sqfs_file_t *file, sqfs_super_t *super, sqfs_compressor_t *cmp); diff --git a/include/util.h b/include/util.h index 93b8a04..e2089da 100644 --- a/include/util.h +++ b/include/util.h @@ -109,6 +109,9 @@ int popd(void); SQFS_INTERNAL int padd_file(int outfd, uint64_t size, size_t blocksize); +SQFS_INTERNAL +int padd_sqfs(sqfs_file_t *file, uint64_t size, size_t blocksize); + /* Helper for allocating data structures with flexible array members. diff --git a/lib/Makemodule.am b/lib/Makemodule.am index e071fd0..4afcae6 100644 --- a/lib/Makemodule.am +++ b/lib/Makemodule.am @@ -48,13 +48,13 @@ libsquashfs_la_SOURCES += include/sqfs/compress.h include/sqfs/block_processor.h libsquashfs_la_SOURCES += include/sqfs/super.h include/sqfs/inode.h libsquashfs_la_SOURCES += include/sqfs/dir.h include/sqfs/xattr.h libsquashfs_la_SOURCES += include/sqfs/table.h include/sqfs/predef.h -libsquashfs_la_SOURCES += include/sqfs/error.h +libsquashfs_la_SOURCES += include/sqfs/error.h include/sqfs/io.h libsquashfs_la_SOURCES += lib/sqfs/meta_writer.c lib/sqfs/super.c libsquashfs_la_SOURCES += lib/sqfs/id_table.c lib/sqfs/dir_writer.c libsquashfs_la_SOURCES += lib/sqfs/write_table.c include/highlevel.h libsquashfs_la_SOURCES += lib/sqfs/read_super.c lib/sqfs/meta_reader.c libsquashfs_la_SOURCES += lib/sqfs/read_inode.c lib/sqfs/write_inode.c -libsquashfs_la_SOURCES += lib/sqfs/readdir.c +libsquashfs_la_SOURCES += lib/sqfs/readdir.c lib/sqfs/io.c libsquashfs_la_SOURCES += lib/sqfs/xattr.c lib/sqfs/xattr_reader.c libsquashfs_la_SOURCES += lib/sqfs/read_table.c libsquashfs_la_SOURCES += lib/sqfs/comp/compressor.c lib/sqfs/comp/internal.h @@ -112,7 +112,7 @@ sqfsinclude_HEADERS += include/sqfs/compress.h include/sqfs/block_processor.h sqfsinclude_HEADERS += include/sqfs/super.h include/sqfs/inode.h sqfsinclude_HEADERS += include/sqfs/dir.h include/sqfs/xattr.h sqfsinclude_HEADERS += include/sqfs/table.h include/sqfs/predef.h -sqfsinclude_HEADERS += include/sqfs/error.h +sqfsinclude_HEADERS += include/sqfs/error.h include/sqfs/io.h noinst_LIBRARIES += libfstree.a libtar.a libsqfshelper.a noinst_LTLIBRARIES += libutil.la diff --git a/lib/sqfs/comp/compressor.c b/lib/sqfs/comp/compressor.c index 4d073f2..c938fe2 100644 --- a/lib/sqfs/comp/compressor.c +++ b/lib/sqfs/comp/compressor.c @@ -43,29 +43,31 @@ static const char *names[] = { [SQFS_COMP_ZSTD] = "zstd", }; -int sqfs_generic_write_options(int fd, const void *data, size_t size) +int sqfs_generic_write_options(sqfs_file_t *file, const void *data, size_t size) { uint8_t buffer[size + 2]; + int ret; *((uint16_t *)buffer) = htole16(0x8000 | size); memcpy(buffer + 2, data, size); - if (write_data("writing compressor options", - fd, buffer, sizeof(buffer))) { - return SQFS_ERROR_IO; - } + ret = file->write_at(file, sizeof(sqfs_super_t), + buffer, sizeof(buffer)); + if (ret) + return ret; return sizeof(buffer); } -int sqfs_generic_read_options(int fd, void *data, size_t size) +int sqfs_generic_read_options(sqfs_file_t *file, void *data, size_t size) { uint8_t buffer[size + 2]; + int ret; - if (read_data_at("reading compressor options", sizeof(sqfs_super_t), - fd, buffer, sizeof(buffer))) { - return SQFS_ERROR_IO; - } + ret = file->read_at(file, sizeof(sqfs_super_t), + buffer, sizeof(buffer)); + if (ret) + return ret; if (le16toh(*((uint16_t *)buffer)) != (0x8000 | size)) return SQFS_ERROR_CORRUPTED; diff --git a/lib/sqfs/comp/gzip.c b/lib/sqfs/comp/gzip.c index 484901a..bec217a 100644 --- a/lib/sqfs/comp/gzip.c +++ b/lib/sqfs/comp/gzip.c @@ -44,7 +44,7 @@ static void gzip_destroy(sqfs_compressor_t *base) free(gzip); } -static int gzip_write_options(sqfs_compressor_t *base, int fd) +static int gzip_write_options(sqfs_compressor_t *base, sqfs_file_t *file) { gzip_compressor_t *gzip = (gzip_compressor_t *)base; gzip_options_t opt; @@ -59,16 +59,16 @@ static int gzip_write_options(sqfs_compressor_t *base, int fd) opt.window = htole16(gzip->opt.window); opt.strategies = htole16(gzip->opt.strategies); - return sqfs_generic_write_options(fd, &opt, sizeof(opt)); + return sqfs_generic_write_options(file, &opt, sizeof(opt)); } -static int gzip_read_options(sqfs_compressor_t *base, int fd) +static int gzip_read_options(sqfs_compressor_t *base, sqfs_file_t *file) { gzip_compressor_t *gzip = (gzip_compressor_t *)base; gzip_options_t opt; int ret; - ret = sqfs_generic_read_options(fd, &opt, sizeof(opt)); + ret = sqfs_generic_read_options(file, &opt, sizeof(opt)); if (ret) return ret; diff --git a/lib/sqfs/comp/internal.h b/lib/sqfs/comp/internal.h index d2410fc..29b875f 100644 --- a/lib/sqfs/comp/internal.h +++ b/lib/sqfs/comp/internal.h @@ -12,13 +12,15 @@ #include "sqfs/predef.h" #include "sqfs/compress.h" #include "sqfs/error.h" +#include "sqfs/io.h" #include "util.h" SQFS_INTERNAL -int sqfs_generic_write_options(int fd, const void *data, size_t size); +int sqfs_generic_write_options(sqfs_file_t *file, const void *data, + size_t size); SQFS_INTERNAL -int sqfs_generic_read_options(int fd, void *data, size_t size); +int sqfs_generic_read_options(sqfs_file_t *file, void *data, size_t size); SQFS_INTERNAL sqfs_compressor_t *xz_compressor_create(const sqfs_compressor_config_t *cfg); diff --git a/lib/sqfs/comp/lz4.c b/lib/sqfs/comp/lz4.c index 446b83e..e96ab45 100644 --- a/lib/sqfs/comp/lz4.c +++ b/lib/sqfs/comp/lz4.c @@ -28,7 +28,7 @@ typedef struct { #define LZ4LEGACY 1 -static int lz4_write_options(sqfs_compressor_t *base, int fd) +static int lz4_write_options(sqfs_compressor_t *base, sqfs_file_t *file) { lz4_compressor_t *lz4 = (lz4_compressor_t *)base; lz4_options opt = { @@ -37,16 +37,16 @@ static int lz4_write_options(sqfs_compressor_t *base, int fd) SQFS_COMP_FLAG_LZ4_HC : 0), }; - return sqfs_generic_write_options(fd, &opt, sizeof(opt)); + return sqfs_generic_write_options(file, &opt, sizeof(opt)); } -static int lz4_read_options(sqfs_compressor_t *base, int fd) +static int lz4_read_options(sqfs_compressor_t *base, sqfs_file_t *file) { lz4_options opt; int ret; (void)base; - ret = sqfs_generic_read_options(fd, &opt, sizeof(opt)); + ret = sqfs_generic_read_options(file, &opt, sizeof(opt)); if (ret) return ret; diff --git a/lib/sqfs/comp/lzo.c b/lib/sqfs/comp/lzo.c index b4cfebf..e4a7ca6 100644 --- a/lib/sqfs/comp/lzo.c +++ b/lib/sqfs/comp/lzo.c @@ -59,7 +59,7 @@ typedef struct { uint32_t level; } lzo_options_t; -static int lzo_write_options(sqfs_compressor_t *base, int fd) +static int lzo_write_options(sqfs_compressor_t *base, sqfs_file_t *file) { lzo_compressor_t *lzo = (lzo_compressor_t *)base; lzo_options_t opt; @@ -77,16 +77,16 @@ static int lzo_write_options(sqfs_compressor_t *base, int fd) opt.level = 0; } - return sqfs_generic_write_options(fd, &opt, sizeof(opt)); + return sqfs_generic_write_options(file, &opt, sizeof(opt)); } -static int lzo_read_options(sqfs_compressor_t *base, int fd) +static int lzo_read_options(sqfs_compressor_t *base, sqfs_file_t *file) { lzo_compressor_t *lzo = (lzo_compressor_t *)base; lzo_options_t opt; int ret; - ret = sqfs_generic_read_options(fd, &opt, sizeof(opt)); + ret = sqfs_generic_read_options(file, &opt, sizeof(opt)); if (ret) return ret; diff --git a/lib/sqfs/comp/xz.c b/lib/sqfs/comp/xz.c index c626f92..24602ec 100644 --- a/lib/sqfs/comp/xz.c +++ b/lib/sqfs/comp/xz.c @@ -36,7 +36,7 @@ static bool is_dict_size_valid(size_t size) return size == (x | (x >> 1)); } -static int xz_write_options(sqfs_compressor_t *base, int fd) +static int xz_write_options(sqfs_compressor_t *base, sqfs_file_t *file) { xz_compressor_t *xz = (xz_compressor_t *)base; xz_options_t opt; @@ -47,16 +47,16 @@ static int xz_write_options(sqfs_compressor_t *base, int fd) opt.dict_size = htole32(xz->dict_size); opt.flags = htole32(xz->flags); - return sqfs_generic_write_options(fd, &opt, sizeof(opt)); + return sqfs_generic_write_options(file, &opt, sizeof(opt)); } -static int xz_read_options(sqfs_compressor_t *base, int fd) +static int xz_read_options(sqfs_compressor_t *base, sqfs_file_t *file) { xz_compressor_t *xz = (xz_compressor_t *)base; xz_options_t opt; int ret; - ret = sqfs_generic_read_options(fd, &opt, sizeof(opt)); + ret = sqfs_generic_read_options(file, &opt, sizeof(opt)); if (ret) return ret; diff --git a/lib/sqfs/comp/zstd.c b/lib/sqfs/comp/zstd.c index dc2387d..5434e1f 100644 --- a/lib/sqfs/comp/zstd.c +++ b/lib/sqfs/comp/zstd.c @@ -25,26 +25,25 @@ typedef struct { uint32_t level; } zstd_options_t; -static int zstd_write_options(sqfs_compressor_t *base, int fd) +static int zstd_write_options(sqfs_compressor_t *base, sqfs_file_t *file) { zstd_compressor_t *zstd = (zstd_compressor_t *)base; zstd_options_t opt; - (void)fd; if (zstd->level == SQFS_ZSTD_DEFAULT_LEVEL) return 0; opt.level = htole32(zstd->level); - return sqfs_generic_write_options(fd, &opt, sizeof(opt)); + return sqfs_generic_write_options(file, &opt, sizeof(opt)); } -static int zstd_read_options(sqfs_compressor_t *base, int fd) +static int zstd_read_options(sqfs_compressor_t *base, sqfs_file_t *file) { zstd_options_t opt; int ret; (void)base; - ret = sqfs_generic_read_options(fd, &opt, sizeof(opt)); + ret = sqfs_generic_read_options(file, &opt, sizeof(opt)); if (ret) return ret; diff --git a/lib/sqfs/id_table.c b/lib/sqfs/id_table.c index 496049e..34db8f7 100644 --- a/lib/sqfs/id_table.c +++ b/lib/sqfs/id_table.c @@ -73,8 +73,8 @@ int sqfs_id_table_index_to_id(const sqfs_id_table_t *tbl, uint16_t index, return 0; } -int sqfs_id_table_read(sqfs_id_table_t *tbl, int fd, sqfs_super_t *super, - sqfs_compressor_t *cmp) +int sqfs_id_table_read(sqfs_id_table_t *tbl, sqfs_file_t *file, + sqfs_super_t *super, sqfs_compressor_t *cmp) { uint64_t upper_limit, lower_limit; void *raw_ids; @@ -106,7 +106,7 @@ int sqfs_id_table_read(sqfs_id_table_t *tbl, int fd, sqfs_super_t *super, tbl->num_ids = super->id_count; tbl->max_ids = super->id_count; - ret = sqfs_read_table(fd, cmp, tbl->num_ids * sizeof(uint32_t), + ret = sqfs_read_table(file, cmp, tbl->num_ids * sizeof(uint32_t), super->id_table_start, lower_limit, upper_limit, &raw_ids); if (ret) @@ -120,8 +120,8 @@ int sqfs_id_table_read(sqfs_id_table_t *tbl, int fd, sqfs_super_t *super, return 0; } -int sqfs_id_table_write(sqfs_id_table_t *tbl, int outfd, sqfs_super_t *super, - sqfs_compressor_t *cmp) +int sqfs_id_table_write(sqfs_id_table_t *tbl, sqfs_file_t *file, + sqfs_super_t *super, sqfs_compressor_t *cmp) { uint64_t start; size_t i; @@ -132,7 +132,7 @@ int sqfs_id_table_write(sqfs_id_table_t *tbl, int outfd, sqfs_super_t *super, super->id_count = tbl->num_ids; - ret = sqfs_write_table(outfd, super, cmp, tbl->ids, + ret = sqfs_write_table(file, super, cmp, tbl->ids, sizeof(tbl->ids[0]) * tbl->num_ids, &start); super->id_table_start = start; diff --git a/lib/sqfs/io.c b/lib/sqfs/io.c new file mode 100644 index 0000000..db60964 --- /dev/null +++ b/lib/sqfs/io.c @@ -0,0 +1,151 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * io.c + * + * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at> + */ +#define SQFS_BUILDING_DLL +#include "config.h" + +#include "sqfs/io.h" +#include "sqfs/error.h" + +#include <stdlib.h> +#include <unistd.h> +#include <errno.h> +#include <fcntl.h> + + +typedef struct { + sqfs_file_t base; + + uint64_t size; + int fd; +} sqfs_file_stdio_t; + + +static void stdio_destroy(sqfs_file_t *base) +{ + sqfs_file_stdio_t *file = (sqfs_file_stdio_t *)base; + + close(file->fd); + free(file); +} + +static int stdio_read_at(sqfs_file_t *base, uint64_t offset, + void *buffer, size_t size) +{ + sqfs_file_stdio_t *file = (sqfs_file_stdio_t *)base; + ssize_t ret; + + while (size > 0) { + ret = pread(file->fd, buffer, size, offset); + + if (ret < 0) { + if (errno == EINTR) + continue; + return SQFS_ERROR_IO; + } + + if (ret == 0) + return SQFS_ERROR_OUT_OF_BOUNDS; + + buffer = (char *)buffer + ret; + size -= ret; + offset += ret; + } + + return 0; +} + +static int stdio_write_at(sqfs_file_t *base, uint64_t offset, + const void *buffer, size_t size) +{ + sqfs_file_stdio_t *file = (sqfs_file_stdio_t *)base; + ssize_t ret; + + while (size > 0) { + ret = pwrite(file->fd, buffer, size, offset); + + if (ret < 0) { + if (errno == EINTR) + continue; + return SQFS_ERROR_IO; + } + + if (ret == 0) + return SQFS_ERROR_OUT_OF_BOUNDS; + + buffer = (const char *)buffer + ret; + size -= ret; + offset += ret; + } + + if (offset >= file->size) + file->size = offset; + + return 0; +} + +static uint64_t stdio_get_size(sqfs_file_t *base) +{ + sqfs_file_stdio_t *file = (sqfs_file_stdio_t *)base; + + return file->size; +} + +static int stdio_truncate(sqfs_file_t *base, uint64_t size) +{ + sqfs_file_stdio_t *file = (sqfs_file_stdio_t *)base; + + if (ftruncate(file->fd, size)) + return SQFS_ERROR_IO; + + file->size = size; + return 0; +} + + +sqfs_file_t *sqfs_open_file(const char *filename, int flags) +{ + sqfs_file_stdio_t *file; + int open_mode, temp; + sqfs_file_t *base; + + if (flags & ~SQFS_FILE_OPEN_ALL_FLAGS) { + errno = EINVAL; + return NULL; + } + + file = calloc(1, sizeof(*file)); + base = (sqfs_file_t *)file; + if (file == NULL) + return NULL; + + if (flags & SQFS_FILE_OPEN_READ_ONLY) { + open_mode = O_RDONLY; + } else { + open_mode = O_CREAT | O_RDWR; + + if (flags & SQFS_FILE_OPEN_OVERWRITE) { + open_mode |= O_TRUNC; + } else { + open_mode |= O_EXCL; + } + } + + file->fd = open(filename, open_mode, 0600); + if (file->fd < 0) { + temp = errno; + free(file); + errno = temp; + return NULL; + } + + base->destroy = stdio_destroy; + base->read_at = stdio_read_at; + base->write_at = stdio_write_at; + base->get_size = stdio_get_size; + base->truncate = stdio_truncate; + return base; +} diff --git a/lib/sqfs/meta_reader.c b/lib/sqfs/meta_reader.c index 295d0de..7d56869 100644 --- a/lib/sqfs/meta_reader.c +++ b/lib/sqfs/meta_reader.c @@ -11,6 +11,7 @@ #include "sqfs/compress.h" #include "sqfs/error.h" #include "sqfs/data.h" +#include "sqfs/io.h" #include "util.h" #include <stdlib.h> @@ -32,7 +33,7 @@ struct sqfs_meta_reader_t { size_t offset; /* The underlying file descriptor to read from */ - int fd; + sqfs_file_t *file; /* A pointer to the compressor to use for extracting data */ sqfs_compressor_t *cmp; @@ -44,7 +45,8 @@ struct sqfs_meta_reader_t { uint8_t scratch[SQFS_META_BLOCK_SIZE]; }; -sqfs_meta_reader_t *sqfs_meta_reader_create(int fd, sqfs_compressor_t *cmp, +sqfs_meta_reader_t *sqfs_meta_reader_create(sqfs_file_t *file, + sqfs_compressor_t *cmp, uint64_t start, uint64_t limit) { sqfs_meta_reader_t *m = calloc(1, sizeof(*m)); @@ -54,7 +56,7 @@ sqfs_meta_reader_t *sqfs_meta_reader_create(int fd, sqfs_compressor_t *cmp, m->start = start; m->limit = limit; - m->fd = fd; + m->file = file; m->cmp = cmp; return m; } @@ -71,6 +73,7 @@ int sqfs_meta_reader_seek(sqfs_meta_reader_t *m, uint64_t block_start, uint16_t header; ssize_t ret; size_t size; + int err; if (block_start < m->start || block_start >= m->limit) return SQFS_ERROR_OUT_OF_BOUNDS; @@ -83,10 +86,9 @@ int sqfs_meta_reader_seek(sqfs_meta_reader_t *m, uint64_t block_start, return 0; } - if (read_data_at("reading meta data header", block_start, - m->fd, &header, 2)) { - return SQFS_ERROR_IO; - } + err = m->file->read_at(m->file, block_start, &header, 2); + if (err) + return err; header = le16toh(header); compressed = (header & 0x8000) == 0; @@ -98,10 +100,9 @@ int sqfs_meta_reader_seek(sqfs_meta_reader_t *m, uint64_t block_start, if ((block_start + 2 + size) > m->limit) return SQFS_ERROR_OUT_OF_BOUNDS; - if (read_data_at("reading meta data block", block_start + 2, - m->fd, m->data, size)) { - return SQFS_ERROR_IO; - } + err = m->file->read_at(m->file, block_start + 2, m->data, size); + if (err) + return err; if (compressed) { ret = m->cmp->do_block(m->cmp, m->data, size, diff --git a/lib/sqfs/meta_writer.c b/lib/sqfs/meta_writer.c index 46f9618..4bd7e56 100644 --- a/lib/sqfs/meta_writer.c +++ b/lib/sqfs/meta_writer.c @@ -11,6 +11,7 @@ #include "sqfs/compress.h" #include "sqfs/error.h" #include "sqfs/data.h" +#include "sqfs/io.h" #include "util.h" #include <string.h> @@ -32,7 +33,7 @@ struct sqfs_meta_writer_t { size_t block_offset; /* The underlying file descriptor to write to */ - int outfd; + sqfs_file_t *file; /* A pointer to the compressor to use for compressing the data */ sqfs_compressor_t *cmp; @@ -45,15 +46,16 @@ struct sqfs_meta_writer_t { meta_block_t *list_end; }; -static int write_block(int fd, meta_block_t *outblk) +static int write_block(sqfs_file_t *file, meta_block_t *outblk) { size_t count = le16toh(((uint16_t *)outblk->data)[0]) & 0x7FFF; + uint64_t off = file->get_size(file); - return write_data("writing meta data block", fd, - outblk->data, count + 2); + return file->write_at(file, off, outblk->data, count + 2); } -sqfs_meta_writer_t *sqfs_meta_writer_create(int fd, sqfs_compressor_t *cmp, +sqfs_meta_writer_t *sqfs_meta_writer_create(sqfs_file_t *file, + sqfs_compressor_t *cmp, bool keep_in_mem) { sqfs_meta_writer_t *m = calloc(1, sizeof(*m)); @@ -62,7 +64,7 @@ sqfs_meta_writer_t *sqfs_meta_writer_create(int fd, sqfs_compressor_t *cmp, return NULL; m->cmp = cmp; - m->outfd = fd; + m->file = file; m->keep_in_mem = keep_in_mem; return m; } @@ -119,8 +121,7 @@ int sqfs_meta_writer_flush(sqfs_meta_writer_t *m) } m->list_end = outblk; } else { - if (write_block(m->outfd, outblk)) - ret = SQFS_ERROR_IO; + ret = write_block(m->file, outblk); free(outblk); } @@ -178,12 +179,14 @@ void sqfs_meta_writer_reset(sqfs_meta_writer_t *m) int sqfs_meta_write_write_to_file(sqfs_meta_writer_t *m) { meta_block_t *blk; + int ret; while (m->list != NULL) { blk = m->list; - if (write_block(m->outfd, blk)) - return SQFS_ERROR_IO; + ret = write_block(m->file, blk); + if (ret) + return ret; m->list = blk->next; free(blk); diff --git a/lib/sqfs/read_super.c b/lib/sqfs/read_super.c index 9f7425c..23909e0 100644 --- a/lib/sqfs/read_super.c +++ b/lib/sqfs/read_super.c @@ -9,19 +9,21 @@ #include "sqfs/super.h" #include "sqfs/error.h" +#include "sqfs/io.h" #include "util.h" #include <endian.h> #include <string.h> -int sqfs_super_read(sqfs_super_t *super, int fd) +int sqfs_super_read(sqfs_super_t *super, sqfs_file_t *file) { size_t block_size = 0; sqfs_super_t temp; - int i; + int i, ret; - if (read_data_at("reading super block", 0, fd, &temp, sizeof(temp))) - return SQFS_ERROR_IO; + ret = file->read_at(file, 0, &temp, sizeof(temp)); + if (ret) + return ret; temp.magic = le32toh(temp.magic); temp.inode_count = le32toh(temp.inode_count); diff --git a/lib/sqfs/read_table.c b/lib/sqfs/read_table.c index 843247e..129ecaf 100644 --- a/lib/sqfs/read_table.c +++ b/lib/sqfs/read_table.c @@ -11,13 +11,14 @@ #include "sqfs/error.h" #include "sqfs/table.h" #include "sqfs/data.h" +#include "sqfs/io.h" #include "util.h" #include <endian.h> #include <stdlib.h> -int sqfs_read_table(int fd, sqfs_compressor_t *cmp, size_t table_size, - uint64_t location, uint64_t lower_limit, +int sqfs_read_table(sqfs_file_t *file, sqfs_compressor_t *cmp, + size_t table_size, uint64_t location, uint64_t lower_limit, uint64_t upper_limit, void **out) { size_t diff, block_count, blk_idx = 0; @@ -43,14 +44,13 @@ int sqfs_read_table(int fd, sqfs_compressor_t *cmp, size_t table_size, goto fail_data; } - if (read_data_at("reading table locations", location, - fd, locations, sizeof(uint64_t) * block_count)) { - err = SQFS_ERROR_IO; + err = file->read_at(file, location, locations, + sizeof(uint64_t) * block_count); + if (err) goto fail_idx; - } /* Read the actual data */ - m = sqfs_meta_reader_create(fd, cmp, lower_limit, upper_limit); + m = sqfs_meta_reader_create(file, cmp, lower_limit, upper_limit); if (m == NULL) { err = SQFS_ERROR_ALLOC; goto fail_idx; diff --git a/lib/sqfs/super.c b/lib/sqfs/super.c index 0489079..b3984d2 100644 --- a/lib/sqfs/super.c +++ b/lib/sqfs/super.c @@ -9,6 +9,7 @@ #include "sqfs/super.h" #include "sqfs/error.h" +#include "sqfs/io.h" #include "util.h" #include <endian.h> @@ -48,7 +49,7 @@ int sqfs_super_init(sqfs_super_t *super, size_t block_size, uint32_t mtime, return 0; } -int sqfs_super_write(sqfs_super_t *super, int fd) +int sqfs_super_write(sqfs_super_t *super, sqfs_file_t *file) { sqfs_super_t copy; @@ -72,14 +73,5 @@ int sqfs_super_write(sqfs_super_t *super, int fd) copy.fragment_table_start = htole64(super->fragment_table_start); copy.export_table_start = htole64(super->export_table_start); - if (lseek(fd, 0, SEEK_SET) == (off_t)-1) - return SQFS_ERROR_IO; - - if (write_data("writing super block", fd, ©, sizeof(copy))) - return SQFS_ERROR_IO; - - if (lseek(fd, 0, SEEK_END) == (off_t)-1) - return SQFS_ERROR_IO; - - return 0; + return file->write_at(file, 0, ©, sizeof(copy)); } diff --git a/lib/sqfs/write_table.c b/lib/sqfs/write_table.c index c264ebd..70c7d19 100644 --- a/lib/sqfs/write_table.c +++ b/lib/sqfs/write_table.c @@ -12,16 +12,18 @@ #include "sqfs/super.h" #include "sqfs/table.h" #include "sqfs/data.h" +#include "sqfs/io.h" #include "util.h" #include <endian.h> #include <stdlib.h> -int sqfs_write_table(int outfd, sqfs_super_t *super, sqfs_compressor_t *cmp, - const void *data, size_t table_size, uint64_t *start) +int sqfs_write_table(sqfs_file_t *file, sqfs_super_t *super, + sqfs_compressor_t *cmp, const void *data, + size_t table_size, uint64_t *start) { size_t block_count, list_size, diff, blkidx = 0; - uint64_t block, *locations; + uint64_t off, block, *locations; sqfs_meta_writer_t *m; uint32_t offset; int ret; @@ -36,7 +38,7 @@ int sqfs_write_table(int outfd, sqfs_super_t *super, sqfs_compressor_t *cmp, return SQFS_ERROR_ALLOC; /* Write actual data */ - m = sqfs_meta_writer_create(outfd, cmp, false); + m = sqfs_meta_writer_create(file, cmp, false); if (m == NULL) { ret = SQFS_ERROR_ALLOC; goto out_idx; @@ -69,11 +71,12 @@ int sqfs_write_table(int outfd, sqfs_super_t *super, sqfs_compressor_t *cmp, *start = super->bytes_used; list_size = sizeof(uint64_t) * block_count; - if (write_data("writing table locations", outfd, - locations, list_size)) { - ret = SQFS_ERROR_IO; + + off = file->get_size(file); + + ret = file->write_at(file, off, locations, list_size); + if (ret) goto out; - } super->bytes_used += list_size; diff --git a/lib/sqfs/xattr_reader.c b/lib/sqfs/xattr_reader.c index 80731ba..1634be8 100644 --- a/lib/sqfs/xattr_reader.c +++ b/lib/sqfs/xattr_reader.c @@ -12,6 +12,7 @@ #include "sqfs/xattr.h" #include "sqfs/error.h" #include "sqfs/data.h" +#include "sqfs/io.h" #include "util.h" #include <stdlib.h> @@ -29,7 +30,7 @@ struct sqfs_xattr_reader_t { sqfs_meta_reader_t *idrd; sqfs_meta_reader_t *kvrd; sqfs_super_t *super; - int sqfsfd; + sqfs_file_t *file; }; int sqfs_xattr_reader_load_locations(sqfs_xattr_reader_t *xr) @@ -47,11 +48,10 @@ int sqfs_xattr_reader_load_locations(sqfs_xattr_reader_t *xr) if (xr->super->xattr_id_table_start >= xr->super->bytes_used) return SQFS_ERROR_OUT_OF_BOUNDS; - if (read_data_at("reading xattr ID location table", - xr->super->xattr_id_table_start, - xr->sqfsfd, &idtbl, sizeof(idtbl))) { - return SQFS_ERROR_IO; - } + err = xr->file->read_at(xr->file, xr->super->xattr_id_table_start, + &idtbl, sizeof(idtbl)); + if (err) + return err; xr->xattr_start = le64toh(idtbl.xattr_table_start); xr->num_ids = le32toh(idtbl.xattr_ids); @@ -68,13 +68,12 @@ int sqfs_xattr_reader_load_locations(sqfs_xattr_reader_t *xr) return SQFS_ERROR_ALLOC; } - if (read_data_at("reading xattr ID block locations", - xr->super->xattr_id_table_start + sizeof(idtbl), - xr->sqfsfd, xr->id_block_starts, - sizeof(uint64_t) * xr->num_id_blocks)) { - err = SQFS_ERROR_IO; + err = xr->file->read_at(xr->file, + xr->super->xattr_id_table_start + sizeof(idtbl), + xr->id_block_starts, + sizeof(uint64_t) * xr->num_id_blocks); + if (err) goto fail; - } for (i = 0; i < xr->num_id_blocks; ++i) { xr->id_block_starts[i] = le64toh(xr->id_block_starts[i]); @@ -254,7 +253,8 @@ void sqfs_xattr_reader_destroy(sqfs_xattr_reader_t *xr) free(xr); } -sqfs_xattr_reader_t *sqfs_xattr_reader_create(int sqfsfd, sqfs_super_t *super, +sqfs_xattr_reader_t *sqfs_xattr_reader_create(sqfs_file_t *file, + sqfs_super_t *super, sqfs_compressor_t *cmp) { sqfs_xattr_reader_t *xr = calloc(1, sizeof(*xr)); @@ -262,26 +262,27 @@ sqfs_xattr_reader_t *sqfs_xattr_reader_create(int sqfsfd, sqfs_super_t *super, if (xr == NULL) return NULL; + xr->file = file; + xr->super = super; + if (super->flags & SQFS_FLAG_NO_XATTRS) return xr; if (super->xattr_id_table_start == 0xFFFFFFFFFFFFFFFF) return xr; - xr->idrd = sqfs_meta_reader_create(sqfsfd, cmp, + xr->idrd = sqfs_meta_reader_create(file, cmp, super->id_table_start, super->bytes_used); if (xr->idrd == NULL) goto fail; - xr->kvrd = sqfs_meta_reader_create(sqfsfd, cmp, + xr->kvrd = sqfs_meta_reader_create(file, cmp, super->id_table_start, super->bytes_used); if (xr->kvrd == NULL) goto fail; - xr->sqfsfd = sqfsfd; - xr->super = super; return xr; fail: sqfs_xattr_reader_destroy(xr); diff --git a/lib/sqfshelper/data_reader.c b/lib/sqfshelper/data_reader.c index fc92e28..d1a9cce 100644 --- a/lib/sqfshelper/data_reader.c +++ b/lib/sqfshelper/data_reader.c @@ -25,7 +25,7 @@ struct data_reader_t { sqfs_compressor_t *cmp; size_t block_size; - int sqfsfd; + sqfs_file_t *file; void *block; void *scratch; @@ -44,8 +44,10 @@ static ssize_t read_block(data_reader_t *data, off_t offset, uint32_t size, if (size > data->block_size) goto fail_bs; - if (read_data_at("reading block", offset, data->sqfsfd, ptr, size)) + if (data->file->read_at(data->file, offset, ptr, size)) { + fputs("error reading data block from input file\n", stderr); return -1; + } if (compressed) { ret = data->cmp->do_block(data->cmp, data->scratch, size, @@ -104,7 +106,7 @@ static int precache_fragment_block(data_reader_t *data, size_t idx) return 0; } -data_reader_t *data_reader_create(int fd, sqfs_super_t *super, +data_reader_t *data_reader_create(sqfs_file_t *file, sqfs_super_t *super, sqfs_compressor_t *cmp) { data_reader_t *data = alloc_flex(sizeof(*data), super->block_size, 3); @@ -123,7 +125,7 @@ data_reader_t *data_reader_create(int fd, sqfs_super_t *super, data->scratch = (char *)data->block + super->block_size; data->frag_block = (char *)data->scratch + super->block_size; data->current_block = -1; - data->sqfsfd = fd; + data->file = file; data->block_size = super->block_size; data->cmp = cmp; @@ -144,7 +146,7 @@ data_reader_t *data_reader_create(int fd, sqfs_super_t *super, return NULL; } - ret = sqfs_read_table(fd, cmp, size, super->fragment_table_start, + ret = sqfs_read_table(file, cmp, size, super->fragment_table_start, super->directory_table_start, super->fragment_table_start, &raw_frag); diff --git a/lib/sqfshelper/data_writer.c b/lib/sqfshelper/data_writer.c index 62e3e2a..b94bdb6 100644 --- a/lib/sqfshelper/data_writer.c +++ b/lib/sqfshelper/data_writer.c @@ -32,7 +32,7 @@ struct data_writer_t { sqfs_compressor_t *cmp; file_info_t *list; sqfs_super_t *super; - int outfd; + sqfs_file_t *file; }; enum { @@ -45,32 +45,19 @@ enum { static int save_position(data_writer_t *data) { data->bytes_written = data->super->bytes_used; - data->start = lseek(data->outfd, 0, SEEK_CUR); - - if (data->start == (off_t)-1) { - perror("querying current position on squashfs image"); - return -1; - } - + data->start = data->file->get_size(data->file); return 0; } static int restore_position(data_writer_t *data) { - if (lseek(data->outfd, data->start, SEEK_SET) == (off_t)-1) - goto fail_seek; - - if (ftruncate(data->outfd, data->start)) - goto fail_truncate; + if (data->file->truncate(data->file, data->start)) { + perror("truncating squashfs image after file deduplication"); + return -1; + } data->super->bytes_used = data->bytes_written; return 0; -fail_seek: - perror("seeking on squashfs image after file deduplication"); - return -1; -fail_truncate: - perror("truncating squashfs image after file deduplication"); - return -1; } static int allign_file(data_writer_t *data) @@ -80,7 +67,7 @@ static int allign_file(data_writer_t *data) if (diff == 0) return 0; - if (padd_file(data->outfd, data->super->bytes_used, data->devblksz)) + if (padd_sqfs(data->file, data->super->bytes_used, data->devblksz)) return -1; data->super->bytes_used += data->devblksz - diff; @@ -122,8 +109,10 @@ static int block_callback(void *user, sqfs_block_t *blk) fi->blocks[blk->index].size = htole32(out); } - if (write_data("writing data block", data->outfd, - blk->data, blk->size)) { + offset = data->file->get_size(data->file); + + if (data->file->write_at(data->file, offset, + blk->data, blk->size)) { return -1; } @@ -489,7 +478,7 @@ int write_data_from_fd_condensed(data_writer_t *data, file_info_t *fi, } data_writer_t *data_writer_create(sqfs_super_t *super, sqfs_compressor_t *cmp, - int outfd, size_t devblksize, + sqfs_file_t *file, size_t devblksize, unsigned int num_jobs) { data_writer_t *data = calloc(1, sizeof(*data)); @@ -504,7 +493,7 @@ data_writer_t *data_writer_create(sqfs_super_t *super, sqfs_compressor_t *cmp, block_callback); data->cmp = cmp; data->super = super; - data->outfd = outfd; + data->file = file; data->devblksz = devblksize; return data; } @@ -529,7 +518,7 @@ int data_writer_write_fragment_table(data_writer_t *data) } size = sizeof(data->fragments[0]) * data->num_fragments; - ret = sqfs_write_table(data->outfd, data->super, data->cmp, + ret = sqfs_write_table(data->file, data->super, data->cmp, data->fragments, size, &start); if (ret) return -1; diff --git a/lib/sqfshelper/deserialize_fstree.c b/lib/sqfshelper/deserialize_fstree.c index 1953f9b..37861e6 100644 --- a/lib/sqfshelper/deserialize_fstree.c +++ b/lib/sqfshelper/deserialize_fstree.c @@ -203,7 +203,7 @@ static int fill_dir(sqfs_meta_reader_t *ir, sqfs_meta_reader_t *dr, } int deserialize_fstree(fstree_t *out, sqfs_super_t *super, - sqfs_compressor_t *cmp, int fd, int flags) + sqfs_compressor_t *cmp, sqfs_file_t *file, int flags) { uint64_t block_start, limit; sqfs_meta_reader_t *ir, *dr; @@ -213,7 +213,7 @@ int deserialize_fstree(fstree_t *out, sqfs_super_t *super, int status = -1; size_t offset; - ir = sqfs_meta_reader_create(fd, cmp, super->inode_table_start, + ir = sqfs_meta_reader_create(file, cmp, super->inode_table_start, super->directory_table_start); if (ir == NULL) return -1; @@ -224,7 +224,7 @@ int deserialize_fstree(fstree_t *out, sqfs_super_t *super, if (super->fragment_table_start < limit) limit = super->fragment_table_start; - dr = sqfs_meta_reader_create(fd, cmp, super->directory_table_start, + dr = sqfs_meta_reader_create(file, cmp, super->directory_table_start, limit); if (dr == NULL) goto out_ir; @@ -233,10 +233,10 @@ int deserialize_fstree(fstree_t *out, sqfs_super_t *super, if (idtbl == NULL) goto out_dr; - if (sqfs_id_table_read(idtbl, fd, super, cmp)) + if (sqfs_id_table_read(idtbl, file, super, cmp)) goto out_id; - xr = sqfs_xattr_reader_create(fd, super, cmp); + xr = sqfs_xattr_reader_create(file, super, cmp); if (xr == NULL) goto out_id; diff --git a/lib/sqfshelper/serialize_fstree.c b/lib/sqfshelper/serialize_fstree.c index dfadedd..ea3d479 100644 --- a/lib/sqfshelper/serialize_fstree.c +++ b/lib/sqfshelper/serialize_fstree.c @@ -41,7 +41,7 @@ static int write_dir_entries(sqfs_dir_writer_t *dirw, tree_node_t *node) return 0; } -int sqfs_serialize_fstree(int outfd, sqfs_super_t *super, fstree_t *fs, +int sqfs_serialize_fstree(sqfs_file_t *file, sqfs_super_t *super, fstree_t *fs, sqfs_compressor_t *cmp, sqfs_id_table_t *idtbl) { sqfs_inode_generic_t *inode; @@ -52,11 +52,11 @@ int sqfs_serialize_fstree(int outfd, sqfs_super_t *super, fstree_t *fs, int ret = -1; size_t i; - im = sqfs_meta_writer_create(outfd, cmp, false); + im = sqfs_meta_writer_create(file, cmp, false); if (im == NULL) return -1; - dm = sqfs_meta_writer_create(outfd, cmp, true); + dm = sqfs_meta_writer_create(file, cmp, true); if (dm == NULL) goto out_im; diff --git a/lib/sqfshelper/sqfs_reader.c b/lib/sqfshelper/sqfs_reader.c index 598b3c4..e9c9c33 100644 --- a/lib/sqfshelper/sqfs_reader.c +++ b/lib/sqfshelper/sqfs_reader.c @@ -18,13 +18,11 @@ int sqfs_reader_open(sqfs_reader_t *rd, const char *filename, int rdtree_flags) memset(rd, 0, sizeof(*rd)); - rd->sqfsfd = open(filename, O_RDONLY); - if (rd->sqfsfd < 0) { - perror(filename); + rd->file = sqfs_open_file(filename, SQFS_FILE_OPEN_READ_ONLY); + if (rd->file == NULL) return -1; - } - if (sqfs_super_read(&rd->super, rd->sqfsfd)) + if (sqfs_super_read(&rd->super, rd->file)) goto fail_fd; if (!sqfs_compressor_exists(rd->super.compression_id)) { @@ -41,21 +39,21 @@ int sqfs_reader_open(sqfs_reader_t *rd, const char *filename, int rdtree_flags) goto fail_fd; if (rd->super.flags & SQFS_FLAG_COMPRESSOR_OPTIONS) { - if (rd->cmp->read_options(rd->cmp, rd->sqfsfd)) + if (rd->cmp->read_options(rd->cmp, rd->file)) goto fail_cmp; } if (rd->super.flags & SQFS_FLAG_NO_XATTRS) rdtree_flags &= ~RDTREE_READ_XATTR; - if (deserialize_fstree(&rd->fs, &rd->super, rd->cmp, rd->sqfsfd, + if (deserialize_fstree(&rd->fs, &rd->super, rd->cmp, rd->file, rdtree_flags)) { goto fail_cmp; } fstree_gen_file_list(&rd->fs); - rd->data = data_reader_create(rd->sqfsfd, &rd->super, rd->cmp); + rd->data = data_reader_create(rd->file, &rd->super, rd->cmp); if (rd->data == NULL) goto fail_fs; @@ -65,7 +63,7 @@ fail_fs: fail_cmp: rd->cmp->destroy(rd->cmp); fail_fd: - close(rd->sqfsfd); + rd->file->destroy(rd->file); memset(rd, 0, sizeof(*rd)); return -1; } @@ -75,6 +73,6 @@ void sqfs_reader_close(sqfs_reader_t *rd) data_reader_destroy(rd->data); fstree_cleanup(&rd->fs); rd->cmp->destroy(rd->cmp); - close(rd->sqfsfd); + rd->file->destroy(rd->file); memset(rd, 0, sizeof(*rd)); } diff --git a/lib/sqfshelper/write_export_table.c b/lib/sqfshelper/write_export_table.c index b0ad4ce..f4c6658 100644 --- a/lib/sqfshelper/write_export_table.c +++ b/lib/sqfshelper/write_export_table.c @@ -12,7 +12,7 @@ #include <stdlib.h> #include <stdio.h> -int write_export_table(int outfd, fstree_t *fs, sqfs_super_t *super, +int write_export_table(sqfs_file_t *file, fstree_t *fs, sqfs_super_t *super, sqfs_compressor_t *cmp) { uint64_t *table, start; @@ -38,7 +38,7 @@ int write_export_table(int outfd, fstree_t *fs, sqfs_super_t *super, } size = sizeof(uint64_t) * (fs->inode_tbl_size - 1); - ret = sqfs_write_table(outfd, super, cmp, table, size, &start); + ret = sqfs_write_table(file, super, cmp, table, size, &start); super->export_table_start = start; super->flags |= SQFS_FLAG_EXPORTABLE; diff --git a/lib/sqfshelper/write_xattr.c b/lib/sqfshelper/write_xattr.c index 6f71eeb..c4fb86e 100644 --- a/lib/sqfshelper/write_xattr.c +++ b/lib/sqfshelper/write_xattr.c @@ -167,7 +167,7 @@ static uint64_t *create_ool_locations_table(fstree_t *fs) return table; } -int write_xattr(int outfd, fstree_t *fs, sqfs_super_t *super, +int write_xattr(sqfs_file_t *file, fstree_t *fs, sqfs_super_t *super, sqfs_compressor_t *cmp) { uint64_t kv_start, id_start, block, *tbl, *ool_locations; @@ -185,7 +185,7 @@ int write_xattr(int outfd, fstree_t *fs, sqfs_super_t *super, if (ool_locations == NULL) return -1; - mw = sqfs_meta_writer_create(outfd, cmp, false); + mw = sqfs_meta_writer_create(file, cmp, false); if (mw == NULL) goto fail_ool; @@ -254,11 +254,14 @@ int write_xattr(int outfd, fstree_t *fs, sqfs_super_t *super, idtbl.xattr_ids = htole32(count); idtbl.unused = 0; - if (write_data("writing xattr ID table", outfd, &idtbl, sizeof(idtbl))) + if (file->write_at(file, file->get_size(file), &idtbl, sizeof(idtbl))) { + perror("writing xattr ID table"); goto fail_tbl; + } - if (write_data("writing xattr ID table", - outfd, tbl, sizeof(tbl[0]) * blocks)) { + if (file->write_at(file, file->get_size(file), + tbl, sizeof(tbl[0]) * blocks)) { + perror("writing xattr ID table"); goto fail_tbl; } diff --git a/lib/util/padd_file.c b/lib/util/padd_file.c index 9a2428d..21950b4 100644 --- a/lib/util/padd_file.c +++ b/lib/util/padd_file.c @@ -6,6 +6,7 @@ */ #include "config.h" +#include "sqfs/io.h" #include "util.h" #include <stdlib.h> @@ -39,3 +40,32 @@ fail_errno: perror("padding output file to block size"); goto out; } + +int padd_sqfs(sqfs_file_t *file, uint64_t size, size_t blocksize) +{ + size_t padd_sz = size % blocksize; + int status = -1; + uint8_t *buffer; + + if (padd_sz == 0) + return 0; + + padd_sz = blocksize - padd_sz; + + buffer = calloc(1, padd_sz); + if (buffer == NULL) + goto fail_errno; + + if (file->write_at(file, file->get_size(file), + buffer, padd_sz)) { + goto fail_errno; + } + + status = 0; +out: + free(buffer); + return status; +fail_errno: + perror("padding output file to block size"); + goto out; +} diff --git a/mkfs/mkfs.c b/mkfs/mkfs.c index 540dbea..05e8481 100644 --- a/mkfs/mkfs.c +++ b/mkfs/mkfs.c @@ -96,11 +96,11 @@ int main(int argc, char **argv) sqfs_compressor_config_t cfg; sqfs_compressor_t *cmp; sqfs_id_table_t *idtbl; + sqfs_file_t *outfile; data_writer_t *data; sqfs_super_t super; options_t opt; fstree_t fs; - int outfd; process_command_line(&opt, argc, argv); @@ -121,22 +121,22 @@ int main(int argc, char **argv) if (idtbl == NULL) goto out_fstree; - outfd = open(opt.outfile, opt.outmode, 0644); - if (outfd < 0) { + outfile = sqfs_open_file(opt.outfile, opt.outmode); + if (outfile == NULL) { perror(opt.outfile); goto out_idtbl; } - if (sqfs_super_write(&super, outfd)) - goto out_outfd; + if (sqfs_super_write(&super, outfile)) + goto out_outfile; if (read_fstree(&fs, &opt)) - goto out_outfd; + goto out_outfile; tree_node_sort_recursive(fs.root); if (fstree_gen_inode_table(&fs)) - goto out_outfd; + goto out_outfile; fstree_gen_file_list(&fs); @@ -145,7 +145,7 @@ int main(int argc, char **argv) #ifdef WITH_SELINUX if (opt.selinux != NULL) { if (fstree_relabel_selinux(&fs, opt.selinux)) - goto out_outfd; + goto out_outfile; } #endif @@ -154,10 +154,10 @@ int main(int argc, char **argv) cmp = sqfs_compressor_create(&cfg); if (cmp == NULL) { fputs("Error creating compressor\n", stderr); - goto out_outfd; + goto out_outfile; } - ret = cmp->write_options(cmp, outfd); + ret = cmp->write_options(cmp, outfile); if (ret < 0) goto out_cmp; @@ -166,7 +166,7 @@ int main(int argc, char **argv) super.bytes_used += ret; } - data = data_writer_create(&super, cmp, outfd, + data = data_writer_create(&super, cmp, outfile, opt.devblksz, opt.num_jobs); if (data == NULL) goto out_cmp; @@ -174,27 +174,27 @@ int main(int argc, char **argv) if (pack_files(data, &fs, &opt)) goto out_data; - if (sqfs_serialize_fstree(outfd, &super, &fs, cmp, idtbl)) + if (sqfs_serialize_fstree(outfile, &super, &fs, cmp, idtbl)) goto out_data; if (data_writer_write_fragment_table(data)) goto out_data; if (opt.exportable) { - if (write_export_table(outfd, &fs, &super, cmp)) + if (write_export_table(outfile, &fs, &super, cmp)) goto out_data; } - if (sqfs_id_table_write(idtbl, outfd, &super, cmp)) + if (sqfs_id_table_write(idtbl, outfile, &super, cmp)) goto out_data; - if (write_xattr(outfd, &fs, &super, cmp)) + if (write_xattr(outfile, &fs, &super, cmp)) goto out_data; - if (sqfs_super_write(&super, outfd)) + if (sqfs_super_write(&super, outfile)) goto out_data; - if (padd_file(outfd, super.bytes_used, opt.devblksz)) + if (padd_sqfs(outfile, super.bytes_used, opt.devblksz)) goto out_data; if (!opt.quiet) { @@ -207,8 +207,8 @@ out_data: data_writer_destroy(data); out_cmp: cmp->destroy(cmp); -out_outfd: - close(outfd); +out_outfile: + outfile->destroy(outfile); out_idtbl: sqfs_id_table_destroy(idtbl); out_fstree: diff --git a/mkfs/mkfs.h b/mkfs/mkfs.h index 24f8e9c..7ad9460 100644 --- a/mkfs/mkfs.h +++ b/mkfs/mkfs.h @@ -13,6 +13,8 @@ #include "sqfs/compress.h" #include "sqfs/id_table.h" #include "sqfs/data.h" +#include "sqfs/io.h" + #include "data_writer.h" #include "highlevel.h" #include "fstree.h" diff --git a/mkfs/options.c b/mkfs/options.c index 9e747d8..7b83ec4 100644 --- a/mkfs/options.c +++ b/mkfs/options.c @@ -146,7 +146,7 @@ void process_command_line(options_t *opt, int argc, char **argv) int i; memset(opt, 0, sizeof(*opt)); - opt->outmode = O_WRONLY | O_CREAT | O_EXCL; + opt->outmode = 0; opt->compressor = compressor_get_default(); opt->blksz = SQFS_DEFAULT_BLOCK_SIZE; opt->devblksz = SQFS_DEVBLK_SIZE; @@ -207,7 +207,7 @@ void process_command_line(options_t *opt, int argc, char **argv) opt->exportable = true; break; case 'f': - opt->outmode = O_WRONLY | O_CREAT | O_TRUNC; + opt->outmode |= SQFS_FILE_OPEN_OVERWRITE; break; case 'q': opt->quiet = true; diff --git a/tar/tar2sqfs.c b/tar/tar2sqfs.c index d2772e6..a27f72b 100644 --- a/tar/tar2sqfs.c +++ b/tar/tar2sqfs.c @@ -10,6 +10,8 @@ #include "sqfs/id_table.h" #include "sqfs/xattr.h" #include "sqfs/data.h" +#include "sqfs/io.h" + #include "data_writer.h" #include "highlevel.h" #include "fstree.h" @@ -94,7 +96,7 @@ static const char *filename; static int block_size = SQFS_DEFAULT_BLOCK_SIZE; static size_t devblksize = SQFS_DEVBLK_SIZE; static bool quiet = false; -static int outmode = O_WRONLY | O_CREAT | O_EXCL; +static int outmode = 0; static unsigned int num_jobs = 1; static E_SQFS_COMPRESSOR comp_id; static char *comp_extra = NULL; @@ -165,7 +167,7 @@ static void process_args(int argc, char **argv) exportable = true; break; case 'f': - outmode = O_WRONLY | O_CREAT | O_TRUNC; + outmode |= SQFS_FILE_OPEN_OVERWRITE; break; case 'q': quiet = true; @@ -354,10 +356,11 @@ fail: int main(int argc, char **argv) { - int outfd, status = EXIT_SUCCESS; sqfs_compressor_config_t cfg; + int status = EXIT_SUCCESS; sqfs_compressor_t *cmp; sqfs_id_table_t *idtbl; + sqfs_file_t *outfile; data_writer_t *data; sqfs_super_t super; fstree_t fs; @@ -370,8 +373,8 @@ int main(int argc, char **argv) return EXIT_FAILURE; } - outfd = open(filename, outmode, 0644); - if (outfd < 0) { + outfile = sqfs_open_file(filename, outmode); + if (outfile == NULL) { perror(filename); return EXIT_FAILURE; } @@ -388,10 +391,10 @@ int main(int argc, char **argv) if (sqfs_super_init(&super, block_size, fs.defaults.st_mtime, comp_id)) goto out_cmp; - if (sqfs_super_write(&super, outfd)) + if (sqfs_super_write(&super, outfile)) goto out_cmp; - ret = cmp->write_options(cmp, outfd); + ret = cmp->write_options(cmp, outfile); if (ret < 0) goto out_cmp; @@ -400,7 +403,7 @@ int main(int argc, char **argv) super.bytes_used += ret; } - data = data_writer_create(&super, cmp, outfd, devblksize, num_jobs); + data = data_writer_create(&super, cmp, outfile, devblksize, num_jobs); if (data == NULL) goto out_cmp; @@ -422,27 +425,27 @@ int main(int argc, char **argv) fstree_xattr_deduplicate(&fs); - if (sqfs_serialize_fstree(outfd, &super, &fs, cmp, idtbl)) + if (sqfs_serialize_fstree(outfile, &super, &fs, cmp, idtbl)) goto out; if (data_writer_write_fragment_table(data)) goto out; if (exportable) { - if (write_export_table(outfd, &fs, &super, cmp)) + if (write_export_table(outfile, &fs, &super, cmp)) goto out; } - if (sqfs_id_table_write(idtbl, outfd, &super, cmp)) + if (sqfs_id_table_write(idtbl, outfile, &super, cmp)) goto out; - if (write_xattr(outfd, &fs, &super, cmp)) + if (write_xattr(outfile, &fs, &super, cmp)) goto out; - if (sqfs_super_write(&super, outfd)) + if (sqfs_super_write(&super, outfile)) goto out; - if (padd_file(outfd, super.bytes_used, devblksize)) + if (padd_sqfs(outfile, super.bytes_used, devblksize)) goto out; if (!quiet) { @@ -460,6 +463,6 @@ out_cmp: out_fs: fstree_cleanup(&fs); out_fd: - close(outfd); + outfile->destroy(outfile); return status; } |