controllib.pl 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4. use English;
  5. use POSIX qw(:errno_h);
  6. use Dpkg;
  7. use Dpkg::Gettext;
  8. use Dpkg::ErrorHandling qw(warning error failure internerr syserr subprocerr);
  9. use Dpkg::Fields qw(capit sort_field_by_importance);
  10. textdomain("dpkg-dev");
  11. our %fi; # - map of fields values. keys are of the form "S# key"
  12. # where S is source (L is changelog, C is control)
  13. # and # is an index
  14. our %p2i; # - map from datafile+packagename to index in controlfile
  15. # (used if multiple packages can be listed). Key is
  16. # "S key" where S is the source and key is the packagename
  17. my $parsechangelog = 'dpkg-parsechangelog';
  18. sub parsechangelog {
  19. my ($changelogfile, $changelogformat, $since) = @_;
  20. defined(my $c = open(CDATA, "-|")) || syserr(_g("fork for parse changelog"));
  21. if ($c) {
  22. binmode(CDATA);
  23. parsecdata(\*CDATA, 'L', 0, _g("parsed version of changelog"));
  24. close(CDATA);
  25. $? && subprocerr(_g("parse changelog"));
  26. } else {
  27. binmode(STDOUT);
  28. my @al = ($parsechangelog);
  29. push(@al,"-l$changelogfile");
  30. push(@al, "-F$changelogformat") if defined($changelogformat);
  31. push(@al, "-v$since") if defined($since);
  32. exec(@al) || &syserr("exec parsechangelog $parsechangelog");
  33. }
  34. }
  35. sub readmd5sum {
  36. (my $md5sum = shift) or return;
  37. $md5sum =~ s/^([0-9a-f]{32})\s*\*?-?\s*\n?$/$1/o
  38. || failure(_g("md5sum gave bogus output `%s'"), $md5sum);
  39. return $md5sum;
  40. }
  41. # XXX: Should not be a global!!
  42. my $whatmsg;
  43. sub parsecdata {
  44. my ($cdata, $source, $many);
  45. ($cdata, $source, $many, $whatmsg) = @_;
  46. # many=0: ordinary control data like output from dpkg-parsechangelog
  47. # many=1: many paragraphs like in source control file
  48. # many=-1: single paragraph of control data optionally signed
  49. my $index = '';
  50. my $cf = '';
  51. my $paraborder = 1;
  52. while (<$cdata>) {
  53. s/\s*\n$//;
  54. next if (m/^$/ and $paraborder);
  55. next if (m/^#/);
  56. $paraborder=0;
  57. if (m/^(\S+?)\s*:\s*(.*)$/) {
  58. $cf = $1;
  59. my $v = $2;
  60. $cf= &capit($cf);
  61. $fi{"$source$index $cf"}= $v;
  62. $fi{"o:$source$index $cf"}= $1;
  63. if (lc $cf eq 'package') { $p2i{"$source $v"}= $index; }
  64. } elsif (m/^\s+\S/) {
  65. length($cf) || &syntax(_g("continued value line not in field"));
  66. $fi{"$source$index $cf"}.= "\n$_";
  67. } elsif (m/^-----BEGIN PGP/ && $many<0) {
  68. $many == -2 && syntax(_g("expected blank line before PGP signature"));
  69. while (<$cdata>) {
  70. last if m/^$/;
  71. }
  72. $many= -2;
  73. } elsif (m/^$/) {
  74. $paraborder = 1;
  75. if ($many>0) {
  76. $index++; $cf='';
  77. } elsif ($many == -2) {
  78. $_ = <$cdata> while defined($_) && $_ =~ /^\s*$/;
  79. length($_) ||
  80. &syntax(_g("expected PGP signature, found EOF after blank line"));
  81. s/\n$//;
  82. m/^-----BEGIN PGP/ ||
  83. &syntax(sprintf(_g("expected PGP signature, found something else \`%s'"), $_));
  84. $many= -3; last;
  85. } else {
  86. while (<$cdata>) {
  87. /^\s*$/ ||
  88. &syntax(_g("found several \`paragraphs' where only one expected"));
  89. }
  90. }
  91. } else {
  92. &syntax(_g("line with unknown format (not field-colon-value)"));
  93. }
  94. }
  95. $many == -2 && &syntax(_g("found start of PGP body but no signature"));
  96. if (length($cf)) { $index++; }
  97. $index || &syntax(_g("empty file"));
  98. return $index;
  99. }
  100. sub syntax {
  101. error(_g("syntax error in %s at line %d: %s"), $whatmsg, $., $_[0]);
  102. }
  103. 1;