aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2020-10-28 13:03:59 +0100
committerDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2020-10-31 17:38:34 +0100
commit5ca4295edfde4c1603d9e3e31546c8f6228e7b8f (patch)
tree2686c399ec3ae507d5ebdb065e2f995d487aee72
parent23e31c1076f7d6a6d09014c3ae2fff54692b9e7f (diff)
Fix: tar2sqfs: if --root-becomes is used, also retarget links
In addition to skipping non-prefixed files and stripping the prefix off of entries we accept, the targets of links also have to be altered, since they can be absolute paths with the root prefix attached. This can affect symbolic links as well. Altough they are allowed to point into nowhere, across filesystem boundaries, they may also be absolute paths refering to existing locations in the filesystem, so no distinction is made by default. However, the later may be intended (e.g. only a subdirectory is packed into SquashFS and then mounted at that location), so a command line switch is added to disable symlink retargetting. Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
-rw-r--r--bin/tar2sqfs/options.c11
-rw-r--r--bin/tar2sqfs/process_tarball.c21
-rw-r--r--bin/tar2sqfs/tar2sqfs.110
-rw-r--r--bin/tar2sqfs/tar2sqfs.h2
4 files changed, 43 insertions, 1 deletions
diff --git a/bin/tar2sqfs/options.c b/bin/tar2sqfs/options.c
index 19017a9..d9c4238 100644
--- a/bin/tar2sqfs/options.c
+++ b/bin/tar2sqfs/options.c
@@ -19,6 +19,7 @@ static struct option long_opts[] = {
{ "no-xattr", no_argument, NULL, 'x' },
{ "no-keep-time", no_argument, NULL, 'k' },
{ "exportable", no_argument, NULL, 'e' },
+ { "no-symlink-retarget", no_argument, NULL, 'S' },
{ "no-tail-packing", no_argument, NULL, 'T' },
{ "force", no_argument, NULL, 'f' },
{ "quiet", no_argument, NULL, 'q' },
@@ -27,7 +28,7 @@ static struct option long_opts[] = {
{ NULL, 0, NULL, 0 },
};
-static const char *short_opts = "r:c:b:B:d:X:j:Q:sxekfqThV";
+static const char *short_opts = "r:c:b:B:d:X:j:Q:sxekfqSThV";
static const char *usagestr =
"Usage: tar2sqfs [OPTIONS...] <sqfsfile>\n"
@@ -43,6 +44,10 @@ static const char *usagestr =
" xattrs, ...) are stored in the root inode.\n"
" If not set and a tarbal has an entry for './'\n"
" or '/', it becomes the root instead.\n"
+" --no-symlink-retarget, -S If --root-becomes is used, link targets are\n"
+" adjusted if they are prefixed by the root\n"
+" path. If this flag is set, symlinks are left\n"
+" untouched and only hard links are changed.\n"
"\n"
" --compressor, -c <name> Select the compressor to use.\n"
" A list of available compressors is below.\n"
@@ -90,6 +95,7 @@ static const char *usagestr =
bool dont_skip = false;
bool keep_time = true;
bool no_tail_pack = false;
+bool no_symlink_retarget = false;
sqfs_writer_cfg_t cfg;
char *root_becomes = NULL;
@@ -106,6 +112,9 @@ void process_args(int argc, char **argv)
break;
switch (i) {
+ case 'S':
+ no_symlink_retarget = true;
+ break;
case 'T':
no_tail_pack = true;
break;
diff --git a/bin/tar2sqfs/process_tarball.c b/bin/tar2sqfs/process_tarball.c
index 1de35fa..984a1ef 100644
--- a/bin/tar2sqfs/process_tarball.c
+++ b/bin/tar2sqfs/process_tarball.c
@@ -156,6 +156,7 @@ int process_tarball(FILE *input_file, sqfs_writer_t *sqfs)
sqfs_u64 offset, count;
sparse_map_t *m;
size_t rootlen;
+ char *target;
int ret;
rootlen = root_becomes == NULL ? 0 : strlen(root_becomes);
@@ -204,6 +205,26 @@ int process_tarball(FILE *input_file, sqfs_writer_t *sqfs)
stderr);
skip = true;
}
+
+ if (hdr.link_target != NULL &&
+ (hdr.is_hard_link || !no_symlink_retarget)) {
+ target = strdup(hdr.link_target);
+ if (target == NULL) {
+ fprintf(stderr, "packing '%s': %s\n",
+ hdr.name, strerror(errno));
+ goto fail;
+ }
+
+ if (canonicalize_name(target) == 0 &&
+ !strncmp(target, root_becomes, rootlen) &&
+ target[rootlen] == '/') {
+ memmove(hdr.link_target,
+ target + rootlen,
+ strlen(target + rootlen) + 1);
+ }
+
+ free(target);
+ }
} else if (hdr.name[0] == '\0') {
is_root = true;
}
diff --git a/bin/tar2sqfs/tar2sqfs.1 b/bin/tar2sqfs/tar2sqfs.1
index da344ec..a2eb084 100644
--- a/bin/tar2sqfs/tar2sqfs.1
+++ b/bin/tar2sqfs/tar2sqfs.1
@@ -20,6 +20,16 @@ paths this way, i.e. if the archive contains an entry for \fB./\fR, it becomes
the root node and the prefix is stripped from all paths (and similar for
absolute paths and \fB/\fR).
.TP
+\fB\-\-no\-symlink\-retarget\fR, \fB\-S\fR
+If \-\-root\-becomes is used, link targets are adjusted if they are prefixed by
+the root path. By default, this is also done on symbolic links, that have a
+target that is prefixed by the root path and they are converted to aboluste
+paths with the prefix removed. However, because symlinks can point across mount
+points, this may actually be intended for some use cases.
+
+This flag allows changing the default behaviour, so only hard links are
+retargeted.
+.TP
\fB\-\-compressor\fR, \fB\-c\fR <name>
Select the compressor to use.
Run \fBtar2sqfs \-\-help\fR to get a list of all available compressors
diff --git a/bin/tar2sqfs/tar2sqfs.h b/bin/tar2sqfs/tar2sqfs.h
index a27a50b..08cdc4d 100644
--- a/bin/tar2sqfs/tar2sqfs.h
+++ b/bin/tar2sqfs/tar2sqfs.h
@@ -17,6 +17,7 @@
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
+#include <errno.h>
#ifdef _WIN32
#include <io.h>
@@ -26,6 +27,7 @@
extern bool dont_skip;
extern bool keep_time;
extern bool no_tail_pack;
+extern bool no_symlink_retarget;
extern sqfs_writer_cfg_t cfg;
extern char *root_becomes;