Package: pristine-tar
Version: 1.26
Severity: normal
Tags: patch

Dear Maintainer,

When importing a tarball that has empty directories containing "\r" within their
path, pristine-tar re-creates these using '\r' (backslash r) rather than "\r"
(carriage return) in the filename, resulting in tar failing with ENOENT when
called with "--files-from manifest"

The reason for this is that tar -t and --files-from (un)quote unprintable
characters in their output[1], which results in these textual \r characters
present in the manifest file.

[1] https://www.gnu.org/software/tar/manual/html_section/quoting-styles.html

-- System Information:
Debian Release: wheezy/sid
  APT prefers raring-updates
  APT policy: (500, 'raring-updates'), (500, 'raring-security'), (500, 
'raring'), (400, 'raring-proposed'), (100, 'raring-backports')
Architecture: amd64 (x86_64)
Foreign Architectures: i386

Kernel: Linux 3.10.3-hyper1 (SMP w/4 CPU cores; PREEMPT)
Locale: LANG=en_GB.UTF-8, LC_CTYPE=en_GB.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash

Versions of packages pristine-tar depends on:
ii  libbz2-1.0    1.0.6-4
ii  libc6         2.17-0ubuntu5
ii  perl-modules  5.14.2-21
ii  xdelta        1.1.3-9build1
ii  zlib1g        1:1.2.7.dfsg-13ubuntu2

Versions of packages pristine-tar recommends:
ii  bzip2     1.0.6-4
ii  pbzip2    1.1.8-1
ii  xz-utils  5.1.1alpha+20120614-2ubuntu1

pristine-tar suggests no packages.

-- no debconf information

-- debsums errors found:
debsums: changed file /usr/bin/pristine-tar (from pristine-tar package)
>From 437acaa2dd0ef7f130145850c238414efdab9fbe Mon Sep 17 00:00:00 2001
From: Chow Loong Jin <hyper...@debian.org>
Date: Thu, 8 Aug 2013 18:27:17 +0800
Subject: [PATCH] Handle unprintable chars in filenames correctly

tar's -t and --files-from options implement quoting/unquoting of unprintable
characters, so we need to unquote the filenames before passing them to mkpath.

Signed-off-by: Chow Loong Jin <hyper...@debian.org>
---
 pristine-tar | 28 +++++++++++++++++++---------
 1 file changed, 19 insertions(+), 9 deletions(-)

diff --git a/pristine-tar b/pristine-tar
index 1c321d4..fdf4195 100755
--- a/pristine-tar
+++ b/pristine-tar
@@ -281,30 +281,40 @@ sub recreatetarball {
 	# in the tarball, since it can easily vary.
 	my $full_sweep=0;
 	foreach my $file (@manifest) {
-		if (-l "$tempdir/workdir/$file") {
+		my $unquoted_file = $file;
+		$unquoted_file =~ s/\\a/\a/g;
+		$unquoted_file =~ s/\\b/\b/g;
+		$unquoted_file =~ s/\\f/\f/g;
+		$unquoted_file =~ s/\\n/\n/g;
+		$unquoted_file =~ s/\\r/\r/g;
+		$unquoted_file =~ s/\\t/\t/g;
+		$unquoted_file =~ s/\\v/\x11/g;
+		$unquoted_file =~ s/\\\\/\\/g;
+
+		if (-l "$tempdir/workdir/$unquoted_file") {
 			# Can't set timestamp of a symlink, so
 			# replace the symlink with an empty file.
-			unlink("$tempdir/workdir/$file") || die "unlink: $!";
-			open(OUT, ">", "$tempdir/workdir/$file") || die "open: $!";
+			unlink("$tempdir/workdir/$unquoted_file") || die "unlink: $!";
+			open(OUT, ">", "$tempdir/workdir/$unquoted_file") || die "open: $!";
 			close OUT;
 		}
-		elsif (! -e "$tempdir/workdir/$file") {
+		elsif (! -e "$tempdir/workdir/$unquoted_file") {
 			debug("$file is listed in the manifest but may not be present in the source directory");
 			$full_sweep=1;
 
 			if ($options{create_missing}) {
 				# Avoid tar failing on the nonexistent item by
 				# creating a dummy directory.
-				debug("creating missing $file");
-				mkpath "$tempdir/workdir/$file";
+				debug("creating missing $unquoted_file");
+				mkpath "$tempdir/workdir/$unquoted_file";
 			}
 		}
 		
-		if (-d "$tempdir/workdir/$file" && (-u _ || -g _ || -k _)) {
+		if (-d "$tempdir/workdir/$unquoted_file" && (-u _ || -g _ || -k _)) {
 			# tar behaves weirdly for some special modes
 			# and ignores --mode, so clear them.
 			debug("chmod $file");
-			chmod(0755, "$tempdir/workdir/$file") ||
+			chmod(0755, "$tempdir/workdir/$unquoted_file") ||
 				die "chmod: $!";
 		}
 	}
@@ -438,7 +448,7 @@ sub genmanifest {
 	my $tarball=shift;
 	my $manifest=shift;
 
-	open(IN, "tar tf $tarball |") || die "tar tf: $!";
+	open(IN, "tar --quoting-style=escape -tf $tarball |") || die "tar tf: $!";
 	open(OUT, ">", $manifest) || die "$!";
 	while (<IN>) {
 		chomp;
-- 
1.8.1.2

Reply via email to