#!/usr/bin/perl use File::stat; use FileHandle; use strict 'refs'; #use RPMQ; # FIXME: a local copy of RPM.pm is here. sub filter_weak { my ($r, $tn, $tf) = @_; my @tf = @{$r->{$tf} || []}; my @res; for (@{$r->{$tn}}) { push @res, $_ unless (shift @tf) & 0x8000000; } return @res; } sub filter_strong { my ($r, $tn, $tf) = @_; my @tf = @{$r->{$tf} || []}; my @res; for (@{$r->{$tn}}) { push @res, $_ if (shift @tf) & 0x8000000; } return @res; } local (@DATADIRS,@LANGUAGES,%SEEN_PACKAGE,%IGNORE_PACKAGE); my %lang_alias = ("czech"=>"cs","english"=>"en","french"=>"fr","german"=>"de","italian"=>"it","spanish"=>"es","hungarian"=>"hu" ); my %tag_short = ("description"=>"Des","notice"=>"Ins","delnotice"=>"Del"); my $ignored_packages = ""; my $ignore_sources = "0"; my $ignore_symlinks = "0"; my $prefer_yastdescr = "0"; my $add_licenses = "0"; my $do_checksums = "0"; while ( $arg = shift ( @ARGV ) ) { if ( $arg eq "-d" ) { push @DATADIRS , shift @ARGV ; } elsif ( $arg eq "-l" ) { push @LANGUAGES , shift @ARGV ; } elsif ( $arg eq "-p" ) { $pdb_data_dir = shift @ARGV ; } elsif ( $arg eq "-x" ) { $extra_provides = shift @ARGV ; } elsif ( $arg eq "-i" ) { $ignore_dir = shift @ARGV ; } elsif ( $arg eq "-I" ) { $ignore_file = shift @ARGV ; } elsif ( $arg eq "-o" ) { $output_dir = shift @ARGV ; } elsif ( $arg eq "-Z" ) { $add_licenses = "1" ; } elsif ( $arg eq "-S" ) { $ignore_sources = "1"; } elsif ( $arg eq "-P" ) { $prefer_yastdescr = "1"; } elsif ( $arg eq "-L" ) { $ignore_symlinks = "1"; } elsif ( $arg eq "-C" ) { $do_checksums = "1"; } else { print "usage: create_package_descr\n"; print " [-d DATADIR1 [-d DATADIR2 [... ] ] ] (default cwd)\n"; print " [-p PDB_DATA_DIR ]\n"; print " [-x EXTRA_PROV_FILE ]\n"; print " [-i IGNORE_DIR ] [-I IGNORE_FILE ]\n"; print " [-l LANG1 [-l LANG2 [... ] ] (default english)\n"; print " [-o OUTPUT_DIR ] (default cwd/setup/descr)\n"; print " [-Z ] (add_licenses)\n"; print " [-S ] (ignore_sources)\n"; print " [-P ] (prefer_yastdescr)\n"; print " [-L ] (ignore_symlinks)\n"; print " [-C ] (do_checksums)\n"; die ("unknown parameter\n"); } } if ( $ignore_symlinks eq "1" ) { $with_links = "-type f"; } else { $with_links = ""; } push @DATADIRS , "." unless ( @DATADIRS ); push @LANGUAGES , "english" unless ( @LANGUAGES ); $output_dir = "./setup/descr/" unless ( $output_dir ); print "\n\nusing settings:\n"; print "datadirs: ".join(",",@DATADIRS)."\n"; print "languages: ".join(",",@LANGUAGES)."\n"; print "output dir: $output_dir\n"; if ( -d $pdb_data_dir ) { print "pdb data: $pdb_data_dir\n"; } else { print "$pdb_data_dir is not a directory: ignoring\n"; $pdb_data_dir = ""; } unless ( -d $output_dir ) { print "creating output directory $output_dir\n"; mkdir_p($output_dir); } if ( $extra_provides ) { if ( -f $extra_provides ) { print "extra_provides: $extra_provides\n"; %xprovlist = %{ReadFileToHash( $extra_provides )}; } else { print "extra_provides: file $extra_provides not found!\n"; } } else { print "extra_provides: not specified\n"; print "WARNING: this means all provides like /bin/sh will be missing\n"; } if ( $ignore_dir ) { if ( -d $ignore_dir && opendir ( IGNDIR, "$ignore_dir") ) { while ( $ign = readdir( IGNDIR ) ) { next if ( $ign =~ /^\./ ); $IGNORE_PACKAGE{$ign} = "yes"; } closedir ( IGNDIR ); print "ignoring packages listed in dir $ignore_dir\n"; } } if ( $ignore_file ) { if ( -f $ignore_file && open ( IGNFILE, "$ignore_file" ) ) { while ( $ign = ) { chomp ( $ign ); $IGNORE_PACKAGE{$ign} = "yes"; } close ( IGNFILE ); print "ignoring packages listed in file $ignore_file\n"; } } if ( $ignore_sources eq "1" ) { print "WARNING: ignoring all source packages\n"; } $pkg_main = OpenFileWrite ( "$output_dir/packages" ); WriteSEntry( $pkg_main, "Ver", "2.0" ); foreach $lang (@LANGUAGES) { $pkg_lang{$lang} = OpenFileWrite ( "$output_dir/packages.$lang_alias{$lang}" ); WriteSEntry( $pkg_lang{$lang}, "Ver", "2.0" ); } $pkg_du = OpenFileWrite ( "$output_dir/packages.DU" ); WriteSEntry( $pkg_du, "Ver", "2.0" ); $media_number = 0; $dotcounter = 0; $allcounter = 0; foreach $datapath (@DATADIRS) { $media_number++; open ( FIND, "find $datapath $with_links -maxdepth 2 -name \"*.[rs]pm\" -print | sort |" ); my @pkg_arr = (); my @src_arr = (); while ( ) { chomp ( $_ ); if ( /\.spm$/ || /src\.rpm$/ ) { push @src_arr, $_; } else { push @pkg_arr, $_; } } close ( FIND ); foreach my $package (@pkg_arr,@src_arr) { #print "found $package\n"; $dotcounter++; $allcounter++; if ( $dotcounter == 10 ) { print "."; $dotcounter = 0; } $filespec = $package; chomp ( $filespec ); $filespec =~ /\/([^\/]*)$/; $filename = $1; $filesize = stat($filespec)->size; # name, version, release, arch, obsolete, requires, provides, # conflicts, copyright, group, buildtime, size, sourcerpm my %res = RPM::rpmq_many($package, 1000, 1001, 1002, 1022, 1090, 1114, 1115, 1047, 1112, 1113, 1049, 1048, 1050, 1054, 1053, 1055, 1156, 1157, 1158, 1159, 1160, 1161, 1027, 1116, 1117, 1118, 1030, 1028, 1095, 1096, 1014, 1016, 1006, 1009, 1044, 1004, 1005); my @depexcl = $res{1054}; my @prereq = rpmq_add_req_flagsvers(\%res, 1049, 1048, 1050); # requires RPM::rpmq_add_flagsvers(\%res, 1047, 1112, 1113); # provides RPM::rpmq_add_flagsvers(\%res, 1090, 1114, 1115); # obsoletes RPM::rpmq_add_flagsvers(\%res, 1054, 1053, 1055); # conflicts RPM::rpmq_add_flagsvers(\%res, 1156, 1158, 1157); # suggests RPM::rpmq_add_flagsvers(\%res, 1159, 1161, 1160); # enhances $rpm_name = $res{1000}[0]; if ( $IGNORE_PACKAGE{$rpm_name} && $IGNORE_PACKAGE{$rpm_name} eq "yes" ) { $ignored_packages .= " $rpm_name"; next; } my $checksum = ""; my $dummy = ""; ($checksum,$dummy) = split('\s+',`sha1sum $package`) if ($do_checksums eq "1"); $srcrpm = $res{1044}[0]; $srcrpm =~ s/^(.*)-([^-]*)-([^-]*)\.([^\.]*)\.rpm$/$1 $2 $3 $4/; if ( $res{1044}[0] ) { @DULIST = RpmToDulist(\%res, ''); $file_arch = $res{1022}[0]; } else { next if ( $ignore_sources eq "1" ); # has no source, so it is a source if ( $filename =~ /\.spm$/ ) { $file_arch = "src"; } else { $file_arch = $filename; $file_arch =~ s/^.*\.([^\.]*)\.rpm$/$1/; } @DULIST = RpmToDulist(\%res, 'usr/src/packages/'); } if ( $xprovlist{"$rpm_name.$file_arch"} ) { foreach $xprov (split('\s', $xprovlist{"$rpm_name.$file_arch"} )) { push (@{$res{1047}},$xprov); } } # should be else if, but merging both is needed right now if ( $xprovlist{$rpm_name} ) { foreach $xprov (split('\s', $xprovlist{$rpm_name} )) { push (@{$res{1047}},$xprov); } } WriteSeparator( $pkg_main ); WriteSEntry( $pkg_main, "Pkg", "$res{1000}[0] $res{1001}[0] $res{1002}[0] $file_arch"); WriteSEntry( $pkg_main, "Cks", "SHA1 $checksum") if ($checksum); if ( $res{1044}[0] ) { # has src, so it's a binary package WriteMEntry( $pkg_main, "Req", @{$res{1049}} ); WriteMEntry( $pkg_main, "Prq", @prereq ); WriteMEntry( $pkg_main, "Prv", @{$res{1047}} ); WriteMEntry( $pkg_main, "Con", @{$res{1054}} ); WriteMEntry( $pkg_main, "Obs", @{$res{1090}} ); WriteMEntry( $pkg_main, "Rec", filter_strong(\%res, 1156, 1158)); WriteMEntry( $pkg_main, "Sug", filter_weak(\%res, 1156, 1158)); WriteMEntry( $pkg_main, "Sup", filter_strong(\%res, 1159, 1161)); WriteMEntry( $pkg_main, "Enh", filter_weak(\%res, 1159, 1161)); WriteSEntry( $pkg_main, "Grp", $res{1016}[0] ); WriteSEntry( $pkg_main, "Lic", $res{1014}[0] ); WriteSEntry( $pkg_main, "Src", $srcrpm ); WriteSEntry( $pkg_main, "Tim", $res{1006}[0] ); WriteSEntry( $pkg_main, "Loc", "$media_number $filename"); } else { WriteSEntry( $pkg_main, "Loc", "$media_number $filename $file_arch"); } WriteSEntry( $pkg_main, "Siz", "$filesize $res{1009}[0]" ); if ( $SEEN_PACKAGE{"$rpm_name $res{1001}[0] $res{1002}[0]"} ) { $found_in = $SEEN_PACKAGE{"$rpm_name $res{1001}[0] $res{1002}[0]"}; WriteSEntry( $pkg_main, "Shr", "$res{1000}[0] $res{1001}[0] $res{1002}[0] $found_in"); } else { if ( $pdb_data_dir ) { my $pac_rpm_name = $rpm_name; $pac_rpm_name =~ s/-debuginfo//; $pac_rpm_name =~ s/-kmp-[^-]*$/-KMP/; delete $INC{"$pdb_data_dir/$pac_rpm_name.pl"}; if ( -f "$pdb_data_dir/$pac_rpm_name.pl") { require "$pdb_data_dir/$pac_rpm_name.pl"; } else { # no pdb data for this package, use rpm summary print "no pdb data for $pac_rpm_name found\n"; $pacdata{$pac_rpm_name}{'english'}{"label"} = "$res{1004}[0]"; } if ( $pacdata{$pac_rpm_name}{'english'}{"label"} =~ /\n/ ) { warn ("newline in summary for package $pac_rpm_name\n"); $pacdata{$pac_rpm_name}{'english'}{"label"} =~ s/\n/ /g; } WriteMEntry( $pkg_main, "Aut", @{$pacdata{$pac_rpm_name}{"authorname"}} ); foreach $lang (@LANGUAGES) { WriteSeparator( $pkg_lang{$lang} ); WriteSEntry( $pkg_lang{$lang}, "Pkg", "$res{1000}[0] $res{1001}[0] $res{1002}[0] $file_arch"); if ( $pacdata{$pac_rpm_name}{$lang}{"label"} ) { if ( $pacdata{$pac_rpm_name}{$lang}{"label"} =~ /\n/ ) { warn ("newline in $lang summary for package $pac_rpm_name\n"); $pacdata{$pac_rpm_name}{$lang}{"label"} =~ s/\n/ /g; } WriteSEntry( $pkg_lang{$lang}, "Sum", $pacdata{$pac_rpm_name}{$lang}{"label"} ); } else { WriteSEntry( $pkg_lang{$lang}, "Sum", $pacdata{$pac_rpm_name}{'english'}{"label"} ); } if ( $prefer_yastdescr eq "1" ) { foreach $tag (keys (%tag_short)) { if ( $pacdata{$pac_rpm_name}{$lang}{$tag._yast} ) { WriteMEntry( $pkg_lang{$lang}, $tag_short{$tag}, @{$pacdata{$pac_rpm_name}{$lang}{$tag._yast}}); } elsif ( $pacdata{$pac_rpm_name}{$lang}{$tag} ) { WriteMEntry( $pkg_lang{$lang}, $tag_short{$tag}, @{$pacdata{$pac_rpm_name}{$lang}{$tag}}); } elsif ( $pacdata{$pac_rpm_name}{'english'}{$tag._yast} ) { WriteMEntry( $pkg_lang{$lang}, $tag_short{$tag}, @{$pacdata{$pac_rpm_name}{'english'}{$tag._yast}}); } else { WriteMEntry( $pkg_lang{$lang}, $tag_short{$tag}, @{$pacdata{$pac_rpm_name}{'english'}{$tag}}); } } if ( $add_licenses eq "1" ) { if ( $pacdata{$pac_rpm_name}{$lang}{'confirmlic_yast'} ) { WriteMEntry( $pkg_lang{$lang}, "Eul", @{$pacdata{$pac_rpm_name}{$lang}{'confirmlic_yast'}}); } elsif ( $pacdata{$pac_rpm_name}{'english'}{'confirmlic_yast'} ) { WriteMEntry( $pkg_lang{$lang}, "Eul", @{$pacdata{$pac_rpm_name}{'english'}{'confirmlic_yast'}}); } } } else { foreach $tag (keys (%tag_short)) { if ( $pacdata{$pac_rpm_name}{$lang}{$tag} ) { WriteMEntry( $pkg_lang{$lang}, $tag_short{$tag}, @{$pacdata{$pac_rpm_name}{$lang}{$tag}}); } else { WriteMEntry( $pkg_lang{$lang}, $tag_short{$tag}, @{$pacdata{$pac_rpm_name}{'english'}{$tag}}); } } } } } else { foreach $lang (@LANGUAGES) { WriteSeparator( $pkg_lang{$lang} ); WriteSEntry( $pkg_lang{$lang}, "Pkg", "$res{1000}[0] $res{1001}[0] $res{1002}[0] $file_arch"); WriteSEntry( $pkg_lang{$lang}, "Sum", "$res{1004}[0]" ); WriteMEntry( $pkg_lang{$lang}, "Des", split('\n', $res{1005}[0] )); } } } WriteSeparator( $pkg_du ); WriteSEntry( $pkg_du, "Pkg", "$res{1000}[0] $res{1001}[0] $res{1002}[0] $file_arch"); WriteMEntry( $pkg_du, "Dir", @DULIST ); $SEEN_PACKAGE{"$rpm_name $res{1001}[0] $res{1002}[0]"} = $file_arch unless $SEEN_PACKAGE{"$rpm_name $res{1001}[0] $res{1002}[0]"}; } } print " done\nprocessed $allcounter packages\n"; if ( $ignored_packages ) { print "following packages were ignored: $ignored_packages\n"; } close ( $pkg_main ); foreach $lang (@LANGUAGES) { close ( $pkg_lang{$lang} ); } close ( $pkg_du ); print "now recoding to UTF-8: "; foreach $file ("packages","packages.DU") { print "$file "; system ( "recode ISO-8859-1...UTF-8 $output_dir/$file" ); } foreach $lang (@LANGUAGES) { $file = "packages.$lang_alias{$lang}"; print "$file "; if ( $lang eq "czech" || $lang eq "hungarian" ) { system ( "recode ISO-8859-2...UTF-8 $output_dir/$file" ); } else { system ( "recode ISO-8859-1...UTF-8 $output_dir/$file" ); } } print "\n"; ##################################################################### ##################################################################### sub mkdir_p { my $dir = shift; return 1 if -d $dir; if ($dir =~ /^(.*)\//) { mkdir_p($1) || return undef; } return undef if !mkdir($dir, 0777); return 1; } sub OpenFileWrite { my $filename = shift; my ($FH) = new FileHandle; open ($FH, ">$filename") || die "ERROR: can't write output file $filename"; return $FH; } sub OpenFileRead { my $filename = shift; my ($FH) = new FileHandle; open ($FH, "<$filename") || die "ERROR: can't read input file $filename"; return $FH; } sub ReadFileToHash { local ($filename) = @_; local (%temp); my $FH = OpenFileRead( $filename ); while (<$FH>) { chomp ($_); last if ( $_ =~ /^:END/ ); next if ( $_ =~ /^\#/ ); next if ( $_ =~ /^\s$/ ); local ($le,$ri) = split (/:/, $_, 2 ); $le =~ s/^\s*(.*)\s*$/$1/; $ri =~ s/^\s*(.*)\s*$/$1/; $temp{$le}=$ri; } close ($FH); \%temp; } sub WriteSeparator { my ($FH) = shift; print $FH "##----------------------------------------\n"; } sub WriteSEntry { my ($FH,$tag,$value) = @_; if ( $value ) { print $FH "=$tag: $value\n"; } } sub WriteMEntry { my ($FH,$tag,@value) = @_; if ( @value && $value[0] ) { print $FH "+$tag:\n"; print $FH join("\n", @value)."\n"; print $FH "-$tag:\n"; } } sub rpmq_add_req_flagsvers { my $res = shift; my $name = shift; my $flags = shift; my $vers = shift; my @prereq = (); return unless $res; my @flags = @{$res->{$flags} || []}; my @vers = @{$res->{$vers} || []}; for (@{$res->{$name}}) { if (@flags && ($flags[0] & 0xe) && @vers) { $_ .= ' '; $_ .= '<' if $flags[0] & 2; $_ .= '>' if $flags[0] & 4; $_ .= '=' if $flags[0] & 8; $_ .= " $vers[0]"; } if ( $flags[0] & 64 ) { push ( @prereq, $_ ); } shift @flags; shift @vers; } return @prereq; } sub RpmToDulist { my $res = shift; my $prefix = shift; if (!$res->{1027}) { my @newfl = (); my @di = @{$res->{1116} || []}; for (@{$res->{1117} || []}) { my $di = shift @di; push @newfl, $res->{1118}->[$di] . $_; } $res->{1027} = [ @newfl ]; } my @modes = @{$res->{1030} || []}; my @devs = @{$res->{1095} || []}; my @inos = @{$res->{1096} || []}; my @names = @{$res->{1027} || []}; my @sizes = @{$res->{1028} || []}; my %seen = (); my %dirnum = (); my %subdirnum = (); my %dirsize = (); my %subdirsize = (); my ($name, $first); for $name (@names) { my $mode = shift @modes; my $dev = shift @devs; my $ino = shift @inos; my $size = shift @sizes; # check if regular file next if ($mode & 0170000) != 0100000; next if $seen{"$dev $ino"}; $seen{"$dev $ino"} = 1; $name =~ s/^\///; $name = "$prefix$name"; $first = 1; $size = int ($size / 1024) + 1; while ($name ne '') { $name = '' unless $name =~ s/\/[^\/]*$//; if ($first) { $dirsize{"$name/"} += $size; $dirnum{"$name/"} += 1; $subdirsize{"$name/"} ||= 0; # so we get all keys } else { $subdirsize{"$name/"} += $size; $subdirnum{"$name/"} += 1; } $first = 0; } } my @dulist = (); for $name (sort keys %subdirsize) { next unless $dirsize{$name} || $subdirsize{$name}; $dirsize{$name} ||= 0; $subdirsize{$name} ||= 0; $dirnum{$name} ||= 0; $subdirnum{$name} ||= 0; push @dulist, "$name $dirsize{$name} $subdirsize{$name} $dirnum{$name} $subdirnum{$name}"; } return @dulist; } #sub RpmToDulist { # local ($filename,$prefix) = @_; # local (%dirsize, %subdirsize, %dirnum, %subdirnum, @dulist); # local (%seen_node); # open ( FILES, "rpm -qp --qf '[%{FILEMODES:perms} %{FILESIZES} %{FILEDEVICES} %{FILEINODES} %{FILENAMES}\n]' $filename |") || die "cant open infile $filename"; # # while () { # # rights is not used, but start of $_ in the if below # ($rights , $size, $f_dev, $f_node, $name ) = split( ' ', $_ ); # $size = int ( $size / 1024 ) + 1; # if ( $rights =~ /^\-/ ) { # next if ( $seen_node{"$f_dev $f_node"} ); # $seen_node{"$f_dev $f_node"} = "yes"; # $name = $prefix.$name; # @path = split ( '/', $name ); # pop ( @path ); # $rpath = join('/',@path) ; # $dirsize{$rpath} += $size; # $dirnum{$rpath} += 1; # $subdirsize{$rpath} += 0; # $subdirnum{$rpath} += 0; # while (pop(@path)) { # $rpath = join('/',@path) ; # $subdirsize{$rpath} += $size; # $subdirnum{$rpath} += 1; # } # } # } # close (FILES); # # foreach $dir ( sort ( keys (%subdirsize) ) ) { # if ( $dirsize{$dir} || $subdirsize{$dir} ) { # $prdir = $dir; # $prdir =~ s/^\///; # $curline = "$prdir/ "; # $curline .= $dirsize{$dir} ? "$dirsize{$dir} " : "0 "; # $curline .= $subdirsize{$dir} ? "$subdirsize{$dir} " : "0 "; # $curline .= $dirnum{$dir} ? "$dirnum{$dir} " : "0 "; # $curline .= $subdirnum{$dir} ? "$subdirnum{$dir} " : "0 "; # push @dulist, $curline; # } # } # return @dulist; #} ####################### copied from RPM.pm by mls ################################# package RPM; sub rpmpq { my $rpm = shift; local *RPM; return undef unless open(RPM, "< $rpm"); my $head; if (sysread(RPM, $head, 75) < 11) { close RPM; return undef; } close RPM; return unpack('@10Z65', $head); } sub rpmq { my $rpm = shift; my $stag = shift; my %ret = rpmq_many($rpm, $stag); return @{$ret{0+$stag} || [undef]}; } sub rpmq_many { my $rpm = shift; my @stags = @_; my %stags = map {0+$_ => 1} @stags; my ($magic, $sigtype, $headmagic, $cnt, $cntdata, $lead, $head, $index, $data, $tag, $type, $offset, $count); local *RPM; return () unless open(RPM, "<$rpm"); if (read(RPM, $lead, 96) != 96) { warn("Bad rpm $rpm\n"); close RPM; return (); } ($magic, $sigtype) = unpack('N@78n', $lead); if ($magic != 0xedabeedb || $sigtype != 5) { warn("Bad rpm $rpm\n"); close RPM; return (); } if (read(RPM, $head, 16) != 16) { warn("Bad rpm $rpm\n"); close RPM; return (); } ($headmagic, $cnt, $cntdata) = unpack('N@8NN', $head); if ($headmagic != 0x8eade801) { warn("Bad rpm $rpm\n"); close RPM; return (); } if (read(RPM, $index, $cnt * 16) != $cnt * 16) { warn("Bad rpm $rpm\n"); close RPM; return (); } $cntdata = ($cntdata + 7) & ~7; if (read(RPM, $data, $cntdata) != $cntdata) { warn("Bad rpm $rpm\n"); close RPM; return (); } if (read(RPM, $head, 16) != 16) { warn("Bad rpm $rpm\n"); close RPM; return (); } ($headmagic, $cnt, $cntdata) = unpack('N@8NN', $head); if ($headmagic != 0x8eade801) { warn("Bad rpm $rpm\n"); close RPM; return (); } if (read(RPM, $index, $cnt * 16) != $cnt * 16) { warn("Bad rpm $rpm\n"); close RPM; return (); } if (read(RPM, $data, $cntdata) != $cntdata) { warn("Bad rpm $rpm\n"); close RPM; return (); } close RPM; my %res = (); while($cnt-- > 0) { ($tag, $type, $offset, $count, $index) = unpack('N4a*', $index); $tag = 0+$tag; if ($stags{$tag}) { eval { if ($type == 0) { $res{$tag} = [ '' ]; } elsif ($type == 1) { $res{$tag} = [ unpack("\@${offset}c$count", $data) ]; } elsif ($type == 2) { $res{$tag} = [ unpack("\@${offset}c$count", $data) ]; } elsif ($type == 3) { $res{$tag} = [ unpack("\@${offset}n$count", $data) ]; } elsif ($type == 4) { $res{$tag} = [ unpack("\@${offset}N$count", $data) ]; } elsif ($type == 5) { $res{$tag} = [ undef ]; } elsif ($type == 6) { $res{$tag} = [ unpack("\@${offset}Z*", $data) ]; } elsif ($type == 7) { $res{$tag} = [ unpack("\@${offset}a$count", $data) ]; } elsif ($type == 8 || $type == 9) { my $d = unpack("\@${offset}a*", $data); my @res = split("\0", $d, $count + 1); $res{$tag} = [ splice @res, 0, $count ]; } else { $res{$tag} = [ undef ]; } }; if ($@) { warn("Bad rpm $rpm: $@\n"); return (); } } } return %res; } sub rpmq_add_flagsvers { my $res = shift; my $name = shift; my $flags = shift; my $vers = shift; return unless $res; my @flags = @{$res->{$flags} || []}; my @vers = @{$res->{$vers} || []}; for (@{$res->{$name}}) { if (@flags && ($flags[0] & 0xe) && @vers) { $_ .= ' '; $_ .= '<' if $flags[0] & 2; $_ .= '>' if $flags[0] & 4; $_ .= '=' if $flags[0] & 8; $_ .= " $vers[0]"; } shift @flags; shift @vers; } } sub rpmq_provreq { my $rpm = shift; my @prov = (); my @req = (); my $r; my %res = rpmq_many($rpm, 1047, 1049, 1048, 1050, 1112, 1113); rpmq_add_flagsvers(\%res, 1047, 1112, 1113); rpmq_add_flagsvers(\%res, 1049, 1048, 1050); return $res{1047}, $res{1049}; } 1;