aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2023-09-08 21:24:07 +0200
committerDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2023-09-08 22:24:44 +0200
commitd17046773702aad9cb3269a23ecd35f5a4a552ff (patch)
tree7cb14d8024a869239763590dcc24722c5a9cb72d
parentf5e46e0444197deee2eca93d36a8ebeb1ffd7a17 (diff)
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 <david.oberhollenzer@sigma-star.at>
-rw-r--r--bin/gensquashfs/gensquashfs.16
-rw-r--r--bin/gensquashfs/src/glob.c5
-rw-r--r--bin/gensquashfs/src/options.c14
-rw-r--r--include/io/dir_iterator.h3
-rw-r--r--lib/io/src/dir_tree_iterator.c14
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;