dpkg-scansources.pl 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  1. #!/usr/bin/perl
  2. #
  3. # Copyright © 1999 Roderick Schertler
  4. # Copyright © 2002 Wichert Akkerman <wakkerma@debian.org>
  5. # Copyright © 2006-2009 Guillem Jover <guillem@debian.org>
  6. #
  7. # This program is free software; you can redistribute it and/or modify
  8. # it under the terms of the GNU General Public License as published by
  9. # the Free Software Foundation; either version 2 of the License, or (at
  10. # your option) any later version.
  11. #
  12. # This program is distributed in the hope that it will be useful,
  13. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. # GNU General Public License for more details.
  16. #
  17. # You should have received a copy of the GNU General Public License
  18. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  19. # Errors with a single package are warned about but don't affect the
  20. # exit code. Only errors which affect everything cause a non-zero exit.
  21. #
  22. # Dependencies are by request non-existant. I used to use the MD5 and
  23. # Proc::WaitStat modules.
  24. use strict;
  25. use warnings;
  26. use Dpkg;
  27. use Dpkg::Gettext;
  28. use Dpkg::ErrorHandling;
  29. use Dpkg::Control;
  30. use Dpkg::Checksums;
  31. use Dpkg::Source::CompressedFile;
  32. use Dpkg::Compression;
  33. textdomain("dpkg-dev");
  34. use Getopt::Long ();
  35. my $Exit = 0;
  36. # %Override is a hash of lists. The subs following describe what's in
  37. # the lists.
  38. my %Override;
  39. sub O_PRIORITY () { 0 }
  40. sub O_SECTION () { 1 }
  41. sub O_MAINT_FROM () { 2 } # undef for non-specific, else listref
  42. sub O_MAINT_TO () { 3 } # undef if there's no maint override
  43. my %Extra_Override;
  44. my %Priority = (
  45. 'extra' => 1,
  46. 'optional' => 2,
  47. 'standard' => 3,
  48. 'important' => 4,
  49. 'required' => 5,
  50. );
  51. # Switches
  52. my $Debug = 0;
  53. my $No_sort = 0;
  54. my $Src_override = undef;
  55. my $Extra_override_file = undef;
  56. my @Option_spec = (
  57. 'debug!' => \$Debug,
  58. 'help!' => \&usage,
  59. 'no-sort|n' => \$No_sort,
  60. 'source-override|s=s' => \$Src_override,
  61. 'extra-override|e=s' => \$Extra_override_file,
  62. 'version' => \&version,
  63. );
  64. sub debug {
  65. print @_, "\n" if $Debug;
  66. }
  67. sub version {
  68. printf _g("Debian %s version %s.\n"), $progname, $version;
  69. exit;
  70. }
  71. sub usage {
  72. printf _g(
  73. "Usage: %s [<option> ...] <binarypath> [<overridefile> [<pathprefix>]] > Sources
  74. Options:
  75. -n, --no-sort don't sort by package before outputting.
  76. -e, --extra-override <file>
  77. use extra override file.
  78. -s, --source-override <file>
  79. use file for additional source overrides, default
  80. is regular override file with .src appended.
  81. --debug turn debugging on.
  82. --help show this help message.
  83. --version show the version.
  84. See the man page for the full documentation.
  85. "), $progname;
  86. exit;
  87. }
  88. # Getopt::Long has some really awful defaults. This function loads it
  89. # then configures it to use more sane settings.
  90. sub getopt(@);
  91. sub configure_getopt {
  92. Getopt::Long->import(2.11);
  93. *getopt = \&Getopt::Long::GetOptions;
  94. # I'm setting this environment variable lest he sneaks more bad
  95. # defaults into the module.
  96. local $ENV{POSIXLY_CORRECT} = 1;
  97. Getopt::Long::config qw(
  98. default
  99. no_autoabbrev
  100. no_getopt_compat
  101. require_order
  102. bundling
  103. no_ignorecase
  104. );
  105. }
  106. sub close_msg {
  107. my $name = shift;
  108. return sprintf(_g("error closing %s (\$? %d, \$! `%s')"),
  109. $name, $?, $!)."\n";
  110. }
  111. sub init {
  112. configure_getopt;
  113. getopt @Option_spec or usage;
  114. }
  115. sub load_override {
  116. my $file = shift;
  117. local $_;
  118. my $comp_file = Dpkg::Source::CompressedFile->new(filename => $file);
  119. my $override_fh = $comp_file->open_for_read();
  120. while (<$override_fh>) {
  121. s/#.*//;
  122. next if /^\s*$/;
  123. s/\s+$//;
  124. my @data = split ' ', $_, 4;
  125. unless (@data == 3 || @data == 4) {
  126. warning(_g("invalid override entry at line %d (%d fields)"),
  127. $., 0 + @data);
  128. next;
  129. }
  130. my ($package, $priority, $section, $maintainer) = @data;
  131. if (exists $Override{$package}) {
  132. warning(_g("ignoring duplicate override entry for %s at line %d"),
  133. $package, $.);
  134. next;
  135. }
  136. if (!$Priority{$priority}) {
  137. warning(_g("ignoring override entry for %s, invalid priority %s"),
  138. $package, $priority);
  139. next;
  140. }
  141. $Override{$package} = [];
  142. $Override{$package}[O_PRIORITY] = $priority;
  143. $Override{$package}[O_SECTION] = $section;
  144. if (!defined $maintainer) {
  145. # do nothing
  146. }
  147. elsif ($maintainer =~ /^(.*\S)\s*=>\s*(.*)$/) {
  148. $Override{$package}[O_MAINT_FROM] = [split m-\s*//\s*-, $1];
  149. $Override{$package}[O_MAINT_TO] = $2;
  150. }
  151. else {
  152. $Override{$package}[O_MAINT_TO] = $maintainer;
  153. }
  154. }
  155. close($override_fh);
  156. $comp_file->cleanup_after_open();
  157. }
  158. sub load_src_override {
  159. my ($user_file, $regular_file) = @_;
  160. my ($file);
  161. local $_;
  162. if (defined $user_file) {
  163. $file = $user_file;
  164. }
  165. elsif (defined $regular_file) {
  166. my $comp = get_compression_from_filename($regular_file);
  167. if (defined($comp)) {
  168. $file = $regular_file;
  169. $file =~ s/\.$comp_ext{$comp}$/.src.$comp_ext{$comp}/;
  170. } else {
  171. $file = "$regular_file.src";
  172. }
  173. return unless -e $file;
  174. }
  175. else {
  176. return;
  177. }
  178. debug "source override file $file";
  179. my $comp_file = Dpkg::Source::CompressedFile->new(filename => $file);
  180. my $override_fh = $comp_file->open_for_read();
  181. while (<$override_fh>) {
  182. s/#.*//;
  183. next if /^\s*$/;
  184. s/\s+$//;
  185. my @data = split ' ', $_;
  186. unless (@data == 2) {
  187. warning(_g("invalid source override entry at line %d (%d fields)"),
  188. $., 0 + @data);
  189. next;
  190. }
  191. my ($package, $section) = @data;
  192. my $key = "source/$package";
  193. if (exists $Override{$key}) {
  194. warning(_g("ignoring duplicate source override entry for %s at line %d"),
  195. $package, $.);
  196. next;
  197. }
  198. $Override{$key} = [];
  199. $Override{$key}[O_SECTION] = $section;
  200. }
  201. close($override_fh);
  202. $comp_file->cleanup_after_open();
  203. }
  204. sub load_override_extra
  205. {
  206. my $extra_override = shift;
  207. my $comp_file = Dpkg::Source::CompressedFile->new(filename => $extra_override);
  208. my $override_fh = $comp_file->open_for_read();
  209. while (<$override_fh>) {
  210. s/\#.*//;
  211. s/\s+$//;
  212. next unless $_;
  213. my ($p, $field, $value) = split(/\s+/, $_, 3);
  214. $Extra_Override{$p}{$field} = $value;
  215. }
  216. close($override_fh);
  217. $comp_file->cleanup_after_open();
  218. }
  219. # Given PREFIX and DSC-FILE, process the file and returns the fields.
  220. sub process_dsc {
  221. my ($prefix, $file) = @_;
  222. # Parse ‘.dsc’ file.
  223. my $fields = Dpkg::Control->new(type => CTRL_PKG_SRC);
  224. $fields->parse($file);
  225. $fields->set_options(type => CTRL_INDEX_SRC);
  226. # Get checksums
  227. my $size;
  228. my $sums = {};
  229. getchecksums($file, $sums, \$size);
  230. my $source = $fields->{Source};
  231. my @binary = split /\s*,\s*/, $fields->{Binary};
  232. error(_g("no binary packages specified in %s"), $file) unless (@binary);
  233. # Rename the source field to package.
  234. $fields->{Package} = $fields->{Source};
  235. delete $fields->{Source};
  236. # The priority for the source package is the highest priority of the
  237. # binary packages it produces.
  238. my @binary_by_priority = sort {
  239. ($Override{$a} ? $Priority{$Override{$a}[O_PRIORITY]} : 0)
  240. <=>
  241. ($Override{$b} ? $Priority{$Override{$b}[O_PRIORITY]} : 0)
  242. } @binary;
  243. my $priority_override = $Override{$binary_by_priority[-1]};
  244. my $priority = $priority_override
  245. ? $priority_override->[O_PRIORITY]
  246. : undef;
  247. $fields->{Priority} = $priority if defined $priority;
  248. # For the section override, first check for a record from the source
  249. # override file, else use the regular override file.
  250. my $section_override = $Override{"source/$source"} || $Override{$source};
  251. my $section = $section_override
  252. ? $section_override->[O_SECTION]
  253. : undef;
  254. $fields->{Section} = $section if defined $section;
  255. # For the maintainer override, use the override record for the first
  256. # binary. Modify the maintainer if necessary.
  257. my $maintainer_override = $Override{$binary[0]};
  258. if ($maintainer_override && defined $maintainer_override->[O_MAINT_TO]) {
  259. if (!defined $maintainer_override->[O_MAINT_FROM] ||
  260. grep { $fields->{Maintainer} eq $_ }
  261. @{ $maintainer_override->[O_MAINT_FROM] }) {
  262. $fields->{Maintainer} = $maintainer_override->[O_MAINT_TO];
  263. }
  264. }
  265. # Process extra override
  266. if (exists $Extra_Override{$source}) {
  267. my ($field, $value);
  268. while(($field, $value) = each %{$Extra_Override{$source}}) {
  269. $fields->{$field} = $value;
  270. }
  271. }
  272. # A directory field will be inserted just before the files field.
  273. my $dir;
  274. $dir = ($file =~ s-(.*)/--) ? $1 : '';
  275. $dir = "$prefix$dir";
  276. $dir =~ s-/+$--;
  277. $dir = '.' if $dir eq '';
  278. $fields->{Directory} = $dir;
  279. # The files field will get an entry for the .dsc file itself.
  280. foreach my $alg (@check_supported) {
  281. if ($alg eq "md5") {
  282. $fields->{Files} =~ s/^\n/\n$sums->{$alg} $size $file\n/;
  283. } else {
  284. my $name = "Checksums-" . ucfirst($alg);
  285. $fields->{$name} =~ s/^\n/\n$sums->{$alg} $size $file\n/
  286. if defined $fields->{$name};
  287. }
  288. }
  289. return $fields;
  290. }
  291. sub main {
  292. my (@out);
  293. init;
  294. @ARGV >= 1 && @ARGV <= 3 or usageerr(_g("1 to 3 args expected\n"));
  295. push @ARGV, undef if @ARGV < 2;
  296. push @ARGV, '' if @ARGV < 3;
  297. my ($dir, $override, $prefix) = @ARGV;
  298. load_override $override if defined $override;
  299. load_src_override $Src_override, $override;
  300. load_extra_override $Extra_override_file if defined $Extra_override_file;
  301. open FIND, "find -L \Q$dir\E -name '*.dsc' -print |"
  302. or syserr(_g("cannot fork for %s"), "find");
  303. while (<FIND>) {
  304. chomp;
  305. s-^\./+--;
  306. my $fields;
  307. # FIXME: Fix it instead to not die on syntax and general errors?
  308. eval {
  309. $fields = process_dsc($prefix, $_);
  310. };
  311. if ($@) {
  312. warn $@;
  313. next;
  314. }
  315. if ($No_sort) {
  316. $fields->output(\*STDOUT);
  317. print "\n";
  318. }
  319. else {
  320. push @out, $fields;
  321. }
  322. }
  323. close FIND or error(close_msg, 'find');
  324. if (@out) {
  325. map {
  326. $_->output(\*STDOUT);
  327. print "\n";
  328. } sort {
  329. $a->{Package} cmp $b->{Package}
  330. } @out;
  331. }
  332. return 0;
  333. }
  334. $Exit = main || $Exit;
  335. $Exit = 1 if $Exit and not $Exit % 256;
  336. exit $Exit;