dpkg-scanpackages.pl 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. #!/usr/bin/perl
  2. $version= '1.2.6'; # This line modified by Makefile
  3. %kmap= ('optional','suggests',
  4. 'recommended','recommends',
  5. 'class','priority',
  6. 'package_revision','revision');
  7. @fieldpri= ('Package',
  8. 'Source',
  9. 'Version',
  10. 'Priority',
  11. 'Section',
  12. 'Essential',
  13. 'Maintainer',
  14. 'Pre-Depends',
  15. 'Depends',
  16. 'Recommends',
  17. 'Suggests',
  18. 'Conflicts',
  19. 'Provides',
  20. 'Replaces',
  21. 'Architecture',
  22. 'Filename',
  23. 'Size',
  24. 'Installed-Size',
  25. 'MD5sum',
  26. 'Description',
  27. 'Origin',
  28. 'Bugs');
  29. $written=0;
  30. $i=100; grep($pri{$_}=$i--,@fieldpri);
  31. $udeb = 0;
  32. $arch = '';
  33. while ($ARGV[0] =~ m/^-.*/) {
  34. my $opt = shift @ARGV;
  35. if ($opt eq '-u') {
  36. $udeb = 1;
  37. } elsif ($opt =~ m/-a(.*)/) {
  38. if ($1) {
  39. $arch = $1;
  40. } else {
  41. $arch = shift @ARGV;
  42. }
  43. } else {
  44. print STDERR "Unknown option($opt)!\n";
  45. exit(1);
  46. }
  47. }
  48. $ext = $udeb ? 'udeb' : 'deb';
  49. $pattern = $arch ? "'(' -name '*_all.$ext' -o -name '*_$arch.$ext' ')'" : "-name '*.$ext'";
  50. if ($ARGV[1] eq '-u') {
  51. $udeb = 1;
  52. shift @ARGV;
  53. }
  54. $#ARGV == 1 || $#ARGV == 2
  55. or die "Usage: dpkg-scanpackages [-u] [-a<arch>] binarypath overridefile [pathprefix] > Packages\n";
  56. ($binarydir, $override, $pathprefix) = @ARGV;
  57. -d $binarydir or die "Binary dir $binarydir not found\n";
  58. -e $override or die "Override file $override not found\n";
  59. sub vercmp {
  60. ($a,$b)=@_;
  61. return $vercache{$a,$b} if defined($vercache{$a,$b});
  62. system("dpkg --compare-versions $a le $b");
  63. $vercache{$a,$a}=$?;
  64. return $?;
  65. }
  66. # The extra slash causes symlinks to be followed.
  67. open(F,"find $binarydir/ -follow $pattern -print |")
  68. or die "Couldn't open pipe to find: $!\n";
  69. while (<F>) {
  70. chomp($fn=$_);
  71. substr($fn,0,length($binarydir)) eq $binarydir
  72. or die "$fn not in binary dir $binarydir\n";
  73. $t= `dpkg-deb -I $fn control`;
  74. if ($t eq "") {
  75. warn "Couldn't call dpkg-deb on $fn: $!, skipping package\n";
  76. next;
  77. }
  78. if ($?) {
  79. warn "\`dpkg-deb -I $fn control' exited with $?, skipping package\n";
  80. next;
  81. }
  82. undef %tv;
  83. $o= $t;
  84. while ($t =~ s/^\n*(\S+):[ \t]*(.*(\n[ \t].*)*)\n//) {
  85. $k= lc $1; $v= $2;
  86. if (defined($kmap{$k})) { $k= $kmap{$k}; }
  87. if (@kn= grep($k eq lc $_, @fieldpri)) {
  88. @kn==1 || die $k;
  89. $k= $kn[0];
  90. }
  91. $v =~ s/\s+$//;
  92. $tv{$k}= $v;
  93. }
  94. $t =~ /^\n*$/
  95. or die "Unprocessed text from $fn control file; info:\n$o / $t\n";
  96. defined($tv{'Package'})
  97. or die "No Package field in control file of $fn\n";
  98. $p= $tv{'Package'}; delete $tv{'Package'};
  99. if (defined($p1{$p})) {
  100. if (&vercmp($tv{'Version'}, $pv{$p,'Version'})) {
  101. print(STDERR " ! Package $p (filename $fn) is repeat but newer version;\n".
  102. " used that one and ignored data from $pfilename{$p} !\n")
  103. || die $!;
  104. delete $p1{$p};
  105. for $k (keys %k1) {
  106. delete $pv{$p,$k};
  107. }
  108. } else {
  109. print(STDERR " ! Package $p (filename $fn) is repeat;\n".
  110. " ignored that one and using data from $pfilename{$p} !\n")
  111. || die $!;
  112. next;
  113. }
  114. }
  115. print(STDERR " ! Package $p (filename $fn) has Filename field!\n") || die $!
  116. if defined($tv{'Filename'});
  117. $tv{'Filename'}= "$pathprefix$fn";
  118. open(C,"md5sum <$fn |") || die "$fn $!";
  119. chop($_=<C>); close(C); $? and die "\`md5sum < $fn' exited with $?\n";
  120. /^([0-9a-f]{32})\s*-?\s*$/ or die "Strange text from \`md5sum < $fn': \`$_'\n";
  121. $tv{'MD5sum'}= $1;
  122. @stat= stat($fn) or die "Couldn't stat $fn: $!\n";
  123. $stat[7] or die "$fn is empty\n";
  124. $tv{'Size'}= $stat[7];
  125. if (length($tv{'Revision'})) {
  126. $tv{'Version'}.= '-'.$tv{'Revision'};
  127. delete $tv{'Revision'};
  128. }
  129. for $k (keys %tv) {
  130. $pv{$p,$k}= $tv{$k};
  131. $k1{$k}= 1;
  132. $p1{$p}= 1;
  133. }
  134. $_= substr($fn,length($binarydir));
  135. s#/[^/]+$##; s#^/*##;
  136. $psubdir{$p}= $_;
  137. $pfilename{$p}= $fn;
  138. }
  139. close(F);
  140. $? and warn "find exited with $?\n";
  141. select(STDERR); $= = 1000; select(STDOUT);
  142. format STDERR =
  143. ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  144. $packages
  145. .
  146. sub writelist {
  147. $title= shift(@_);
  148. return unless @_;
  149. print(STDERR " $title\n") || die $!;
  150. $packages= join(' ',sort @_);
  151. while (length($packages)) { write(STDERR) || die $!; }
  152. print(STDERR "\n") || die $!;
  153. }
  154. @samemaint=();
  155. open(O, $override)
  156. or die "Couldn't open override file $override: $!\n";
  157. while (<O>) {
  158. s/\#.*//;
  159. s/\s+$//;
  160. ($p,$priority,$section,$maintainer)= split(/\s+/,$_,4);
  161. next unless defined($p1{$p});
  162. if (length($maintainer)) {
  163. if ($maintainer =~ m/\s*=\>\s*/) {
  164. $oldmaint= $`; $newmaint= $'; $debmaint= $pv{$p,'Maintainer'};
  165. if (!grep($debmaint eq $_, split(m:\s*//\s*:, $oldmaint))) {
  166. push(@changedmaint,
  167. " $p (package says $pv{$p,'Maintainer'}, not $oldmaint)\n");
  168. } else {
  169. $pv{$p,'Maintainer'}= $newmaint;
  170. }
  171. } elsif ($pv{$p,'Maintainer'} eq $maintainer) {
  172. push(@samemaint," $p ($maintainer)\n");
  173. } else {
  174. print(STDERR " * Unconditional maintainer override for $p *\n") || die $!;
  175. $pv{$p,'Maintainer'}= $maintainer;
  176. }
  177. }
  178. $pv{$p,'Priority'}= $priority;
  179. $pv{$p,'Section'}= $section;
  180. ($sectioncut = $section) =~ s:^[^/]*/::;
  181. if (length($psubdir{$p}) && $section ne $psubdir{$p} &&
  182. $sectioncut ne $psubdir{$p}) {
  183. if (length($psubdir{$p}) && $section ne $psubdir{$p}) {
  184. print(STDERR " !! Package $p has \`Section: $section',".
  185. " but file is in \`$psubdir{$p}' !!\n") || die $!;
  186. $ouches++;
  187. }
  188. }
  189. $o1{$p}= 1;
  190. }
  191. close(O);
  192. print(STDERR "\n") || die $! if $ouches;
  193. $k1{'Maintainer'}= 1;
  194. $k1{'Priority'}= 1;
  195. $k1{'Section'}= 1;
  196. @missingover=();
  197. for $p (sort keys %p1) {
  198. if (!defined($o1{$p})) {
  199. push(@missingover,$p);
  200. }
  201. $r= "Package: $p\n";
  202. for $k (sort { $pri{$b} <=> $pri{$a} } keys %k1) {
  203. next unless length($pv{$p,$k});
  204. $r.= "$k: $pv{$p,$k}\n";
  205. }
  206. $r.= "\n";
  207. $written++;
  208. $p1{$p}= 1;
  209. print(STDOUT $r) or die "Failed when writing stdout: $!\n";
  210. }
  211. close(STDOUT) or die "Couldn't close stdout: $!\n";
  212. @spuriousover= grep(!defined($p1{$_}),sort keys %o1);
  213. &writelist("** Packages in archive but missing from override file: **",
  214. @missingover);
  215. if (@changedmaint) {
  216. print(STDERR
  217. " ++ Packages in override file with incorrect old maintainer value: ++\n",
  218. @changedmaint,
  219. "\n") || die $!;
  220. }
  221. if (@samemaint) {
  222. print(STDERR
  223. " -- Packages specifying same maintainer as override file: --\n",
  224. @samemaint,
  225. "\n") || die $!;
  226. }
  227. if (@spuriousover) {
  228. print(STDERR
  229. " -- Packages in override file but not in archive: --\n",
  230. @spuriousover,
  231. "\n") || die $!;
  232. }
  233. print(STDERR " Wrote $written entries to output Packages file.\n") || die $!;