diff options
| -rw-r--r-- | include/fstree.h | 3 | ||||
| -rw-r--r-- | lib/fstree/fstree_from_file.c | 25 | ||||
| -rw-r--r-- | tests/libfstree/Makemodule.am | 6 | ||||
| -rw-r--r-- | tests/libfstree/sort_file.c | 215 | 
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; +}  | 
