aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2019-09-08 14:53:30 +0200
committerDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2019-09-08 14:53:30 +0200
commit3a851dfe87c88ac1d4dddc2a26cc48b037f852f9 (patch)
treea8a8f34291aa58b25737088d247a91a7f60b4fec
parent60064dd0412a149fe00cfc4e2f2361c22656db57 (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>
-rw-r--r--include/data_reader.h2
-rw-r--r--include/data_writer.h2
-rw-r--r--include/highlevel.h11
-rw-r--r--include/sqfs/compress.h4
-rw-r--r--include/sqfs/id_table.h4
-rw-r--r--include/sqfs/io.h44
-rw-r--r--include/sqfs/meta_reader.h2
-rw-r--r--include/sqfs/meta_writer.h2
-rw-r--r--include/sqfs/predef.h1
-rw-r--r--include/sqfs/super.h4
-rw-r--r--include/sqfs/table.h4
-rw-r--r--include/sqfs/xattr.h2
-rw-r--r--include/util.h3
-rw-r--r--lib/Makemodule.am6
-rw-r--r--lib/sqfs/comp/compressor.c22
-rw-r--r--lib/sqfs/comp/gzip.c8
-rw-r--r--lib/sqfs/comp/internal.h6
-rw-r--r--lib/sqfs/comp/lz4.c8
-rw-r--r--lib/sqfs/comp/lzo.c8
-rw-r--r--lib/sqfs/comp/xz.c8
-rw-r--r--lib/sqfs/comp/zstd.c9
-rw-r--r--lib/sqfs/id_table.c12
-rw-r--r--lib/sqfs/io.c151
-rw-r--r--lib/sqfs/meta_reader.c23
-rw-r--r--lib/sqfs/meta_writer.c23
-rw-r--r--lib/sqfs/read_super.c10
-rw-r--r--lib/sqfs/read_table.c14
-rw-r--r--lib/sqfs/super.c14
-rw-r--r--lib/sqfs/write_table.c19
-rw-r--r--lib/sqfs/xattr_reader.c35
-rw-r--r--lib/sqfshelper/data_reader.c12
-rw-r--r--lib/sqfshelper/data_writer.c39
-rw-r--r--lib/sqfshelper/deserialize_fstree.c10
-rw-r--r--lib/sqfshelper/serialize_fstree.c6
-rw-r--r--lib/sqfshelper/sqfs_reader.c18
-rw-r--r--lib/sqfshelper/write_export_table.c4
-rw-r--r--lib/sqfshelper/write_xattr.c13
-rw-r--r--lib/util/padd_file.c30
-rw-r--r--mkfs/mkfs.c38
-rw-r--r--mkfs/mkfs.h2
-rw-r--r--mkfs/options.c4
-rw-r--r--tar/tar2sqfs.c33
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, &copy, 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, &copy, 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;
}