From 74f25ae0f3ebc1cd435f29c21ab164a9028af980 Mon Sep 17 00:00:00 2001
From: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
Date: Fri, 13 Dec 2019 01:19:27 +0100
Subject: Add --no-tail-packing option to gensquashfs, tar2sqfs

Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
---
 mkfs/mkfs.c    |  8 +++++++-
 mkfs/mkfs.h    |  1 +
 mkfs/options.c |  8 +++++++-
 tar/tar2sqfs.c | 14 +++++++++++++-
 4 files changed, 28 insertions(+), 3 deletions(-)

diff --git a/mkfs/mkfs.c b/mkfs/mkfs.c
index 6ddcdb0..ea01452 100644
--- a/mkfs/mkfs.c
+++ b/mkfs/mkfs.c
@@ -51,6 +51,7 @@ static int pack_files(sqfs_data_writer_t *data, fstree_t *fs,
 	char *node_path;
 	file_info_t *fi;
 	size_t size;
+	int flags;
 	int ret;
 
 	if (set_working_dir(opt))
@@ -115,7 +116,12 @@ static int pack_files(sqfs_data_writer_t *data, fstree_t *fs,
 
 		fi->user_ptr = inode;
 
-		ret = write_data_from_file(path, data, inode, file, 0);
+		flags = 0;
+
+		if (opt->no_tail_packing && filesize > opt->cfg.block_size)
+			flags |= SQFS_BLK_DONT_FRAGMENT;
+
+		ret = write_data_from_file(path, data, inode, file, flags);
 		file->destroy(file);
 		free(node_path);
 
diff --git a/mkfs/mkfs.h b/mkfs/mkfs.h
index 57bc39f..21e1715 100644
--- a/mkfs/mkfs.h
+++ b/mkfs/mkfs.h
@@ -37,6 +37,7 @@ typedef struct {
 	const char *infile;
 	const char *packdir;
 	const char *selinux;
+	bool no_tail_packing;
 } options_t;
 
 enum {
diff --git a/mkfs/options.c b/mkfs/options.c
index 4dce84e..94707cb 100644
--- a/mkfs/options.c
+++ b/mkfs/options.c
@@ -22,6 +22,7 @@ static struct option long_opts[] = {
 #endif
 	{ "one-file-system", no_argument, NULL, 'o' },
 	{ "exportable", no_argument, NULL, 'e' },
+	{ "no-tail-packing", no_argument, NULL, 'T' },
 	{ "force", no_argument, NULL, 'f' },
 	{ "quiet", no_argument, NULL, 'q' },
 #ifdef WITH_SELINUX
@@ -31,7 +32,7 @@ static struct option long_opts[] = {
 	{ "help", no_argument, NULL, 'h' },
 };
 
-static const char *short_opts = "F:D:X:c:b:B:d:j:Q:kxoefqhV"
+static const char *short_opts = "F:D:X:c:b:B:d:j:Q:kxoefqThV"
 #ifdef WITH_SELINUX
 "s:"
 #endif
@@ -93,6 +94,8 @@ static const char *help_string =
 "  --one-file-system, -o       When using --pack-dir only, stay in local file\n"
 "                              system and do not cross mount points.\n"
 "  --exportable, -e            Generate an export table for NFS support.\n"
+"  --no-tail-packing, -T       Do not perform tail end packing on files that\n"
+"                              are larger than block size.\n"
 "  --force, -f                 Overwrite the output file if it exists.\n"
 "  --quiet, -q                 Do not print out progress reports.\n"
 "  --help, -h                  Print help text and exit.\n"
@@ -157,6 +160,9 @@ void process_command_line(options_t *opt, int argc, char **argv)
 			break;
 
 		switch (i) {
+		case 'T':
+			opt->no_tail_packing = true;
+			break;
 		case 'c':
 			have_compressor = true;
 			ret = sqfs_compressor_id_from_name(optarg);
diff --git a/tar/tar2sqfs.c b/tar/tar2sqfs.c
index cc0ccfb..5d40fc5 100644
--- a/tar/tar2sqfs.c
+++ b/tar/tar2sqfs.c
@@ -32,13 +32,14 @@ static struct option long_opts[] = {
 	{ "no-xattr", no_argument, NULL, 'x' },
 	{ "no-keep-time", no_argument, NULL, 'k' },
 	{ "exportable", no_argument, NULL, 'e' },
+	{ "no-tail-packing", no_argument, NULL, 'T' },
 	{ "force", no_argument, NULL, 'f' },
 	{ "quiet", no_argument, NULL, 'q' },
 	{ "help", no_argument, NULL, 'h' },
 	{ "version", no_argument, NULL, 'V' },
 };
 
-static const char *short_opts = "r:c:b:B:d:X:j:Q:sxekfqhV";
+static const char *short_opts = "r:c:b:B:d:X:j:Q:sxekfqThV";
 
 static const char *usagestr =
 "Usage: tar2sqfs [OPTIONS...] <sqfsfile>\n"
@@ -84,6 +85,8 @@ static const char *usagestr =
 "  --no-keep-time, -k          Do not keep the time stamps stored in the\n"
 "                              archive. Instead, set defaults on all files.\n"
 "  --exportable, -e            Generate an export table for NFS support.\n"
+"  --no-tail-packing, -T       Do not perform tail end packing on files that\n"
+"                              are larger than block size.\n"
 "  --force, -f                 Overwrite the output file if it exists.\n"
 "  --quiet, -q                 Do not print out progress reports.\n"
 "  --help, -h                  Print help text and exit.\n"
@@ -98,6 +101,7 @@ static const char *usagestr =
 
 static bool dont_skip = false;
 static bool keep_time = true;
+static bool no_tail_pack = false;
 static sqfs_writer_cfg_t cfg;
 static sqfs_writer_t sqfs;
 static FILE *input_file = NULL;
@@ -116,6 +120,9 @@ static void process_args(int argc, char **argv)
 			break;
 
 		switch (i) {
+		case 'T':
+			no_tail_pack = true;
+			break;
 		case 'b':
 			cfg.block_size = strtol(optarg, NULL, 0);
 			break;
@@ -242,6 +249,7 @@ static int write_file(tar_header_decoded_t *hdr, file_info_t *fi,
 	size_t size, max_blk_count;
 	sqfs_file_t *file;
 	sqfs_u64 sum;
+	int flags;
 	int ret;
 
 	max_blk_count = filesize / cfg.block_size;
@@ -285,6 +293,10 @@ static int write_file(tar_header_decoded_t *hdr, file_info_t *fi,
 		}
 	}
 
+	flags = 0;
+	if (no_tail_pack && filesize > cfg.block_size)
+		flags |= SQFS_BLK_DONT_FRAGMENT;
+
 	ret = write_data_from_file(hdr->name, sqfs.data, inode, file, 0);
 	file->destroy(file);
 
-- 
cgit v1.2.3