rename.pl 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. #!/usr/bin/perl
  2. # (c) 2011 by Immo 'FaUl' Wehrenberg
  3. # be most verbose
  4. use strict; use warnings; use diagnostics;
  5. use IO::Uncompress::Bunzip2;
  6. use IO::Uncompress::Gunzip;
  7. # use IO::Uncompress::UnLzma; #does not exist on debian
  8. use Storable;
  9. use Env qw($HOME);
  10. use vars qw($cache $dists $arch @sources @distributions);
  11. # directory with mirror from
  12. $arch = "i386";
  13. $dists = "dists/";
  14. #distris in cronological order
  15. @distributions = ("potato", "woody", "sarge", "etch", "lenny", "squeeze");
  16. $cache = "$HOME/.apt-sec/cache/";
  17. eval {
  18. mkdir "$HOME/.apt-sec";
  19. mkdir $cache;
  20. };
  21. sub recursor($$$);
  22. sub getarrayofpackeges($);
  23. sub getfilehandle($) {
  24. my $name = pop;
  25. my $fd;
  26. if ($name =~ /.bz2$/) {
  27. $fd = new IO::Uncompress::Bunzip2 $name or die "$name: $!";
  28. }
  29. elsif ($name =~ /.gz$/) {
  30. $fd = new IO::Uncompress::Gunzip $name or die "$name: $!";
  31. }
  32. # elsif ($name =~ /.lzma$/) {
  33. # $fd new IO::Uncompress::UnLzma $name or die "$name: $!";
  34. else {
  35. open $fd, $name or die "$name: $!";
  36. }
  37. return $fd;
  38. }
  39. sub cachename($;$) {
  40. my $f = shift;
  41. my $suffix = shift;
  42. $suffix = "cache" if ! defined $suffix;
  43. my @a = stat $f;
  44. $f =~ s/\/\//\//g;
  45. $f =~ s/\//_/g;
  46. my $x = $cache."/".$f."_".$a[9].".".$suffix;
  47. return $x;
  48. }
  49. sub getcached ($;$) {
  50. my %file;
  51. my $cachename = cachename shift(), shift();
  52. eval {
  53. my $file = retrieve $cachename;
  54. %file = %{$file};
  55. };
  56. return %file;
  57. }
  58. # parsefile($filehandle)
  59. # returns hash of the package file given with $filename, key is package name,
  60. # value is a reference to a hash with key: value
  61. sub parsefile($) {
  62. my $filename = pop;
  63. # do we have stuff cached?
  64. my %file = getcached($filename, "parsefile.cache");
  65. return %file if %file;
  66. my $fd = getfilehandle $filename;
  67. # this is the parser
  68. my $savedsl = $/;
  69. $/ = "\n\n";
  70. while (<$fd>) {
  71. my %dict;
  72. $_ = "\n".$_;
  73. ($_, %dict) = split /\n(\w+): /; # first is crap
  74. $file{$dict{"Package"}} = \%dict;
  75. }
  76. $/ = $savedsl;
  77. close $fd;
  78. # cache result
  79. store \%file, cachename ($filename, "parsefile.cache");
  80. return %file;
  81. }
  82. # getarrayofpackeges($field)
  83. # Returns an array of all packages given in @fields (as returned by getfield()
  84. # strips versions
  85. sub getarrayofpackages($) {
  86. $_ = pop or return;
  87. s/(\(.*?\)|\s)//g; # remove everything inside parathesis and whitespaces
  88. return split /,/ or ();
  89. }
  90. # parsesource($filehandle)
  91. # parses the sourcefile represented by the open file in $filehandle
  92. # returns a dict with each binary package name reference to a
  93. # source package hash
  94. sub parsesource($) {
  95. my $filename = pop;
  96. # do we have stuff cached?
  97. my %file = getcached($filename, "parsesource.cache");
  98. return %file if %file;
  99. # if not, parse
  100. my $savedsl = $/;
  101. $/ = "\n\n";
  102. my $fd = getfilehandle $filename;
  103. while (<$fd>) {
  104. my %dict;
  105. $_ = "\n".$_;
  106. ($_, %dict) = split /\n(\w+): /; # first is crap
  107. foreach my $bin (getarrayofpackages ($dict{"Binary"})) {
  108. $file{$bin} = \%dict;
  109. }
  110. }
  111. $/ = $savedsl;
  112. close $fd;
  113. # cache
  114. store \%file, cachename ($filename, "parsesource.cache");
  115. return %file;
  116. }
  117. # intersection (\@array1, \@array2)
  118. # returns intersection of both arrays
  119. sub intersection($$) {
  120. my @arr1 = uniq(pop);
  121. my @arr2 = uniq(pop);
  122. my @intersection;
  123. my %c;
  124. foreach (@arr1, @arr2){
  125. $c{$_}++;
  126. }
  127. foreach (keys %c) {
  128. if ($c{$_} > 1) {
  129. push @intersection, $_;
  130. }
  131. }
  132. return @intersection;
  133. }
  134. # uniq(\@array)
  135. # returns an array which all unique elements of @array
  136. sub uniq($) {
  137. my %c = map {$_, 1} @{pop()};
  138. return keys %c;
  139. }
  140. # old_names_in_file($name, $filehandle)
  141. # returns array of alternative names to $name in the opened Package
  142. # file ($filehandle)
  143. sub old_names_in_file($) {
  144. my %pkg = %{pop()};
  145. my @replaces = getarrayofpackages($pkg{"Replaces"});
  146. my @conflicts = getarrayofpackages($pkg{"Conflicts"});
  147. return intersection(\@replaces, \@conflicts);
  148. }
  149. # pkg2src(%sources, $packagename)
  150. # return the source package to a given binary package
  151. sub pkg2src($$){
  152. my $p = pop;
  153. my %f = %{pop()};
  154. if (!$p || !$f{$p}) {
  155. return ();
  156. }
  157. return $f{$p}->{"Package"};
  158. }
  159. # recursor (\@distris, \@names, $start)
  160. # recursively works through all @dists (filenames of uncompressed Package files
  161. # from debian) from last to first. Tries to find alternative names to the names
  162. # given in @names), if $start = 1, dies if name is not found in the current dist
  163. sub recursor($$$) {
  164. my $start = pop;
  165. my @names = @{pop()};
  166. my @distris = @{pop()};
  167. my $dist = pop(@distris);
  168. my %pkg;
  169. my @list = @names;
  170. my %binfile = parsefile "$dists/$dist/binary-$arch/Packages.bz2";
  171. my %sourcefile = parsesource "$dists/$dist/source/Sources.bz2";
  172. foreach my $p (@names) {
  173. eval {
  174. push @sources, pkg2src(\%sourcefile, $p);
  175. @sources = uniq(\@sources);
  176. %pkg = %{$binfile{$p}};
  177. @list = old_names_in_file(\%pkg);
  178. @names = (@names, @list);
  179. @names = uniq(\@names);
  180. } or do {
  181. die "Could not find any package named '$p'" if grep ($p, @ARGV) && $start;
  182. };
  183. }
  184. @names = uniq(\@names);
  185. if (@distris){
  186. return recursor(\@distris, \@names, 0);
  187. } else {
  188. return (@names);
  189. }
  190. }
  191. sub main() {
  192. $\ = "\n";
  193. $, = "\n";
  194. my @dists = @distributions;
  195. my $F;
  196. my @binpackages = recursor(\@dists, \@ARGV, 1);
  197. #print @l;
  198. #print "---";
  199. print @sources;
  200. }
  201. main();