From ed7a39e3d18cdef0e1067e50e4ad421e63bb78d0 Mon Sep 17 00:00:00 2001 From: joey Date: Sun, 25 Aug 2002 19:10:56 +0000 Subject: [PATCH] * Added support inspired by aj for converted rpm packages that create users/groups in their preinst, and which alien therefore cannot ship the files with proper ownerships in the .deb. In this case alien will now insert appropriate chown commands into the postinst script of the converted package. * That only works when converting rpm to deb, not the other way around, for now. * Removed the cpio directory permissions fixup code, which was probably broken, and is obsolete since I get directory perms from the rpm now. --- Alien/Package.pm | 7 ++++ Alien/Package/Deb.pm | 34 +++++++++++++++++ Alien/Package/Rpm.pm | 87 ++++++++++++++++++-------------------------- debian/changelog | 14 +++++++ 4 files changed, 91 insertions(+), 51 deletions(-) diff --git a/Alien/Package.pm b/Alien/Package.pm index f99f48e..7dbec40 100644 --- a/Alien/Package.pm +++ b/Alien/Package.pm @@ -130,6 +130,13 @@ to a true value. Points to a directory where the package has been unpacked. +=item owninfo + +If set this will be a reference to a hash, with filename as key, that holds +ownership/group information for files that cannot be represented on the +filesystem. Typically that is because the owners or groups just don't exist +yet. It will be set at unpack time. + =back =head1 METHODS diff --git a/Alien/Package/Deb.pm b/Alien/Package/Deb.pm index 7e4a79f..7188601 100644 --- a/Alien/Package/Deb.pm +++ b/Alien/Package/Deb.pm @@ -703,6 +703,40 @@ sub username { return $username; } +=item postinst + +Returns the postinst. This may include generated shell code to set owners +and groups from the owninfo field. + +=cut + +sub postinst { + my $this=shift; + + my $owninfo = $this->owninfo; + my $postinst = $this->{postinst}; + return $postinst unless ref $owninfo; + + # If there is no postinst, let's make one up.. + $postinst="#!/bin/sh\n" unless defined $postinst; + + my ($firstline, $rest)=split(/\n/, $postinst, 2); + if ($firstline !~ m/^#!\s*\/bin\/sh/) { + print STDERR "warning: unable to add ownership fixup code to postinst as the postinst is not a shell script!\n"; + return $postinst; + } + + my $permscript="# alien added permissions fixup code\n"; + foreach my $file (keys %$owninfo) { + my $quotedfile=$file; + $quotedfile=~s/'/'"'"'/g; # no single quotes in single quotes.. + $permscript.="chown '$owninfo->{$file}' '$quotedfile'\n"; + } + return "$firstline\n$permscript\n$rest"; +} + +=cut + =head1 AUTHOR Joey Hess diff --git a/Alien/Package/Rpm.pm b/Alien/Package/Rpm.pm index 3135dff..601469c 100644 --- a/Alien/Package/Rpm.pm +++ b/Alien/Package/Rpm.pm @@ -176,63 +176,48 @@ sub unpack { or die "error moving unpacked files into the default prefix directory: $!"; } - # When cpio extracts the file, any child directories that are - # present, but whose parent directories are not, end up mode 700. - # This next block corrects that to 755, which is more reasonable. - # - # Of course, this whole thing assumes we get the filelist in sorted - # order. - my $lastdir=''; - my %tochmod; - foreach my $file (@{$this->filelist}) { - $file=~s/^\///; - if (($lastdir && $file !~ m:^\Q$lastdir\E/[^/]*$:) || !$lastdir) { - # We've found one of the nasty directories. Fix it - # up. - # - # Note that I strip the trailing filename off $file - # here, for two reasons. First, it makes the loop - # easier, we don't need to fix the perms on the - # last file, after all! Second, it makes the -d - # test below fire, which saves us from trying to - # fix a parent directory twice. - $file=$1 if $file=~m:(.*)/.*?:; - my $dircollect=''; - - foreach my $dir (split(/\//,$file)) { - $dircollect.="$dir/"; - # Use a hash to prevent duplicate chmods. - $tochmod{"$workdir/$dircollect"}=1; - } + # cpio does not necessarily store all parent directories in an + # archive, and so some directories, if it has to make them and has + # no permission info, may come out mode 700. Here I just chown all + # extracted directories to mode 755, which is more reasonable. + # Note that the next section overrides these default permissions, + # if override data exists in the rpm permissions info. And such + # data should always exist, so this is probably a no-op. + system("find $workdir -type d -perm 700 -print0 | xargs --no-run-if-empty -0 chmod 700"); + + # rpm files have two sets of permissions; the set in the cpio + # archive, and the set in the control data; which override them. + # The set in the control data are more correct, so let's use those. + # Some permissions setting may have to be postponed until the + # postinst. + my %owninfo = (); + open (GETPERMS, 'rpm --queryformat \'[%{FILEMODES} %{FILEUSERNAME} %{FILEGROUPNAME} %{FILENAMES}\n]\' -qp '.$this->filename.' |'); + while () { + chomp; + my ($mode, $owner, $group, $file) = split(/ /, $_, 4); + $mode = $mode & 07777; # remove filetype + my $uid = getpwnam($owner); + if (! defined $uid || $> != 0) { + $owninfo{$file}=$owner; + $uid=0; } - $lastdir=$file if -d "./$file"; - } - chmod 0755, keys %tochmod if %tochmod; - - if ($> == 0) { - # rpm files have two sets of permissions; the set in the cpio - # archive, and the set in the control data; which override them. - # The set in the control data are more correct, so let's use those. - open (GETPERMS, 'rpm --queryformat \'[%{FILEMODES} %{FILEUSERNAME} %{FILEGROUPNAME} %{FILENAMES}\n]\' -qp '.$this->filename.' |'); - while () { - chomp; - my ($mode, $owner, $group, $file) = split(/ /, $_, 4); - $mode = $mode & 07777; # remove filetype - my $uid = getpwnam($owner); - if (! defined $uid) { - print STDERR "WARNING: $file is owned by a user ($owner) not on this system; using root instead\n"; - $uid=0; + my $gid = getgrnam($group); + if (! defined $gid || $> != 0) { + if (exists $owninfo{$file}) { + $owninfo{$file}.=":$group"; } - my $gid = getgrnam($group); - if (! defined $gid) { - print STDERR "WARNING: $file is owned by a group ($group) not on this system; using group root instead\n"; - $gid=0; + else { + $owninfo{$file}=":$group"; } - next unless -e "$workdir/$file"; # skip broken links + $gid=0; + } + next unless -e "$workdir/$file"; # skip broken links + if ($> == 0) { chown($uid, $gid, "$workdir/$file") || die "failed chowning $file to $uid\:$gid\: $!"; - chmod($mode, "$workdir/$file") || die "failed changing mode of $file to $mode\: $!"; } + chmod($mode, "$workdir/$file") || die "failed changing mode of $file to $mode\: $!"; } + $this->owninfo(\%owninfo); return 1; } diff --git a/debian/changelog b/debian/changelog index a5baf0d..f898795 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,17 @@ +alien (8.20) unstable; urgency=low + + * Added support inspired by aj for converted rpm packages that create + users/groups in their preinst, and which alien therefore cannot ship the + files with proper ownerships in the .deb. In this case alien will now + insert appropriate chown commands into the postinst script of the + converted package. + * That only works when converting rpm to deb, not the other way around, + for now. + * Removed the cpio directory permissions fixup code, which was probably + broken, and is obsolete since I get directory perms from the rpm now. + + -- Joey Hess Sun, 25 Aug 2002 15:17:57 -0400 + alien (8.19) unstable; urgency=low * Added upsated jdk patches from Gerald Turner.