From a9fe21f068524faa2e32a76c412a29371bba08da Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Tue, 6 Aug 1996 02:31:52 +0100 Subject: [PATCH] dpkg (1.3.0) experimental; urgency=LOW * dpkg can install named pipes. * dpkg-deb supports directory for destination, generates filename. * dpkg-{source,gencontrol,genchanges,parsechangelog,buildpackage}, dpkg-distaddfile scripts to support new source package format. * a.out build no longer supported. * Changed to new source package format. -- Ian Jackson Tue, 6 Aug 1996 02:31:52 +0100 --- Makefile.in | 9 +- debian.buildscript | 25 -- debian.changestemplate | 18 - debian.control | 15 - debian.mkchanges | 36 -- debian.rules | 86 ---- debian.Changelog => debian/changelog | 12 +- debian.controlaout => debian/control | 12 +- debian.README => debian/copyright | 0 debian.postinst => debian/postinst | 0 debian.preinst => debian/preinst | 0 debian.prerm => debian/prerm | 0 debian/rules | 62 +++ dpkg-deb/build.c | 29 +- dpkg-deb/dpkg-deb.8 | 18 +- dselect/pkgcmds.cc | 17 +- dselect/pkglist.h | 1 - main/archives.c | 8 +- scripts/Makefile.in | 16 +- scripts/cl-dpkg | 143 ++++++ scripts/cl-dpkg.pl | 143 ++++++ scripts/controllib.pl | 177 ++++++++ scripts/dpkg-buildpackage.sh | 77 ++++ scripts/dpkg-distaddfile.pl | 59 +++ scripts/dpkg-genchanges.pl | 258 +++++++++++ scripts/dpkg-gencontrol.pl | 203 +++++++++ scripts/dpkg-parsechangelog.pl | 69 +++ scripts/dpkg-source.pl | 637 +++++++++++++++++++++++++++ split/dpkg-split.8 | 4 +- version.h | 2 +- 30 files changed, 1916 insertions(+), 220 deletions(-) delete mode 100644 debian.buildscript delete mode 100644 debian.changestemplate delete mode 100644 debian.control delete mode 100644 debian.mkchanges delete mode 100755 debian.rules rename debian.Changelog => debian/changelog (99%) rename debian.controlaout => debian/control (77%) rename debian.README => debian/copyright (100%) rename debian.postinst => debian/postinst (100%) rename debian.preinst => debian/preinst (100%) rename debian.prerm => debian/prerm (100%) create mode 100755 debian/rules create mode 100755 scripts/cl-dpkg create mode 100644 scripts/cl-dpkg.pl create mode 100644 scripts/controllib.pl create mode 100644 scripts/dpkg-buildpackage.sh create mode 100644 scripts/dpkg-distaddfile.pl create mode 100644 scripts/dpkg-genchanges.pl create mode 100644 scripts/dpkg-gencontrol.pl create mode 100644 scripts/dpkg-parsechangelog.pl create mode 100644 scripts/dpkg-source.pl diff --git a/Makefile.in b/Makefile.in index 40f01b68..4f595803 100644 --- a/Makefile.in +++ b/Makefile.in @@ -29,6 +29,7 @@ sbindir = $(exec_prefix)/sbin libdir = $(prefix)/lib dpkglibdir = $(libdir)/dpkg methodsdir = $(dpkglibdir)/methods +parsechangelogdir = $(dpkglibdir)/parsechangelog datadir = /var/lib/dpkg methodsdatadir = $(datadir)/methods methodsmnt = $(datadir)/methods/mnt @@ -75,10 +76,10 @@ all: version install: all $(BOURNESHELL) $(srcdir)/mkinstalldirs $(bindir) $(sbindir) \ - $(man1dir) $(man5dir) $(man8dir) $(devdocdir) \ - $(libdir) $(datadir) $(pinfodir) $(pupdatesdir) \ - $(dpkglibdir) $(methodsdir) $(methodsdatadir) $(methodsmnt) \ - $(altsdatadir) $(altsetcdir) $(partsdir) $(infodir) + $(man1dir) $(man5dir) $(man8dir) $(devdocdir) $(infodir) \ + $(libdir) $(dpkglibdir) $(methodsdir) $(parsechangelogdir) \ + $(datadir) $(pinfodir) $(pupdatesdir) $(methodsdatadir) \ + $(methodsmnt) $(altsdatadir) $(altsetcdir) $(partsdir) set -e; for d in $(SUBDIRS) ; do \ cd $$d ; \ $(MAKE) 'CC=$(CC)' 'LDFLAGS=$(LDFLAGS)' 'XLIBS=$(XLIBS)' \ diff --git a/debian.buildscript b/debian.buildscript deleted file mode 100644 index 116dbbb9..00000000 --- a/debian.buildscript +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/sh -set -e -x -really ./debian.rules clean -./debian.rules diff source - -./debian.rules build -really ./debian.rules binary - -curd="`pwd`" -newd="`basename \"$curd\"`"elf -rm -rf ../"$newd" -cp -dpR . ../"$newd" - -PATH=/usr/i486-linuxaout/bin:$PATH -export PATH - -really ./debian.rules clean -./debian.rules build -really ./debian.rules binary -cp doc/guidelines.texi .. - -version=`sed -n 's/^version=//p' debian.rules` -perl debian.mkchanges "$version" ../dpkg-$version.`dpkg --print-architecture`.changes -echo diff --git a/debian.changestemplate b/debian.changestemplate deleted file mode 100644 index ee309f35..00000000 --- a/debian.changestemplate +++ /dev/null @@ -1,18 +0,0 @@ -Date: =d -Format: 1.5 -Distribution: unstable -Source: dpkg -Binary: dpkg -Architecture: source =a -Version: =v -Maintainer: Ian Jackson -Description: - dpkg: Package maintenance system for Debian Linux -Changes:=c -Files: - =f:dpkg-=v.tar.gz base required - =f:dpkg-=velf.=a.deb base required - =f:dpkg-=v.=a.deb byhand - - =f:dpkg-=velf.=a.nondebbin.tar.gz byhand - - =f:dpkg-=v.=a.nondebbin.tar.gz byhand - - =f:guidelines.texi byhand - diff --git a/debian.control b/debian.control deleted file mode 100644 index f38dbd9f..00000000 --- a/debian.control +++ /dev/null @@ -1,15 +0,0 @@ -Package: dpkg -Version: =elf -Architecture: = -Essential: yes -Pre-Depends: libc5=, ncurses3.0 -Conflicts: dpkgname -Replaces: dpkgname -Maintainer: Ian Jackson -Description: Package maintenance system for Debian Linux - This package contains the programs which handle the installation and - removal of packages on your system. - . - The primary interface for the dpkg suite is the `dselect' program; - a more low-level and less user-friendly interface is available in - the form of the `dpkg' command. diff --git a/debian.mkchanges b/debian.mkchanges deleted file mode 100644 index 82b57e17..00000000 --- a/debian.mkchanges +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/perl -# Usage: -# perl debian.mkchanges thing.changes - -$x=time; sub z { $_[1]+$_[2]*60; }; @l=localtime($x); $od=1440; -$d=&z(@l)-&z(gmtime($x)); $d+=$od; $d%=$od; $s=$d>$od/2?($d=$od-$d,'-'):'+'; -$date=sprintf("%s, %d %s %d %02d:%02d:%02d %s%02d%02d", - (Sun,Mon,Tue,Wed,Thu,Fri,Sat)[$l[6]], $l[3], - (Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec)[$l[4]], $l[5]+1900, - $l[2],$l[1],$l[0], $s,$d/60,$d%60); - -($version)=@ARGV; -chop($arch=`dpkg --print-architecture`); - -open(Z,"debian.Changelog"); -while() { $changes.=$_; last if m/^ --/; } -close(Z); $changes =~ s/^/ /g; $changes =~ s/^/\n/; $changes =~ s/\n$//; - -chdir(".."); - -while () { - s/=a/$arch/g; - s/=v/$version/g; - if (m/^ =f:(\S+) (\S+) (\S+)$/) { - ($file,$sec,$pri)=($1,$2,$3); - $!=0; chop($md5sum=`md5sum <$file`); $? && die "$file: $? $!"; - $!=0; $size=`ls -l $file`; $? && die "$file: $? $!"; - $size =~ m/^\S+\s+\d+\s+\S+\s+\S+\s+(\d+)\s/ || die "$file: `$size'"; - $size= $1; - $_= " $md5sum $size $sec $pri $file\n"; - } else { - s/=c/$changes/ || s/=d/$date/g; - } - print || die $!; -} -close(STDOUT) || die $!; diff --git a/debian.rules b/debian.rules deleted file mode 100755 index 992a34f3..00000000 --- a/debian.rules +++ /dev/null @@ -1,86 +0,0 @@ -#!/usr/bin/make -f - -package=dpkg -version=1.2.14 - -archi=$(shell dpkg --print-architecture) -DIR:=$(shell pwd) - -build: - $(checkdir) - ./configure --prefix=/usr - $(MAKE) - touch build - -clean: - $(checkdir) - -rm -f build - -$(MAKE) -i distclean - -rm -rf debian-tmp* *~ *.orig ./#*# tmp.* - -rm -f config.cache config.status config.h install config.log - find -name '*~' -print0 | xargs -r0 rm -- - -binary: -#checkroot build - -rm -rf debian-tmp - mkdir debian-tmp debian-tmp/DEBIAN - install -d debian-tmp/usr/doc/{copyright,dpkg} - cp debian.preinst debian-tmp/DEBIAN/preinst - if file main/dpkg | grep -q ELF; then \ - if [ $(archi) = i386 ]; then \ - sed -e '5s/=/ (>= 5.2.18-2)/' tmp.control ; \ - sed -e 's/^# i386elf: //' debian-tmp/DEBIAN/preinst ; \ - else \ - sed -e '5s/=//' tmp.control ; \ - fi ; \ - else \ - cp debian.controlaout tmp.control ; \ - fi - sed -e '2s/=/$(version)/; 3s/=/$(archi)/' tmp.control >debian-tmp/DEBIAN/control - cp debian.prerm debian-tmp/DEBIAN/prerm - cp debian.postinst debian-tmp/DEBIAN/postinst - chmod +x debian-tmp/DEBIAN/{postinst,prerm,preinst} - $(MAKE) prefix=$(DIR)/debian-tmp/usr \ - datadir=$(DIR)/debian-tmp/var/lib/dpkg \ - etcdir=$(DIR)/debian-tmp/etc \ - install - gzip -9 debian-tmp/usr/info/guidelines.info* - cp debian.README debian-tmp/usr/doc/copyright/dpkg - cp TODO debian-tmp/usr/doc/dpkg/WISHLIST - touch debian-tmp/var/lib/dpkg/{status,available} - chown -R root.root debian-tmp - chmod -R g-ws debian-tmp - cd debian-tmp && \ - tar cf ../../$(package)-$(version).$(archi).nondebbin.tar usr var && \ - gzip -9vf ../../$(package)-$(version).$(archi).nondebbin.tar - mv debian-tmp/usr/bin/dpkg-deb{,.dist} - rm debian-tmp/var/lib/dpkg/{status,available} - set -e; if file main/dpkg | grep -q ELF; then \ - dpkg-deb --build --new debian-tmp ; \ - mv debian-tmp.deb ../dpkg-$(version)elf.$(archi).deb ; \ - mv ../dpkg-$(version).$(archi).nondebbin.tar.gz \ - ../dpkg-$(version)elf.$(archi).nondebbin.tar.gz ; \ - else \ - dpkg-deb --build --old debian-tmp ; \ - mv debian-tmp.deb ../dpkg-$(version).$(archi).deb ; \ - fi - -define checkdir - test -f include/dpkg.h -endef - -source: clean - chmod +x debian.rules - cd .. && \ - tar cf $(package)-$(version).tar $(package)-$(version) && \ - gzip -9vf $(package)-$(version).tar - -diff: - @echo '((( no diff - this package is a Debian special )))' - -checkroot: - $(checkdir) - test root = "`whoami`" - -.PHONY: binary source diff clean checkroot diff --git a/debian.Changelog b/debian/changelog similarity index 99% rename from debian.Changelog rename to debian/changelog index 7ae991d2..85255418 100644 --- a/debian.Changelog +++ b/debian/changelog @@ -1,9 +1,13 @@ -dpkg (1.2.14) stable unstable; urgency=MEDIUM +dpkg (1.3.0) experimental; urgency=LOW - * dselect +/-/_/= on lines for all broken, new, local or whatever - packages do not affect _all_ packages. (Bug#4129.) + * dpkg can install named pipes. + * dpkg-deb supports directory for destination, generates filename. + * dpkg-{source,gencontrol,genchanges,parsechangelog,buildpackage}, + dpkg-distaddfile scripts to support new source package format. + * a.out build no longer supported. + * Changed to new source package format. - -- Ian Jackson Thu, 22 Aug 1996 00:39:52 +0100 + -- Ian Jackson Tue, 6 Aug 1996 02:31:52 +0100 dpkg (1.2.13) unstable; urgency=LOW diff --git a/debian.controlaout b/debian/control similarity index 77% rename from debian.controlaout rename to debian/control index 89447013..b55ec8b1 100644 --- a/debian.controlaout +++ b/debian/control @@ -1,11 +1,15 @@ +Source: dpkg +Section: base +Priority: required +Maintainer: Ian Jackson +Standards-Version: 0.1 + Package: dpkg -Version: = -Architecture: = +Architecture: any Essential: yes +Pre-Depends: libc5${libcver}, ncurses3.0 Conflicts: dpkgname Replaces: dpkgname -Pre-Depends: libc4 | libc -Maintainer: Ian Jackson Description: Package maintenance system for Debian Linux This package contains the programs which handle the installation and removal of packages on your system. diff --git a/debian.README b/debian/copyright similarity index 100% rename from debian.README rename to debian/copyright diff --git a/debian.postinst b/debian/postinst similarity index 100% rename from debian.postinst rename to debian/postinst diff --git a/debian.preinst b/debian/preinst similarity index 100% rename from debian.preinst rename to debian/preinst diff --git a/debian.prerm b/debian/prerm similarity index 100% rename from debian.prerm rename to debian/prerm diff --git a/debian/rules b/debian/rules new file mode 100755 index 00000000..c3194638 --- /dev/null +++ b/debian/rules @@ -0,0 +1,62 @@ +#!/usr/bin/make -f + +DIR:=$(shell pwd) + +arch=$(shell dpkg --print-architecture) +cidir=debian/tmp/DEBIAN + +build: + $(checkdir) + ./configure --prefix=/usr + $(MAKE) + touch build + +clean: + $(checkdir) + -rm -f build + -$(MAKE) -i distclean || $(MAKE) -f Makefile.in -i distclean + -rm -rf debian/tmp* *~ *.orig ./#*# tmp.* debian/files* + -rm -f config.cache config.status config.h install config.log + find -name '*~' -print0 | xargs -r0 rm -- + +binary: checkroot build + -rm -rf debian/tmp + mkdir debian/tmp debian/tmp/DEBIAN + install -d debian/tmp/usr/doc/{copyright,dpkg} + set -e; if [ $(arch) = i386 ]; then \ + dpkg-gencontrol -Vlibcver=' (>= 5.2.18-2)' >$(cidir)/control ; \ + sed -e 's/^# i386elf: //' $(cidir)/preinst ; \ + else \ + dpkg-gencontrol -Vlibcver='' >$(cidir)/control ; \ + sed -e '/^# i386elf: /d' debian/preinst >$(cidir)/preinst ; \ + fi + cp debian/{prerm,postinst} debian/tmp/DEBIAN/. + chmod +x debian/tmp/DEBIAN/{postinst,prerm,preinst} + $(MAKE) prefix=$(DIR)/debian/tmp/usr \ + datadir=$(DIR)/debian/tmp/var/lib/dpkg \ + etcdir=$(DIR)/debian/tmp/etc \ + install + gzip -9 debian/tmp/usr/info/guidelines.info* + cp debian/copyright debian/tmp/usr/doc/copyright/dpkg + cp TODO debian/tmp/usr/doc/dpkg/WISHLIST + touch debian/tmp/var/lib/dpkg/{status,available} + chown -R root.root debian/tmp + chmod -R g-ws debian/tmp + set -e; cd debian/tmp; \ + version=`sed -n 's/^Version: //p' DEBIAN/control`; \ + file=dpkg_$${version}_$(arch).nondebbin.tar; \ + tar cf ../../../$${file} usr var && gzip -9vf ../../../$${file}; \ + cd ../..; dpkg-distaddfile $${file}.gz byhand - + mv debian/tmp/usr/bin/dpkg-deb{,.dist} + rm debian/tmp/var/lib/dpkg/{status,available} + dpkg-deb --build debian/tmp .. + +define checkdir + test -f include/dpkg.h +endef + +checkroot: + $(checkdir) + test root = "`whoami`" + +.PHONY: binary source diff clean checkroot diff --git a/dpkg-deb/build.c b/dpkg-deb/build.c index 7e9b7fa5..61f3dd2a 100644 --- a/dpkg-deb/build.c +++ b/dpkg-deb/build.c @@ -58,27 +58,38 @@ void do_build(const char *const *argv) { }; char *m; - const char *debar, *directory, *const *mscriptp; + const char *debar, *directory, *const *mscriptp, *versionstring, *arch; char *controlfile; struct pkginfo *checkedinfo; struct arbitraryfield *field; FILE *ar, *gz, *cf; - int p1[2],p2[2], warns, errs, n, c; + int p1[2],p2[2], warns, errs, n, c, subdir; pid_t c1,c2,c3,c4,c5; - struct stat controlstab, datastab, mscriptstab; + struct stat controlstab, datastab, mscriptstab, debarstab; char conffilename[MAXCONFFILENAME+1]; time_t thetime= 0; directory= *argv++; if (!directory) badusage("--build needs a directory argument"); + subdir= 0; if ((debar= *argv++) !=0) { if (*argv) badusage("--build takes at most two arguments"); + if (debar) { + if (stat(debar,&debarstab)) { + if (errno != ENOENT) + ohshite("unable to check for existence of archive `%.250s'",debar); + } else if (S_ISDIR(debarstab.st_mode)) { + subdir= 1; + } + } } else { m= m_malloc(strlen(directory) + sizeof(DEBEXT)); strcpy(m,directory); strcat(m,DEBEXT); debar= m; } - + if (nocheckflag) { + if (subdir) + ohshit("target is directory - cannot skip control file check"); printf(BACKEND ": warning, not checking contents of control area.\n" BACKEND ": building an unknown package in `%s'.\n", debar); } else { @@ -110,6 +121,16 @@ void do_build(const char *const *argv) { checkversion(checkedinfo->available.version.version,"(upstream) version",&errs); checkversion(checkedinfo->available.version.revision,"Debian revision",&errs); if (errs) ohshit("%d errors in control file",errs); + + if (subdir) { + versionstring= versiondescribe(&checkedinfo->available.version,vdew_never); + m= m_malloc(strlen(debar)+1+strlen(checkedinfo->name)+1+ + strlen(versionstring)+sizeof(DEBEXT)); + arch= checkedinfo->available.architecture; if (!arch) arch= ""; + sprintf(m,"%s/%s_%s%s%s" DEBEXT,debar,checkedinfo->name,versionstring, + arch[0] ? "_" : "", arch); + debar= m; + } printf(BACKEND ": building package `%s' in `%s'.\n", checkedinfo->name, debar); strcpy(controlfile, directory); diff --git a/dpkg-deb/dpkg-deb.8 b/dpkg-deb/dpkg-deb.8 index 47917b75..1d9d0d18 100644 --- a/dpkg-deb/dpkg-deb.8 +++ b/dpkg-deb/dpkg-deb.8 @@ -6,7 +6,7 @@ dpkg\-deb \- Debian package archive (.deb) manipulation tool .SH SYNOPSIS .B dpkg-deb .BR -b | --build -.IR directory " [" archive ] +.IR directory " [" archive | directory ] .br .B dpkg-deb .BR -I | --info @@ -80,6 +80,22 @@ will write the package into the file .IR directory \fB.deb\fR. If the archive to be created already exists it will be overwritten. + +If the second argument is a directory then +.B dpkg\-deb +will write to the file +.IB package _ version _ arch .deb\fR, +or +.IB package _ version .deb +if no +.B Architecture +field is present in the package control file. When a target directory +is specified, rather than a file, the +.B \-\-no\-check +option may not be used (since +.B dpkg\-deb +needs to read and parse the package control file to determine which +filename to use). .TP .BR \-\-info ", " -I Provides information about a binary package archive. diff --git a/dselect/pkgcmds.cc b/dselect/pkgcmds.cc index 7950bb9b..26a32566 100644 --- a/dselect/pkgcmds.cc +++ b/dselect/pkgcmds.cc @@ -33,19 +33,7 @@ extern "C" { #include "dselect.h" #include "pkglist.h" -int packagelist::affectedmatches(struct pkginfo *pkg, struct pkginfo *comparewith) { - switch (statsortorder) { - case sso_avail: - if (comparewith->clientdata->ssavail != pkg->clientdata->ssavail) return 0; - break; - case sso_state: - if (comparewith->clientdata->ssstate != pkg->clientdata->ssstate) return 0; - break; - case sso_unsorted: - break; - default: - internerr("unknown statsortorder in affectedmatches"); - } +static int matches(struct pkginfo *pkg, struct pkginfo *comparewith) { if (comparewith->priority != pkginfo::pri_unset && (comparewith->priority != pkg->priority || comparewith->priority == pkginfo::pri_other && @@ -72,8 +60,7 @@ void packagelist::affectedrange(int *startp, int *endp) { return; } *startp= index; - while (index < nitems && affectedmatches(table[index]->pkg,table[cursorline]->pkg)) - index++; + while (index < nitems && matches(table[index]->pkg,table[cursorline]->pkg)) index++; *endp= index; } diff --git a/dselect/pkglist.h b/dselect/pkglist.h index 4bfc8435..c93db253 100644 --- a/dselect/pkglist.h +++ b/dselect/pkglist.h @@ -160,7 +160,6 @@ class packagelist : public baselist { void addheading(enum ssavailval, enum ssstateval, pkginfo::pkgpriority, const char*, const char *section); void sortinplace(); - int affectedmatches(struct pkginfo *pkg, struct pkginfo *comparewith); void affectedrange(int *startp, int *endp); void setwant(pkginfo::pkgwant nw); void sethold(int hold); diff --git a/main/archives.c b/main/archives.c index 86215486..cbe7723d 100644 --- a/main/archives.c +++ b/main/archives.c @@ -312,7 +312,7 @@ int tarobject(struct TarInfo *ti) { } break; case NormalFile0: case NormalFile1: - case CharacterDevice: case BlockDevice: + case CharacterDevice: case BlockDevice: case FIFO: case HardLink: break; default: @@ -405,6 +405,12 @@ int tarobject(struct TarInfo *ti) { ohshite("error closing/writing `%.255s'",ti->Name); newtarobject_utime(fnamenewvb.buf,ti); break; + case FIFO: + if (mkfifo(fnamenewvb.buf,ti->Mode & S_IFMT)) + ohshite("error creating pipe `%.255s'",ti->Name); + debug(dbg_eachfiledetail,"tarobject FIFO"); + newtarobject_allmodes(fnamenewvb.buf,ti); + break; case CharacterDevice: case BlockDevice: if (mknod(fnamenewvb.buf,ti->Mode & S_IFMT,ti->Device)) ohshite("error creating device `%.255s'",ti->Name); diff --git a/scripts/Makefile.in b/scripts/Makefile.in index 12a5d6e8..2d1d8ce5 100644 --- a/scripts/Makefile.in +++ b/scripts/Makefile.in @@ -30,16 +30,20 @@ man1 = 1 man8 = 8 libdir = $(prefix)/lib dpkglibdir = $(libdir)/dpkg +parsechangelogdir = $(dpkglibdir)/parsechangelog etcdir= /etc altsetcdir = $(etcdir)/alternatives perlpath = @perlpath@ MAN1 = dpkg-name -EXC = dpkg-name +EXC = dpkg-name dpkg-source dpkg-genchanges dpkg-gencontrol \ + dpkg-buildpackage dpkg-parsechangelog dpkg-distaddfile MAN8 = update-rc.d start-stop-daemon update-alternatives install-info \ dpkg-scanpackages SBIN = update-rc.d start-stop-daemon update-alternatives install-info \ dpkg-scanpackages dpkg-divert cleanup-info +LIB = controllib.pl +CHGLGS = cl-dpkg INSTALL = @INSTALL@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ @@ -48,7 +52,8 @@ INSTALL_DATA = @INSTALL_DATA@ .SUFFIXES: .pl .sh .gzuue .pl: - sed <$@.pl 's:^#!/usr/bin/perl:#!$(perlpath):' \ + sed <$@.pl 's:^#!/usr/bin/perl:#!$(perlpath):; \ + s:\$dpkglibdir= "\.":\$dpkglibdir= "$(dpkglibdir)":' \ | ../insert-version.pl >$@.new chmod +x $@.new mv $@.new $@ @@ -56,6 +61,7 @@ INSTALL_DATA = @INSTALL_DATA@ .sh: sed <$@.sh 's:^dpkglibdir=/usr/lib/dpkg$$:dpkglibdir=$(dpkglibdir):' \ | ../insert-version.pl >$@.new + chmod +x $@.new mv $@.new $@ .gzuue: @@ -65,7 +71,7 @@ INSTALL_DATA = @INSTALL_DATA@ rm $@.gz mv $@.new $@ -all: $(EXC) $(SBIN) +all: $(EXC) $(SBIN) $(CHGLGS) clean: rm -f $(EXC) $(SBIN) core *.new @@ -78,3 +84,7 @@ install: all for f in $(MAN1) ; do $(INSTALL_DATA) $$f.1 $(man1dir)/$$f.$(man1) ; done for f in $(SBIN) ; do $(INSTALL_PROGRAM) $$f $(sbindir)/$$f ; done for f in $(MAN8) ; do $(INSTALL_DATA) $$f.8 $(man8dir)/$$f.$(man8) ; done + for f in $(LIB) ; do $(INSTALL_DATA) $$f $(dpkglibdir)/$$f; done + for f in $(CHGLGS) ; do $(INSTALL_PROGRAM) $$f \ + $(dpkglibdir)/parsechangelog/`echo $$f | sed -e 's/^cl-//'` ; \ + done diff --git a/scripts/cl-dpkg b/scripts/cl-dpkg new file mode 100755 index 00000000..8fdb2460 --- /dev/null +++ b/scripts/cl-dpkg @@ -0,0 +1,143 @@ +#!/usr/bin/perl +# +# Options: +# -v +# changes since + +$dpkglibdir= "/usr/lib/dpkg"; +$version= '1.3.0'; # This line modified by Makefile + +$controlfile= 'debian/control'; +$changelogfile= 'debian/changelog'; +$fileslistfile= 'debian/files'; +$varlistfile= 'debian/substvars'; + +push(@INC,$dpkglibdir); +require 'controllib.pl'; + +$progname= "parsechangelog/$progname"; + +$since=''; + +sub usageversion { + print STDERR +"Debian GNU/Linux parsechangelog/dpkg $version. Copyright (C) 1996 +Ian Jackson. This is free software; see the GNU General Public Licence +version 2 or later for copying conditions. There is NO warranty. + +Usage: parsechangelog/dpkg [-v) { + s/\s*\n$//; +# printf(STDERR "%-39.39s %-39.39s\n",$expect,$_); + if (m/^(\w[-+0-9a-z.]+) \(([^\(\) \t]+)\)((\s+[-0-9a-z]+)+)\;/i) { + if ($expect eq 'first heading') { + $f{'Source'}= $1; + $f{'Version'}= $2; + $f{'Distribution'}= $3; + &error("-v option specifies most recent version") if + $2 eq $since; + $f{'Distribution'} =~ s/^\s+//; + } elsif ($expect eq 'next heading or eof') { + last if $2 eq $since; + $f{'Changes'}.= " .\n"; + } else { + &clerror("found start of entry where expected $expect"); + } + $rhs= $'; $rhs =~ s/^\s+//; + undef %kvdone; + for $kv (split(/\s*,\s*/,$rhs)) { + $kv =~ m/^([-0-9a-z]+)\=\s*(.*\S)$/i || + &clerror("bad key-value after \`;': \`$kv'"); + $k=(uc substr($1,0,1)).(lc substr($1,1)); $v=$2; + $kvdone{$k}++ && &clwarn("repeated key-value $k"); + if ($k eq 'Urgency') { + $v =~ m/^([-0-9a-z]+)((\s+.*)?)$/i || + &clerror("badly formatted urgency value, at changelog "); + $newurg= lc $1; + $newurgn= $urgencies{lc $1}; $newcomment= $2; + $newurgn || + &clwarn("unknown urgency value $newurg - comparing very low"); + if (defined($f{'Urgency'})) { + $f{'Urgency'} =~ m/^([-0-9a-z]+)((\s+.*)?)$/i || + &internerr("urgency >$f{'Urgency'}<"); + $oldurg= lc $1; + $oldurgn= $urgencies{lc $1}; $oldcomment= $2; + } else { + $oldurgn= -1; + $oldcomment= ''; + } + $f{'Urgency'}= + (($newurgn > $oldurgn ? $newurg : $oldurg). + $oldcomment. + $newcomment); + } elsif (defined($mapkv{$k})) { + $f{$mapkv{$k}}= $v; + } elsif ($k =~ m/^X[BCS]+-/i) { + # Extensions - XB for putting in Binary, + # XC for putting in Control, XS for putting in Source + $f{$k}= $v; + } else { + &clwarn("unknown key-value key $k - copying to XS-$k"); + $f{"XS-$k"}= $v; + } + } + $expect= 'start of change data'; $blanklines=0; + $f{'Changes'}.= " $_\n .\n"; + } elsif (m/^\S/) { + &clerror("badly formatted heading line"); + } elsif (m/^ \-\- (\S.*\S) ((\w+\,\s*)?\d{1,2}\s+\w+\s+\d{4}\s+\d{1,2}:\d\d:\d\d\s+[-+]\d{4}(\s+\([^\\\(\)]\))?)$/) { + $expect eq 'more change data or trailer' || + &clerror("found trailer where expected $expect"); + $f{'Maintainer'}= $1 unless defined($f{'Maintainer'}); + $f{'Date'}= $2 unless defined($f{'Date'}); +# $f{'Changes'}.= " .\n $_\n"; + $expect= 'next heading or eof'; + last if $since eq ''; + } elsif (m/^ \-\-/) { + &clerror("badly formatted trailer line"); + } elsif (m/^\s{2,}\S/) { + $expect eq 'start of change data' || $expect eq 'more change data or trailer' || + &clerror("found change data where expected $expect"); + $f{'Changes'}.= (" .\n"x$blanklines)." $_\n"; $blanklines=0; + $expect= 'more change data or trailer'; + } elsif (!m/\S/) { + next if $expect eq 'start of change data' || $expect eq 'next heading or eof'; + $expect eq 'more change data or trailer' || + &clerror("found blank line where expected $expect"); + $blanklines++; + } else { + &clerror("unrecognised line"); + } +} + +$expect eq 'next heading or eof' || die "found eof where expected $expect"; + +$f{'Changes'} =~ s/\n$//; +$f{'Changes'} =~ s/^/\n/; + +&outputclose; + +sub clerror { &error("$_[0], at changelog line $."); } +sub clwarn { &warn("$_[0], at changelog line $."); } diff --git a/scripts/cl-dpkg.pl b/scripts/cl-dpkg.pl new file mode 100644 index 00000000..e97327c3 --- /dev/null +++ b/scripts/cl-dpkg.pl @@ -0,0 +1,143 @@ +#!/usr/bin/perl +# +# Options: +# -v +# changes since + +$dpkglibdir= "."; +$version= '1.3.0'; # This line modified by Makefile + +$controlfile= 'debian/control'; +$changelogfile= 'debian/changelog'; +$fileslistfile= 'debian/files'; +$varlistfile= 'debian/substvars'; + +push(@INC,$dpkglibdir); +require 'controllib.pl'; + +$progname= "parsechangelog/$progname"; + +$since=''; + +sub usageversion { + print STDERR +"Debian GNU/Linux parsechangelog/dpkg $version. Copyright (C) 1996 +Ian Jackson. This is free software; see the GNU General Public Licence +version 2 or later for copying conditions. There is NO warranty. + +Usage: parsechangelog/dpkg [-v) { + s/\s*\n$//; +# printf(STDERR "%-39.39s %-39.39s\n",$expect,$_); + if (m/^(\w[-+0-9a-z.]+) \(([^\(\) \t]+)\)((\s+[-0-9a-z]+)+)\;/i) { + if ($expect eq 'first heading') { + $f{'Source'}= $1; + $f{'Version'}= $2; + $f{'Distribution'}= $3; + &error("-v option specifies most recent version") if + $2 eq $since; + $f{'Distribution'} =~ s/^\s+//; + } elsif ($expect eq 'next heading or eof') { + last if $2 eq $since; + $f{'Changes'}.= " .\n"; + } else { + &clerror("found start of entry where expected $expect"); + } + $rhs= $'; $rhs =~ s/^\s+//; + undef %kvdone; + for $kv (split(/\s*,\s*/,$rhs)) { + $kv =~ m/^([-0-9a-z]+)\=\s*(.*\S)$/i || + &clerror("bad key-value after \`;': \`$kv'"); + $k=(uc substr($1,0,1)).(lc substr($1,1)); $v=$2; + $kvdone{$k}++ && &clwarn("repeated key-value $k"); + if ($k eq 'Urgency') { + $v =~ m/^([-0-9a-z]+)((\s+.*)?)$/i || + &clerror("badly formatted urgency value, at changelog "); + $newurg= lc $1; + $newurgn= $urgencies{lc $1}; $newcomment= $2; + $newurgn || + &clwarn("unknown urgency value $newurg - comparing very low"); + if (defined($f{'Urgency'})) { + $f{'Urgency'} =~ m/^([-0-9a-z]+)((\s+.*)?)$/i || + &internerr("urgency >$f{'Urgency'}<"); + $oldurg= lc $1; + $oldurgn= $urgencies{lc $1}; $oldcomment= $2; + } else { + $oldurgn= -1; + $oldcomment= ''; + } + $f{'Urgency'}= + (($newurgn > $oldurgn ? $newurg : $oldurg). + $oldcomment. + $newcomment); + } elsif (defined($mapkv{$k})) { + $f{$mapkv{$k}}= $v; + } elsif ($k =~ m/^X[BCS]+-/i) { + # Extensions - XB for putting in Binary, + # XC for putting in Control, XS for putting in Source + $f{$k}= $v; + } else { + &clwarn("unknown key-value key $k - copying to XS-$k"); + $f{"XS-$k"}= $v; + } + } + $expect= 'start of change data'; $blanklines=0; + $f{'Changes'}.= " $_\n .\n"; + } elsif (m/^\S/) { + &clerror("badly formatted heading line"); + } elsif (m/^ \-\- (\S.*\S) ((\w+\,\s*)?\d{1,2}\s+\w+\s+\d{4}\s+\d{1,2}:\d\d:\d\d\s+[-+]\d{4}(\s+\([^\\\(\)]\))?)$/) { + $expect eq 'more change data or trailer' || + &clerror("found trailer where expected $expect"); + $f{'Maintainer'}= $1 unless defined($f{'Maintainer'}); + $f{'Date'}= $2 unless defined($f{'Date'}); +# $f{'Changes'}.= " .\n $_\n"; + $expect= 'next heading or eof'; + last if $since eq ''; + } elsif (m/^ \-\-/) { + &clerror("badly formatted trailer line"); + } elsif (m/^\s{2,}\S/) { + $expect eq 'start of change data' || $expect eq 'more change data or trailer' || + &clerror("found change data where expected $expect"); + $f{'Changes'}.= (" .\n"x$blanklines)." $_\n"; $blanklines=0; + $expect= 'more change data or trailer'; + } elsif (!m/\S/) { + next if $expect eq 'start of change data' || $expect eq 'next heading or eof'; + $expect eq 'more change data or trailer' || + &clerror("found blank line where expected $expect"); + $blanklines++; + } else { + &clerror("unrecognised line"); + } +} + +$expect eq 'next heading or eof' || die "found eof where expected $expect"; + +$f{'Changes'} =~ s/\n$//; +$f{'Changes'} =~ s/^/\n/; + +&outputclose; + +sub clerror { &error("$_[0], at changelog line $."); } +sub clwarn { &warn("$_[0], at changelog line $."); } diff --git a/scripts/controllib.pl b/scripts/controllib.pl new file mode 100644 index 00000000..f6ce8758 --- /dev/null +++ b/scripts/controllib.pl @@ -0,0 +1,177 @@ +$parsechangelog= 'dpkg-parsechangelog'; + +grep($capit{lc $_}=$_, qw(Pre-Depends Standards-Version)); + +$substvar{'Format'}= 1.5; +$substvar{'newline'}= "\n"; +$substvar{'space'}= " "; +$substvar{'tab'}= "\t"; + +$progname= $0; $progname= $& if $progname =~ m,[^/]+$,; + +sub capit { + return defined($capit{lc $_[0]}) ? $capit{lc $_[0]} : + (uc substr($_[0],0,1)).(lc substr($_[0],1)); +} + +sub findarch { + $arch=`dpkg --print-architecture`; + $? && &subprocerr("dpkg --print-archictecture"); + $arch =~ s/\n$//; + $substvar{'arch'}= $arch; +} + +sub substvars { + my ($v) = @_; + my $lhs,$vn,$rhs; + while ($v =~ m/\$\{([-:0-9a-z]+)\}/i) { + $lhs=$`; $vn=$1; $rhs=$'; + if (defined($substvar{$vn})) { + $v= $lhs.$substvar{$vn}.$rhs; + } else { + &warn("unknown substitution variable \${$vn}"); + $v= $lhs.$rhs; + } + } + return $v; +} + +sub outputclose { + for $f (keys %f) { $substvar{"f:$f"}= $f{$f}; } + if (length($varlistfile)) { + $varlistfile="./$varlistfile" if $varlistfile =~ m/\s/; + if (open(SV,"< $varlistfile")) { + while () { + next if m/^\#/; + s/\s*\n$//; + m/^(\w+)\=/ || + &error("bad line in substvars file $varlistfile at line $."); + $substvar{$1}= $'; + } + close(SV); + } elsif ($! !~ m/no such file or directory/i) { + &error("unable to open substvars file $varlistvile: $!"); + } + } + for $f (sort { $fieldimps{$b} <=> $fieldimps{$a} } keys %f) { + $v= $f{$f}; + $v= &substvars($v); + $v =~ m/\n\S/ && &internerr("field $f has newline then non whitespace >$v<"); + $v =~ m/\n[ \t]*\n/ && &internerr("field $f has blank lines >$v<"); + $v =~ m/\n$/ && &internerr("field $f has trailing newline >$v<"); + $v =~ s/\$\{\}/\$/g; + print("$f: $v\n") || &syserr("write error on control data"); + } + + close(STDOUT) || &syserr("write error on close control data"); +} + +sub parsecontrolfile { + $controlfile="./$controlfile" if $controlfile =~ m/^\s/; + + open(CDATA,"< $controlfile") || &error("cannot read control file $controlfile: $!"); + $indices= &parsecdata('C',1,"control file $controlfile"); + $indices >= 2 || &error("control file must have at least one binary package part"); + + for ($i=1;$i<$indices;$i++) { + defined($fi{"C$i Package"}) || + &error("per-package paragraph $i in control info file is ". + "missing Package line"); + } +} + +sub parsechangelog { + defined($c=open(CDATA,"-|")) || &syserr("fork for parse changelog"); + if (!$c) { + @al=($parsechangelog); + push(@al,"-F$changelogformat") if length($changelogformat); + push(@al,"-v$since") if length($since); + push(@al,"-l$changelogfile"); + exec(@al) || &syserr("exec parsechangelog $parsechangelog"); + } + &parsecdata('L',0,"parsed version of changelog"); + close(CDATA); $? && &subprocerr("parse changelog"); + $substvar{'sourceversion'}= $fi{"L Version"}; +} + + +sub setsourcepackage { + if (length($sourcepackage)) { + $v eq $sourcepackage || + &error("source package has two conflicting values - $sourcepackage and $v"); + } else { + $sourcepackage= $v; + } +} + +sub parsecdata { + local ($source,$many,$whatmsg) = @_; + # many=0: ordinary control data like output from dpkg-parsechangelog + # many=1: many paragraphs like in source control file + # many=-1: single paragraph of control data optionally signed + local ($index,$cf); + $index=''; $cf=''; + while () { + s/\s*\n$//; + if (m/^(\S+)\s*:\s*(.*)$/) { + $cf=$1; $v=$2; + $cf= &capit($cf); + $fi{"$source$index $cf"}= $v; + if (lc $cf eq 'package') { $p2i{"$source $v"}= $index; } + } elsif (m/^\s+\S/) { + length($cf) || &syntax("continued value line not in field"); + $fi{"$source$index $cf"}.= "\n$_"; + } elsif (m/^-----BEGIN PGP/ && $many<0) { + while () { last if m/^$/; } + $many= -2; + } elsif (m/^$/) { + if ($many>0) { + $index++; $cf=''; + } elsif ($many == -2) { + $_= ; + length($_) || + &syntax("expected PGP signature, found EOF after blank line"); + s/\n$//; + m/^-----BEGIN PGP/ || + &syntax("expected PGP signature, found something else \`$_'"); + $many= -3; last; + } else { + &syntax("found several \`paragraphs' where only one expected"); + } + } else { + &syntax("line with unknown format (not field-colon-value)"); + } + } + $many == -2 && &syntax("found start of PGP body but no signature"); + if (length($cf)) { $index++; } + $index || &syntax("empty file"); + return $index; +} + +sub unknown { + &warn("unknown information field $_ in input data in $_[0]"); +} + +sub syntax { + &error("syntax error in $whatmsg at line $.: $_[0]"); +} + +sub failure { die "$progname: failure: $_[0]\n"; } +sub syserr { die "$progname: failure: $_[0]: $!\n"; } +sub error { die "$progname: error: $_[0]\n"; } +sub internerr { die "$progname: internal error: $_[0]\n"; } +sub warn { warn "$progname: warning: $_[0]\n"; } +sub usageerr { print(STDERR "$progname: @_\n\n"); &usageversion; exit(2); } + +sub subprocerr { + local ($p) = @_; + if (WIFEXITED($?)) { + die "$progname: failure: $p gave error exit status ".WEXITSTATUS($?)."\n"; + } elsif (WIFSIGNALED($?)) { + die "$progname: failure: $p died from signal ".WTERMSIG($?)."\n"; + } else { + die "$progname: failure: $p failed with unknown exit code $?\n"; + } +} + +1; diff --git a/scripts/dpkg-buildpackage.sh b/scripts/dpkg-buildpackage.sh new file mode 100644 index 00000000..dbb5603c --- /dev/null +++ b/scripts/dpkg-buildpackage.sh @@ -0,0 +1,77 @@ +#!/bin/sh + +set -e + +version="1.3.0"; # This line modified by Makefile + +progname="`basename \"$0\"`" +usageversion () { + cat >&2 < + -p + -b (binary-only) + -B (binary-only, no arch-indep files) + -us (unsigned source) + -uc (unsigned changes) +END +} + +rootcommand='' +pgpcommand=pgp +signsource=signfile +signchanges=signfile + +while [ $# != 0 ] +do + value="`echo x\"$1\" | sed -e 's/^x-.//'`" + case "$1" in + -h) usageversion; exit 0 ;; + -r*) rootcommand="$value" ;; + -p*) pgpcommand="$value" ;; + -us) signsource=: ;; + -uc) signchanges=: ;; + -b|-B) binaryonly=$1 ;; + *) echo >&2 "$progname: unknown option or argument $1"; exit 2 ;; + esac + shift +done + +mustsetvar () { + if [ "x$2" = x ]; then + echo >&2 "$progname: unable to determine $3" + exit 1 + else + echo "$progname: $3 is $2" + eval "$1=\"\$2\"" + fi +} + +curd="`pwd`" +dirn="`basename \"$curd\"`" +mustsetvar package "`dpkg-parsechangelog | sed -n 's/^Source: //p'`" "source package" +mustsetvar version "`dpkg-parsechangelog | sed -n 's/^Version: //p'`" "source version" +mustsetvar arch "`dpkg --print-architecture`" "build architecture" +pv="${package}_${version}" +pva="${package}_${version}_${arch}" + +signfile () { + $pgpcommand -fast <"../$1" >"../$1.asc" + mv -- "../$1.asc" "../$1" +} + +set -x -e + +$rootcommand debian/rules clean +if [ x$binaryonly = x ]; then + cd ..; dpkg-source -b "$dirn"; cd "$dirn" +fi +debian/rules build +$rootcommand debian/rules binary +$signsource "$pv.dsc" +dpkg-genchanges $binaryonly >../"$pva.changes" +$signchanges "$pva.changes" diff --git a/scripts/dpkg-distaddfile.pl b/scripts/dpkg-distaddfile.pl new file mode 100644 index 00000000..a5f5d2ed --- /dev/null +++ b/scripts/dpkg-distaddfile.pl @@ -0,0 +1,59 @@ +#!/usr/bin/perl + +$dpkglibdir= "."; +$version= '1.3.0'; # This line modified by Makefile + +use POSIX; +use POSIX qw(:errno_h :signal_h); + +$fileslistfile= 'debian/files'; + +push(@INC,$dpkglibdir); +require 'controllib.pl'; + +sub usageversion { + print STDERR +"Debian GNU/Linux dpkg-distaddfile $version. Copyright (C) 1996 +Ian Jackson. This is free software; see the GNU General Public Licence +version 2 or later for copying conditions. There is NO warranty. + +Usage: + dpkg-addfile
+Options: -f get files list from this file +"; +} + +while (@ARGV && $ARGV[0] =~ m/^-/) { + $_=shift(@ARGV); + if (m/^-f/) { + $fileslistfile= $'; + } elsif (m/^-h$/) { + &usageversion; exit(0); + } elsif (m/^--$/) { + last; + } else { + &usageerr("unknown option $_"); + } +} + +@ARGV==3 || &usageerr("need exactly a filename, section and priority"); +($file,$section,$priority)= @ARGV; + +($file =~ m/\s/ || $section =~ m/\s/ || $priority =~ m/\s/) && + &error("filename, section and priority may contain no whitespace"); + +$fileslistfile="./$fileslistfile" if $fileslistfile =~ m/^\s/; +open(Y,"> $fileslistfile.new") || &syserr("open new files list file"); +if (open(X,"< $fileslistfile")) { + while () { + s/\n$//; + next if m/^(\S+) / && $1 eq $file; + print(Y "$_\n") || &syserr("copy old entry to new files list file"); + } +} elsif ($! != ENOENT) { + &syserr("read old files list file"); +} +print(Y "$file $section $priority\n") + || &syserr("write new entry to new files list file"); +close(Y) || &syserr("close new files list file"); +rename("$fileslistfile.new",$fileslistfile) || &syserr("install new files list file"); diff --git a/scripts/dpkg-genchanges.pl b/scripts/dpkg-genchanges.pl new file mode 100644 index 00000000..0994330a --- /dev/null +++ b/scripts/dpkg-genchanges.pl @@ -0,0 +1,258 @@ +#!/usr/bin/perl + +$dpkglibdir= "."; +$version= '1.3.0'; # This line modified by Makefile + +$controlfile= 'debian/control'; +$changelogfile= 'debian/changelog'; +$fileslistfile= 'debian/files'; +$varlistfile= 'debian/substvars'; +$uploadfilesdir= '..'; + +use POSIX; +use POSIX qw(:errno_h :signal_h); + +push(@INC,$dpkglibdir); +require 'controllib.pl'; + +sub usageversion { + print STDERR +"Debian GNU/Linux dpkg-genchanges $version. Copyright (C) 1996 +Ian Jackson. This is free software; see the GNU General Public Licence +version 2 or later for copying conditions. There is NO warranty. + +Usage: dpkg-genchanges [options ...] + +Options: -b binary-only build - no source files + -B architecture-only build - no src or \`all' + -c get control info from this file + -l get per-version info from this file + -f get .deb files list from this file + -v include all changes later than version + -d use change description from this file + -m override changelog's maintainer value + -u directory with files (default is \`..' + -F force change log format + -D= override or add a field and value + -U remove a field + -V= set a substitution variable + -T read variables here, not debian/substvars +"; +} + +$i=100;grep($fieldimps{$_}=$i--, + qw(Format Date Source Binary Architecture Version + Distribution Urgency Maintainer Description Changes Files)); + +while (@ARGV) { + $_=shift(@ARGV); + if (m/^-b$/) { + $binaryonly= 1; + } elsif (m/^-B$/) { + $binaryonly= 2; + } elsif (m/^-c/) { + $controlfile= $'; + } elsif (m/^-l/) { + $changelogfile= $'; + } elsif (m/^-d/) { + $changesdescription= $'; + } elsif (m/^-f/) { + $fileslistfile= $'; + } elsif (m/^-v/) { + $since= $'; + } elsif (m/^-T/) { + $varlistfile= $'; + } elsif (m/^-m/) { + $forcemaint= $'; + } elsif (m/^-F([0-9a-z]+)$/) { + $changelogformat=$1; + } elsif (m/^-D([^\=:]+)[=:]/) { + $override{$1}= $'; + } elsif (m/^-U([^\=:]+)$/) { + $remove{$1}= 1; + } elsif (m/^-V(\w+)[=:]/) { + $substvar{$1}= $'; + } elsif (m/^-h$/) { + &usageversion; exit(0); + } else { + &usageerr("unknown option \`$_'"); + } +} + +&findarch; +&parsechangelog; +&parsecontrolfile; + +$fileslistfile="./$fileslistfile" if $fileslistfile =~ m/^\s/; +open(FL,"< $fileslistfile") || &syserr("cannot read files list file"); +while() { + if (m/^(([-+.0-9a-z]+)_([^_]+)_(\w+)\.deb) (\S+) (\S+)$/) { + defined($p2f{$2}) && + &warn("duplicate files list entry for package $2 (line $.)"); + $p2f{$2}= $1; + $p2ver{$2}= $3; + defined($f2sec{$1}) && + &warn("duplicate files list entry for file $1 (line $.)"); + $f2sec{$1}= $5; + $f2pri{$1}= $6; + next if $4 eq 'all' && $binaryonly>=2; + push(@fileslistfiles,$1); + } elsif (m/^([-+.,_0-9a-zA-Z]+) (\S+) (\S+)$/) { + defined($f2sec{$1}) && + &warn("duplicate files list entry for file $1 (line $.)"); + $f2sec{$1}= $2; + $f2pri{$1}= $3; + push(@fileslistfiles,$1); + } else { + &error("badly formed line in files list file, line $."); + } +} +close(FL); + +$archspecific=0; +for $_ (keys %fi) { + $v= $fi{$_}; + if (s/^C //) { +#print STDERR "G key >$_< value >$v<\n"; + if (m/^Source$/) { &setsourcepackage; } + elsif (m/^Section$|^Priority$/) { $sourcedefault{$_}= $v; } + elsif (s/^X[BS]*C[BS]*-//i) { $f{$_}= $v; } + elsif (m/|^X[BS]+-|^Standards-Version$|^Maintainer$/i) { } + else { &unknown('general section of control info file'); } + } elsif (s/^C(\d+) //) { +#print STDERR "P key >$_< value >$v<\n"; + $i=$1; $p=$fi{"C$i Package"}; + defined($p2f{$p}) || &error("package $p in control file but not in files list"); + $f= $p2f{$p}; + if (m/^Description$/) { + $v=$` if $v =~ m/\n/; + push(@descriptions,sprintf("%-10s - %-.65s",$p,$v)); + } elsif (m/^Section$/) { + $f2seccf{$f}= $v; + } elsif (m/^Priority$/) { + $f2pricf{$f}= $v; + } elsif (s/^X[BS]*C[BS]*-//i) { + $f{$_}= $v; + } elsif (m/^Architecture$/) { + next if $v eq 'all' && $binaryonly>=2; + $v= $arch if $v eq 'any'; + push(@archvalues,$v) unless $archadded{$v}++; + } elsif (m/^(Package|Essential|Pre-Depends|Depends|Provides)$/ || + m/^(Recommends|Suggests|Optional|Conflicts|Replaces)$/ || + m/^X[CS]+-/i) { + } else { + &unknown("package's section of control info file"); + } + } elsif (s/^L //) { +#print STDERR "L key >$_< value >$v<\n"; + if (m/^Source$/) { + &setsourcepackage; + } elsif (m/^(Version|Maintainer|Changes|Urgency|Distribution|Date)$/) { + $f{$_}= $v; + } elsif (s/^X[BS]*C[BS]*-//i) { + $f{$_}= $v; + } elsif (!m/^X[BS]+-/i) { + &unknown("parsed version of changelog"); + } + } else { + &internerr("value from nowhere, with key >$_< and value >$v<"); + } +} + +if ($changesdescription) { + $changesdescription="./$changesdescription" if $changesdescription =~ m/^\s/; + $f{'Changes'}= ''; + open(X,"< $changesdescription") || &syserr("read changesdescription"); + while() { + s/\s*\n$//; + $_= '.' unless m/\S/; + $f{'Changes'}.= "\n $_"; + } +} + +for $p (keys %p2f) { + defined($p2i{"C $p"}) || + &warn("package $p listed in files list but not in control info"); +} + +for $p (keys %p2f) { + $f= $p2f{$p}; + $sec= $f2seccf{$f}; $sec= $sourcedefault{'Section'} if !length($sec); + $sec eq $f2sec{$f} || &error("package $p has section $sec in control file". + " but $f2sec{$f} in files list"); + $pri= $f2pricf{$f}; $pri= $sourcedefault{'Priority'} if !length($pri); + $pri eq $f2pri{$f} || &error("package $p has priority $pri in control". + " file but $f2pri{$f} in files list"); +} + +if (!$binaryonly) { + $version= $f{'Version'}; + $origversion= $version; $origversion =~ s/-[^-]+$//; + $sec= $sourcedefault{'Section'}; + if (!length($sec)) { $sec='-'; &warn("missing Section for source files"); } + $pri= $sourcedefault{'Priority'}; + if (!length($pri)) { $pri='-'; &warn("missing Priority for source files"); } + + $dsc= "$uploadfilesdir/${sourcepackage}_${version}.dsc"; + open(CDATA,"< $dsc") || &error("cannot open .dsc file $dsc: $!"); + push(@sourcefiles,"${sourcepackage}_${version}.dsc"); + + &parsecdata('S',-1,"source control file $dsc"); + $files= $fi{'S Files'}; + for $file (split(/\n /,$files)) { + next if $file eq ''; + $file =~ m/^([0-9a-f]{32})[ \t]+\d+[ \t]+([0-9a-zA-Z][-+:.,=0-9a-zA-Z_]+)$/ + || &error("Files field contains bad line \`$file'"); + ($md5sum{$2},$file) = ($1,$2); + push(@sourcefiles,$file); + } + for $f (@sourcefiles) { $f2sec{$f}= $sec; $f2pri{$f}= $pri; } +} + +$f{'Format'}= $substvar{'Format'}; + +if (!length($f{'Date'})) { + chop($date822=`822-date`); $? && subprocerr("822-date"); + $f{'Date'}= $date822; +} + +$f{'Binary'}= join(' ',grep(s/C //,keys %p2i)); + +unshift(@archvalues,'source') unless $binaryonly; +$f{'Architecture'}= join(' ',@archvalues); + +$f{'Description'}= "\n ".join("\n ",sort @descriptions); + +$f{'Files'}= ''; +for $f (@sourcefiles,@fileslistfiles) { + next if $filedone{$f}++; + $uf= "$uploadfilesdir/$f"; + open(STDIN,"< $uf") || &syserr("cannot open upload file $uf for reading"); + (@s=stat(STDIN)) || &syserr("cannot fstat upload file $uf"); + $size= $s[7]; $size || &warn("upload file $uf is empty"); + $md5sum=`md5sum`; $? && subprocerr("md5sum upload file $uf"); + $md5sum =~ m/^([0-9a-f]{32})\s*$/i || + &failure("md5sum upload file $uf gave strange output \`$md5sum'"); + $md5sum= $1; + defined($md5sum{$f}) && $md5sum{$f} ne $md5sum && + &error("md5sum of source file $uf ($md5sum) is different from md5sum in $dsc". + " ($md5sum{$f})"); + $f{'Files'}.= "\n $md5sum $size $f2sec{$f} $f2pri{$f} $f"; +} + +$f{'Source'}= $sourcepackage; + +$f{'Maintainer'}= $forcemaint if length($forcemaint); + +for $f (qw(Version Distribution Maintainer Changes)) { + defined($f{$f}) || &error("missing information for critical output field $f"); +} + +for $f (qw(Urgency)) { + defined($f{$f}) || &warn("missing information for output field $f"); +} + +for $f (keys %override) { $f{&capit($f)}= $override{$f}; } +for $f (keys %remove) { delete $f{&capit($f)}; } + +&outputclose; diff --git a/scripts/dpkg-gencontrol.pl b/scripts/dpkg-gencontrol.pl new file mode 100644 index 00000000..f91cb479 --- /dev/null +++ b/scripts/dpkg-gencontrol.pl @@ -0,0 +1,203 @@ +#!/usr/bin/perl + +$dpkglibdir= "."; +$version= '1.3.0'; # This line modified by Makefile + +$controlfile= 'debian/control'; +$changelogfile= 'debian/changelog'; +$fileslistfile= 'debian/files'; +$varlistfile= 'debian/substvars'; + +use POSIX; +use POSIX qw(:errno_h); + +push(@INC,$dpkglibdir); +require 'controllib.pl'; + +sub usage { + print STDERR +"Debian GNU/Linux dpkg-gencontrol $version. Copyright (C) 1996 +Ian Jackson. This is free software; see the GNU General Public Licence +version 2 or later for copying conditions. There is NO warranty. + +Usage: dpkg-gencontrol [options ...] + +Options: -p print control file for package + -c get control info from this file + -l get per-version info from this file + -F force change log format + -v set version of binary package + -f write files here instead of debian/files + -is include section field + -ip include priority field + -isp|-ips include both section and priority + -D= override or add a field and value + -U remove a field + -V= set a substitution variable + -T read variables here, not debian/substvars +"; +} + +$i=100;grep($fieldimps{$_}=$i--, + qw(Package Version Section Priority Architecture Essential + Pre-Depends Depends Recommends Suggests Optional Conflicts Replaces + Provides Maintainer Source Description)); + +while (@ARGV) { + $_=shift(@ARGV); + if (m/^-p([-+0-9a-z.]+)$/) { + $oppackage= $1; + } elsif (m/^-c/) { + $controlfile= $'; + } elsif (m/^-l/) { + $changelogfile= $'; + } elsif (m/^-f/) { + $fileslistfile= $'; + } elsif (m/^-v(.+)$/) { + $forceversion= $1; + } elsif (m/^-is$/) { + $spinclude{'Section'}=1; + } elsif (m/^-ip$/) { + $spinclude{'Priority'}=1; + } elsif (m/^-isp$/ || m/^-ips$/) { + $spinclude{'Section'}=1; + $spinclude{'Priority'}=1; + } elsif (m/^-F([0-9a-z]+)$/) { + $changelogformat=$1; + } elsif (m/^-D([^\=:]+)[=:]/) { + $override{$1}= $'; + } elsif (m/^-U([^\=:]+)$/) { + $remove{$1}= 1; + } elsif (m/^-V(\w+)[=:]/) { + $substvar{$1}= $'; + } elsif (m/^-T/) { + $varlistfile= $'; + } elsif (m/^-h$/) { + &usageversion; exit(0); + } else { + &usageerr("unknown option \`$_'"); + } +} + +$arch=`dpkg --print-architecture`; +$? && &subprocerr("dpkg --print-architecture"); +$arch =~ s/\n$//; + +&parsechangelog; +&parsecontrolfile; + +if (length($oppackage)) { + defined($p2i{"C $oppackage"}) || &error("package $oppackage not in control info"); + $myindex= $p2i{"C $oppackage"}; +} else { + @packages= grep(m/^C /,keys %p2i); + @packages==1 || + &error("must specify package since control info has many (@packages)"); + $myindex=1; +} + +#print STDERR "myindex $myindex\n"; + +for $_ (keys %fi) { + $v= $fi{$_}; + if (s/^C //) { +#print STDERR "G key >$_< value >$v<\n"; + if (m/^Maintainer$/) { $f{$_}=$v; } + elsif (m/^Source$/) { &setsourcepackage; } + elsif (s/^X[CS]*B[CS]*-//i) { $f{$_}= $v; } + elsif (m/^X[CS]+-|^Standards-Version$/i) { } + elsif (m/^Section$|^Priority$/) { $spdefault{$_}= $v; } + else { &unknown('general section of control info file'); } + } elsif (s/^C$myindex //) { +#print STDERR "P key >$_< value >$v<\n"; + if (m/^(Package|Description|Essential|Pre-Depends|Depends)$/ || + m/^(Recommends|Suggests|Optional|Conflicts|Provides|Replaces)$/) { + $f{$_}= $v; + } elsif (m/^Section$|^Priority$/) { + $spvalue{$_}= $v; + } elsif (m/^Architecture$/) { + if ($v eq 'all') { + $f{$_}= $v; + } elsif ($v eq 'any') { + $f{$_}= $arch; + } else { + @archlist= split(/\s+/,$v); + grep($arch eq $_, @archlist) || + &error("current build architecture $arch does not". + " appear in package's list (@archlist)"); + $f{$_}= $arch; + } + } elsif (s/^X[CS]*B[CS]*-//i) { + $f{$_}= $v; + } elsif (!m/^X[CS]+-/i) { + &unknown("package's section of control info file"); + } + } elsif (m/^C\d+ /) { +#print STDERR "X key >$_< value not shown<\n"; + } elsif (s/^L //) { +#print STDERR "L key >$_< value >$v<\n"; + if (m/^Source$/) { + &setsourcepackage; + } elsif (m/^Version$/) { + $sourceversion= $v; + $f{$_}= $v unless length($forceversion); + } elsif (m/^(Maintainer|Changes|Urgency|Distribution|Date)$/) { + } elsif (s/^X[CS]*B[CS]*-//i) { + $f{$_}= $v; + } elsif (!m/^X[CS]+-/i) { + &unknown("parsed version of changelog"); + } + } else { + &internerr("value from nowhere, with key >$_< and value >$v<"); + } +} + +$f{'Version'}= $forceversion if length($forceversion); + +for $f (qw(Section Priority)) { + $spvalue{$f}= $spdefault{$f} unless length($spvalue{$f}); + $f{$f}= $spvalue{$f} if $spinclude{$f} && length($spvalue{$f}); +} + +for $f (qw(Package Version)) { + defined($f{$f}) || &error("missing information for output field $f"); +} +for $f (qw(Maintainer Description Architecture)) { + defined($f{$f}) || &warn("missing information for output field $f"); +} +$oppackage= $f{'Package'}; + +$verdiff= $f{'Version'} ne $sourceversion; +if ($oppackage ne $sourcepackage || $verdiff) { + $f{'Source'}= $sourcepackage; + $f{'Source'}.= " ($sourceversion)" if $verdiff; +} + +$fileslistfile="./$fileslistfile" if $fileslistfile =~ m/^\s/; +open(Y,"> $fileslistfile.new") || &syserr("open new files list file"); +if (open(X,"< $fileslistfile")) { + while () { + s/\n$//; + next if m/^([-+0-9a-z.]+)_[^_]+_\w+\.deb / && $1 eq $oppackage; + print(Y "$_\n") || &syserr("copy old entry to new files list file"); + } +} elsif ($! != ENOENT) { + &syserr("read old files list file"); +} +print(Y &substvars(sprintf("%s_%s_%s.deb %s %s\n", + $oppackage,$f{'Version'},$f{'Architecture'}, + &spfileslistvalue('Section'), &spfileslistvalue('Priority')))) + || &syserr("write new entry to new files list file"); +close(Y) || &syserr("close new files list file"); +rename("$fileslistfile.new",$fileslistfile) || &syserr("install new files list file"); + +for $f (keys %override) { $f{&capit($f)}= $override{$f}; } +for $f (keys %remove) { delete $f{&capit($f)}; } + +&outputclose; + +sub spfileslistvalue { + $r= $spvalue{$_[0]}; + $r= '-' if !length($r); + return $r; +} diff --git a/scripts/dpkg-parsechangelog.pl b/scripts/dpkg-parsechangelog.pl new file mode 100644 index 00000000..e9967947 --- /dev/null +++ b/scripts/dpkg-parsechangelog.pl @@ -0,0 +1,69 @@ +#!/usr/bin/perl + +$dpkglibdir= "."; +$version= '1.3.0'; # This line modified by Makefile + +$format='dpkg'; +$changelogfile='debian/changelog'; +@parserpath= ("/usr/local/lib/dpkg/parsechangelog", + "$dpkglibdir/parsechangelog"); + +use POSIX; +use POSIX qw(:errno_h); + +push(@INC,$dpkglibdir); +require 'controllib.pl'; + +sub usageversion { + print STDERR +"Debian GNU/Linux dpkg-source $version. Copyright (C) 1996 +Ian Jackson. This is free software; see the GNU General Public Licence +version 2 or later for copying conditions. There is NO warranty. + +Usage: dpkg-parsechangelog [-L] [-F] [-v] + [-lchangelogfile] +"; +} + +@ap=(); +while (@ARGV) { + last unless $ARGV[0] =~ m/^-/; + $_= shift(@ARGV); + if (m/^-L/ && length($_)>2) { $libdir=$'; next; } + if (m/^-F([0-9a-z]+)$/) { $force=1; $format=$1; next; } + if (m/^-l/ && length($_)>2) { $changelogfile=$'; next; } + push(@ap,$_); + m/^--$/ && last; + m/^-v/ && next; + &usageerr("unknown option \`$_'"); +} + +@ARGV && &usageerr("$progname takes no non-option arguments"); +$changelogfile= "./$changelogfile" if $changelogfile =~ m/^\s/; + +if (!$force) { + open(STDIN,"< $changelogfile") || + &error("cannot open $changelogfile to find format: $!"); + open(P,"tail -40 |") || die "cannot fork: $!\n"; + while(

) { + next unless m/\schangelog-format:\s+([0-9a-z]+)\W/; + $format=$1; + } + close(P); $? && &subprocerr("tail of $changelogfile"); +} + +for $pd (@parserpath) { + $pa= "$pd/$format"; + if (!stat("$pa")) { + $! == ENOENT || &syserr("failed to check for format parser $pa"); + } elsif (!-x _) { + &warn("format parser $pa not executable"); + } else { + $pf= $pa; + } +} + +defined($pf) || &error("format $pa unknown"); + +open(STDIN,"< $changelogfile") || die "cannot open $changelogfile: $!\n"; +exec($pf,@ap); die "cannot exec format parser: $!\n"; diff --git a/scripts/dpkg-source.pl b/scripts/dpkg-source.pl new file mode 100644 index 00000000..51a5ae7c --- /dev/null +++ b/scripts/dpkg-source.pl @@ -0,0 +1,637 @@ +#!/usr/bin/perl + +use POSIX; +use POSIX qw(:errno_h :signal_h); + +$dpkglibdir= "."; +$version= '1.3.0'; # This line modified by Makefile + +push(@INC,$dpkglibdir); +require 'controllib.pl'; + +sub usageversion { + print STDERR +"Debian GNU/Linux dpkg-source $version. Copyright (C) 1996 +Ian Jackson. This is free software; see the GNU General Public Licence +version 2 or later for copying conditions. There is NO warranty. + +Usage: + dpkg-source -x .dsc + dpkg-source -b [|\'\'] +Options: -c get control info from this file\n". +"(for -b) -l get per-version info from this file + -F force change log format + -D= override or add a .dsc field and value + -U remove a field + -V= set a substitution variable + -h print this message +Relative filenames for -c and -l are interpreted starting at the +source tree's top level directory. If is omitted then +it defaults to .orig if that exists or to \'\' (indicating a +Debian-special package without a diff) if .orig doesn\`t. +"; +} + +$i=100;grep($fieldimps{$_}=$i--, + qw(Source Version Binary Maintainer Architecture Standards-Version)); + +while (@ARGV && $ARGV[0] =~ m/^-/) { + $_=shift(@ARGV); + if (m/^-b$/) { + &setopmode('build'); + } elsif (m/^-x$/) { + &setopmode('extract'); + } 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/^-V(\w+)[=:]/) { + $substvar{$1}= $'; + } elsif (m/^-h$/) { + &usageversion; exit(0); + } elsif (m/^--$/) { + last; + } else { + &usageerr("unknown option $_"); + } +} + +defined($opmode) || &usageerr("need -x or -b"); + +if ($opmode eq 'build') { + + @ARGV || &usageerr("-b needs a directory"); + @ARGV<=2 || &usageerr("-b takes at most a directory and an orig directory"); + $dir= shift(@ARGV); + $dir= "./$dir" unless $dir =~ m:^/:; + stat($dir) || &error("cannot stat directory $dir: $!"); + -d $dir || &error("directory argument $dir is not a directory"); + + $!=0; if (@ARGV) { + $origdir= shift(@ARGV); + if (length($origdir)) { + stat($origdir) || &error("cannot find orig directory $origdir: $!"); + -d $origdir || &error("orig directory argument $origdir is not a directory"); + } + } elsif (!stat("$dir.orig")) { + $! == ENOENT || &error("cannot stat tentative orig dir $dir.orig: $!"); + $origdir= ''; + } elsif (-d _) { + $origdir= "$dir.orig"; + } else { + &error("tentative orig directory $dir.orig is not a directory"); + } + + $changelogfile= "$dir/debian/changelog" unless defined($changelogfile); + $controlfile= "$dir/debian/control" unless defined($controlfile); + + &parsechangelog; + &parsecontrolfile; + + $archspecific=0; + for $_ (keys %fi) { + $v= $fi{$_}; + if (s/^C //) { +#print STDERR "G key >$_< value >$v<\n"; + if (m/^Source$/) { &setsourcepackage; } + elsif (m/^Standards-Version$|^Maintainer$/) { $f{$_}= $v; } + elsif (s/^X[BC]*S[BC]*-//i) { $f{$_}= $v; } + elsif (m/^(Section|Priority|Files)$/ || m/^X[BC]+-/i) { } + else { &unknown('general section of control info file'); } + } elsif (s/^C(\d+) //) { +#print STDERR "P key >$_< value >$v<\n"; + $i=$1; $p=$fi{"C$i Package"}; + push(@binarypackages,$p) unless $packageadded{$p}++; + if (m/^Architecture$/) { +#print STDERR "$p >$v< >".join(' ',@sourcearch)."<\n"; + 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)$/ || + m/^(Recommends|Suggests|Optional|Conflicts|Replaces)$/ || + m/^(Description|Section|Priority)$/ || + m/^X[CS]+-/i) { + } else { + &unknown("package's section of control info file"); + } + } elsif (s/^L //) { +#print STDERR "L key >$_< value >$v<\n"; + 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)$/ || + m/^X[BS]+-/i) { + } else { + &unknown("parsed version of changelog"); + } + } 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+://; + $basenamerev= $basename= $sourcepackage.'_'.$version; + $basename =~ s/-[^_]+$//; + $basedirname= $basename; +#print STDERR ">$basedirname<\n"; + $basedirname =~ s/_/-/; +#print STDERR ">$basedirname<\n"; + + $dirbase= $dir; $dirbase =~ s,/?$,,; $dirbase =~ s,[^/]+$,,; $dirname= $&; + if (length($origdir)) { + $origdirbase= $origdir; $origdirbase =~ s,/?$,,; + $origdirbase =~ s,[^/]+$,,; $origdirname= $&; + + $origdirname eq "$basedirname.orig" || + &warn(".orig directory name $origdirname is not package-origversion". + " (wanted $basedirname.orig)"); + $tardirbase= $origdirbase; $tardirname= $origdirname; + $tarname= "$basename.orig.tar.gz"; + } else { + $tardirbase= $dirbase; $tardirname= $dirname; + $tarname= "$basename.tar.gz"; + } + + print("$progname: building $sourcepackage in $tarname\n") + || &syserr("write building tar message"); + &forkgzipwrite($tarname); + defined($c2= fork) || &syserr("fork for tar"); + if (!$c2) { + chdir($tardirbase) || &syserr("chdir to above (orig) source $tardirbase"); + open(STDOUT,">&GZIP") || &syserr("reopen gzip for tar"); + exec('tar','-cO','--',$tardirname); &syserr("exec tar"); + } + close(GZIP); + &reapgzip; + $c2 == waitpid($c2,0) || &syserr("wait for tar"); + $? && !(WIFSIGNALED($c2) && WTERMSIG($c2) == SIGPIPE) && subprocerr("tar"); + addfile("$tarname"); + + if (length($origdir)) { + print("$progname: building $sourcepackage in $basenamerev.diff.gz\n") + || &syserr("write building diff message"); + &forkgzipwrite("$basenamerev.diff.gz"); + + defined($c2= open(FIND,"-|")) || &syserr("fork for find"); + if (!$c2) { + chdir($dirname) || &syserr("chdir to $dirname for find"); + exec('find','.','-print0'); &syserr("exec find"); + } + $/= "\0"; + + file: + while (defined($fn= )) { + $fn =~ s/\0$//; $fn =~ s,^\./,,; + lstat("$dir/$fn") || &syserr("cannot stat file $dir/$fn"); + if (-l _) { + $type{$fn}= 'symlink'; + &checktype('-l') || next; + defined($n= readlink("$dir/$fn")) || + &syserr("cannot read link $dir/$fn"); + defined($n2= readlink("$origdir/$fn")) || + &syserr("cannot read orig link $origdir/$fn"); + $n eq $nw || &unrepdiff2("symlink to $n2","symlink to $n"); + } elsif (-f _) { + $type{$fn}= 'plain file'; + if (!lstat("$origdir/$fn")) { + $! == ENOENT || &syserr("cannot stat orig file $origdir/$fn"); + $ofnread= '/dev/null'; + } elsif (-f _) { + $ofnread= "$origdir/$fn"; + } else { + &unrepdiff2("something else","plain file"); + next; + } + defined($c3= open(DIFFGEN,"-|")) || &syserr("fork for diff"); + if (!$c3) { + exec('diff','-u', + '-L',"$basedirname.orig/$fn", + '-L',"$basedirname/$fn", + '--',"$ofnread","$dir/$fn"); &syserr("exec diff"); + } + $difflinefound= 0; + $/= "\n"; + while () { + if (m/^binary/i) { + close(DIFFGEN); $/= "\0"; + &unrepdiff("binary file contents changed"); + next file; + } elsif (m/^[-+\@ ]/) { + $difflinefound=1; + } else { + s/\n$//; + &internerr("unknown line from diff -u on $dirname/$fn: \`$_'"); + } + print(GZIP $_) || &syserr("failed to write to gzip"); + } + close(DIFFGEN); $/= "\0"; + if (WIFEXITED($?) && (($es=WEXITSTATUS($?))==0 || $es==1)) { + if ($es==1 && !$difflinefound) { + &unrepdiff("diff gave 1 but no diff lines found"); + } + } else { + subprocerr("diff on $dirname/$fn"); + } + } elsif (-p _) { + $type{$fn}= 'pipe'; + &checktype('-p'); + } elsif (-b _ || -c _ || -S _) { + &unrepdiff("device or socket is not allowed"); + } elsif (-d _) { + $type{$fn}= 'directory'; + } else { + &unrepdiff("unknown file type ($!)"); + } + } + close(FIND); $? && subprocerr("find on $dirname"); + close(GZIP) || &syserr("finish write to gzip pipe"); + &reapgzip; + + defined($c2= open(FIND,"-|")) || &syserr("fork for 2nd find"); + if (!$c2) { + chdir($origdirname) || &syserr("chdir to $origdirname for 2nd find"); + exec('find','.','-print0'); &syserr("exec 2nd find"); + } + $/= "\0"; + while (defined($fn= )) { + $fn =~ s/\0$//; $fn =~ s,^\./,,; + next if defined($type{$fn}); + lstat("$origdir/$fn") || &syserr("cannot check orig file $origdir/$fn"); + if (-f _) { + &warn("ignoring deletion of file $fn"); + } elsif (-d _) { + &warn("ignoring deletion of directory $fn"); + } elsif (-l _) { + &warn("ignoring deletion of symlink $fn"); + } else { + &unrepdiff2('not a file, directory or link','nonexistent'); + } + } + close(FIND); $? && subprocerr("find on $dirname"); + + &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; + + exit($ur ? 1 : 0); + +} else { + + @ARGV==1 || &usageerr("-x needs exactly one argument, the .dsc"); + $dsc= shift(@ARGV); + $dsc= "./$dsc" unless $dsc =~ m:^/:; + $dscdir= $dsc; $dscdir= "./$dscdir" unless $dsc =~ m,^/|^\./,; + $dscdir =~ s,/[^/]+$,,; + + open(CDATA,"< $dsc") || &error("cannot open .dsc file $dsc: $!"); + &parsecdata('S',-1,"source control file $dsc"); + + for $f (qw(Source Version Files)) { + defined($fi{"S $f"}) || + &error("missing critical source control field $f"); + } + + $sourcepackage= $fi{'S Source'}; + $sourcepackage =~ m/[^-+.0-9a-z]/ && + &error("source package name contains illegal character \`$&'"); + $sourcepackage =~ m/^[0-9a-z]./ || + &error("source package name is too short or starts with non-alphanum"); + + $version= $fi{'S Version'}; + $version =~ m/[^-+:.0-9a-zA-Z]/ && + &error("version number contains illegal character \`$&'"); + $version =~ s/^\d+://; + if ($version =~ m/-([^-]+)$/) { + $baseversion= $`; $revision= $1; + } else { + $baseversion= $version; $revision= ''; + } + + $files= $fi{'S Files'}; + for $file (split(/\n /,$files)) { + next if $file eq ''; + $file =~ m/^([0-9a-f]{32})[ \t]+(\d+)[ \t]+([0-9a-zA-Z][-+:.,=0-9a-zA-Z_]+)$/ + || &error("Files field contains bad line \`$file'"); + ($md5sum{$3},$size{$3},$file) = ($1,$2,$3); + &setfile(\$tarfile) if $file =~ m/\.tar\.gz$/; + &setfile(\$difffile) if $file =~ m/\.diff\.gz$/; + } + + $newdirectory= $sourcepackage.'-'.$baseversion; + $expectprefix= $newdirectory; $expectprefix.= '.orig' if length($difffile); + + length($tarfile) || &error("no tarfile in Files field"); + checkstats($tarfile); + checkstats($difffile) if length($difffile); + + &forkgzipread("$dscdir/$tarfile"); + defined($c2= open(CPIO,"-|")) || &syserr("fork for cpio"); + if (!$c2) { + open(STDIN,"<&GZIP") || &syserr("reopen gzip for cpio"); + open(STDERR,"| egrep -v '^[0-9]+ blocks\$' >&2") || + &syserr("reopen stderr for cpio to grep out blocks message"); + exec('cpio','-0t'); &syserr("exec cpio"); + } + $/= "\0"; + close(GZIP); + file: + while (defined($fn= )) { + $fn =~ s/\0$//; $pname= $fn; $pname =~ y/ -~/?/c; + $fn =~ m/\n/ && + &error("tarfile contains object with newline in its name ($pname)"); + $slash= substr($fn,length($expectprefix),1); + (($slash || '/' || $slash eq '') && + substr($fn,0,length($expectprefix)) eq $expectprefix) || + &error("tarfile contains object ($pname) not in expected directory". + " ($expectprefix)"); + $fn =~ m,/\.\./, && + &error("tarfile contains object with /../ in its name ($pname)"); + } + close(CPIO); $? && subprocerr("cpio"); + $/= "\n"; + &reapgzip; + + &forkgzipread("$dscdir/$tarfile"); + defined($c2= open(TAR,"-|")) || &syserr("fork for tar -t"); + if (!$c2) { + $ENV{'LANG'}= 'C'; + open(STDIN,"<&GZIP") || &syserr("reopen gzip for tar -t"); + exec('tar','-vvtf','-'); &syserr("exec tar -vvtf -"); + } + close(GZIP); + file: + while (defined($fn= )) { + $fn =~ s/\n$//; + $fn =~ m,^(\S{10})\s+\S+/\S+\s+\d+\s+\w+\s+\d+\s+\d+:\d\d\s+\d+ (.*)$, || + &error("tarfile contains unknown object listed by tar as \`$_'"); + $_= $1; $fn= $2; + s/^([-dpsl])// || + &error("tarfile contains object \`$fn' with unknown or forbidden type \`". + substr($_,0,1)."'"); + $fn =~ m/\.dpkg-orig$/ && + &error("tarfile contains file with name ending .dpkg-orig"); + $type= $&; + m/[sStT]/ && $type ne 'd' && + &error("tarfile contains setuid, setgid or sticky object \`$fn'"); + $fn eq "$expectprefix/debian" && $type ne 'd' && + &error("tarfile contains object `debian' that isn't a directory"); + $fn =~ s,/$,, if $type eq 'd'; + $dirname= $fn; + $dirname =~ s,/[^/]+$,, && !defined($dirincluded{$dirname}) && + &error("tarfile contains object \`$fn' but its containing ". + "directory \`$dirname' does not precede it"); + $dirincluded{$fn}= 1 if $type eq 'd'; + $notfileobject{$fn}= 1 if $type ne '-'; + } + close(TAR); $? && subprocerr("tar -t"); + &reapgzip; + + if (length($difffile)) { + if (!$dirincluded{"$expectprefix/debian"}) { + $mkdebian=1; $dirincluded{"$expectprefix/debian"}= 1; + } + + &forkgzipread("$dscdir/$difffile"); + $/="\n"; + while (length($_=)) { + s/\n$// || &error("diff is missing trailing newline"); + if (m/^--- /) { + $fn= $'; + substr($fn,0,length($expectprefix)+1) eq "$expectprefix/" || + &error("diff patches file ($fn) not in expected subdirectory"); + $fn =~ m/\.dpkg-orig$/ && + &error("diff patches file with name ending .dpkg-orig"); + $dirname= $fn; + $dirname =~ s,/[^/]+$,, && defined($dirincluded{$dirname}) || + &error("diff patches file ($fn) whose directory does not appear". + " in tarfile"); + defined($notfileobject{$fn}) && + &error("diff patches something which is not a plain file"); + $_= ; s/\n$// || + &error("diff finishes in middle of ---/+++ (line $.)"); + $_ eq '+++ '.$newdirectory.substr($fn,length($expectprefix)) || + &error("line after --- for file $fn isn't as expected"); + $filepatched{$fn}++ && &error("diff patches file $fn twice"); + } elsif (!m/^[-+ \@]/) { + &error("diff contains unknown line \`$_'"); + } + } + close(GZIP); + + &reapgzip; + } + + print("$progname: extracting $sourcepackage in $newdirectory". + ($difffile ? " and $expectprefix" : '')."\n") + || &syserr("write extracting message"); + + &erasedir($newdirectory); + &erasedir("$newdirectory.orig"); + + &extracttar; + + if (length($difffile)) { + rename($expectprefix,$newdirectory) || + &syserr("failed to rename newly-extracted $expectprefix to $newdirectory"); + + &extracttar; + + if ($mkdebian) { + mkdir("$newdirectory/debian",0777) || + &syserr("failed to create $newdirectory/debian subdirectory"); + } + &forkgzipread("$dscdir/$difffile"); + defined($c2= fork) || &syserr("fork for patch"); + if (!$c2) { + open(STDIN,"<&GZIP") || &syserr("reopen gzip for patch"); + chdir($newdirectory) || &syserr("chdir to $newdirectory for patch"); + exec('patch','-b','.dpkg-orig','-s','-t','-F','0','-N','-p1','-u'); + &syserr("exec patch"); + } + close(GZIP); + $c2 == waitpid($c2,0) || &syserr("wait for patch"); + $? && subprocerr("patch"); + &reapgzip; + + for $fn (keys %filepatched) { + $ftr= "$newdirectory/".substr($fn,length($expectprefix)+1).".dpkg-orig"; + unlink($ftr) || &syserr("remove patch backup file $ftr"); + } + + if (!(@s= lstat("$newdirectory/debian/rules"))) { + $! == ENOENT || &syserr("cannot stat $newdirectory/debian/rules"); + &warn("$newdirectory/debian/rules does not exist"); + } elsif (-f _) { + chmod($s[2] | 0111, "$newdirectory/debian/rules") || + &syserr("cannot make $newdirectory/debian/rules executable"); + } else { + &warn("$newdirectory/debian/rules is not a plain file"); + } + } + + exit(0); +} + +sub checkstats { + my ($f)= @_; + my @s,$m; + open(STDIN,"< $dscdir/$f") || &syserr("cannot read $dscdir/$f"); + (@s= stat(STDIN)) || &syserr("cannot fstat $dscdir/$f"); + $s[7] == $size{$f} || &error("file $f has size $s[7] instead of expected $size{$f}"); + $m= `md5sum`; $? && subprocerr("md5sum $f"); $m =~ s/\n$//; + $m =~ m/^[0-9a-f]{32}$/ || &failure("md5sum of $f gave bad output \`$m'"); + $m eq $md5sum{$f} || &error("file $f has md5sum $m instead of expected $md5sum{$f}"); + open(STDIN," $_[0]") || &syserr("create file $_[0]"); + pipe(GZIPREAD,GZIP) || &syserr("pipe for gzip"); + defined($cgz= fork) || &syserr("fork for gzip"); + if (!$cgz) { + open(STDIN,"<&GZIPREAD") || &syserr("reopen gzip pipe"); close(GZIPREAD); + close(GZIP); open(STDOUT,">&GZIPFILE") || &syserr("reopen tar.gz"); + exec('gzip','-9'); &syserr("exec gzip"); + } + close(GZIPREAD); + $gzipsigpipeok= 0; +} + +sub forkgzipread { +#print STDERR "forkgzipread $_[0]\n"; + open(GZIPFILE,"< $_[0]") || &syserr("read file $_[0]"); + pipe(GZIP,GZIPWRITE) || &syserr("pipe for gunzip"); + defined($cgz= fork) || &syserr("fork for gunzip"); + if (!$cgz) { + open(STDOUT,">&GZIPWRITE") || &syserr("reopen gunzip pipe"); close(GZIPWRITE); + close(GZIP); open(STDIN,"<&GZIPFILE") || &syserr("reopen input file"); + exec('gunzip'); &syserr("exec gunzip"); + } + close(GZIPWRITE); + $gzipsigpipeok= 1; +} + +sub reapgzip { +#print STDERR "reapgzip $_[0]\n"; + $cgz == waitpid($cgz,0) || &syserr("wait for gzip"); + !$? || ($gzipsigpipeok && WIFSIGNALED($?) && WTERMSIG($?)==SIGPIPE) || + subprocerr("gzip"); + (@stat= stat(GZIPFILE)) || &syserr("cannot stat file after run gzip"); + $size= $stat[7]; + close(GZIPFILE); +} + +sub addfile { + my ($filename)= @_; + my $md5sum= `md5sum <$filename`; + $? && &subprocerr("md5sum $filename"); + $md5sum =~ s/^([0-9a-f]{32})\n$/$1/ || + die "$progname: failure: md5sum gave bogus output \`$_'\n"; + $f{'Files'}.= "\n $md5sum $size $filename"; +} diff --git a/split/dpkg-split.8 b/split/dpkg-split.8 index 9b7253d9..ccab6921 100644 --- a/split/dpkg-split.8 +++ b/split/dpkg-split.8 @@ -83,8 +83,8 @@ been generated by the same invocation of The parts' filenames are not significant for the reassembly process. By default the output file is called -.IB package - version .deb -\&. +.IB package - version .deb\fR. + .TP .BR --info ", " -I Prints information, in a human-readable format, about the part file(s) diff --git a/version.h b/version.h index 42be7bd9..5692879a 100644 --- a/version.h +++ b/version.h @@ -1 +1 @@ -#define DPKG_VERSION "1.2.14" /* This line modified by Makefile */ +#define DPKG_VERSION "1.3.0" /* This line modified by Makefile */ -- 2.39.5