summaryrefslogtreecommitdiff
path: root/split
diff options
context:
space:
mode:
Diffstat (limited to 'split')
-rw-r--r--split/Makefile.in80
-rwxr-xr-xsplit/debugmake3
-rw-r--r--split/dpkg-split.819
-rw-r--r--split/dpkg-split.h72
-rw-r--r--split/info.c230
-rw-r--r--split/join.c134
-rw-r--r--split/junk36
-rw-r--r--split/magic5
-rw-r--r--split/main.c176
-rwxr-xr-xsplit/mksplit88
-rw-r--r--split/mksplit.pl88
-rw-r--r--split/old-mksplit.sh113
-rw-r--r--split/queue.c273
-rw-r--r--split/split.c71
14 files changed, 1388 insertions, 0 deletions
diff --git a/split/Makefile.in b/split/Makefile.in
new file mode 100644
index 000000000..8cdeaf0a7
--- /dev/null
+++ b/split/Makefile.in
@@ -0,0 +1,80 @@
+# Copyright (C) 1994 Ian Murdock <imurdock@debian.org>
+# Copyright (C) 1994,1995 Ian Jackson <ijackson@nyx.cs.du.edu>
+#
+# This is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2,
+# or (at your option) any later version.
+#
+# This is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public
+# License along with dpkg; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+prefix = @prefix@
+exec_prefix = $(prefix)
+bindir = $(exec_prefix)/bin
+libdir = $(prefix)/lib
+dpkglibdir = $(libdir)/dpkg
+datadir = /var/lib/dpkg
+partsdir = $(datadir)/parts
+mandir = $(prefix)/man
+man8dir = $(mandir)/man8
+man8 = 8
+perlpath = @perlpath@
+
+SRC = main.c split.c info.c queue.c join.c
+OBJ = main.o split.o info.o queue.o join.o
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+
+CC = @CC@
+
+CFLAGS = @CFLAGS@ @CWARNS@ -g $(XCFLAGS)
+LDFLAGS = $(XLDFLAGS)
+LIBS = -L../lib -ldpkg $(XLIBS)
+ALL_CFLAGS = -I../include -I.. @DEFS@ $(CFLAGS)
+
+.SUFFIXES: .c .o .pl
+
+.c.o:
+ $(CC) $(ALL_CFLAGS) -c $<
+
+.pl:
+ sed <$@.pl 's:^#!/usr/bin/perl:#!$(perlpath):' \
+ | ../insert-version.pl >$@.new
+ chmod +x $@.new
+ mv $@.new $@
+
+all: dpkg-split mksplit
+
+dpkg-split: $(OBJ) ../lib/libdpkg.a
+ $(CC) $(LDFLAGS) -o dpkg-split $(OBJ) $(LIBS)
+
+split.o: split.c
+ $(CC) -DMKSPLITSCRIPT=\"$(dpkglibdir)/mksplit\" $(ALL_CFLAGS) -c $<
+
+$(OBJ): dpkg-split.h ../config.h ../include/dpkg.h
+build.o split.o queue.o join.o main.o: ../include/dpkg-db.h
+info.o extract.o main.o: ../include/myopt.h
+main.o: ../version.h
+
+clean:
+ rm -f *.o core dpkg-split
+
+distclean: clean
+ rm -f Makefile *.orig *~ *.~* ./#*#
+
+install: all
+ $(INSTALL_PROGRAM) -s dpkg-split $(bindir)/dpkg-split
+ $(INSTALL_PROGRAM) mksplit $(dpkglibdir)/mksplit
+# $(INSTALL_DATA) dpkg-split.8 $(man8dir)/dpkg-split.$(man8)
diff --git a/split/debugmake b/split/debugmake
new file mode 100755
index 000000000..53497bcd5
--- /dev/null
+++ b/split/debugmake
@@ -0,0 +1,3 @@
+#!/bin/sh
+set -x
+make 'XCFLAGS=-g -O0' LDFLAGS=-g 'LIBS= -lefence -L../lib -ldpkg' "$@"
diff --git a/split/dpkg-split.8 b/split/dpkg-split.8
new file mode 100644
index 000000000..399868d48
--- /dev/null
+++ b/split/dpkg-split.8
@@ -0,0 +1,19 @@
+.\" Hey, Emacs! This is an -*- nroff -*- source file.
+.TH DPKG\-SPLIT 8 "29th November 1995" "Debian Project" "Debian GNU/Linux"
+.SH NAME
+dpkg\-split \- Debian multipart package manipulation tool
+.SH DESCRIPTION
+.B dpkg\-split
+does not have a useful man page. Please do not report this as a bug,
+as this has already been done many times.
+
+Instead, if you are a competent and accurate writer and are willing to
+spend the time reading the source code and writing good manpages
+please write a better man page than this one.
+
+Type
+.B dpkg\-split \-\-help
+for a brief summary of how to use dpkg.
+
+.SH AUTHOR
+Ian Jackson <ijackson@gnu.ai.mit.edu>.
diff --git a/split/dpkg-split.h b/split/dpkg-split.h
new file mode 100644
index 000000000..7caee5333
--- /dev/null
+++ b/split/dpkg-split.h
@@ -0,0 +1,72 @@
+/*
+ * dpkg-split - splitting and joining of multipart *.deb archives
+ * dpkg-split.h - external definitions for this program
+ *
+ * Copyright (C) 1995 Ian Jackson <iwj10@cus.cam.ac.uk>
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2,
+ * or (at your option) any later version.
+ *
+ * This is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with dpkg; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef DPKG_SPLIT_H
+#define DPKG_SPLIT_H
+
+typedef void dofunction(const char *const *argv);
+dofunction do_split, do_join, do_info, do_auto, do_queue, do_discard;
+
+struct partinfo {
+ const char *filename;
+ const char *fmtversion;
+ const char *package;
+ const char *version;
+ const char *md5sum;
+ unsigned long orglength;
+ int thispartn, maxpartn;
+ unsigned long maxpartlen;
+ unsigned long thispartoffset;
+ unsigned long thispartlen;
+ unsigned long headerlen; /* size of header in part file */
+ unsigned long filesize;
+};
+
+struct partqueue {
+ struct partqueue *nextinqueue;
+ struct partinfo info;
+ /* only fields filename, md5sum, maxpartlen, thispartn, maxpartn
+ * are valid; the rest are null. If the file is not named correctly
+ * to be a part file md5sum is null too and the numbers are zero.
+ */
+};
+
+extern dofunction *action;
+extern const struct cmdinfo *cipaction;
+extern long maxpartsize;
+extern const char *depotdir, *outputfile;
+extern struct partqueue *queue;
+extern int npquiet, msdos;
+
+void rerr(const char *fn) NONRETURNING;
+void rerreof(FILE *f, const char *fn) NONRETURNING;
+void print_info(const struct partinfo *pi);
+struct partinfo *read_info(FILE *partfile, const char *fn, struct partinfo *ir);
+
+void scandepot(void);
+void reassemble(struct partinfo **partlist, const char *outputfile);
+void mustgetpartinfo(const char *filename, struct partinfo *ri);
+void addtopartlist(struct partinfo**, struct partinfo*, struct partinfo *refi);
+
+#define PARTMAGIC "!<arch>\ndebian-split "
+#define HEADERALLOWANCE 1024
+
+#endif /* DPKG_SPLIT_H */
diff --git a/split/info.c b/split/info.c
new file mode 100644
index 000000000..fcc36d2b1
--- /dev/null
+++ b/split/info.c
@@ -0,0 +1,230 @@
+/*
+ * dpkg-split - splitting and joining of multipart *.deb archives
+ * info.c - information about split archives
+ *
+ * Copyright (C) 1995 Ian Jackson <iwj10@cus.cam.ac.uk>
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2,
+ * or (at your option) any later version.
+ *
+ * This is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with dpkg; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <assert.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <ar.h>
+#include <ctype.h>
+
+#include "config.h"
+#include "dpkg.h"
+#include "dpkg-db.h"
+#include "dpkg-split.h"
+
+static unsigned long unsignedlong(const char *value, const char *fn, const char *what) {
+ unsigned long r;
+ char *endp;
+
+ r= strtoul(value,&endp,10);
+ if (*endp)
+ ohshit("file `%.250s' is corrupt - bad digit (code %d) in %s",fn,*endp,what);
+ return r;
+}
+
+static unsigned long parseheaderlength(const char *inh, size_t len,
+ const char *fn, const char *what) {
+ char lintbuf[15];
+
+ if (memchr(inh,0,len))
+ ohshit("file `%.250s' is corrupt - %.250s length contains nulls",fn,what);
+ assert(sizeof(lintbuf) > len);
+ memcpy(lintbuf,inh,len);
+ lintbuf[len]= ' ';
+ *strchr(lintbuf,' ')= 0;
+ return unsignedlong(lintbuf,fn,what);
+}
+
+static char *nextline(char **ripp, const char *fn, const char *what) {
+ char *newline, *rip;
+
+ rip= *ripp;
+ if (!rip) ohshit("file `%.250s' is corrupt - %.250s missing",fn,what);
+ newline= strchr(rip,'\n');
+ if (!newline)
+ ohshit("file `%.250s' is corrupt - missing newline after %.250s",fn,what);
+ *ripp= newline+1;
+ while (newline > rip && isspace(newline[-1])) newline--;
+ *newline= 0;
+ return rip;
+}
+
+struct partinfo *read_info(FILE *partfile, const char *fn, struct partinfo *ir) {
+ /* returns info (nfmalloc'd) if was an archive part and we read it, 0 if it wasn't */
+ static char *readinfobuf= 0;
+ static int readinfobuflen= 0;
+
+ unsigned long thisilen, templong;
+ char magicbuf[sizeof(PARTMAGIC)-1], *rip, *partnums, *slash;
+ struct ar_hdr arh;
+ int c;
+ struct stat stab;
+
+ if (fread(magicbuf,1,sizeof(PARTMAGIC)-1,partfile) != sizeof(PARTMAGIC)-1)
+ if (ferror(partfile)) rerr(fn); else return 0;
+ if (memcmp(magicbuf,PARTMAGIC,sizeof(magicbuf))) return 0;
+ if (fseek(partfile,-sizeof(arh.ar_name),SEEK_CUR))
+ ohshite("unable to seek back");
+
+ if (fread(&arh,1,sizeof(arh),partfile) != sizeof(arh)) rerreof(partfile,fn);
+ if (memcmp(arh.ar_fmag,ARFMAG,sizeof(arh.ar_fmag)))
+ ohshit("file `%.250s' is corrupt - bad magic at end of first header",fn);
+ thisilen= parseheaderlength(arh.ar_size,sizeof(arh.ar_size),fn,"info length");
+ if (thisilen >= readinfobuflen) {
+ readinfobuflen= thisilen+1;
+ readinfobuf= m_realloc(readinfobuf,readinfobuflen);
+ }
+ if (fread(readinfobuf,1,thisilen,partfile) != thisilen) rerreof(partfile,fn);
+ if (thisilen & 1) {
+ c= getc(partfile); if (c==EOF) rerreof(partfile,fn);
+ if (c != '\n')
+ ohshit("file `%.250s' is corrupt - bad padding character (code %d)",fn,c);
+ }
+ readinfobuf[thisilen]= 0;
+ if (memchr(readinfobuf,0,thisilen))
+ ohshit("file `%.250s' is corrupt - nulls in info section",fn);
+
+ ir->filename= fn;
+
+ rip= readinfobuf;
+ ir->fmtversion= nfstrsave(nextline(&rip,fn,"format version number"));
+ if (strcmp(ir->fmtversion,SPLITVERSION))
+ ohshit("file `%.250s' is format version `%.250s' - you need a newer " SPLITTER,
+ fn,ir->fmtversion);
+
+ ir->package= nfstrsave(nextline(&rip,fn,"package name"));
+ ir->version= nfstrsave(nextline(&rip,fn,"package version number"));
+ ir->md5sum= nfstrsave(nextline(&rip,fn,"package file MD5 checksum"));
+ if (strlen(ir->md5sum) != 32 ||
+ strspn(ir->md5sum,"0123456789abcdef") != 32)
+ ohshit("file `%.250s' is corrupt - bad MD5 checksum `%.250s'",fn,ir->md5sum);
+
+ ir->orglength= unsignedlong(nextline(&rip,fn,"total length"),fn,"total length");
+ ir->maxpartlen= unsignedlong(nextline(&rip,fn,"part offset"),fn,"part offset");
+
+ partnums= nextline(&rip,fn,"part numbers");
+ slash= strchr(partnums,'/');
+ if (!slash) ohshit("file `%.250s' is corrupt - no slash between part numbers",fn);
+ *slash++= 0;
+
+ templong= unsignedlong(slash,fn,"number of parts");
+ if (templong <= 0 || templong > INT_MAX)
+ ohshit("file `%.250s' is corrupt - bad number of parts",fn);
+ ir->maxpartn= templong;
+ templong= unsignedlong(partnums,fn,"parts number");
+ if (templong <= 0 || templong > ir->maxpartn)
+ ohshit("file `%.250s' is corrupt - bad part number",fn);
+ ir->thispartn= templong;
+
+ if (fread(&arh,1,sizeof(arh),partfile) != sizeof(arh)) rerreof(partfile,fn);
+ if (memcmp(arh.ar_fmag,ARFMAG,sizeof(arh.ar_fmag)))
+ ohshit("file `%.250s' is corrupt - bad magic at end of second header",fn);
+ if (strncmp(arh.ar_name,"data",4))
+ ohshit("file `%.250s' is corrupt - second member is not data member",fn);
+
+ ir->thispartlen= parseheaderlength(arh.ar_size,sizeof(arh.ar_size),fn,"data length");
+ ir->thispartoffset= (ir->thispartn-1)*ir->maxpartlen;
+
+ if (ir->maxpartn != (ir->orglength+ir->maxpartlen-1)/ir->maxpartlen)
+ ohshit("file `%.250s' is corrupt - wrong number of parts for quoted sizes",fn);
+ if (ir->thispartlen !=
+ (ir->thispartn == ir->maxpartn
+ ? ir->orglength - ir->thispartoffset : ir->maxpartlen))
+ ohshit("file `%.250s' is corrupt - size is wrong for quoted part number",fn);
+
+ ir->filesize= (SARMAG +
+ sizeof(arh) + thisilen + (thisilen&1) +
+ sizeof(arh) + ir->thispartlen + (ir->thispartlen&1));
+
+ if (fstat(fileno(partfile),&stab)) ohshite("unable to fstat part file `%.250s'",fn);
+ if (S_ISREG(stab.st_mode)) {
+ /* Don't do this check if it's coming from a pipe or something. It's
+ * only an extra sanity check anyway.
+ */
+ if (stab.st_size < ir->filesize)
+ ohshit("file `%.250s' is corrupt - too short",fn);
+ }
+
+ ir->headerlen= SARMAG + sizeof(arh) + thisilen + (thisilen&1) + sizeof(arh);
+
+ return ir;
+}
+
+void mustgetpartinfo(const char *filename, struct partinfo *ri) {
+ FILE *part;
+
+ part= fopen(filename,"r");
+ if (!part) ohshite("cannot open archive part file `%.250s'",filename);
+ if (!read_info(part,filename,ri))
+ ohshite("file `%.250s' is not an archive part",filename);
+ fclose(part);
+}
+
+void print_info(const struct partinfo *pi) {
+ printf("%s:\n"
+ " Part format version: %s\n"
+ " Part of package: %s\n"
+ " ... version: %s\n"
+ " ... MD5 checksum: %s\n"
+ " ... length: %lu bytes\n"
+ " ... split every: %lu bytes\n"
+ " Part number: %d/%d\n"
+ " Part length: %lu bytes\n"
+ " Part offset: %lu bytes\n"
+ " Part file size (used portion): %lu bytes\n\n",
+ pi->filename,
+ pi->fmtversion,
+ pi->package,
+ pi->version,
+ pi->md5sum,
+ pi->orglength,
+ pi->maxpartlen,
+ pi->thispartn,
+ pi->maxpartn,
+ pi->thispartlen,
+ pi->thispartoffset,
+ pi->filesize);
+}
+
+void do_info(const char *const *argv) {
+ const char *thisarg;
+ struct partinfo *pi, ps;
+ FILE *part;
+
+ if (!*argv) badusage("--info requires one or more part file arguments");
+
+ while ((thisarg= *argv++)) {
+ part= fopen(thisarg,"r");
+ if (!part) ohshite("cannot open archive part file `%.250s'",thisarg);
+ pi= read_info(part,thisarg,&ps);
+ fclose(part);
+ if (pi) {
+ print_info(pi);
+ } else {
+ printf("file `%s' is not an archive part\n",thisarg);
+ }
+ if (ferror(stdout)) werr("stdout");
+ }
+}
diff --git a/split/join.c b/split/join.c
new file mode 100644
index 000000000..9e99f643b
--- /dev/null
+++ b/split/join.c
@@ -0,0 +1,134 @@
+/*
+ * dpkg-split - splitting and joining of multipart *.deb archives
+ * join.c - joining
+ *
+ * Copyright (C) 1995 Ian Jackson <iwj10@cus.cam.ac.uk>
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2,
+ * or (at your option) any later version.
+ *
+ * This is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with dpkg; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <assert.h>
+#include <string.h>
+
+#include "config.h"
+#include "dpkg.h"
+#include "dpkg-db.h"
+#include "dpkg-split.h"
+
+void reassemble(struct partinfo **partlist, const char *outputfile) {
+ FILE *output, *input;
+ void *buffer;
+ struct partinfo *pi;
+ int i,nr;
+ long buffersize;
+
+ printf("Putting package %s together from %d parts: ",
+ partlist[0]->package,partlist[0]->maxpartn);
+
+ buffersize= partlist[0]->maxpartlen;
+ for (i=0; i<partlist[0]->maxpartn; i++)
+ if (partlist[0]->headerlen > buffersize) buffersize= partlist[0]->headerlen;
+ buffer= m_malloc(partlist[0]->maxpartlen);
+ output= fopen(outputfile,"w");
+ if (!output) ohshite("unable to open output file `%.250s'",outputfile);
+ for (i=0; i<partlist[0]->maxpartn; i++) {
+ pi= partlist[i];
+ input= fopen(pi->filename,"r");
+ if (!input) ohshite("unable to (re)open input part file `%.250s'",pi->filename);
+ assert(pi->headerlen <= buffersize);
+ nr= fread(buffer,1,pi->headerlen,input);
+ if (nr != pi->headerlen) rerreof(input,pi->filename);
+ assert(pi->thispartlen <= buffersize);
+ printf("%d ",i+1);
+ nr= fread(buffer,1,pi->thispartlen,input);
+ if (nr != pi->thispartlen) rerreof(input,pi->filename);
+ if (pi->thispartlen & 1)
+ if (getc(input) == EOF) rerreof(input,pi->filename);
+ if (ferror(input)) rerr(pi->filename);
+ fclose(input);
+ nr= fwrite(buffer,1,pi->thispartlen,output);
+ if (nr != pi->thispartlen) werr(outputfile);
+ }
+ if (fclose(output)) werr(outputfile);
+ printf("done\n");
+}
+
+
+void addtopartlist(struct partinfo **partlist,
+ struct partinfo *pi, struct partinfo *refi) {
+ int i;
+
+ if (strcmp(pi->package,refi->package) ||
+ strcmp(pi->version,refi->version) ||
+ strcmp(pi->md5sum,refi->md5sum) ||
+ pi->orglength != refi->orglength ||
+ pi->maxpartn != refi->maxpartn ||
+ pi->maxpartlen != refi->maxpartlen) {
+ print_info(pi);
+ print_info(refi);
+ ohshit("files `%.250s' and `%.250s' are not parts of the same file",
+ pi->filename,refi->filename);
+ }
+ i= pi->thispartn-1;
+ if (partlist[i])
+ ohshit("there are several versions of part %d - at least `%.250s' and `%.250s'",
+ pi->thispartn, pi->filename, partlist[i]->filename);
+ partlist[i]= pi;
+}
+
+void do_join(const char *const *argv) {
+ char *p;
+ const char *thisarg;
+ struct partqueue *pq;
+ struct partinfo *refi, *pi, **partlist;
+ int i;
+
+ assert(!queue);
+ if (!*argv) badusage("--join requires one or more part file arguments");
+ while ((thisarg= *argv++)) {
+ pq= nfmalloc(sizeof(struct partqueue));
+
+ mustgetpartinfo(thisarg,&pq->info);
+
+
+ pq->nextinqueue= queue;
+ queue= pq;
+ }
+ refi= 0;
+ for (pq= queue; pq; pq= pq->nextinqueue)
+ if (!refi || pq->info.thispartn < refi->thispartn) refi= &pq->info;
+ assert(refi);
+ partlist= nfmalloc(sizeof(struct partinfo*)*refi->maxpartn);
+ for (i=0; i<refi->maxpartn; i++) partlist[i]= 0;
+ for (pq= queue; pq; pq= pq->nextinqueue) {
+ pi= &pq->info;
+ addtopartlist(partlist,pi,refi);
+ }
+ for (i=0; i<refi->maxpartn; i++) {
+ if (!partlist[i]) ohshit("part %d is missing",i+1);
+ }
+ if (!outputfile) {
+ p= nfmalloc(strlen(refi->package)+1+strlen(refi->version)+sizeof(DEBEXT));
+ strcpy(p,refi->package);
+ strcat(p,"-");
+ strcat(p,refi->version);
+ strcat(p,DEBEXT);
+ outputfile= p;
+ }
+ reassemble(partlist,outputfile);
+}
diff --git a/split/junk b/split/junk
new file mode 100644
index 000000000..d71a8cbb3
--- /dev/null
+++ b/split/junk
@@ -0,0 +1,36 @@
+ struct partqueue *backinpackage; /* circular doubly linked list of */
+ struct partqueue *nextinpackage; /* parts of a particular split file */
+ /* in ascending order of part number */
+ /* singly linked list of all files in depot */
+ pq->nextinpackage= pq->backinpackage= 0;
+
+ for (search= queue;
+ search && !(!strcmp(pq->info.md5sum,search->info.md5sum) &&
+ pq->info.maxpartlen == search->info.maxpartlen);
+ search= search->next);
+ if (search) {
+ /* insert after search */
+ while (!(search == search->nextinpackage ||
+ (search->info.thispartn < search->nextinpackage->info.thispartn ?
+ (search->info.thispartn <= pq->info.thispartn &&
+ pq->info.thispartn < search->nextinpackage->info.thispartn) :
+ (search->info.thispartn <= pq->info.thispartn ||
+ search->nextinpackage->info.thispartn > pq->info.thispartn))))
+ search= search->nextinpackage;
+ if (search->info.maxpartn != pq->info.maxpartn)
+ ohshit("inconsistency in parts depot - "
+ "md5sum `%s' part length %lu has both %d and %d parts",
+ pq->info.md5sum, pq->info.maxpartlen, pq->info.maxpartn,
+ search->info.maxpartn);
+ if (search->info.thispartn == pq->info.thispartn)
+ ohshit("inconsistency in parts depot - two instances of "
+ "md5sum `%s' part length %ld part %d/%d",
+ pq->info.md5sum, pq->info.maxpartlen, pq->info.thispartn,
+ pq->info.maxpartn);
+ pq->nextinpackage= search->nextinpackage;
+ pq->backinpackage= search;
+ pq->nextinpackage->backinpackage= pq;
+ pq->backinpackage->nextinpackage= pq;
+ } else {
+ pq->nextinpackage= pq->backinpackage= pq;
+ }
diff --git a/split/magic b/split/magic
new file mode 100644
index 000000000..b4819a651
--- /dev/null
+++ b/split/magic
@@ -0,0 +1,5 @@
+0 string !<arch> archive
+>8 string debian-binary - Debian binary package
+>8 string debian-split - part of multipart Debian package
+>8 string __.SYMDEF random library
+>8 string
diff --git a/split/main.c b/split/main.c
new file mode 100644
index 000000000..08645350f
--- /dev/null
+++ b/split/main.c
@@ -0,0 +1,176 @@
+/*
+ * dpkg-split - splitting and joining of multipart *.deb archives
+ * main.c - main program
+ *
+ * Copyright (C) 1995 Ian Jackson <iwj10@cus.cam.ac.uk>
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2,
+ * or (at your option) any later version.
+ *
+ * This is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with dpkg; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <assert.h>
+
+#include "config.h"
+#include "dpkg.h"
+#include "dpkg-db.h"
+#include "version.h"
+#include "myopt.h"
+
+#include "dpkg-split.h"
+
+static void printversion(void) {
+ if (!fputs
+ ("Debian GNU/Linux `" SPLITTER "' package archive split/join tool;\n"
+ "version " DPKG_VERSION_ARCH
+ ". Copyright (C) 1994,1995 Ian Jackson. This is free\n"
+ "software; see the GNU General Public Licence version 2 or later for copying\n"
+ "conditions. There is NO warranty. See dpkg-split --licence for details.\n",
+ stderr)) werr("stderr");
+}
+
+static void usage(void) {
+ if (!fputs("\
+Usage: " SPLITTER " -s|--split <file> [<prefix>] Split an archive.\n\
+ " SPLITTER " -j|--join <part> <part> ... Join parts together.\n\
+ " SPLITTER " -I|--info <part> ... Display info about a part.\n\
+ " SPLITTER " -h|--help|--version|--licence Show help/version/licence.\n\
+\n\
+ " SPLITTER " -a|--auto -o <complete> <part> Auto-accumulate parts.\n\
+ " SPLITTER " -l|--listq List unmatched pieces.\n\
+ " SPLITTER " -d|--discard [<filename> ...] Discard unmatched pieces.\n\
+\n\
+Options: --depotdir <directory> (default is /var/lib/dpkg/parts)\n\
+ -S|--partsize <size> (in Kb, for -s, default is 450)\n\
+ -o|--output <file> (for -j, default is <package>-<version>.deb)\n\
+ -Q|--npquiet (be quiet when -a is not a part)\n\
+ --msdos (generate 8.3 filenames)\n\
+\n\
+Exit status: 0 = OK; 1 = -a is not a part; 2 = trouble!\n",
+ stderr)) werr("stderr");
+}
+
+const char thisname[]= SPLITTER;
+const char printforhelp[]= "Type " SPLITTER " --help for help.";
+
+dofunction *action=0;
+const struct cmdinfo *cipaction=0;
+long maxpartsize= SPLITPARTDEFMAX;
+const char *depotdir= ADMINDIR "/" PARTSDIR, *outputfile= 0;
+struct partqueue *queue= 0;
+int npquiet= 0, msdos= 0;
+
+void rerr(const char *fn) {
+ ohshite("error reading %s",fn);
+}
+
+void rerreof(FILE *f, const char *fn) {
+ if (ferror(f)) ohshite("error reading %.250s",fn);
+ ohshit("unexpected end of file in %.250s",fn);
+}
+
+static void helponly(const struct cmdinfo *cip, const char *value) {
+ usage(); exit(0);
+}
+static void versiononly(const struct cmdinfo *cip, const char *value) {
+ printversion(); exit(0);
+}
+
+static void setaction(const struct cmdinfo *cip, const char *value);
+
+static void setpartsize(const struct cmdinfo *cip, const char *value) {
+ long newpartsize;
+ char *endp;
+
+ newpartsize= strtol(value,&endp,10);
+ if (newpartsize <= 0 || newpartsize > (INT_MAX >> 10))
+ badusage("part size is far too large or is not positive");
+
+ maxpartsize= newpartsize << 10;
+ if (maxpartsize <= HEADERALLOWANCE)
+ badusage("part size must be at least %dk (to allow for header)",
+ (HEADERALLOWANCE >> 10) + 1);
+}
+
+static dofunction *const dofunctions[]= {
+ do_split,
+ do_join,
+ do_info,
+ do_auto,
+ do_queue,
+ do_discard,
+};
+
+/* NB: the entries using setaction must appear first and be in the
+ * same order as dofunctions:
+ */
+static const struct cmdinfo cmdinfos[]= {
+ { "split", 's', 0, 0, 0, setaction },
+ { "join", 'j', 0, 0, 0, setaction },
+ { "info", 'I', 0, 0, 0, setaction },
+ { "auto", 'a', 0, 0, 0, setaction },
+ { "listq", 'l', 0, 0, 0, setaction },
+ { "discard", 'd', 0, 0, 0, setaction },
+ { "help", 'h', 0, 0, 0, helponly },
+ { "version", 0, 0, 0, 0, versiononly },
+ { "licence", 0, 0, 0, 0, showcopyright }, /* UK spelling */
+ { "license", 0, 0, 0, 0, showcopyright }, /* US spelling */
+ { "depotdir", 0, 1, 0, &depotdir, 0 },
+ { "partsize", 'S', 1, 0, 0, setpartsize },
+ { "output", 'o', 1, 0, &outputfile, 0 },
+ { "npquiet", 'Q', 0, &npquiet, 0, 0, 1 },
+ { "msdos", 0, 0, &msdos, 0, 0, 1 },
+ { 0, 0 }
+};
+
+static void setaction(const struct cmdinfo *cip, const char *value) {
+ if (cipaction)
+ badusage("conflicting actions --%s and --%s",cip->olong,cipaction->olong);
+ cipaction= cip;
+ assert(cip-cmdinfos < sizeof(dofunctions)*sizeof(dofunction*));
+ action= dofunctions[cip-cmdinfos];
+}
+
+int main(int argc, const char *const *argv) {
+ jmp_buf ejbuf;
+ int l;
+ char *p;
+
+ if (setjmp(ejbuf)) { /* expect warning about possible clobbering of argv */
+ error_unwind(ehflag_bombout); exit(2);
+ }
+ push_error_handler(&ejbuf,print_error_fatal,0);
+
+ myopt(&argv,cmdinfos);
+ if (!cipaction) badusage("need an action option");
+
+ l= strlen(depotdir);
+ if (l && depotdir[l-1] != '/') {
+ p= nfmalloc(l+2);
+ strcpy(p,depotdir);
+ strcpy(p+l,"/");
+ depotdir= p;
+ }
+
+ setvbuf(stdout,0,_IONBF,0);
+ action(argv);
+
+ if (ferror(stderr)) werr("stderr");
+
+ set_error_display(0,0);
+ error_unwind(ehflag_normaltidy);
+ exit(0);
+}
diff --git a/split/mksplit b/split/mksplit
new file mode 100755
index 000000000..2ed17704b
--- /dev/null
+++ b/split/mksplit
@@ -0,0 +1,88 @@
+#!/usr/bin/perl --
+# This script is only supposed to be called by dpkg-split.
+# Its arguments are:
+# <sourcefile> <partsize> <prefix> <totalsize> <partsizeallow> <msdostruncyesno>
+# Stdin is also redirected from the source archive by dpkg-split.
+
+# Copyright (C) 1995 Ian Jackson <ijackson@nyx.cs.du.edu>
+#
+# This is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2,
+# or (at your option) any later version.
+#
+# This is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public
+# License along with dpkg; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+@ARGV == 6 || die "mksplit: bad invocation\n";
+
+($sourcefile,$partsize,$prefix,$orgsize,$partsizeallow,$msdos) = @ARGV;
+
+sub output {
+ $!=0; $rv= `$_[0]`; $? && die "mksplit $_[0]: $! $?\n";
+ $rv =~ s/\n$//; $rv =~ s/\s+$//; $rv =~ s/^\s+//;
+ $rv;
+}
+
+$myversion='2.1';
+$csum= &output("md5sum <\"$sourcefile\"");
+$package= &output("dpkg-deb --field \"$sourcefile\" Package");
+$version= &output("dpkg-deb --field \"$sourcefile\" Version");
+$revision= &output("dpkg-deb --field \"$sourcefile\" Package_Revision");
+$version.= "-$revision" if length($revision);
+$nparts=int(($orgsize+$partsize-1)/$partsize);
+$startat=0;
+$showpartnum=1;
+
+$|=1;
+print("Splitting package $package into $nparts parts: ");
+
+$msdos= ($msdos eq 'yes');
+if ($msdos) {
+ $prefixdir= $prefix; $prefixdir =~ s:(/?)/*[^/]+$:$1:;
+ $cleanprefix= $prefix; $cleanprefix =~ s:^.*/+::;
+ $cleanprefix =~ y/-A-Za-z0-9+/-a-za-z0-9x/d;
+}
+
+sub add {
+ $data .=
+ sprintf("%-16s%-12d0 0 100644 %-10d%c\n%s%s",
+ $_[0], time, length($_[1]), 0140, $_[1],
+ (length($_[1]) & 1) ? "\n" : "");
+}
+
+while ($startat < $orgsize) {
+ $dsp= "$myversion\n$package\n$version\n$csum\n$orgsize\n$partsize\n".
+ "$showpartnum/$nparts\n";
+ defined($thispartreallen= read(STDIN,$pd,$partsize)) || die "mksplit: read: $!\n";
+ $data= "!<arch>\n";
+ print("$showpartnum ");
+ &add('debian-split',$dsp);
+ &add("data.$showpartnum",$pd);
+ if ($thispartreallen > $partsizeallow) {
+ die "Header is too long, making part too long. Your package name or version\n".
+ "numbers must be extraordinarily long, or something. Giving up.\n";
+ }
+ if ($msdos) {
+ $basename= "${showpartnum}of$nparts.$cleanprefix";
+ $basename= substr($basename,0,9);
+ $basename =~ s/^([^.]*)\.(.*)$/$2$1/;
+ $basename= "$prefixdir$basename";
+ } else {
+ $basename= "$prefix.${showpartnum}of$nparts";
+ }
+ open(O,"> $basename.deb") || die("mksplit: open $basename.deb: $!\n");
+ print(O $data) || die("mksplit: write $basename.deb: $!\n");
+ close(O) || die("mksplit: close $basename.deb: $!\n");
+ $startat += $partsize;
+ $showpartnum++;
+}
+print("done\n");
+
+exit(0);
diff --git a/split/mksplit.pl b/split/mksplit.pl
new file mode 100644
index 000000000..2ed17704b
--- /dev/null
+++ b/split/mksplit.pl
@@ -0,0 +1,88 @@
+#!/usr/bin/perl --
+# This script is only supposed to be called by dpkg-split.
+# Its arguments are:
+# <sourcefile> <partsize> <prefix> <totalsize> <partsizeallow> <msdostruncyesno>
+# Stdin is also redirected from the source archive by dpkg-split.
+
+# Copyright (C) 1995 Ian Jackson <ijackson@nyx.cs.du.edu>
+#
+# This is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2,
+# or (at your option) any later version.
+#
+# This is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public
+# License along with dpkg; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+@ARGV == 6 || die "mksplit: bad invocation\n";
+
+($sourcefile,$partsize,$prefix,$orgsize,$partsizeallow,$msdos) = @ARGV;
+
+sub output {
+ $!=0; $rv= `$_[0]`; $? && die "mksplit $_[0]: $! $?\n";
+ $rv =~ s/\n$//; $rv =~ s/\s+$//; $rv =~ s/^\s+//;
+ $rv;
+}
+
+$myversion='2.1';
+$csum= &output("md5sum <\"$sourcefile\"");
+$package= &output("dpkg-deb --field \"$sourcefile\" Package");
+$version= &output("dpkg-deb --field \"$sourcefile\" Version");
+$revision= &output("dpkg-deb --field \"$sourcefile\" Package_Revision");
+$version.= "-$revision" if length($revision);
+$nparts=int(($orgsize+$partsize-1)/$partsize);
+$startat=0;
+$showpartnum=1;
+
+$|=1;
+print("Splitting package $package into $nparts parts: ");
+
+$msdos= ($msdos eq 'yes');
+if ($msdos) {
+ $prefixdir= $prefix; $prefixdir =~ s:(/?)/*[^/]+$:$1:;
+ $cleanprefix= $prefix; $cleanprefix =~ s:^.*/+::;
+ $cleanprefix =~ y/-A-Za-z0-9+/-a-za-z0-9x/d;
+}
+
+sub add {
+ $data .=
+ sprintf("%-16s%-12d0 0 100644 %-10d%c\n%s%s",
+ $_[0], time, length($_[1]), 0140, $_[1],
+ (length($_[1]) & 1) ? "\n" : "");
+}
+
+while ($startat < $orgsize) {
+ $dsp= "$myversion\n$package\n$version\n$csum\n$orgsize\n$partsize\n".
+ "$showpartnum/$nparts\n";
+ defined($thispartreallen= read(STDIN,$pd,$partsize)) || die "mksplit: read: $!\n";
+ $data= "!<arch>\n";
+ print("$showpartnum ");
+ &add('debian-split',$dsp);
+ &add("data.$showpartnum",$pd);
+ if ($thispartreallen > $partsizeallow) {
+ die "Header is too long, making part too long. Your package name or version\n".
+ "numbers must be extraordinarily long, or something. Giving up.\n";
+ }
+ if ($msdos) {
+ $basename= "${showpartnum}of$nparts.$cleanprefix";
+ $basename= substr($basename,0,9);
+ $basename =~ s/^([^.]*)\.(.*)$/$2$1/;
+ $basename= "$prefixdir$basename";
+ } else {
+ $basename= "$prefix.${showpartnum}of$nparts";
+ }
+ open(O,"> $basename.deb") || die("mksplit: open $basename.deb: $!\n");
+ print(O $data) || die("mksplit: write $basename.deb: $!\n");
+ close(O) || die("mksplit: close $basename.deb: $!\n");
+ $startat += $partsize;
+ $showpartnum++;
+}
+print("done\n");
+
+exit(0);
diff --git a/split/old-mksplit.sh b/split/old-mksplit.sh
new file mode 100644
index 000000000..8743f9446
--- /dev/null
+++ b/split/old-mksplit.sh
@@ -0,0 +1,113 @@
+#!/bin/bash
+# This script is only supposed to be called by dpkg-split.
+# Its arguments are:
+# <sourcefile> <partsize> <prefix> <totalsize> <partsizeallow> <msdostruncyesno>
+# Stdin is also redirected from the source archive by dpkg-split.
+
+# Copyright (C) 1995 Ian Jackson <ijackson@nyx.cs.du.edu>
+#
+# This is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2,
+# or (at your option) any later version.
+#
+# This is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public
+# License along with dpkg; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+set -ex
+
+if [ "$#" != 6 ]; then echo >&2 'Bad invocation of mksplit.sh.'; exit 1; fi
+
+sourcefile="$1"
+partsize="$2"
+prefix="$3"
+orgsize="$4"
+partsizeallow="$5"
+msdos="$6"
+
+myversion=2.1
+csum=`md5sum <"$sourcefile"`
+package="`dpkg-deb --field \"$sourcefile\" Package`"
+version="`dpkg-deb --field \"$sourcefile\" Version`"
+revision="`dpkg-deb --field \"$sourcefile\" Package_Revision`"
+if [ "x$revision" != x ]; then version="$version-$revision"; fi
+nparts=$[($orgsize+$partsize-1)/$partsize]
+startat=0
+partnum=0
+
+td=/tmp/ds$$
+mkdir $td
+ec=1
+trap "rm -r $td; exit $ec" 0
+dsp=$td/debian-split
+
+echo -n "Splitting package $package into $nparts parts: "
+
+if [ yes = "$msdos" ]
+then
+ prefixdir="`dirname \"$prefix\"`"
+ cleanprefix="`basename \"$prefix\" | tr A-Z+ a-zx | tr -dc 0-9a-z-`"
+fi
+
+ar-include () {
+ perl -e '
+ $f= $ARGV[0];
+ (@s= stat(STDIN)) || die "$f: $!";
+ undef $/; read(STDIN,$d,$s[7]) == $s[7] || die "$f: $!";
+ printf("%-16s%-12d0 0 100644 %-10d%c\n%s%s",
+ $f, time, $s[7], 0140, $d,
+ ($s[7] & 1) ? "\n" : "") || die "$f: $!";
+ close(STDOUT) || die "$f: $!";
+ ' "$1" <"$td/$1"
+}
+
+while [ $startat -lt $orgsize ]
+do
+ showpartnum=$[$partnum+1]
+ echo $myversion >$dsp
+ echo $package >>$dsp
+ echo $version >>$dsp
+ echo $csum >>$dsp
+ echo $orgsize >>$dsp
+ echo $partsize >>$dsp
+ echo $showpartnum/$nparts >>$dsp
+ dd bs=$partsize skip=$partnum count=1 \
+ of=$td/data.$showpartnum \
+ 2>&1 | (egrep -v '.* records (in|out)' || true)
+ rm -f $td/part
+ echo -n "$showpartnum "
+ echo '!<arch>' >$td/part
+ ar-include debian-split >>$td/part
+ ar-include data.$showpartnum >>$td/part
+ thispartreallen="`ls -l $td/part | awk '{print $5}'`"
+ if ! [ "$thispartreallen" -le "$partsizeallow" ]
+ then
+ cat >&2 <<END
+
+Header is too long, making part too long. Your package name or version
+numbers must be extraordinarily long, or something. Giving up.
+END
+ exit 1
+ fi
+ if [ yes = "$msdos" ]
+ then
+ basename="`echo ${showpartnum}of$nparts.\"$cleanprefix\" | \
+ dd bs=9 count=1 2>/dev/null | \
+ sed -e 's/^\([^.]*\)\.\(.*\)$/\2\1/'`"
+ basename="$prefixdir/$basename"
+ else
+ basename="$prefix.${showpartnum}of$nparts"
+ fi
+ mv $td/part $basename.deb
+ startat=$[$startat+$partsize]
+ partnum=$showpartnum
+done
+echo "done"
+
+ec=0
diff --git a/split/queue.c b/split/queue.c
new file mode 100644
index 000000000..35d0418d1
--- /dev/null
+++ b/split/queue.c
@@ -0,0 +1,273 @@
+/*
+ * dpkg-split - splitting and joining of multipart *.deb archives
+ * queue.c - queue management
+ *
+ * Copyright (C) 1995 Ian Jackson <iwj10@cus.cam.ac.uk>
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2,
+ * or (at your option) any later version.
+ *
+ * This is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with dpkg; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * Queue, in /var/lib/dpkg/parts, is a plain directory with one
+ * file per part.
+ *
+ * parts are named
+ * <md5sum>.<maxpartlen>.<thispartn>.<maxpartn>
+ * all numbers in hex
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <assert.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <string.h>
+
+#include "config.h"
+#include "dpkg.h"
+#include "dpkg-db.h"
+#include "dpkg-split.h"
+
+static int decompose_filename(const char *filename, struct partqueue *pq) {
+ const char *p;
+ char *q;
+
+ if (strspn(filename,"0123456789abcdef") != 32 || filename[32] != '.') return 0;
+ q= nfmalloc(33);
+ memcpy(q,filename,32); q[32]= 0;
+ pq->info.md5sum= q;
+ p= filename+33;
+ pq->info.maxpartlen= strtol(p,&q,16); if (q==p || *q++ != '.') return 0;
+ p=q; pq->info.thispartn= (int)strtol(p,&q,16); if (q==p || *q++ != '.') return 0;
+ p=q; pq->info.maxpartn= (int)strtol(p,&q,16); if (q==p || *q) return 0;
+ return 1;
+}
+
+void scandepot(void) {
+ DIR *depot;
+ struct dirent *de;
+ struct partqueue *pq;
+ char *p;
+
+ assert(!queue);
+ depot= opendir(depotdir);
+ if (!depot) ohshite("unable to read depot directory `%.250s'",depotdir);
+ while ((de= readdir(depot))) {
+ if (de->d_name[0] == '.') continue;
+ pq= nfmalloc(sizeof(struct partqueue));
+ pq->info.fmtversion= pq->info.package= pq->info.version= 0;
+ pq->info.orglength= pq->info.thispartoffset= pq->info.thispartlen= 0;
+ pq->info.headerlen= 0;
+ p= nfmalloc(strlen(depotdir)+strlen(de->d_name)+1);
+ strcpy(p,depotdir);
+ strcat(p,de->d_name);
+ pq->info.filename= p;
+ if (!decompose_filename(de->d_name,pq)) {
+ pq->info.md5sum= 0;
+ pq->info.maxpartlen= pq->info.thispartn= pq->info.maxpartn= 0;
+ }
+ pq->nextinqueue= queue;
+ queue= pq;
+ }
+}
+
+static int partmatches(struct partinfo *pi, struct partinfo *refi) {
+ return (pi->md5sum &&
+ !strcmp(pi->md5sum,refi->md5sum) &&
+ pi->maxpartn == refi->maxpartn &&
+ pi->maxpartlen == refi->maxpartlen);
+}
+
+void do_auto(const char *const *argv) {
+ const char *partfile;
+ struct partinfo *pi, *refi, *npi, **partlist, *otherthispart;
+ struct partqueue *pq;
+ int i, nr, j, ap;
+ FILE *part;
+ void *buffer;
+ char *p, *q;
+
+ if (!outputfile) badusage("--auto requires the use of the --output option");
+ if (!(partfile= *argv++) || *argv)
+ badusage("--auto requires exactly one part file arguments");
+
+ refi= nfmalloc(sizeof(struct partqueue));
+ part= fopen(partfile,"r");
+ if (!part) ohshite("unable to read part file `%.250s'",partfile);
+ if (!read_info(part,partfile,refi)) {
+ if (!npquiet)
+ printf("File `%.250s' is not part of a multipart archive.\n",partfile);
+ if (fclose(stdout)) werr("stdout");
+ exit(1);
+ }
+ fclose(part);
+ scandepot();
+ partlist= nfmalloc(sizeof(struct partinfo*)*refi->maxpartn);
+ for (i=0; i<refi->maxpartn; i++) partlist[i]= 0;
+ for (pq= queue; pq; pq= pq->nextinqueue) {
+ pi= &pq->info;
+ if (!partmatches(pi,refi)) continue;
+ npi= nfmalloc(sizeof(struct partinfo));
+ mustgetpartinfo(pi->filename,npi);
+ addtopartlist(partlist,npi,refi);
+ }
+ /* If we already have a copy of this version we ignore it and prefer the
+ * new one, but we still want to delete the one in the depot, so we
+ * save its partinfo (with the filename) for later. This also prevents
+ * us from accidentally deleting the source file.
+ */
+ otherthispart= partlist[refi->thispartn-1];
+ partlist[refi->thispartn-1]= refi;
+ for (j=refi->maxpartn-1; j>=0 && partlist[j]; j--);
+
+ if (j>=0) {
+
+ part= fopen(partfile,"r");
+ if (!part) ohshite("unable to reopen part file `%.250s'",partfile);
+ buffer= nfmalloc(refi->filesize);
+ nr= fread(buffer,1,refi->filesize,part);
+ if (nr != refi->filesize) rerreof(part,partfile);
+ if (getc(part) != EOF) ohshit("part file `%.250s' has trailing garbage",partfile);
+ if (ferror(part)) rerr(partfile);
+ fclose(part);
+ p= nfmalloc(strlen(depotdir)+50);
+ q= nfmalloc(strlen(depotdir)+200);
+ sprintf(p,"%st.%lx",depotdir,(long)getpid());
+ sprintf(q,"%s%s.%lx.%x.%x",depotdir,refi->md5sum,
+ refi->maxpartlen,refi->thispartn,refi->maxpartn);
+ part= fopen(p,"w");
+ if (!part) ohshite("unable to open new depot file `%.250s'",p);
+ nr= fwrite(buffer,1,refi->filesize,part);
+ if (nr != refi->filesize) werr(p);
+ if (fclose(part)) werr(p);
+ if (rename(p,q)) ohshite("unable to rename new depot file `%.250s' to `%.250s'",p,q);
+
+ printf("Part %d of package %s filed (still want ",refi->thispartn,refi->package);
+ /* There are still some parts missing. */
+ for (i=0, ap=0; i<refi->maxpartn; i++)
+ if (!partlist[i])
+ printf("%s%d", !ap++ ? "" : i==j ? " and " : ", ", i+1);
+ printf(").\n");
+
+ } else {
+
+ /* We have all the parts. */
+ reassemble(partlist,outputfile);
+
+ /* OK, delete all the parts (except the new one, which we never copied). */
+ partlist[refi->thispartn-1]= otherthispart;
+ for (i=0; i<refi->maxpartn; i++)
+ if (partlist[i])
+ if (unlink(partlist[i]->filename))
+ ohshite("unable to delete used-up depot file `%.250s'",partlist[i]->filename);
+
+ }
+
+ if (ferror(stderr)) werr("stderr");
+}
+
+void do_queue(const char *const *argv) {
+ struct partqueue *pq, *qq;
+ struct partinfo ti;
+ const char *head;
+ struct stat stab;
+ unsigned long bytes;
+ int i;
+
+ if (*argv) badusage("--listq does not take any arguments");
+ scandepot();
+
+ head= "Junk files left around in the depot directory:\n";
+ for (pq= queue; pq; pq= pq->nextinqueue) {
+ if (pq->info.md5sum) continue;
+ fputs(head,stdout); head= "";
+ if (lstat(pq->info.filename,&stab))
+ ohshit("unable to stat `%.250s'",pq->info.filename);
+ if (S_ISREG(stab.st_mode)) {
+ bytes= stab.st_size;
+ printf(" %s (%lu bytes)\n",pq->info.filename,bytes);
+ } else {
+ printf(" %s (not a plain file)\n",pq->info.filename);
+ }
+ }
+ if (!*head) putchar('\n');
+
+ head= "Packages not yet reassembled:\n";
+ for (pq= queue; pq; pq= pq->nextinqueue) {
+ if (!pq->info.md5sum) continue;
+ mustgetpartinfo(pq->info.filename,&ti);
+ fputs(head,stdout); head= "";
+ printf(" Package %s: part(s) ",ti.package);
+ bytes= 0;
+ for (i=0; i<ti.maxpartn; i++) {
+ for (qq= pq;
+ qq && !(partmatches(&qq->info,&ti) && qq->info.thispartn == i+1);
+ qq= qq->nextinqueue);
+ if (qq) {
+ printf("%d ",i+1);
+ if (lstat(qq->info.filename,&stab))
+ ohshite("unable to stat `%.250s'",qq->info.filename);
+ if (!S_ISREG(stab.st_mode))
+ ohshit("part file `%.250s' is not a plain file",qq->info.filename);
+ bytes+= stab.st_size;
+ qq->info.md5sum= 0; /* don't find this package again */
+ }
+ }
+ printf("(total %lu bytes)\n",bytes);
+ }
+ if (fclose(stdout)) werr("stdout");
+}
+
+enum discardwhich { ds_junk, ds_package, ds_all };
+
+static void discardsome(enum discardwhich which, const char *package) {
+ struct partqueue *pq;
+
+ for (pq= queue; pq; pq= pq->nextinqueue) {
+ switch (which) {
+ case ds_junk:
+ if (pq->info.md5sum) continue;
+ break;
+ case ds_package:
+ if (!pq->info.md5sum || strcasecmp(pq->info.package,package)) continue;
+ break;
+ case ds_all:
+ break;
+ default: internerr("bad discardsome which");
+ }
+ if (unlink(pq->info.filename))
+ ohshite("unable to discard `%.250s'",pq->info.filename);
+ printf("Deleted %s.\n",pq->info.filename);
+ }
+}
+
+void do_discard(const char *const *argv) {
+ const char *thisarg;
+ struct partqueue *pq;
+
+ scandepot();
+ if (*argv) {
+ for (pq= queue; pq; pq= pq->nextinqueue)
+ if (pq->info.md5sum)
+ mustgetpartinfo(pq->info.filename,&pq->info);
+ discardsome(ds_junk,0);
+ while ((thisarg= *argv++)) discardsome(ds_package,thisarg);
+ } else {
+ discardsome(ds_all,0);
+ }
+}
diff --git a/split/split.c b/split/split.c
new file mode 100644
index 000000000..facdeb0e5
--- /dev/null
+++ b/split/split.c
@@ -0,0 +1,71 @@
+/*
+ * dpkg-split - splitting and joining of multipart *.deb archives
+ * split.c - splitting archives
+ *
+ * Copyright (C) 1995 Ian Jackson <iwj10@cus.cam.ac.uk>
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2,
+ * or (at your option) any later version.
+ *
+ * This is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with dpkg; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <assert.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "config.h"
+#include "dpkg.h"
+#include "dpkg-db.h"
+#include "dpkg-split.h"
+
+void do_split(const char *const *argv) {
+ const char *sourcefile, *prefix;
+ char *palloc;
+ int l, fd;
+ char partsizebuf[30], lengthbuf[30], partsizeallowbuf[30];
+ struct stat stab;
+
+ sourcefile= *argv++;
+ if (!sourcefile)
+ badusage("--split needs a source filename argument");
+ prefix= *argv++;
+ if (prefix && *argv)
+ badusage("--split takes at most a source filename and destination prefix");
+ if (!prefix) {
+ l= strlen(sourcefile);
+ palloc= nfmalloc(l+1);
+ strcpy(palloc,sourcefile);
+ if (!strcmp(palloc+l-(sizeof(DEBEXT)-1),DEBEXT)) {
+ l -= (sizeof(DEBEXT)-1);
+ palloc[l]= 0;
+ }
+ prefix= palloc;
+ }
+ sprintf(partsizebuf,"%ld",maxpartsize-HEADERALLOWANCE);
+ sprintf(partsizeallowbuf,"%ld",maxpartsize);
+ fd= open(sourcefile,O_RDONLY);
+ if (!fd) ohshite("unable to open source file `%.250s'",sourcefile);
+ if (fstat(fd,&stab)) ohshite("unable to fstat source file");
+ if (!S_ISREG(stab.st_mode)) ohshit("source file `%.250s' not a plain file",sourcefile);
+ sprintf(lengthbuf,"%lu",(unsigned long)stab.st_size);
+ m_dup2(fd,0);
+ execl(MKSPLITSCRIPT,MKSPLITSCRIPT,
+ sourcefile,partsizebuf,prefix,lengthbuf,partsizeallowbuf,msdos?"yes":"no",
+ (char*)0);
+ ohshite("unable to exec " MKSPLITSCRIPT);
+}