# 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 @@ -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; +/* Do we have an extra_info metadata block? */ +int extra_info = FALSE; +/* parameters for the extra_info block */ +char *volume_label = NULL; +char *uuid = NULL; + /* Is Mksquashfs streaming the output filesystem to stdout? */ int streaming = FALSE; @@ -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 }; 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; + const int UUID_LEN = 16; /* avoid depending on uuid-dev for now */ + int label_len; + + /* The extra_info section contains one or more entries of the form: + TAG byte + LEN byte + VAL byte_1 ... byte_len + + Terminated by the tag: SQUASHFS_EXTRA_INFO_TAG_END + */ + if (volume_label) { + label_len = strlen(volume_label); + if (label_len > 255) label_len = 255; + bytes += 1 + 1 + label_len; + } + if (uuid) + bytes += 1 + 1 + UUID_LEN; + if (!bytes) + return NULL; + bytes += 1; /* TAG_END */ + + buf = malloc(bytes); + + if (volume_label) { + buf[pos++] = SQUASHFS_EXTRA_INFO_TAG_LABEL; + buf[pos++] = label_len; + memcpy(&buf[pos], volume_label, label_len); + pos += label_len; + } + if (uuid) { + char *puuid = uuid; + buf[pos++] = SQUASHFS_EXTRA_INFO_TAG_UUID; + buf[pos++] = UUID_LEN; + /* poor man's uuid_parse() */ + for (int i = 0; i < UUID_LEN; i++) { + char hex[3] = {}; + char *endptr = NULL; + if (*puuid == '-') { + puuid++; + } + if (puuid[0] && puuid[1]) { + memcpy(&hex[0], puuid, 2); + buf[pos++] = strtoul(hex, &endptr, 16); + } + if (endptr != hex + 2) { + ERROR("invalid UUID: %s\n", uuid); + exit(1); + } + puuid += 2; + } + } + buf[pos++] = SQUASHFS_EXTRA_INFO_TAG_END; + if (pos != bytes) { + ERROR("extra_info legth mismatch\n"); + exit(1); + } + *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; @@ -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", + argv[0]); + exit(1); + } + volume_label = argv[i]; + } else if (strcmp(argv[i], "-uuid") == 0) { + if(++i == argc) { + ERROR("%s: -uuid: missing uuid\n", + argv[0]); + exit(1); + } + uuid = argv[i]; } 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, @@ -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); + + int info_size; + void *info_data = info_dump(&info_size); 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, 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 \tSet the volume label\n", + "-uuid \tSet the volume UUID\n" "\n", "Filesystem time options:", "\n", "-mkfs-time