mirror of
https://github.com/libguestfs/libguestfs.git
synced 2026-03-21 22:53:37 +00:00
tar_in: add keepdirlink option for --keep-directory-symlink
Add a new optional boolean argument 'keepdirlink' to tar_in that passes --keep-directory-symlink to tar. This preserves existing symlinks to directories when extracting, which is important for usrmerge systems where /lib is a symlink to /usr/lib. Without this option, extracting a tarball containing lib/modules/... to / would replace the /lib symlink with a real directory, breaking the system. Signed-off-by: Anders Roxell <anders.roxell@linaro.org>
This commit is contained in:
12
daemon/tar.c
12
daemon/tar.c
@@ -134,7 +134,7 @@ write_cb (void *fd_ptr, const void *buf, size_t len)
|
||||
/* Has one FileIn parameter. */
|
||||
/* Takes optional arguments, consult optargs_bitmask. */
|
||||
int
|
||||
do_tar_in (const char *dir, const char *compress, int xattrs, int selinux, int acls)
|
||||
do_tar_in (const char *dir, const char *compress, int xattrs, int selinux, int acls, int keepdirlink)
|
||||
{
|
||||
const char *filter;
|
||||
int err, r;
|
||||
@@ -179,6 +179,9 @@ do_tar_in (const char *dir, const char *compress, int xattrs, int selinux, int a
|
||||
if (!(optargs_bitmask & GUESTFS_TAR_IN_ACLS_BITMASK))
|
||||
acls = 0;
|
||||
|
||||
if (!(optargs_bitmask & GUESTFS_TAR_IN_KEEPDIRLINK_BITMASK))
|
||||
keepdirlink = 0;
|
||||
|
||||
fd = mkstemp (error_file);
|
||||
if (fd == -1) {
|
||||
err = errno;
|
||||
@@ -203,7 +206,7 @@ do_tar_in (const char *dir, const char *compress, int xattrs, int selinux, int a
|
||||
}
|
||||
fprintf (fp, "tar -C ");
|
||||
sysroot_shell_quote (dir, fp);
|
||||
fprintf (fp, "%s -xf - %s%s%s%s2> %s",
|
||||
fprintf (fp, "%s -xf - %s%s%s%s%s2> %s",
|
||||
filter,
|
||||
chown_supported ? "" : "--no-same-owner ",
|
||||
/* --xattrs-include=* is a workaround for a bug
|
||||
@@ -213,6 +216,7 @@ do_tar_in (const char *dir, const char *compress, int xattrs, int selinux, int a
|
||||
xattrs ? "--xattrs --xattrs-include='*' " : "",
|
||||
selinux ? "--selinux " : "",
|
||||
acls ? "--acls " : "",
|
||||
keepdirlink ? "--keep-directory-symlink " : "",
|
||||
error_file);
|
||||
if (fclose (fp) == EOF)
|
||||
goto cmd_error;
|
||||
@@ -272,7 +276,7 @@ int
|
||||
do_tgz_in (const char *dir)
|
||||
{
|
||||
optargs_bitmask = GUESTFS_TAR_IN_COMPRESS_BITMASK;
|
||||
return do_tar_in (dir, "gzip", 0, 0, 0);
|
||||
return do_tar_in (dir, "gzip", 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
/* Has one FileIn parameter. */
|
||||
@@ -280,7 +284,7 @@ int
|
||||
do_txz_in (const char *dir)
|
||||
{
|
||||
optargs_bitmask = GUESTFS_TAR_IN_COMPRESS_BITMASK;
|
||||
return do_tar_in (dir, "xz", 0, 0, 0);
|
||||
return do_tar_in (dir, "xz", 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
/* Has one FileOut parameter. */
|
||||
|
||||
@@ -2631,21 +2631,21 @@ To get the checksums for many files, use C<guestfs_checksums_out>.|} };
|
||||
|
||||
{ defaults with
|
||||
name = "tar_in"; added = (1, 0, 3);
|
||||
style = RErr, [String (FileIn, "tarfile"); String (Pathname, "directory")], [OString "compress"; OBool "xattrs"; OBool "selinux"; OBool "acls"];
|
||||
style = RErr, [String (FileIn, "tarfile"); String (Pathname, "directory")], [OString "compress"; OBool "xattrs"; OBool "selinux"; OBool "acls"; OBool "keepdirlink"];
|
||||
once_had_no_optargs = true;
|
||||
cancellable = true;
|
||||
tests = [
|
||||
InitScratchFS, Always, TestResultString (
|
||||
[["mkdir"; "/tar_in"];
|
||||
["tar_in"; "$srcdir/../test-data/files/helloworld.tar"; "/tar_in"; "NOARG"; ""; ""; ""];
|
||||
["tar_in"; "$srcdir/../test-data/files/helloworld.tar"; "/tar_in"; "NOARG"; ""; ""; ""; ""];
|
||||
["cat"; "/tar_in/hello"]], "hello\n"), [];
|
||||
InitScratchFS, Always, TestResultString (
|
||||
[["mkdir"; "/tar_in_gz"];
|
||||
["tar_in"; "$srcdir/../test-data/files/helloworld.tar.gz"; "/tar_in_gz"; "gzip"; ""; ""; ""];
|
||||
["tar_in"; "$srcdir/../test-data/files/helloworld.tar.gz"; "/tar_in_gz"; "gzip"; ""; ""; ""; ""];
|
||||
["cat"; "/tar_in_gz/hello"]], "hello\n"), [];
|
||||
InitScratchFS, IfAvailable "xz", TestResultString (
|
||||
[["mkdir"; "/tar_in_xz"];
|
||||
["tar_in"; "$srcdir/../test-data/files/helloworld.tar.xz"; "/tar_in_xz"; "xz"; ""; ""; ""];
|
||||
["tar_in"; "$srcdir/../test-data/files/helloworld.tar.xz"; "/tar_in_xz"; "xz"; ""; ""; ""; ""];
|
||||
["cat"; "/tar_in_xz/hello"]], "hello\n"), []
|
||||
];
|
||||
shortdesc = "unpack tarfile to directory";
|
||||
@@ -2674,6 +2674,12 @@ If set to true, SELinux contexts are restored from the tar file.
|
||||
|
||||
If set to true, POSIX ACLs are restored from the tar file.
|
||||
|
||||
=item C<keepdirlink>
|
||||
|
||||
If set to true, existing symlinks to directories are followed when
|
||||
extracting from the tar file. This is important for usrmerge systems
|
||||
where F</lib> is a symlink to F</usr/lib>.
|
||||
|
||||
=back|} };
|
||||
|
||||
{ defaults with
|
||||
|
||||
Reference in New Issue
Block a user