From: Frank Lichtenheld Date: Sat, 30 Jun 2007 23:35:58 +0000 (+0000) Subject: correct permission and owner/group handling when extracting X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e818d3b0cfc363ee7624c7a61f3e07f837312ad1;p=dpkg correct permission and owner/group handling when extracting tar balls to match more the user's preferences instead of ours or the ones from the originator of the tar ball. Patch by Ian Jackson. Closes: #390915, #207289 --- diff --git a/ChangeLog b/ChangeLog index b42a8378..4ad24a85 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2007-07-01 Ian Jackson + + * scripts/dpkg-source.pl: Don't remove setgid bits + on directories when extracting the .orig tarball + since the user might prefer to have them. Also don't + manually override user and group for extracted + directories. Instead we will take tar take of most + of that. + (extracttar): Explicetly specify --no-same-owner + and --no-same-permissions. They are default anyway + for non-root users, but no need to handle the source + differently (i.e. more carelessly) if working as root. + Since tar still insists on honoring the file permissions in the + tar ball, fix them up so that they match what the user would + expect according to his umask. + 2007-06-12 Jiří Paleček * dpkg-shlibdeps.pl: Support colon separated list of paths in the diff --git a/debian/changelog b/debian/changelog index 50a9b567..4982aaae 100644 --- a/debian/changelog +++ b/debian/changelog @@ -25,6 +25,10 @@ dpkg (1.14.5) UNRELEASED; urgency=low [ Frank Lichtenheld ] * Fix typo in German translation of start-stop-daemon(8). Noted by Joachim Breitner. Closes: #430008 + * Correct permission and owner/group handling when extracting + tar balls to match more the user's preferences instead of + ours or the ones from the originator of the tar ball. Patch + by Ian Jackson. Closes: #390915, #207289 [ Updated dselect translations ] * French (Christian Perrier) diff --git a/scripts/dpkg-source.pl b/scripts/dpkg-source.pl index bcd3e400..6b40d086 100755 --- a/scripts/dpkg-source.pl +++ b/scripts/dpkg-source.pl @@ -817,10 +817,8 @@ if ($opmode eq 'build') { (my $t = $target) =~ s!.*/!!; mkdir($tmp,0700) || &syserr(sprintf(_g("unable to create `%s'"), $tmp)); - system "chmod", "g-s", $tmp; printf(_g("%s: unpacking %s")."\n", $progname, $tarfile); extracttar("$dscdir/$tarfile",$tmp,$t); - system "chown", '-R', '-f', join(':', getfowner()), "$tmp/$t"; rename("$tmp/$t",$target) || &syserr(sprintf(_g("unable to rename `%s' to `%s'"), "$tmp/$t", $target)); rmdir($tmp) @@ -1298,19 +1296,49 @@ sub checkdiff sub extracttar { my ($tarfileread,$dirchdir,$newtopdir) = @_; + my ($mode, $modes_set, $i, $j); &forkgzipread("$tarfileread"); defined(my $c2 = fork) || syserr(_g("fork for tar -xkf -")); if (!$c2) { open(STDIN,"<&GZIP") || &syserr(_g("reopen gzip for tar -xkf -")); &cpiostderr; chdir($dirchdir) || &syserr(sprintf(_g("cannot chdir to `%s' for tar extract"), $dirchdir)); - exec('tar','-xkf','-') or &syserr(_g("exec tar -xkf -")); + exec('tar','--no-same-owner','--no-same-permissions', + '-xkf','-') or &syserr(_g("exec tar -xkf -")); } close(GZIP); $c2 == waitpid($c2,0) || &syserr(_g("wait for tar -xkf -")); $? && subprocerr("tar -xkf -"); &reapgzip; + # Unfortunately tar insists on applying our umask _to the original + # permissions_ rather than mostly-ignoring the original + # permissions. We fix it up with chmod -R (which saves us some + # work) but we have to construct a u+/- string which is a bit + # of a palaver. (Numeric doesn't work because we need [ugo]+X + # and [ugo]= doesn't work because that unsets sgid on dirs.) + # + # We still need --no-same-permissions because otherwise tar might + # extract directory setgid (which we want inherited, not + # extracted); we need --no-same-owner because putting the owner + # back is tedious - in particular, correct group ownership would + # have to be calculated using mount options and other madness. + # + # It would be nice if tar could do it right, or if pax could cope + # with GNU format tarfiles with long filenames. + # + $mode= 0777 & ~umask; + for ($i=0; $i<9; $i+=3) { + $modes_set.= ',' if $i; + $modes_set.= qw(u g o)[$i/3]; + for ($j=0; $j<3; $j++) { + $modes_set.= $mode & (0400 >> ($i+$j)) ? '+' : '-'; + $modes_set.= qw(r w X)[$j]; + } + } + system 'chmod','-R',$modes_set,'--',$dirchdir; + $? && subprocerr("chmod -R $modes_set $dirchdir"); + opendir(D,"$dirchdir") || &syserr(sprintf(_g("Unable to open dir %s"), $dirchdir)); my @dirchdirfiles = grep($_ ne "." && $_ ne "..", readdir(D)); closedir(D) || &syserr(sprintf(_g("Unable to close dir %s"), $dirchdir));