From d17046773702aad9cb3269a23ecd35f5a4a552ff Mon Sep 17 00:00:00 2001 From: David Oberhollenzer Date: Fri, 8 Sep 2023 21:24:07 +0200 Subject: genquashfs: detect/filter hardlinks when scanning a directory The new behavior is enabled by default (except on Windows) and needs to be turned off explicitly. Signed-off-by: David Oberhollenzer --- bin/gensquashfs/gensquashfs.1 | 6 ++++++ bin/gensquashfs/src/glob.c | 5 +++++ bin/gensquashfs/src/options.c | 14 +++++++++++++- include/io/dir_iterator.h | 3 ++- lib/io/src/dir_tree_iterator.c | 14 +++++++++++--- 5 files changed, 37 insertions(+), 5 deletions(-) diff --git a/bin/gensquashfs/gensquashfs.1 b/bin/gensquashfs/gensquashfs.1 index 88f58c4..5b53bcd 100644 --- a/bin/gensquashfs/gensquashfs.1 +++ b/bin/gensquashfs/gensquashfs.1 @@ -106,6 +106,11 @@ Generate an export table for NFS support. Do not perform tail end packing on files that are larger than the specified block size. .TP +\fB\-\-no\-hard\-links\fR, \fB\-H\fR +Do not perform hard link detection when scanning directories. By default, +gensquashfs records device and inode numbers to find hard links in the input +directory hierarchy. +.TP \fB\-\-force\fR, \fB\-f\fR Overwrite the output file if it exists. .TP @@ -206,6 +211,7 @@ T} \-xdev;Do not cross mount points during a recursive glob. \-mount;An alias for \fB\-xdev\fR \-keeptime;Use the time stamps from the scanned files. +\-nohardlinks;Do not perform hard link detection. \-nonrecursive;T{ Do not descend into directories. diff --git a/bin/gensquashfs/src/glob.c b/bin/gensquashfs/src/glob.c index 27b7baa..bc6edee 100644 --- a/bin/gensquashfs/src/glob.c +++ b/bin/gensquashfs/src/glob.c @@ -47,6 +47,7 @@ static const struct { { "-mount", DIR_SCAN_ONE_FILESYSTEM }, { "-keeptime", DIR_SCAN_KEEP_TIME }, { "-nonrecursive", DIR_SCAN_NO_RECURSION }, + { "-nohardlinks", DIR_SCAN_NO_HARDLINKS }, }; static bool set_scan_flag(const char *arg, dir_tree_cfg_t *cfg) @@ -176,6 +177,10 @@ int glob_files(fstree_t *fs, const char *filename, size_t line_num, cfg.prefix = prefix; cfg.flags = glob_flags; +#if defined(_WIN32) || defined(__WINDOWS__) + cfg.flags |= DIR_SCAN_NO_HARDLINKS; +#endif + while (sep->count != 0) { if (sep->args[0][0] != '-') break; diff --git a/bin/gensquashfs/src/options.c b/bin/gensquashfs/src/options.c index f263bce..c8bf64b 100644 --- a/bin/gensquashfs/src/options.c +++ b/bin/gensquashfs/src/options.c @@ -35,6 +35,7 @@ static struct option long_opts[] = { #ifdef WITH_SELINUX { "selinux", required_argument, NULL, 's' }, #endif + { "no-hard-links", no_argument, NULL, 'H' }, { "xattr-file", required_argument, NULL, 'A' }, { "sort-file", required_argument, NULL, 'S' }, { "version", no_argument, NULL, 'V' }, @@ -42,7 +43,7 @@ static struct option long_opts[] = { { NULL, 0, NULL, 0 }, }; -static const char *short_opts = "F:D:X:c:b:B:d:u:g:j:Q:S:A:kxoefqThV" +static const char *short_opts = "HF:D:X:c:b:B:d:u:g:j:Q:S:A:kxoefqThV" #ifdef WITH_SELINUX "s:" #endif @@ -123,6 +124,10 @@ const char *extra_options = " --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" +#if !defined(_WIN32) && !defined(__WINDOWS__) +" --no-hard-links, -H When scanning a directory, do not attempt to\n" +" detect hard links.\n" +#endif " --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" @@ -223,6 +228,9 @@ void process_command_line(options_t *opt, int argc, char **argv) case 'T': opt->no_tail_packing = true; break; + case 'H': + opt->dirscan_flags |= DIR_SCAN_NO_HARDLINKS; + break; case 'c': have_compressor = true; ret = sqfs_compressor_id_from_name(optarg); @@ -332,6 +340,10 @@ void process_command_line(options_t *opt, int argc, char **argv) } } +#if defined(_WIN32) || defined(__WINDOWS__) + opt->dirscan_flags |= DIR_SCAN_NO_HARDLINKS; +#endif + if (opt->cfg.num_jobs < 1) opt->cfg.num_jobs = 1; diff --git a/include/io/dir_iterator.h b/include/io/dir_iterator.h index 210316f..7154b08 100644 --- a/include/io/dir_iterator.h +++ b/include/io/dir_iterator.h @@ -26,7 +26,8 @@ enum { DIR_SCAN_ONE_FILESYSTEM = 0x1000, DIR_SCAN_NO_RECURSION = 0x2000, - DIR_SCAN_MATCH_FULL_PATH = 0x4000, + DIR_SCAN_NO_HARDLINKS = 0x4000, + DIR_SCAN_MATCH_FULL_PATH = 0x8000, }; typedef struct { diff --git a/lib/io/src/dir_tree_iterator.c b/lib/io/src/dir_tree_iterator.c index 3c25529..5688489 100644 --- a/lib/io/src/dir_tree_iterator.c +++ b/lib/io/src/dir_tree_iterator.c @@ -229,9 +229,15 @@ sqfs_dir_iterator_t *dir_tree_iterator_create(const char *path, ret = sqfs_dir_iterator_create_recursive(&it->rec, dir); sqfs_drop(dir); - if (ret) { - fprintf(stderr, "%s: out of memory\n", path); - goto fail; + if (ret) + goto fail_oom; + + if (!(cfg->flags & DIR_SCAN_NO_HARDLINKS)) { + ret = sqfs_hard_link_filter_create(&dir, it->rec); + sqfs_drop(it->rec); + it->rec = dir; + if (ret) + goto fail_oom; } sqfs_object_init(it, destroy, NULL); @@ -243,6 +249,8 @@ sqfs_dir_iterator_t *dir_tree_iterator_create(const char *path, ((sqfs_dir_iterator_t *)it)->read_xattr = read_xattr; return (sqfs_dir_iterator_t *)it; +fail_oom: + fprintf(stderr, "%s: out of memory\n", path); fail: free(it); return NULL; -- cgit v1.2.3