diff options
Diffstat (limited to 'split')
-rw-r--r-- | split/Makefile.in | 80 | ||||
-rwxr-xr-x | split/debugmake | 3 | ||||
-rw-r--r-- | split/dpkg-split.8 | 19 | ||||
-rw-r--r-- | split/dpkg-split.h | 72 | ||||
-rw-r--r-- | split/info.c | 230 | ||||
-rw-r--r-- | split/join.c | 134 | ||||
-rw-r--r-- | split/junk | 36 | ||||
-rw-r--r-- | split/magic | 5 | ||||
-rw-r--r-- | split/main.c | 176 | ||||
-rwxr-xr-x | split/mksplit | 88 | ||||
-rw-r--r-- | split/mksplit.pl | 88 | ||||
-rw-r--r-- | split/old-mksplit.sh | 113 | ||||
-rw-r--r-- | split/queue.c | 273 | ||||
-rw-r--r-- | split/split.c | 71 |
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); +} |