mirror of
https://github.com/Project-OSS-Revival/alien.git
synced 2026-04-24 14:00:17 +00:00
315 lines
7.2 KiB
Perl
315 lines
7.2 KiB
Perl
#!/usr/bin/perl -w
|
|
|
|
=head1 NAME
|
|
|
|
Alien::Package::Rpm - an object that represents a rpm package
|
|
|
|
=cut
|
|
|
|
package Alien::Package::Rpm;
|
|
use strict;
|
|
use Alien::Package; # perlbug
|
|
use base qw(Alien::Package);
|
|
|
|
=head1 DESCRIPTION
|
|
|
|
This is an object class that represents a rpm package. It is derived from
|
|
Alien::Package.
|
|
|
|
=head1 FIELDS
|
|
|
|
=over 4
|
|
|
|
=item prefixes
|
|
|
|
Relocatable rpm packages have a prefixes field.
|
|
|
|
=head1 METHODS
|
|
|
|
=over 4
|
|
|
|
=item install
|
|
|
|
Install a rpm. If RPMINSTALLOPT is set in the environement, the options in
|
|
it are passed to rpm on its command line.
|
|
|
|
=cut
|
|
|
|
sub install {
|
|
my $this=shift;
|
|
|
|
system("rpm -ivh $ENV{RPMINSTALLOPT} ".$this->filename) &&
|
|
die "Unable to install: $!";
|
|
}
|
|
|
|
=item read_file
|
|
|
|
Implement the read_file method to read a rpm file.
|
|
|
|
=cut
|
|
|
|
sub read_file {
|
|
my $this=shift;
|
|
$this->SUPER::read_file(@_);
|
|
my $file=$this->filename;
|
|
|
|
my %fieldtrans=(
|
|
PREIN => 'preinst',
|
|
POSTIN => 'postinst',
|
|
PREUN => 'prerm',
|
|
POSTUN => 'postrm',
|
|
);
|
|
|
|
# These fields need no translation except case.
|
|
foreach (qw{name version release arch changelogtext summary
|
|
description copyright prefixes}) {
|
|
$fieldtrans{uc $_}=$_;
|
|
}
|
|
|
|
# Use --queryformat to pull out all the fields we need.
|
|
foreach my $field (keys(%fieldtrans)) {
|
|
$_=`LANG=C rpm -qp $file --queryformat \%{$field}`;
|
|
$field=$fieldtrans{$field};
|
|
$this->$field($_) if $_ ne '(none)';
|
|
}
|
|
|
|
# Get the conffiles list.
|
|
$this->conffiles([map { chomp; $_ } `rpm -qcp $file`]);
|
|
|
|
$this->binary_info(scalar `rpm -qpi $file`);
|
|
|
|
# Get the filelist.
|
|
$this->filelist([map { chomp; $_ } `rpm -qpl $file`]);
|
|
|
|
# Sanity check and sanitize fields.
|
|
unless (defined $this->summary) {
|
|
# Older rpms will have no summary, but will have a
|
|
# description. We'll take the 1st line out of the
|
|
# description, and use it for the summary.
|
|
$this->summary($this->description."\n")=~m/(.*?)\n/m;
|
|
|
|
# Fallback.
|
|
if (! $this->summary) {
|
|
$this->summary('Converted RPM package');
|
|
}
|
|
}
|
|
unless (defined $this->copyright) {
|
|
$this->copyright('unknown');
|
|
}
|
|
unless (defined $this->description) {
|
|
$this->description($this->summary);
|
|
}
|
|
if (! defined $this->release || ! defined $this->version ||
|
|
! defined $this->name) {
|
|
die "Error querying rpm file";
|
|
}
|
|
|
|
$this->distribution("Red Hat");
|
|
$this->origformat("rpm");
|
|
|
|
return 1;
|
|
}
|
|
|
|
=item unpack
|
|
|
|
Implement the unpack method to unpack a rpm file. This is a little nasty
|
|
because it has to handle relocatable rpms and has to do a bit of
|
|
permissions fixing as well.
|
|
|
|
=cut
|
|
|
|
sub unpack {
|
|
my $this=shift;
|
|
$this->SUPER::unpack(@_);
|
|
my $workdir=$this->unpacked_tree;
|
|
|
|
system ("rpm2cpio ".$this->filename." | (cd $workdir; cpio --extract --make-directories --no-absolute-filenames --preserve-modification-time) 2>/dev/null") &&
|
|
die "Unpacking of `".$this->filename."' failed: $!";
|
|
|
|
# If the package is relocatable. We'd like to move it to be under
|
|
# the $this->prefixes directory. However, it's possible that that
|
|
# directory is in the package - it seems some rpm's are marked as
|
|
# relocatable and unpack already in the directory they can relocate
|
|
# to, while some are marked relocatable and the directory they can
|
|
# relocate to is removed from all filenames in the package. I
|
|
# suppose this is due to some change between versions of rpm, but
|
|
# none of this is adequatly documented, so we'll just muddle
|
|
# through.
|
|
#
|
|
# Test to see if the package contains the prefix directory already.
|
|
if (defined $this->prefixes && ! -e "$workdir/".$this->prefixes) {
|
|
# Get the files to move.
|
|
my $filelist=join ' ',glob("$workdir/*");
|
|
|
|
# Now, make the destination directory.
|
|
my $collect=$workdir;
|
|
foreach (split m:/:, $this->prefixes) {
|
|
if ($_ ne undef) { # this keeps us from using anything but relative paths.
|
|
$collect.="$_/";
|
|
mkdir $collect,0755 || die "unable to mkdir $collect: $!";
|
|
}
|
|
}
|
|
# Now move all files in the package to the directory we made.
|
|
system "mv $filelist $workdir/".$this->prefixes &&
|
|
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 correctsthat to 755, which is more reasonable.
|
|
#
|
|
# Of course, this whole thing assumes we get the filelist in sorted
|
|
# order.
|
|
my $lastdir='';
|
|
foreach my $file (@{$this->filelist}) {
|
|
$file=~s/^\///;
|
|
if (($lastdir && $file=~m:^\Q$lastdir\E/[^/]*$: eq undef) || !$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)=$file=~m:(.*)/.*?:;
|
|
my $dircollect='';
|
|
foreach my $dir (split(/\//,$file)) {
|
|
$dircollect.="$dir/";
|
|
chmod 0755,$dircollect; # TADA!
|
|
}
|
|
}
|
|
$lastdir=$file if -d "./$file";
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
=item version
|
|
|
|
Set/get version.
|
|
|
|
When retreiving the version, remove any dashes in it.
|
|
|
|
=cut
|
|
|
|
sub version {
|
|
my $this=shift;
|
|
|
|
# set
|
|
$this->{version} = shift if @_;
|
|
|
|
# get
|
|
return unless defined wantarray; # optimization
|
|
$_=$this->{version};
|
|
tr/-/_/;
|
|
return $_;
|
|
}
|
|
|
|
=item postinst
|
|
|
|
=item postrm
|
|
|
|
=item preinst
|
|
|
|
=item prerm
|
|
|
|
Set/get script fields.
|
|
|
|
When retreiving a value, we have to do some truely sick mangling. Since
|
|
debian/slackware scripts can be anything -- perl programs or binary files
|
|
-- and rpm is limited to only shell scripts, we need to encode the files
|
|
and add a scrap of shell script to make it unextract and run on the fly.
|
|
|
|
=cut
|
|
|
|
# This helper function deals with all the scripts.
|
|
sub _script_helper {
|
|
my $this=shift;
|
|
my $script=shift;
|
|
|
|
# set
|
|
$this->{$script} = shift if @_;
|
|
|
|
# get
|
|
return unless defined wantarray; # optimization
|
|
$_=$this->{$script};
|
|
return $_ if ! defined $_ || m/^\s*$/;
|
|
my $f = pack("u",$_);
|
|
$f =~ s/%/%%/g; # Rpm expands %S, so escape such things.
|
|
return "set -e\n".
|
|
"mkdir /tmp/alien.\$\$\n".
|
|
qq{perl -pe '\$_=unpack("u",\$_)' << '__EOF__' > /tmp/alien.\$\$/script\n}.
|
|
$f."__EOF__\n".
|
|
"chmod 755 /tmp/alien.\$\$/script\n".
|
|
"/tmp/alien.\$\$/script \"\$@\"\n".
|
|
"rm -f /tmp/alien.\$\$/script\n".
|
|
"rmdir /tmp/alien.\$\$";
|
|
}
|
|
sub postinst {
|
|
my $this=shift;
|
|
$this->_script_helper($this, 'postinst', @_);
|
|
}
|
|
sub postrm {
|
|
my $this=shift;
|
|
$this->_script_helper($this, 'postrm', @_);
|
|
}
|
|
sub preinst {
|
|
my $this=shift;
|
|
$this->_script_helper($this, 'preinst', @_);
|
|
}
|
|
sub prerm {
|
|
my $this=shift;
|
|
$this->_script_helper($this, 'prerm', @_);
|
|
}
|
|
|
|
=item arch
|
|
|
|
Set/get arch field. When the arch field is set, some sanitizing is done
|
|
first to convert it to the debian format used internally.
|
|
|
|
=cut
|
|
|
|
sub arch {
|
|
my $this=shift;
|
|
return $this->{arch} unless @_;
|
|
my $arch=shift;
|
|
|
|
if ($arch eq 1) {
|
|
$arch='i386';
|
|
}
|
|
elsif ($arch eq 2) {
|
|
$arch='alpha';
|
|
}
|
|
elsif ($arch eq 3) {
|
|
$arch='sparc';
|
|
}
|
|
elsif ($arch eq 6) {
|
|
$arch='m68k';
|
|
}
|
|
elsif ($arch eq 'noarch') {
|
|
$arch='all';
|
|
}
|
|
elsif ($arch eq 'ppc') {
|
|
$arch='powerpc';
|
|
}
|
|
|
|
# Treat 486, 586, etc, as 386.
|
|
if ($arch =~ m/i\d86/i || $arch =~ m/pentium/i) {
|
|
$arch='i386';
|
|
}
|
|
|
|
return $this->{arch}=$arch;
|
|
}
|
|
|
|
=back
|
|
|
|
=head1 AUTHOR
|
|
|
|
Joey Hess <joey@kitenet.net>
|
|
|
|
=cut
|
|
|
|
1
|