summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/fstree.h3
-rw-r--r--lib/fstree/fstree_from_file.c25
-rw-r--r--tests/libfstree/Makemodule.am6
-rw-r--r--tests/libfstree/sort_file.c215
4 files changed, 241 insertions, 8 deletions
diff --git a/include/fstree.h b/include/fstree.h
index 9868e8e..aa8efd5 100644
--- a/include/fstree.h
+++ b/include/fstree.h
@@ -195,6 +195,9 @@ tree_node_t *fstree_add_generic(fstree_t *fs, const char *path,
int fstree_from_file(fstree_t *fs, const char *filename,
const char *basepath);
+int fstree_from_file_stream(fstree_t *fs, istream_t *file,
+ const char *basepath);
+
/*
This function performs all the necessary post processing steps on the file
system tree, i.e. recursively sorting all directory entries by name,
diff --git a/lib/fstree/fstree_from_file.c b/lib/fstree/fstree_from_file.c
index d2f0b4a..e77f19a 100644
--- a/lib/fstree/fstree_from_file.c
+++ b/lib/fstree/fstree_from_file.c
@@ -540,16 +540,14 @@ out_desc:
return -1;
}
-int fstree_from_file(fstree_t *fs, const char *filename, const char *basepath)
+int fstree_from_file_stream(fstree_t *fs, istream_t *fp, const char *basepath)
{
+ const char *filename;
size_t line_num = 1;
- istream_t *fp;
char *line;
int ret;
- fp = istream_open_file(filename);
- if (fp == NULL)
- return -1;
+ filename = istream_get_filename(fp);
for (;;) {
ret = istream_get_line(fp, &line, &line_num,
@@ -570,10 +568,23 @@ int fstree_from_file(fstree_t *fs, const char *filename, const char *basepath)
++line_num;
}
- sqfs_destroy(fp);
return 0;
fail_line:
free(line);
- sqfs_destroy(fp);
return -1;
}
+
+int fstree_from_file(fstree_t *fs, const char *filename, const char *basepath)
+{
+ istream_t *fp;
+ int ret;
+
+ fp = istream_open_file(filename);
+ if (fp == NULL)
+ return -1;
+
+ ret = fstree_from_file_stream(fs, fp, basepath);
+
+ sqfs_destroy(fp);
+ return ret;
+}
diff --git a/tests/libfstree/Makemodule.am b/tests/libfstree/Makemodule.am
index d589026..c7ecdd5 100644
--- a/tests/libfstree/Makemodule.am
+++ b/tests/libfstree/Makemodule.am
@@ -61,6 +61,9 @@ test_fstree_epoch_SOURCES = tests/libfstree/epoch.c
test_fstree_epoch_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/lib/fstree
test_fstree_epoch_SOURCES += lib/fstree/source_date_epoch.c
+test_sort_file_SOURCES = tests/libfstree/sort_file.c
+test_sort_file_LDADD = libfstree.a libfstream.a libcompat.a
+
fstree_fuzz_SOURCES = tests/libfstree/fstree_fuzz.c
fstree_fuzz_LDADD = libfstree.a libfstream.a libcompat.a
@@ -69,7 +72,8 @@ FSTREE_TESTS = \
test_mknode_reg test_mknode_dir test_gen_inode_numbers \
test_add_by_path test_get_path test_fstree_sort test_fstree_from_file \
test_fstree_init test_filename_sane test_filename_sane_w32 \
- test_fstree_from_dir test_fstree_glob1 test_fstree_epoch
+ test_fstree_from_dir test_fstree_glob1 test_fstree_epoch \
+ test_sort_file
if BUILD_TOOLS
check_PROGRAMS += $(FSTREE_TESTS)
diff --git a/tests/libfstree/sort_file.c b/tests/libfstree/sort_file.c
new file mode 100644
index 0000000..39e4f23
--- /dev/null
+++ b/tests/libfstree/sort_file.c
@@ -0,0 +1,215 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later */
+/*
+ * sort_file.c
+ *
+ * Copyright (C) 2021 David Oberhollenzer <goliath@infraroot.at>
+ */
+#include "config.h"
+
+#include "sqfs/block.h"
+#include "fstree.h"
+#include "../test.h"
+
+static const char *listing =
+"dir /bin 0755 0 0\n"
+"dir /lib 0755 0 0\n"
+"dir /usr 0755 0 0\n"
+"dir /usr/share 0755 0 0\n"
+"\n"
+"file /bin/chown 0755 0 0\n"
+"file /bin/ls 0755 0 0\n"
+"file /bin/chmod 0755 0 0\n"
+"file /bin/dir 0755 0 0\n"
+"file /bin/cp 0755 0 0\n"
+"file /bin/dd 0755 0 0\n"
+"file /bin/ln 0755 0 0\n"
+"file /bin/mkdir 0755 0 0\n"
+"file /bin/mknod 0755 0 0\n"
+"\n"
+"file /lib/libssl.so 0755 0 0\n"
+"file /lib/libfoobar.so 0755 0 0\n"
+"file /lib/libwhatever.so 0755 0 0\n"
+"\n"
+"file /usr/share/bla.txt 0644 0 0\n";
+
+static const char *sort_file =
+"# Blockwise reverse the order of the /bin files\n"
+" 10 [glob] /bin/mk*\n"
+" 20 [glob] /bin/ch*\n"
+" 30 [glob] /bin/d*\n"
+" 40 /bin/cp\n"
+" 50 [glob] /bin/*\n"
+"\n"
+"# Make this file appear first\n"
+" -10000 [dont_compress,dont_fragment,align] /usr/share/bla.txt";
+
+static const char *initial_order[] = {
+ "bin/chmod",
+ "bin/chown",
+ "bin/cp",
+ "bin/dd",
+ "bin/dir",
+ "bin/ln",
+ "bin/ls",
+ "bin/mkdir",
+ "bin/mknod",
+ "lib/libfoobar.so",
+ "lib/libssl.so",
+ "lib/libwhatever.so",
+ "usr/share/bla.txt",
+};
+
+static const char *after_sort_order[] = {
+ "usr/share/bla.txt",
+ "lib/libfoobar.so",
+ "lib/libssl.so",
+ "lib/libwhatever.so",
+ "bin/mkdir",
+ "bin/mknod",
+ "bin/chmod",
+ "bin/chown",
+ "bin/dd",
+ "bin/dir",
+ "bin/cp",
+ "bin/ln",
+ "bin/ls",
+};
+
+static sqfs_s64 priorities[] = {
+ -10000,
+ 0,
+ 0,
+ 0,
+ 10,
+ 10,
+ 20,
+ 20,
+ 30,
+ 30,
+ 40,
+ 50,
+ 50,
+};
+
+static int flags[] = {
+ SQFS_BLK_DONT_COMPRESS | SQFS_BLK_ALIGN | SQFS_BLK_DONT_FRAGMENT,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+};
+
+/*****************************************************************************/
+
+static sqfs_u8 temp_buffer[2048];
+static const char *input_file = NULL;
+
+static void destroy_noop(sqfs_object_t *obj)
+{
+ (void)obj;
+}
+
+static int memfile_load(istream_t *strm)
+{
+ strcpy((char *)temp_buffer, input_file);
+ strm->eof = true;
+ strm->buffer_used = strlen(input_file);
+ return 0;
+}
+
+static const char *get_filename(istream_t *strm)
+{
+ (void)strm;
+ return "memstream";
+}
+
+static istream_t memstream = {
+ .base = {
+ .destroy = destroy_noop,
+ },
+
+ .buffer_used = 0,
+ .buffer_offset = 0,
+ .eof = false,
+ .buffer = temp_buffer,
+
+ .precache = memfile_load,
+ .get_filename = get_filename,
+};
+
+/*****************************************************************************/
+
+int main(void)
+{
+ file_info_t *fi;
+ fstree_t fs;
+ size_t i;
+
+ input_file = listing;
+ memstream.buffer_used = 0;
+ memstream.buffer_offset = 0;
+ memstream.eof = false;
+
+ TEST_ASSERT(fstree_init(&fs, NULL) == 0);
+ TEST_ASSERT(fstree_from_file_stream(&fs, &memstream, NULL) == 0);
+
+ fstree_post_process(&fs);
+
+ for (i = 0, fi = fs.files; fi != NULL; fi = fi->next, ++i) {
+ tree_node_t *n = container_of(fi, tree_node_t, data.file);
+ char *path = fstree_get_path(n);
+ int ret;
+
+ TEST_NOT_NULL(path);
+
+ ret = canonicalize_name(path);
+ TEST_EQUAL_I(ret, 0);
+
+ TEST_STR_EQUAL(initial_order[i], path);
+ free(path);
+
+ TEST_EQUAL_I(fi->priority, 0);
+ TEST_EQUAL_I(fi->flags, 0);
+ }
+
+ TEST_EQUAL_UI(i, sizeof(initial_order) / sizeof(initial_order[0]));
+
+
+ input_file = sort_file;
+ memstream.buffer_used = 0;
+ memstream.buffer_offset = 0;
+ memstream.eof = false;
+
+ TEST_ASSERT(fstree_sort_files(&fs, &memstream) == 0);
+
+ for (i = 0, fi = fs.files; fi != NULL; fi = fi->next, ++i) {
+ tree_node_t *n = container_of(fi, tree_node_t, data.file);
+ char *path = fstree_get_path(n);
+ int ret;
+
+ TEST_NOT_NULL(path);
+
+ ret = canonicalize_name(path);
+ TEST_EQUAL_I(ret, 0);
+
+ TEST_STR_EQUAL(after_sort_order[i], path);
+ free(path);
+
+ TEST_EQUAL_I(fi->priority, priorities[i]);
+ TEST_EQUAL_I(fi->flags, flags[i]);
+ }
+
+ TEST_EQUAL_UI(i, sizeof(after_sort_order) /
+ sizeof(after_sort_order[0]));
+
+ fstree_cleanup(&fs);
+ return EXIT_SUCCESS;
+}