-# From https://github.com/plougher/squashfs-tools/pull/264
+# Initially from https://github.com/plougher/squashfs-tools/pull/264
+# Ported from squashfs-tools 4.6 → 4.7
diff --git a/squashfs-tools/mksquashfs.c b/squashfs-tools/mksquashfs.c
--- a/squashfs-tools/mksquashfs.c
+++ b/squashfs-tools/mksquashfs.c
-@@ -182,6 +182,12 @@ int exit_on_error = FALSE;
+@@ -207,6 +207,12 @@ int mem_options_disabled = FALSE;
/* Is filesystem stored at an offset from the start of the block device/file? */
long long start_offset = 0;
+char *volume_label = NULL;
+char *uuid = NULL;
+
- /* File count statistics used to print summary and fill in superblock */
- unsigned int file_count = 0, sym_count = 0, dev_count = 0, dir_count = 0,
- fifo_count = 0, sock_count = 0, id_count = 0;
-@@ -342,7 +348,7 @@ char *option_table[] = { "comp", "b", "mkfs-time", "fstime", "all-time",
- "vaf", "taf", "faf", "read-queue", "write-queue", "fragment-queue",
- "root-time", "root-uid", "root-gid", "xattrs-exclude", "xattrs-include",
- "xattrs-add", "default-mode", "default-uid", "default-gid",
-- "mem-percent", NULL
-+ "mem-percent", "label", "uuid", NULL
- };
-
- char *sqfstar_option_table[] = { "comp", "b", "mkfs-time", "fstime", "all-time",
-@@ -6252,6 +6258,8 @@ static void print_options(FILE *stream, char *name, int total_mem)
- fprintf(stream, "-keep-as-directory\tif one source directory is specified, ");
- fprintf(stream, "create a root\n");
- fprintf(stream, "\t\t\tdirectory containing that directory, rather than the\n");
-+ fprintf(stream, "-label <volume-label>\tSet the volume label\n");
-+ fprintf(stream, "-uuid <UUID>\tSet the volume UUID\n");
- fprintf(stream, "\t\t\tcontents of the directory\n");
- fprintf(stream, "\nFilesystem filter options:\n");
- fprintf(stream, "-p <pseudo-definition>\tadd pseudo file ");
-@@ -7555,6 +7563,7 @@ int sqfstar(int argc, char *argv[])
- SQUASHFS_MAJOR, SQUASHFS_MINOR,
- destination_file, block_size);
-
-+ bytes = sizeof(struct squashfs_super_block);
- /*
- * store any compressor specific options after the superblock,
- * and set the COMP_OPT flag to show that the filesystem has
-@@ -7568,11 +7577,9 @@ int sqfstar(int argc, char *argv[])
- sizeof(c_byte), &c_byte);
- write_destination(fd, sizeof(struct squashfs_super_block) +
- sizeof(c_byte), size, comp_data);
-- bytes = sizeof(struct squashfs_super_block) + sizeof(c_byte)
-- + size;
-+ bytes += sizeof(c_byte) + size;
- comp_opts = TRUE;
-- } else
-- bytes = sizeof(struct squashfs_super_block);
-+ }
+ /* Is Mksquashfs streaming the output filesystem to stdout? */
+ int streaming = FALSE;
- if(path)
- paths = add_subdir(paths, path);
-@@ -7593,7 +7600,7 @@ int sqfstar(int argc, char *argv[])
- sBlk.block_log = block_log;
- sBlk.flags = SQUASHFS_MKFLAGS(noI, noD, noF, noX, noId, no_fragments,
- always_use_fragments, duplicate_checking, exportable,
-- no_xattrs, comp_opts);
-+ no_xattrs, comp_opts, extra_info);
- sBlk.mkfs_time = mkfs_time_opt ? mkfs_time : time(NULL);
+@@ -378,7 +384,7 @@ char *option_table[] = { "comp", "b", "mkfs-time", "fstime", "inode-time",
+ "mem-percent", "-pd", "-pseudo-dir", "help-option", "ho", "help-section",
+ "hs", "info-file", "force-file-mode", "force-dir-mode",
+ "small-readers", "block-readers", "uid-gid-offset", "all-time",
+- "overcommit", "repro-time", "cols", NULL
++ "overcommit", "repro-time", "cols", "label", "uuid", NULL
+ };
- disable_info();
-@@ -7643,6 +7650,70 @@ int sqfstar(int argc, char *argv[])
+ char *sqfstar_option_table[] = { "comp", "b", "mkfs-time", "fstime",
+@@ -6546,6 +6552,68 @@ static void fix_file(char *filename)
+ BAD_ERROR("Failed to truncate file \"%s\" because %s\n", filename, strerror(errno));
}
-
+void *info_dump(int *psize) {
+ int bytes = 0, pos = 0;
+ unsigned char *buf;
+ *psize = bytes;
+ return buf;
+}
+
+ static int sqfstar(int argc, char *argv[])
+ {
+@@ -6563,7 +6631,7 @@ static int sqfstar(int argc, char *argv[])
+ int Xhelp = FALSE;
+ int dest_index;
+ struct file_buffer **fragment = NULL;
+- int size;
++ int comp_size;
+ void *comp_data;
+ int overcommit = OVERCOMMIT_DEFAULT;
+ int repro_opt = FALSE;
+@@ -7404,7 +7472,10 @@ static int sqfstar(int argc, char *argv[])
+ memset(dupl_block, 0, 1048576 * sizeof(struct file_info *));
+ memset(dupl_frag, 0, block_size * sizeof(struct file_info *));
+
+- comp_data = compressor_dump_options(comp, block_size, &size);
++ comp_data = compressor_dump_options(comp, block_size, &comp_size);
+
++ int info_size;
++ void *info_data = info_dump(&info_size);
+
+ if(!quiet)
+ printf("Creating %d.%d filesystem on %s, block size %d.\n",
+@@ -7426,18 +7497,28 @@ static int sqfstar(int argc, char *argv[])
+ * and set the COMP_OPT flag to show that the filesystem has
+ * compressor specfic options
+ */
++ long long super_end = sizeof(struct squashfs_super_block);
+ if(comp_data) {
+- unsigned short c_byte = size | SQUASHFS_COMPRESSED_BIT;
++ unsigned short c_byte = comp_size | SQUASHFS_COMPRESSED_BIT;
+
+ SQUASHFS_INSWAP_SHORTS(&c_byte, 1);
+- write_destination(fd, sizeof(struct squashfs_super_block),
+- sizeof(c_byte), &c_byte);
+- write_destination(fd, sizeof(struct squashfs_super_block) +
+- sizeof(c_byte), size, comp_data);
+- set_pos(sizeof(struct squashfs_super_block) + sizeof(c_byte) + size);
++ write_destination(fd, super_end, sizeof(c_byte), &c_byte);
++ super_end += sizeof(c_byte);
++ write_destination(fd, super_end, comp_size, comp_data);
++ super_end += comp_size;
+ comp_opts = TRUE;
+- } else
+- set_pos(sizeof(struct squashfs_super_block));
++ }
++ if (info_data) {
++ unsigned short i_byte = info_size | SQUASHFS_COMPRESSED_BIT;
+
++ SQUASHFS_INSWAP_SHORTS(&i_byte, 1);
++ write_destination(fd, super_end, sizeof(i_byte), &i_byte);
++ super_end += sizeof(i_byte);
++ write_destination(fd, super_end, info_size, info_data);
++ super_end += info_size;
++ extra_info = TRUE;
++ }
++ set_pos(super_end);
+
+ if(path)
+ paths = add_subdir(paths, path);
+@@ -7458,7 +7539,7 @@ static int sqfstar(int argc, char *argv[])
+ sBlk.block_log = block_log;
+ sBlk.flags = SQUASHFS_MKFLAGS(noI, noD, noF, noX, noId, no_fragments,
+ always_use_fragments, duplicate_checking, exportable,
+- no_xattrs, comp_opts);
++ no_xattrs, comp_opts, extra_info);
+ if(mkfs_time_opt)
+ sBlk.mkfs_time = mkfs_time;
+ else if(mkfs_inode_opt)
+@@ -7513,7 +7594,6 @@ static int sqfstar(int argc, char *argv[])
+ return 0;
+ }
+
+-
int main(int argc, char *argv[])
{
struct stat buf, source_buf;
-@@ -8436,6 +8507,20 @@ int main(int argc, char *argv[])
- i++;
- } else if(strcmp(argv[i], "-4k-align") == 0) {
- do_4k_align = TRUE;
+@@ -8337,6 +8417,20 @@ int main(int argc, char *argv[])
+ !parse_number(argv[i], &overcommit, 2) ||
+ (overcommit > 100))
+ mksquashfs_option_help(argv[i - 1], "mksquashfs: -overcommit missing or invalid percentage: it should be 0 - 100%%\n");
+ } else if (strcmp(argv[i], "-label") == 0) {
+ if(++i == argc) {
+ ERROR("%s: -label: missing label\n",
+ exit(1);
+ }
+ uuid = argv[i];
- } else {
- ERROR("%s: invalid option\n\n", argv[0]);
- print_options(stderr, argv[0], total_mem);
-@@ -8661,6 +8746,7 @@ int main(int argc, char *argv[])
- exportable = SQUASHFS_EXPORTABLE(sBlk.flags);
- no_xattrs = SQUASHFS_NO_XATTRS(sBlk.flags);
- comp_opts = SQUASHFS_COMP_OPTS(sBlk.flags);
-+ extra_info = SQUASHFS_EXTRA_INFO(sBlk.flags);
+ } else
+ mksquashfs_invalid_option(argv[i]);
}
+@@ -8706,6 +8800,7 @@ int main(int argc, char *argv[])
+ exportable = SQUASHFS_EXPORTABLE(sBlk.flags);
+ no_xattrs = SQUASHFS_NO_XATTRS(sBlk.flags);
+ comp_opts = SQUASHFS_COMP_OPTS(sBlk.flags);
++ extra_info = SQUASHFS_EXTRA_INFO(sBlk.flags);
+ }
- initialise_threads(readq, fragq, bwriteq, fwriteq, !appending,
-@@ -8682,33 +8768,44 @@ int main(int argc, char *argv[])
- memset(dupl_frag, 0, block_size * sizeof(struct file_info *));
+ initialise_threads(readq, fragq, bwriteq, fwriteq, !appending,
+@@ -8721,9 +8816,12 @@ int main(int argc, char *argv[])
+ memset(dupl_frag, 0, block_size * sizeof(struct file_info *));
- if(!appending) {
-- int size;
-+ int comp_size;
- void *comp_data = compressor_dump_options(comp, block_size,
-- &size);
-+ &comp_size);
+ if(!appending) {
+- int size;
++ int comp_size;
+ void *comp_data = compressor_dump_options(comp, block_size,
+- &size);
++ &comp_size);
+
-+ int info_size;
-+ void *info_data = info_dump(&info_size);
++ int info_size;
++ void *info_data = info_dump(&info_size);
- if(!quiet)
- printf("Creating %d.%d filesystem on %s, block size %d.\n",
- SQUASHFS_MAJOR, SQUASHFS_MINOR,
- destination_file, block_size);
-
-+ bytes = sizeof(struct squashfs_super_block);
- /*
- * store any compressor specific options after the superblock,
- * and set the COMP_OPT flag to show that the filesystem has
- * compressor specfic options
- */
- if(comp_data) {
-- unsigned short c_byte = size | SQUASHFS_COMPRESSED_BIT;
-+ unsigned short c_byte = comp_size | SQUASHFS_COMPRESSED_BIT;
-
- SQUASHFS_INSWAP_SHORTS(&c_byte, 1);
-- write_destination(fd, sizeof(struct squashfs_super_block),
-- sizeof(c_byte), &c_byte);
-- write_destination(fd, sizeof(struct squashfs_super_block) +
-- sizeof(c_byte), size, comp_data);
-- bytes = sizeof(struct squashfs_super_block) + sizeof(c_byte)
-- + size;
-+ write_destination(fd, bytes, sizeof(c_byte), &c_byte);
-+ bytes += sizeof(c_byte);
-+ write_destination(fd, bytes, comp_size, comp_data);
-+ bytes += comp_size;
- comp_opts = TRUE;
-- } else
-- bytes = sizeof(struct squashfs_super_block);
-+ }
-+ if (info_data) {
-+ unsigned short i_byte = info_size | SQUASHFS_COMPRESSED_BIT;
+ if(!quiet)
+ printf("Creating %d.%d filesystem on %s, block size %d.\n",
+@@ -8746,18 +8844,28 @@ int main(int argc, char *argv[])
+ * and set the COMP_OPT flag to show that the filesystem has
+ * compressor specfic options
+ */
++ long long super_end = sizeof(struct squashfs_super_block);
+ if(comp_data) {
+- unsigned short c_byte = size | SQUASHFS_COMPRESSED_BIT;
++ unsigned short c_byte = comp_size | SQUASHFS_COMPRESSED_BIT;
+
+ SQUASHFS_INSWAP_SHORTS(&c_byte, 1);
+- write_destination(fd, sizeof(struct squashfs_super_block),
+- sizeof(c_byte), &c_byte);
+- write_destination(fd, sizeof(struct squashfs_super_block) +
+- sizeof(c_byte), size, comp_data);
+- set_pos(sizeof(struct squashfs_super_block) + sizeof(c_byte) + size);
++ write_destination(fd, super_end, sizeof(c_byte), &c_byte);
++ super_end += sizeof(c_byte);
++ write_destination(fd, super_end, comp_size, comp_data);
++ super_end += comp_size;
+ comp_opts = TRUE;
+- } else
+- set_pos(sizeof(struct squashfs_super_block));
++ }
++ if (info_data) {
++ unsigned short i_byte = info_size | SQUASHFS_COMPRESSED_BIT;
+
-+ SQUASHFS_INSWAP_SHORTS(&i_byte, 1);
-+ write_destination(fd, bytes, sizeof(i_byte), &i_byte);
-+ bytes += sizeof(i_byte);
-+ write_destination(fd, bytes, info_size, info_data);
-+ bytes += info_size;
-+ extra_info = TRUE;
-+ }
- } else {
- unsigned int last_directory_block, inode_dir_file_size,
- root_inode_size, inode_dir_start_block,
-@@ -8868,7 +8965,7 @@ int main(int argc, char *argv[])
- sBlk.block_log = block_log;
- sBlk.flags = SQUASHFS_MKFLAGS(noI, noD, noF, noX, noId, no_fragments,
- always_use_fragments, duplicate_checking, exportable,
-- no_xattrs, comp_opts);
-+ no_xattrs, comp_opts, extra_info);
- sBlk.mkfs_time = mkfs_time_opt ? mkfs_time : time(NULL);
-
- disable_info();
++ SQUASHFS_INSWAP_SHORTS(&i_byte, 1);
++ write_destination(fd, super_end, sizeof(i_byte), &i_byte);
++ super_end += sizeof(i_byte);
++ write_destination(fd, super_end, info_size, info_data);
++ super_end += info_size;
++ extra_info = TRUE;
++ }
++ set_pos(super_end);
+ } else {
+ unsigned int last_directory_block, inode_dir_file_size,
+ root_inode_size, inode_dir_start_block,
+@@ -8913,7 +9021,7 @@ int main(int argc, char *argv[])
+ sBlk.block_log = block_log;
+ sBlk.flags = SQUASHFS_MKFLAGS(noI, noD, noF, noX, noId, no_fragments,
+ always_use_fragments, duplicate_checking, exportable,
+- no_xattrs, comp_opts);
++ no_xattrs, comp_opts, extra_info);
+ if(mkfs_time_opt)
+ sBlk.mkfs_time = mkfs_time;
+ else if(mkfs_inode_opt)
+diff --git a/squashfs-tools/mksquashfs_help.c b/squashfs-tools/mksquashfs_help.c
+--- a/squashfs-tools/mksquashfs_help.c
++++ b/squashfs-tools/mksquashfs_help.c
+@@ -243,6 +243,8 @@ static char *mksquashfs_text[]={
+ "-keep-as-directory\tif one source directory is specified, create a "
+ "root directory containing that directory, rather than the "
+ "contents of the directory\n",
++ "-label <volume-label>\tSet the volume label\n",
++ "-uuid <UUID>\tSet the volume UUID\n"
+ "\n", "Filesystem time options:", "\n",
+ "-mkfs-time <time>\tset filesystem creation timestamp to <time>. "
+ "<time> can be \"inode\", which means use the latest inode "
diff --git a/squashfs-tools/squashfs_fs.h b/squashfs-tools/squashfs_fs.h
--- a/squashfs-tools/squashfs_fs.h
+++ b/squashfs-tools/squashfs_fs.h
-@@ -72,6 +72,7 @@
+@@ -74,6 +74,7 @@
#define SQUASHFS_NO_XATTR 9
#define SQUASHFS_COMP_OPT 10
#define SQUASHFS_NOID 11
#define SQUASHFS_BIT(flag, bit) ((flag >> bit) & 1)
-@@ -108,12 +109,16 @@
+@@ -110,12 +111,16 @@
#define SQUASHFS_UNCOMPRESSED_IDS(flags) SQUASHFS_BIT(flags, \
SQUASHFS_NOID)
/* Max number of types and file types */
#define SQUASHFS_DIR_TYPE 1
-@@ -289,6 +294,10 @@ typedef long long squashfs_inode;
+@@ -291,6 +296,10 @@ typedef long long squashfs_inode;
#define LZ4_COMPRESSION 5
#define ZSTD_COMPRESSION 6
-+#define SQUASHFS_EXTRA_INFO_TAG_END 0
-+#define SQUASHFS_EXTRA_INFO_TAG_LABEL 1
-+#define SQUASHFS_EXTRA_INFO_TAG_UUID 2
++#define SQUASHFS_EXTRA_INFO_TAG_END 0
++#define SQUASHFS_EXTRA_INFO_TAG_LABEL 1
++#define SQUASHFS_EXTRA_INFO_TAG_UUID 2
+
struct squashfs_super_block {
unsigned int s_magic;