summaryrefslogtreecommitdiff
path: root/pristine-tar
diff options
context:
space:
mode:
authorMatthew Vernon <matthew@debian.org>2022-11-08 10:11:17 +0000
committerMatthew Vernon <matthew@debian.org>2022-11-08 10:11:17 +0000
commitcdc511a457e03d84e297b66fd491ee7bccd7ad04 (patch)
treee148697f319a5a516176f7fc6243313e9197fc12 /pristine-tar
parent9401d7c09f575173d84727cae58674dbcc20106e (diff)
parent1b9f8be97b47d5fe4934073a55b725b29c12c435 (diff)
Merge branch 'matthew_fix_manifest' into 'master'HEADdebian/1.50archive/debian/1.50master
quote manifests, fix unquoting of paths, use tar --null (closes: #1010024, #784635, #736201, #719078) See merge request debian/pristine-tar!9
Diffstat (limited to 'pristine-tar')
-rwxr-xr-xpristine-tar112
1 files changed, 78 insertions, 34 deletions
diff --git a/pristine-tar b/pristine-tar
index 081dca1..7ec8d3e 100755
--- a/pristine-tar
+++ b/pristine-tar
@@ -362,6 +362,28 @@ Options:
sub unquote_filename {
my $filename = shift;
+ my %tar_escapes = (
+ 'a' => "\a",
+ 'b' => "\b",
+ 'f' => "\f",
+ 'n' => "\n",
+ 'r' => "\r",
+ 't' => "\t",
+ 'v' => "\x11",
+ '\\' => '\\',
+ );
+ $filename =~ s/\\([abfnrtv\\]|[0-9]{3})/$tar_escapes{$1} or chr(oct($1))/ge;
+
+ return $filename;
+}
+
+#This is unquote_filename from pristine-tar 1.49; it isn't correct.
+#But we need to be able to identically mis-unquote paths in order to
+#generate identical tarballs to those buggy versions to apply deltas
+#against.
+sub buggy_unquote_filename {
+ my $filename = shift;
+
$filename =~ s/\\a/\a/g;
$filename =~ s/\\b/\b/g;
$filename =~ s/\\f/\f/g;
@@ -430,7 +452,12 @@ sub recreatetarball {
# in the tarball, since it can easily vary.
my $full_sweep = 0;
foreach my $file (@manifest) {
- my $unquoted_file = unquote_filename($file);
+ my $unquoted_file;
+ if ($options{buggy_unquote}) {
+ $unquoted_file = buggy_unquote_filename($file);
+ } else {
+ $unquoted_file = unquote_filename($file);
+ }
if (-l "$tempdir/workdir/$unquoted_file") {
# Can't set timestamp of a symlink, so
@@ -464,7 +491,12 @@ sub recreatetarball {
# Set file times only after modifying of the directory content is
# done.
foreach my $file (@manifest) {
- my $unquoted_file = unquote_filename($file);
+ my $unquoted_file;
+ if ($options{buggy_unquote}) {
+ $unquoted_file = buggy_unquote_filename($file);
+ } else {
+ $unquoted_file = unquote_filename($file);
+ }
if (-e "$tempdir/workdir/$unquoted_file") {
utime(0, 0, "$tempdir/workdir/$unquoted_file") || die "utime: $file: $!";
}
@@ -508,6 +540,26 @@ sub recreatetarball_helper {
my %options = @_;
my $tempdir = $recreatetarball_tempdir;
+ # Most manifests are quoted; we want to unquote and null-separate them
+ # to pass to tar --null --files-from. Unfortunately, some versions of
+ # pristine-tar wrote unquoted manifests; for many of these, unquoting
+ # is a no-op.
+ # So we try unquote-and-null-separate; if that fails, try just
+ # null-separate (there should be no unquoted manifests with paths with
+ # newlines in).
+ open(IN, "<", "$tempdir/manifest") || die "$tempdir/manifest: $!";
+ open(OUT, ">", "$tempdir/nulledmanifest") || die "$!";
+ while (<IN>) {
+ chomp;
+ if ($options{buggy_unquote}) {
+ print OUT buggy_unquote_filename($_) . "\0" if length $_;
+ } else {
+ print OUT unquote_filename($_) . "\0" if length $_;
+ }
+ }
+ close IN;
+ close OUT;
+
my $ret = "$tempdir/recreatetarball";
my @cmd = (
$tar_program, "cf",
@@ -516,14 +568,26 @@ sub recreatetarball_helper {
0, "--numeric-owner",
"-C", "$tempdir/workdir",
"--no-recursion", "--mode",
- "0644", "--verbatim-files-from",
- "--files-from", "$tempdir/manifest"
+ "0644", "--null",
+ "--files-from", "$tempdir/nulledmanifest"
);
if (exists $options{tar_format}) {
push @cmd, ("-H", $options{tar_format});
}
- doit(@cmd);
+ if (try_doit(@cmd) != 0) {
+ debug "tar failed with unquoted manifest, retrying without unquoting";
+ open(IN, "<", "$tempdir/manifest") || die "$tempdir/manifest: $!";
+ open(OUT, ">", "$tempdir/nulledmanifest") || die "$!";
+ while (<IN>) {
+ chomp;
+ print OUT "$_\0" if length $_;
+ }
+ close IN;
+ close OUT;
+ doit(@cmd);
+ }
+# unlink("$tempdir/nulledmanifest") || die "unlink $tempdir/nulledmanifest: $!";
return $ret;
}
@@ -560,33 +624,6 @@ sub recreatetarball_broken_numeric_owner {
return recreatetarball_helper();
}
-sub recreatetarball_broken_verbatim {
- # To fix #851286, the option --verbatim-files-from was added by
- # default. But now some older older stored tarballs won't reproduce
- # (#933031). Try again *without* that option to tar.
- my %options = @_;
- my $tempdir = $recreatetarball_tempdir;
-
- my $ret = "$tempdir/recreatetarball";
- my @cmd = (
- $tar_program, "cf",
- $ret, "--owner",
- 0, "--group",
- 0, "--numeric-owner",
- "-C", "$tempdir/workdir",
- "--no-recursion", "--mode",
- "0644",
- "--files-from", "$tempdir/manifest"
- );
- if (exists $options{tar_format}) {
- push @cmd, ("-H", $options{tar_format});
- }
-
- doit(@cmd);
-
- return $ret;
-}
-
sub gentar {
my $deltafile = shift;
my $tarball = shift;
@@ -624,6 +661,14 @@ sub gentar {
%opts
);
};
+ push @try, sub {
+ recreatetarball(
+ $delta->{manifest}, getcwd,
+ clobber_source => 0,
+ buggy_unquote => 1,
+ %opts
+ );
+ };
push @try, \&recreatetarball_longlink_100;
push @try, sub {
recreatetarball(
@@ -641,7 +686,6 @@ sub gentar {
%opts
);
};
- push @try, \&recreatetarball_broken_verbatim;
push @try, \&recreatetarball_broken_numeric_owner;
my $ok;
@@ -692,7 +736,7 @@ sub genmanifest {
chomp;
# ./ or / in the manifest just confuses tar
s/^\.?\/+//;
- print OUT unquote_filename($_) . "\n" if length $_;
+ print OUT "$_\n" if length $_;
}
close IN;
close OUT;