#! /usr/bin/perl my $dpkglibdir="/usr/lib/dpkg"; my $version="1.0"; my @filesinarchive; my %dirincluded; my %notfileobject; my $fn; $sourcestyle = 'X'; $min_dscformat = 1; $max_dscformat = 2; $def_dscformat = "1.0"; # default format for -b use POSIX; use POSIX qw (:errno_h :signal_h); use strict 'refs'; push (@INC, $dpkglibdir); require 'controllib.pl'; # Make sure patch doesn't get any funny ideas delete $ENV{'POSIXLY_CORRECT'}; my @exit_handlers = (); sub exit_handler { &$_ foreach ( reverse @exit_handlers ); exit(127); } $SIG{'INT'} = \&exit_handler; $SIG{'HUP'} = \&exit_handler; $SIG{'QUIT'} = \&exit_handler; sub usageversion { print STDERR "Debian dpkg-gendsc $version. Copyright (C) 2005 Anand Kumria. Based upon dpkg-source by Ian Jackson and Klee Dienes. This is free software; see the GNU General Public Licence version 2 or later for copying conditions. There is NO warranty. Usage: dpkg-gendsc [||\'\'] Build options: -c get control info from this file -l get per-version info from this file -F force change log format -V= set a substitution variable -T read variables here, not debian/substvars -D= override or add a .dsc field and value -U remove a field -W Turn certain errors into warnings. -E When -W is enabled, -E disables it. -sa auto select orig source (-sA is default) -I filter out files when building tarballs. -sk use packed orig source (unpack & keep) -sp use packed orig source (unpack & remove) -su use unpacked orig source (pack & keep) -sr use unpacked orig source (pack & remove) -ss trust packed & unpacked orig src are same -sn there is no diff, do main tarfile only -sA,-sK,-sP,-sU,-sR like -sa,-sp,-sk,-su,-sr but may overwrite General options: -h print this message "; } sub handleformat { my $fmt = shift; return unless $fmt =~ /^(\d+)/; # only check major version return $1 >= $min_dscformat && $1 <= $max_dscformat; } $i = 100; grep ($fieldimps {$_} = $i--, qw (Format Source Version Binary Origin Maintainer Architecture Standards-Version Build-Depends Build-Depends-Indep Build-Conflicts Build-Conflicts-Indep)); while (@ARGV && $ARGV[0] =~ m/^-/) { $_=shift(@ARGV); if (m/^-s([akpursnAKPUR])$/) { $sourcestyle= $1; } elsif (m/^-c/) { $controlfile= $'; } elsif (m/^-l/) { $changelogfile= $'; } elsif (m/^-F([0-9a-z]+)$/) { $changelogformat=$1; } elsif (m/^-D([^\=:]+)[=:]/) { $override{$1}= "$'"; } elsif (m/^-U([^\=:]+)$/) { $remove{$1}= 1; } elsif (m/^-I(.+)$/) { push @tar_ignore, "--exclude=$1"; } elsif (m/^-V(\w[-:0-9A-Za-z]*)[=:]/) { $substvar{$1}= "$'"; } elsif (m/^-T/) { $varlistfile= "$'"; } elsif (m/^-h$/) { &usageversion; exit(0); } elsif (m/^-W$/) { $warnable_error= 1; } elsif (m/^-E$/) { $warnable_error= 0; } elsif (m/^--$/) { last; } else { &usageerr("unknown option $_"); } } $SIG{'PIPE'} = 'DEFAULT'; { $sourcestyle =~ y/X/A/; $sourcestyle =~ m/[akpursnAKPUR]/ || &usageerr("source handling style -s$sourcestyle not allowed with -b"); @ARGV || &usageerr("-b needs a directory"); @ARGV<=3 || &usageerr("-b takes at most a directory and an orig source argument"); $dir= shift(@ARGV); $dir= "./$dir" unless $dir =~ m:^/:; $dir =~ s,/*$,,; stat($dir) || &error("cannot stat directory $dir: $!"); -d $dir || &error("directory argument $dir is not a directory"); $changelogfile= "$dir/debian/changelog" unless defined($changelogfile); $controlfile= "$dir/debian/control" unless defined($controlfile); &parsechangelog; &parsecontrolfile; $f{"Format"}=$def_dscformat; $archspecific=0; for $_ (keys %fi) { $v= $fi{$_}; if (s/^C //) { if (m/^Source$/i) { &setsourcepackage; } elsif (m/^(Standards-Version|Origin|Maintainer|Uploaders)$/i) { $f{$_}= $v; } elsif (m/^Build-(Depends|Conflicts)(-Indep)?$/i) { $f{$_}= $v; } elsif (s/^X[BC]*S[BC]*-//i) { $f{$_}= $v; } elsif (m/^(Section|Priority|Files|Bugs)$/i || m/^X[BC]+-/i) { } else { &unknown('general section of control info file'); } } elsif (s/^C(\d+) //) { $i=$1; $p=$fi{"C$i Package"}; push(@binarypackages,$p) unless $packageadded{$p}++; if (m/^Architecture$/) { if ($v eq 'any') { @sourcearch= ('any'); } elsif ($v eq 'all') { if (!@sourcearch || $sourcearch[0] eq 'all') { @sourcearch= ('all'); } else { @sourcearch= ('any'); } } else { if (grep($sourcearch[0] eq $_, 'any','all')) { @sourcearch= ('any'); } else { for $a (split(/\s+/,$v)) { &error("architecture $a only allowed on its own". " (list for package $p is `$a')") if grep($a eq $_, 'any','all'); push(@sourcearch,$a) unless $archadded{$a}++; } } } $f{'Architecture'}= join(' ',@sourcearch); } elsif (s/^X[BC]*S[BC]*-//i) { $f{$_}= $v; } elsif (m/^(Package|Essential|Pre-Depends|Depends|Provides)$/i || m/^(Recommends|Suggests|Optional|Conflicts|Replaces)$/i || m/^(Enhances|Description|Section|Priority)$/i || m/^X[CS]+-/i) { } else { &unknown("package's section of control info file"); } } elsif (s/^L //) { if (m/^Source$/) { &setsourcepackage; } elsif (m/^Version$/) { $f{$_}= $v; } elsif (s/^X[BS]*C[BS]*-//i) { $f{$_}= $v; } elsif (m/^(Maintainer|Changes|Urgency|Distribution|Date|Closes)$/i || m/^X[BS]+-/i) { } else { &unknown("parsed version of changelog"); } } elsif (m/^o:.*/) { } else { &internerr("value from nowhere, with key >$_< and value >$v<"); } } $f{'Binary'}= join(', ',@binarypackages); for $f (keys %override) { $f{&capit($f)}= $override{$f}; } for $f (qw(Version)) { defined($f{$f}) || &error("missing information for critical output field $f"); } for $f (qw(Maintainer Architecture Standards-Version)) { defined($f{$f}) || &warn("missing information for output field $f"); } defined($sourcepackage) || &error("unable to determine source package name !"); $f{'Source'}= $sourcepackage; for $f (keys %remove) { delete $f{&capit($f)}; } $version= $f{'Version'}; $version =~ s/^\d+://; $upstreamversion= $version; $upstreamversion =~ s/-[^-]*$//; $basenamerev= $sourcepackage.'_'.$version; $basename= $sourcepackage.'_'.$upstreamversion; $basedirname= $basename; $basedirname =~ s/_/-/; $origdir= "$dir.orig"; $origtargz= "$basename.orig.tar.gz"; if (@ARGV) { $origarg= shift(@ARGV); if (length($origarg)) { stat($origarg) || &error("cannot stat orig argument $origarg: $!"); if (-d _) { $origdir= $origarg; $origdir= "./$origdir" unless $origdir =~ m,^/,; $origdir =~ s,/*$,,; $sourcestyle =~ y/aA/rR/; $sourcestyle =~ m/[ursURS]/ || &error("orig argument is unpacked but source handling style". " -s$sourcestyle calls for packed (.orig.tar.gz)"); } elsif (-f _) { $origtargz= $origarg; $sourcestyle =~ y/aA/pP/; $sourcestyle =~ m/[kpsKPS]/ || &error("orig argument is packed but source handling style". " -s$sourcestyle calls for unpacked (.orig/)"); } else { &error("orig argument $origarg is not a plain file or directory"); } } else { $sourcestyle =~ y/aA/nn/; $sourcestyle =~ m/n/ || &error("orig argument is empty (means no orig, no diff)". " but source handling style -s$sourcestyle wants something"); } } if ($sourcestyle =~ m/[aA]/) { if (stat("$origtargz")) { -f _ || &error("packed orig `$origtargz' exists but is not a plain file"); $sourcestyle =~ y/aA/pP/; } elsif ($! != ENOENT) { &syserr("unable to stat putative packed orig `$origtargz'"); } elsif (stat("$origdir")) { -d _ || &error("unpacked orig `$origdir' exists but is not a directory"); $sourcestyle =~ y/aA/rR/; } elsif ($! != ENOENT) { &syserr("unable to stat putative unpacked orig `$origdir'"); } else { $sourcestyle =~ y/aA/nn/; } } $dirbase= $dir; $dirbase =~ s,/?$,,; $dirbase =~ s,[^/]+$,,; $dirname= $&; $dirname eq $basedirname || &warn("source directory `$dir' is not ". "- `$basedirname'"); if ($sourcestyle ne 'n') { $origdirbase= $origdir; $origdirbase =~ s,/?$,,; $origdirbase =~ s,[^/]+$,,; $origdirname= $&; $origdirname eq "$basedirname.orig" || &warn(".orig directory name $origdirname is not ". "- (wanted $basedirname.orig)"); $tardirbase= $origdirbase; $tardirname= $origdirname; $tarname= $origtargz; $tarname eq "$basename.orig.tar.gz" || &warn(".orig.tar.gz name $tarname is not _". ".orig.tar.gz (wanted $basename.orig.tar.gz)"); } else { $tardirbase= $dirbase; $tardirname= $dirname; $tarname= "$basenamerev.tar.gz"; } addfile("$tarname"); if ($sourcestyle =~ m/[kpursKPUR]/) { &addfile("$basenamerev.diff.gz"); } print("$progname: building $sourcepackage in $basenamerev.dsc\n") || &syserr("write building message"); open(STDOUT,"> $basenamerev.dsc") || &syserr("create $basenamerev.dsc"); &outputclose(1); if ($ur) { print(STDERR "$progname: unrepresentable changes to source\n") || &syserr("write error msg: $!"); exit(1); } exit(0); } use strict 'vars'; no strict 'vars'; sub addfile { my ($filename)= @_; stat($filename) || &syserr("could not stat output file `$filename'"); $size= (stat _)[7]; my $md5sum= `md5sum <$filename`; $? && &subprocerr("md5sum $filename"); $md5sum =~ s/^([0-9a-f]{32})\s*-?\s*\n$/$1/ || &failure("md5sum gave bogus output `$_'"); $f{'Files'}.= "\n $md5sum $size $filename"; }