aboutsummaryrefslogtreecommitdiff
path: root/lib/sqfs
diff options
context:
space:
mode:
authorDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2023-06-12 21:21:40 +0200
committerDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2023-06-15 13:38:25 +0200
commitba99ef34e7b073c03519ef74f017091de6c9bee8 (patch)
tree8c134f72990200550ac96e46bd47d4cc0ba85810 /lib/sqfs
parente811851deba9c45f3d9b3c5b4ad5eaa7945382d5 (diff)
Move sqfs_istream_t & sqfs_ostream_t into libsquashfs
For now, only the interfaces and helper functions are moved, the concrete implementations remain in libio. Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
Diffstat (limited to 'lib/sqfs')
-rw-r--r--lib/sqfs/Makemodule.am15
-rw-r--r--lib/sqfs/src/istream.c100
-rw-r--r--lib/sqfs/test/istream_read.c105
-rw-r--r--lib/sqfs/test/istream_skip.c94
-rw-r--r--lib/sqfs/test/stream_splice.c96
5 files changed, 407 insertions, 3 deletions
diff --git a/lib/sqfs/Makemodule.am b/lib/sqfs/Makemodule.am
index d54134c..2727b11 100644
--- a/lib/sqfs/Makemodule.am
+++ b/lib/sqfs/Makemodule.am
@@ -30,7 +30,7 @@ libsquashfs_la_SOURCES = $(LIBSQFS_HEARDS) lib/sqfs/src/id_table.c \
lib/sqfs/src/block_processor/block_processor.c \
lib/sqfs/src/block_processor/backend.c \
lib/sqfs/src/frag_table.c lib/sqfs/src/block_writer.c \
- lib/sqfs/src/misc.c
+ lib/sqfs/src/misc.c lib/sqfs/src/istream.c
libsquashfs_la_CPPFLAGS = $(AM_CPPFLAGS)
libsquashfs_la_LDFLAGS = $(AM_LDFLAGS) -version-info $(LIBSQUASHFS_SO_VERSION)
libsquashfs_la_CFLAGS = $(AM_CFLAGS) $(PTHREAD_CFLAGS) $(ZLIB_CFLAGS)
@@ -122,9 +122,18 @@ xattr_benchmark_LDADD = libcommon.a libsquashfs.la libcompat.a
test_get_node_path_SOURCES = lib/sqfs/test/get_node_path.c
test_get_node_path_LDADD = libcommon.a libsquashfs.la libcompat.a
-LIBSQFS_TESTS = \
- test_abi test_xattr test_table test_xattr_writer test_get_node_path
+test_istream_read_SOURCES = lib/sqfs/test/istream_read.c
+test_istream_read_LDADD = libio.a libsquashfs.la libutil.a libcompat.a
+
+test_istream_skip_SOURCES = lib/sqfs/test/istream_skip.c
+test_istream_skip_LDADD = libsquashfs.la libio.a libutil.a libcompat.a
+test_stream_splice_SOURCES = lib/sqfs/test/stream_splice.c
+test_stream_splice_LDADD = libsquashfs.la libio.a libutil.a libcompat.a
+
+LIBSQFS_TESTS = \
+ test_abi test_xattr test_table test_xattr_writer test_get_node_path \
+ test_istream_read test_istream_skip test_stream_splice
noinst_PROGRAMS += xattr_benchmark
check_PROGRAMS += $(LIBSQFS_TESTS)
diff --git a/lib/sqfs/src/istream.c b/lib/sqfs/src/istream.c
new file mode 100644
index 0000000..3d89461
--- /dev/null
+++ b/lib/sqfs/src/istream.c
@@ -0,0 +1,100 @@
+/* SPDX-License-Identifier: LGPL-3.0-or-later */
+/*
+ * istream.c
+ *
+ * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at>
+ */
+#define SQFS_BUILDING_DLL
+#include "config.h"
+
+#include "sqfs/io.h"
+
+#include <string.h>
+
+sqfs_s32 sqfs_istream_read(sqfs_istream_t *strm, void *data, size_t size)
+{
+ sqfs_s32 total = 0;
+
+ if (size > 0x7FFFFFFF)
+ size = 0x7FFFFFFF;
+
+ while (size > 0) {
+ const sqfs_u8 *ptr;
+ size_t diff;
+ int ret;
+
+ ret = strm->get_buffered_data(strm, &ptr, &diff, size);
+ if (ret > 0)
+ break;
+ if (ret < 0)
+ return ret;
+
+ if (diff > size)
+ diff = size;
+
+ memcpy(data, ptr, diff);
+ strm->advance_buffer(strm, diff);
+ data = (char *)data + diff;
+ size -= diff;
+ total += diff;
+ }
+
+ return total;
+}
+
+int sqfs_istream_skip(sqfs_istream_t *strm, sqfs_u64 size)
+{
+ while (size > 0) {
+ const sqfs_u8 *ptr;
+ size_t diff;
+ int ret;
+
+ ret = strm->get_buffered_data(strm, &ptr, &diff, size);
+ if (ret < 0)
+ return ret;
+ if (ret > 0)
+ break;
+
+ if ((sqfs_u64)diff > size)
+ diff = size;
+
+ size -= diff;
+ strm->advance_buffer(strm, diff);
+ }
+
+ return 0;
+}
+
+sqfs_s32 sqfs_istream_splice(sqfs_istream_t *in, sqfs_ostream_t *out,
+ sqfs_u32 size)
+{
+ sqfs_s32 total = 0;
+
+ if (size > 0x7FFFFFFF)
+ size = 0x7FFFFFFF;
+
+ while (size > 0) {
+ const sqfs_u8 *ptr;
+ size_t diff;
+ int ret;
+
+ ret = in->get_buffered_data(in, &ptr, &diff, size);
+ if (ret < 0)
+ return ret;
+ if (ret > 0)
+ break;
+
+ if (diff > size)
+ diff = size;
+
+ ret = out->append(out, ptr, diff);
+ if (ret)
+ return ret;
+
+ total += diff;
+ size -= diff;
+ in->advance_buffer(in, diff);
+ }
+
+ return total;
+}
diff --git a/lib/sqfs/test/istream_read.c b/lib/sqfs/test/istream_read.c
new file mode 100644
index 0000000..f8facea
--- /dev/null
+++ b/lib/sqfs/test/istream_read.c
@@ -0,0 +1,105 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later */
+/*
+ * istream_read.c
+ *
+ * Copyright (C) 2023 David Oberhollenzer <goliath@infraroot.at>
+ */
+#include "config.h"
+
+#include "util/test.h"
+#include "sqfs/io.h"
+#include "io/mem.h"
+
+static const sqfs_u64 end0 = 449; /* region 1: filled with 'A' */
+static const sqfs_u64 end1 = 521; /* region 2: filled with 'B' */
+static const sqfs_u64 end2 = 941; /* region 3: filled with 'C' */
+
+static sqfs_u8 rd_buffer[941];
+
+static sqfs_u8 byte_at_offset(sqfs_u64 off)
+{
+ if (off < end0)
+ return 'A';
+ if (off < end1)
+ return 'B';
+ return 'C';
+}
+
+static void init_rd_buffer(void)
+{
+ for (size_t i = 0; i < end2; ++i)
+ rd_buffer[i] = byte_at_offset(i);
+}
+
+int main(int argc, char **argv)
+{
+ sqfs_u8 read_buffer[61];
+ sqfs_u64 read_off = 0;
+ sqfs_istream_t *dummy;
+ (void)argc; (void)argv;
+
+ init_rd_buffer();
+ dummy = istream_memory_create("dummy file", 103,
+ rd_buffer, sizeof(rd_buffer));
+ TEST_NOT_NULL(dummy);
+
+ /* region 1 */
+ while (read_off < end0) {
+ size_t read_diff = end0 - read_off;
+
+ if (read_diff > sizeof(read_buffer))
+ read_diff = sizeof(read_buffer);
+
+ int ret = sqfs_istream_read(dummy, read_buffer, read_diff);
+ TEST_ASSERT(ret > 0);
+ TEST_ASSERT((size_t)ret <= read_diff);
+
+ for (int i = 0; i < ret; ++i) {
+ TEST_EQUAL_UI(read_buffer[i], 'A');
+ }
+
+ read_off += ret;
+ }
+
+ /* region 2 */
+ while (read_off < end1) {
+ size_t read_diff = end1 - read_off;
+
+ if (read_diff > sizeof(read_buffer))
+ read_diff = sizeof(read_buffer);
+
+ int ret = sqfs_istream_read(dummy, read_buffer, read_diff);
+ TEST_ASSERT(ret > 0);
+ TEST_ASSERT((size_t)ret <= read_diff);
+
+ for (int i = 0; i < ret; ++i) {
+ TEST_EQUAL_UI(read_buffer[i], 'B');
+ }
+
+ read_off += ret;
+ }
+
+ /* region 3 */
+ for (;;) {
+ size_t read_diff = sizeof(read_buffer);
+
+ int ret = sqfs_istream_read(dummy, read_buffer, read_diff);
+ TEST_ASSERT(ret >= 0);
+ TEST_ASSERT((size_t)ret <= read_diff);
+
+ if (ret == 0) {
+ TEST_EQUAL_UI(read_off, end2);
+ break;
+ }
+
+ for (int i = 0; i < ret; ++i) {
+ TEST_EQUAL_UI(read_buffer[i], 'C');
+ }
+
+ read_off += ret;
+ TEST_ASSERT(read_off <= end2);
+ }
+
+ sqfs_drop(dummy);
+ return EXIT_SUCCESS;
+}
diff --git a/lib/sqfs/test/istream_skip.c b/lib/sqfs/test/istream_skip.c
new file mode 100644
index 0000000..d8a81f2
--- /dev/null
+++ b/lib/sqfs/test/istream_skip.c
@@ -0,0 +1,94 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later */
+/*
+ * istream_skip.c
+ *
+ * Copyright (C) 2023 David Oberhollenzer <goliath@infraroot.at>
+ */
+#include "config.h"
+
+#include "sqfs/io.h"
+#include "util/test.h"
+#include "io/mem.h"
+
+static const sqfs_u64 end0 = 449; /* region 1: filled with 'A' */
+static const sqfs_u64 end1 = 521; /* region 2: filled with 'B' */
+static const sqfs_u64 end2 = 941; /* region 3: filled with 'C' */
+
+static sqfs_u8 rd_buffer[941];
+
+static sqfs_u8 byte_at_offset(sqfs_u64 off)
+{
+ if (off < end0)
+ return 'A';
+ if (off < end1)
+ return 'B';
+ return 'C';
+}
+
+static void init_rd_buffer(void)
+{
+ for (size_t i = 0; i < end2; ++i)
+ rd_buffer[i] = byte_at_offset(i);
+}
+
+int main(int argc, char **argv)
+{
+ sqfs_u8 read_buffer[61];
+ sqfs_u64 read_off = 0;
+ sqfs_istream_t *dummy;
+ (void)argc; (void)argv;
+
+ init_rd_buffer();
+ dummy = istream_memory_create("dummy file", 103,
+ rd_buffer, sizeof(rd_buffer));
+ TEST_NOT_NULL(dummy);
+
+ /* region 1 */
+ while (read_off < end0) {
+ size_t read_diff = end0 - read_off;
+
+ if (read_diff > sizeof(read_buffer))
+ read_diff = sizeof(read_buffer);
+
+ int ret = sqfs_istream_read(dummy, read_buffer, read_diff);
+ TEST_ASSERT(ret > 0);
+ TEST_ASSERT((size_t)ret <= read_diff);
+
+ for (int i = 0; i < ret; ++i) {
+ TEST_EQUAL_UI(read_buffer[i], 'A');
+ }
+
+ read_off += ret;
+ }
+
+ /* region 2 */
+ {
+ int ret = sqfs_istream_skip(dummy, end2 - end1);
+ TEST_EQUAL_I(ret, 0);
+ read_off += (end2 - end1);
+ }
+
+ /* region 3 */
+ for (;;) {
+ size_t read_diff = sizeof(read_buffer);
+
+ int ret = sqfs_istream_read(dummy, read_buffer, read_diff);
+ TEST_ASSERT(ret >= 0);
+ TEST_ASSERT((size_t)ret <= read_diff);
+
+ if (ret == 0) {
+ TEST_EQUAL_UI(read_off, end2);
+ break;
+ }
+
+ for (int i = 0; i < ret; ++i) {
+ TEST_EQUAL_UI(read_buffer[i], 'C');
+ }
+
+ read_off += ret;
+ TEST_ASSERT(read_off <= end2);
+ }
+
+ sqfs_drop(dummy);
+ return EXIT_SUCCESS;
+}
diff --git a/lib/sqfs/test/stream_splice.c b/lib/sqfs/test/stream_splice.c
new file mode 100644
index 0000000..6f40d1f
--- /dev/null
+++ b/lib/sqfs/test/stream_splice.c
@@ -0,0 +1,96 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later */
+/*
+ * stream_splice.c
+ *
+ * Copyright (C) 2023 David Oberhollenzer <goliath@infraroot.at>
+ */
+#include "config.h"
+
+#include "io/mem.h"
+#include "util/test.h"
+#include "sqfs/io.h"
+
+static const sqfs_u64 end0 = 449; /* region 1: filled with 'A' */
+static const sqfs_u64 end1 = 521; /* region 2: filled with 'B' */
+static const sqfs_u64 end2 = 941; /* region 3: filled with 'C' */
+
+static sqfs_u8 rd_buffer[941];
+
+static sqfs_u8 byte_at_offset(sqfs_u64 off)
+{
+ if (off < end0)
+ return 'A';
+ if (off < end1)
+ return 'B';
+ return 'C';
+}
+
+static void init_rd_buffer(void)
+{
+ for (size_t i = 0; i < end2; ++i)
+ rd_buffer[i] = byte_at_offset(i);
+}
+
+/*****************************************************************************/
+
+static int out_append(sqfs_ostream_t *strm, const void *data, size_t size);
+
+static sqfs_u64 out_offset = 0;
+
+static sqfs_ostream_t out = {
+ { 1, NULL, NULL },
+ out_append,
+ NULL,
+ NULL,
+};
+
+static int out_append(sqfs_ostream_t *strm, const void *data, size_t size)
+{
+ const sqfs_u8 *ptr = data;
+
+ TEST_ASSERT(strm == &out);
+ TEST_ASSERT(size > 0);
+
+ while (size--) {
+ sqfs_u8 x = *(ptr++);
+ sqfs_u8 y = byte_at_offset(out_offset++);
+
+ TEST_EQUAL_UI(x, y);
+ TEST_ASSERT(out_offset <= end2);
+ }
+
+ return 0;
+}
+
+/*****************************************************************************/
+
+int main(int argc, char **argv)
+{
+ sqfs_u64 total = 0;
+ sqfs_istream_t *in;
+ sqfs_s32 ret;
+ (void)argc; (void)argv;
+
+ init_rd_buffer();
+ in = istream_memory_create("memory_in", 109,
+ rd_buffer, sizeof(rd_buffer));
+ TEST_NOT_NULL(in);
+
+ for (;;) {
+ ret = sqfs_istream_splice(in, &out, 211);
+ TEST_ASSERT(ret >= 0);
+
+ if (ret == 0)
+ break;
+
+ total += ret;
+ TEST_ASSERT(total <= end2);
+ TEST_ASSERT(out_offset <= end2);
+ TEST_EQUAL_UI(total, out_offset);
+ }
+
+ TEST_EQUAL_UI(total, end2);
+ TEST_EQUAL_UI(out_offset, end2);
+ sqfs_drop(in);
+ return EXIT_SUCCESS;
+}