Bug#34727: bzip support for dpkg
Package: dpkg
Version: 1.4.x
Enclosed is a patch from Richard Kettlewell to support bzip etc. in
dpkg-deb. I might well include it some day.
Ian.
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="arrangements-arrangements-zEW80kTM7+bJD8+h"
Content-Transfer-Encoding: 7bit
Return-path: <richard@greenend.org.uk>
Envelope-to: ian@davenant.greenend.org.uk
Delivery-date: Tue, 16 Mar 1999 23:38:34 +0000
Received: from (sfere.greenend.org.uk) [172.18.45.1]
by davenant.greenend.org.uk with esmtp (Exim 1.92 #1)
id 10N3Pt-00006p-00 (Debian); Tue, 16 Mar 1999 23:38:33 +0000
Received: from richard by sfere.greenend.org.uk with local (Exim 2.02 #1 (Debian))
id 10N3Cu-0005pK-00; Tue, 16 Mar 1999 23:25:08 +0000
Message-Id: <Pine.just.say.no.cSXKxk47-9@sfere.greenend.org.uk>
X-Mailer: VM 6.30 under 20.4 "Emerald" XEmacs Lucid
X-UIDL: 5785906d52f7032c9586e24ff71d2d05
From: Richard Kettlewell <rjk@greenend.org.uk>
To: ian@davenant.greenend.org.uk
Subject: diff against dpkg
Date: Tue, 16 Mar 99 23:25:08 +0000 (GMT)
--arrangements-arrangements-zEW80kTM7+bJD8+h
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Attached is my first cut at a diff. I've built `hello' and got
dpkg-deb to understand the resulting package. All of the changes bar
a couple of lines are to dpkg-deb.
When you build a package you can specify how it is compressed, with
considerable freedom. The options to play with are documented in
dpkg-deb.1.
However when you extract a package, you have no freedom at all: the
appropriate action is deduced from the archive member names. It knows
about gzip, bzip and bzip2 (bzip support not tested yet).
Iff the compression extensions is such that `control.tar.<ext>' is too
long, dpkg-deb will use `ctrl.tar.<ext>' when building. It will
recognize either of `control.tar.<ext>' and `ctrl.tar.<ext>' when
extracting, however.
I'll try some performance testing at another time.
ttfn/rjk
--arrangements-arrangements-zEW80kTM7+bJD8+h
Content-Type: text/plain
Content-Disposition: inline;
filename="diff"
Content-Transfer-Encoding: 7bit
Index: dpkg/dpkg-deb/build.c
===================================================================
RCS file: /usr/src/CVS/dpkg/dpkg-deb/build.c,v
retrieving revision 1.2
diff -u -r1.2 build.c
--- build.c 1999/03/02 23:17:33 1.2
+++ build.c 1999/03/16 23:16:16
@@ -68,7 +68,13 @@
struct stat controlstab, datastab, mscriptstab, debarstab;
char conffilename[MAXCONFFILENAME+1];
time_t thetime= 0;
+ char adminmembername[17], datamembername[17];
+ /* use the old-style names if possible, but use the shorter control
+ member name if necessary */
+ if(strlen(compressext) > 2) sprintf(adminmembername, "ctrl.tar.%-7s", compressext);
+ else sprintf(adminmembername, "control.tar.%-4s", compressext);
+ sprintf(datamembername, "data.tar.%-7s", compressext);
directory= *argv++; if (!directory) badusage("--build needs a directory argument");
subdir= 0;
if ((debar= *argv++) !=0) {
@@ -211,10 +217,10 @@
if (!(gz= tmpfile())) ohshite("failed to make tmpfile (control)");
if (!(c2= m_fork())) {
m_dup2(p1[0],0); m_dup2(fileno(gz),1); close(p1[0]);
- execlp(GZIP,"gzip","-9c",(char*)0); ohshite("failed to exec gzip -9c");
+ execlp(compressname,compressname,compressflags,(char*)0); ohshite("failed to exec %s %s", compressname, compressflags);
}
close(p1[0]);
- waitsubproc(c2,"gzip -9c",0);
+ waitsubproc(c2,compressname,0);
waitsubproc(c1,"tar -cf",0);
if (fstat(fileno(gz),&controlstab)) ohshite("failed to fstat tmpfile (control)");
if (oldformatflag) {
@@ -227,9 +233,10 @@
"debian-binary %-12lu0 0 100644 %-10ld`\n"
ARCHIVEVERSION "\n"
"%s"
- ADMINMEMBER "%-12lu0 0 100644 %-10ld`\n",
+ "%s%-12lu0 0 100644 %-10ld`\n",
thetime,
(long)sizeof(ARCHIVEVERSION),
+ adminmembername,
(sizeof(ARCHIVEVERSION)&1) ? "\n" : "",
(unsigned long)thetime,
(long)controlstab.st_size) == EOF)
@@ -258,18 +265,19 @@
if (!(c5= m_fork())) {
m_dup2(p2[0],0); close(p2[0]);
m_dup2(oldformatflag ? fileno(ar) : fileno(gz),1);
- execlp(GZIP,"gzip","-9c",(char*)0);
- ohshite("failed to exec gzip -9c from tar --exclude");
+ execlp(compressname,compressname,compressflags,(char*)0);
+ ohshite("failed to exec %s %s from tar --exclude", compressname, compressflags);
}
close(p2[0]);
- waitsubproc(c5,"gzip -9c from tar --exclude",0);
+ waitsubproc(c5,"compress from tar --exclude",0);
waitsubproc(c4,"tar --exclude",0);
if (!oldformatflag) {
if (fstat(fileno(gz),&datastab)) ohshite("failed to fstat tmpfile (data)");
if (fprintf(ar,
"%s"
- DATAMEMBER "%-12lu0 0 100644 %-10ld`\n",
+ "%s%-12lu0 0 100644 %-10ld`\n",
(controlstab.st_size & 1) ? "\n" : "",
+ datamembername,
(unsigned long)thetime,
(long)datastab.st_size) == EOF)
werr(debar);
Index: dpkg/dpkg-deb/dpkg-deb.1
===================================================================
RCS file: /usr/src/CVS/dpkg/dpkg-deb/dpkg-deb.1,v
retrieving revision 1.1
diff -u -r1.1 dpkg-deb.1
--- dpkg-deb.1 1998/10/25 22:24:28 1.1
+++ dpkg-deb.1 1999/03/16 23:16:16
@@ -211,8 +211,24 @@
usual checks on the proposed contents of an archive. You can build
any archive you want, no matter how broken, this way.
.TP
+.BR --compress
+Specify the program to use to compress archive members. The default
+is "gzip".
+.TP
+.BR --compress-flags
+Specify the option argument to the compression program. The default
+is "-9c", suitable for gzip.
+.TP
+.BR --compress-ext
+Specifty the extension to use for compressed data, excluding the
+initial ".". The default is "gz".
+.TP
.BR --debug ", " -D
Enables debugging output. This is not very interesting.
+.PP
+Note that there is no way to specify the compression program to use
+for extraction - this is deduced from the names in the archive and the
+relevant information is compiled into the program.
.SH BUGS
.B dpkg-deb -I
.IB package1 .deb
Index: dpkg/dpkg-deb/dpkg-deb.h
===================================================================
RCS file: /usr/src/CVS/dpkg/dpkg-deb/dpkg-deb.h,v
retrieving revision 1.1
diff -u -r1.1 dpkg-deb.h
--- dpkg-deb.h 1998/10/25 22:24:30 1.1
+++ dpkg-deb.h 1999/03/16 23:16:16
@@ -29,12 +29,13 @@
extern int debugflag, nocheckflag, oldformatflag;
extern const struct cmdinfo *cipaction;
extern dofunction *action;
+extern const char *compressname;
+extern const char *compressflags;
+extern const char *compressext;
void extracthalf(const char *debar, const char *directory,
const char *taroption, int admininfo);
#define DEBMAGIC "!<arch>\ndebian-binary "
-#define ADMINMEMBER "control.tar.gz "
-#define DATAMEMBER "data.tar.gz "
#endif /* DPKG_DEB_H */
Index: dpkg/dpkg-deb/extract.c
===================================================================
RCS file: /usr/src/CVS/dpkg/dpkg-deb/extract.c,v
retrieving revision 1.1
diff -u -r1.1 extract.c
--- extract.c 1998/10/25 22:24:30 1.1
+++ extract.c 1999/03/16 23:16:17
@@ -39,6 +39,31 @@
#include "dpkg-deb.h"
#include "myopt.h"
+/* valid member name stems (excluding only a suffix to indicate the
+ kind of compression employed */
+
+static const char *validstems[] = {
+ "control.tar",
+ "ctrl.tar",
+ "data.tar",
+ 0
+};
+
+/* table of rules for decompressing data. If a program requires more
+ than 1 argv entry for correct use with dpkg then you must either
+ fix the program or fix dpkg. */
+
+static struct decompressrule {
+ const char *extension; /* extension INCLUDING the dot */
+ const char *program; /* program to decompress */
+ const char *options; /* flags to decompressor */
+} decompressrules[] = {
+ { ".gz", "gzip", "-dc" },
+ { ".bz", "bzip", "-d" },
+ { ".bz2", "bzip2", "-d" },
+ { 0 }
+};
+
static void movecontrolfiles(const char *thing) {
char buf[200];
pid_t c1;
@@ -102,6 +127,10 @@
char *cur;
struct ar_hdr arh;
int readfromfd, oldformat, header_done, adminmember, c;
+ char membername[sizeof(arh.ar_name) + 1];
+ int i, j;
+ struct decompressrule *dc_rule = 0;
+ size_t mnlen;
ar= fopen(debar,"r"); if (!ar) ohshite("failed to read archive `%.255s'",debar);
if (fstat(fileno(ar),&stab)) ohshite("failed to fstat archive");
@@ -146,10 +175,27 @@
*/
skipmember(ar,debar,memberlen);
} else {
- adminmember=
- !memcmp(arh.ar_name,ADMINMEMBER,sizeof(arh.ar_name)) ? 1 :
- !memcmp(arh.ar_name,DATAMEMBER,sizeof(arh.ar_name)) ? 0 :
- -1;
+ /* we compare for {control,ctrl,data}.tar.<ext> for some
+ extension that we know about. It's complicated slightly by
+ the fact that the names are padded with spaces rather than
+ terminated with \0. */
+ adminmember = -1;
+ for(i = 0; validstems[i]; i++)
+ for(j = 0; decompressrules[j].extension; j++) {
+ if(strlen(validstems[i])
+ + strlen(decompressrules[j].extension) >= sizeof(arh.ar_name))
+ continue;
+ mnlen = sprintf(membername, "%s%s",
+ validstems[i], decompressrules[j].extension);
+ memset(membername+mnlen, ' ', sizeof(arh.ar_name) - mnlen);
+ if(!memcmp(arh.ar_name,membername,sizeof(arh.ar_name))) {
+ if(dc_rule && dc_rule != &decompressrules[j])
+ ohshite("file `%.250s' uses inconsistent compression conventions", debar);
+ dc_rule = &decompressrules[j];
+ adminmember = (validstems[i][0] == 'c');
+ break;
+ }
+ }
if (adminmember == -1) {
ohshit("file `%.250s' contains ununderstood data member %.*s, giving up",
debar, (int)sizeof(arh.ar_name), arh.ar_name);
@@ -195,7 +241,8 @@
errno=0; if (fread(ctrlarea,1,ctrllennum,ar) != ctrllennum)
readfail(ar,debar,"ctrlarea");
-
+ dc_rule = &decompressrules[0];
+
} else {
if (!strncmp(versionbuf,"!<arch>",7)) {
@@ -208,6 +255,7 @@
ohshit("`%.255s' is not a debian format archive",debar);
}
+ assert(dc_rule);
fflush(ar);
if (oldformat) {
@@ -217,8 +265,8 @@
close(p1[0]);
if (!(pi= fdopen(p1[1],"w"))) ohshite("failed to fdopen p1 in paste");
errno=0; if (fwrite(ctrlarea,1,ctrllennum,pi) != ctrllennum)
- ohshit("failed to write to gzip -dc");
- if (fclose(pi)) ohshit("failed to close gzip -dc");
+ ohshit("failed to write to %s %s", dc_rule->program, dc_rule->options);
+ if (fclose(pi)) ohshit("failed to close %s %s", dc_rule->program, dc_rule->options);
exit(0);
}
close(p1[1]);
@@ -252,7 +300,7 @@
m_dup2(readfromfd,0);
if (admininfo) close(p1[0]);
if (taroption) { m_dup2(p2[1],1); close(p2[0]); close(p2[1]); }
- execlp(GZIP,"gzip","-dc",(char*)0); ohshite("failed to exec gzip -dc");
+ execlp(dc_rule->program,dc_rule->program,dc_rule->options,(char*)0); ohshite("failed to exec %s %s",dc_rule->program,dc_rule->program);
}
if (readfromfd != fileno(ar)) close(readfromfd);
close(p2[1]);
@@ -282,7 +330,7 @@
waitsubproc(c3,"tar",0);
}
- waitsubproc(c2,"gzip -dc",1);
+ waitsubproc(c2,dc_rule->program,1);
if (c1 != -1) waitsubproc(c1,"paste",0);
if (oldformat && admininfo) {
if (versionnum == 0.931F) {
Index: dpkg/dpkg-deb/main.c
===================================================================
RCS file: /usr/src/CVS/dpkg/dpkg-deb/main.c,v
retrieving revision 1.2
diff -u -r1.2 main.c
--- main.c 1999/03/13 14:13:10 1.2
+++ main.c 1999/03/16 23:16:17
@@ -32,6 +32,7 @@
#include <limits.h>
#include <ctype.h>
#include <assert.h>
+#include <locale.h>
#include "config.h"
#include "dpkg.h"
@@ -65,6 +66,8 @@
<cfield> is the name of a field in the main `control' file.\n\
Options: -D for debugging output; --old or --new controls archive format;\n\
--no-check to suppress control file check (build bad package).\n\
+ --compress to set compression program, --compress-flags to set\n\
+ flags; the compressed file extension is set with --compress-ext.\n\
\n\
Use `" DPKG "' to install and remove packages from your system, or\n\
`" DSELECT "' for user-friendly package management. Packages unpacked\n\
@@ -81,6 +84,10 @@
const struct cmdinfo *cipaction=0;
dofunction *action=0;
+const char *compressname = "gzip";
+const char *compressflags = "-9c";
+const char *compressext = "gz";
+
static void helponly(const struct cmdinfo *cip, const char *value) {
usage(); exit(0);
}
@@ -121,6 +128,9 @@
{ "version", 0, 0, 0, 0, versiononly },
{ "licence", 0, 0, 0, 0, showcopyright }, /* UK spelling */
{ "license", 0, 0, 0, 0, showcopyright }, /* US spelling */
+ { "compress", 0, 1, 0, &compressname, 0 },
+ { "compress-flags",0, 1, 0, &compressflags, 0 },
+ { "compress-ext", 0, 1, 0, &compressext, 0 },
{ 0, 0 }
};
@@ -144,6 +154,7 @@
myopt(&argv,cmdinfos);
if (!cipaction) badusage("need an action option");
+ if(strlen(compressext) > 4) badusage("compression extension too long");
unsetenv("GZIP");
action(argv);
Index: dpkg/main/main.c
===================================================================
RCS file: /usr/src/CVS/dpkg/main/main.c,v
retrieving revision 1.1
diff -u -r1.1 main.c
--- main.c 1998/10/25 22:25:42 1.1
+++ main.c 1999/03/16 23:16:18
@@ -281,7 +281,8 @@
static const char *const passlongopts[]= {
"build", "contents", "control", "info", "field", "extract", "new", "old",
- "vextract", "fsys-tarfile", 0
+ "vextract", "fsys-tarfile", "compress", "compress-flags", "compress-ext",
+ 0
};
static const char passshortopts[]= "bceIfxX";
--arrangements-arrangements-zEW80kTM7+bJD8+h--
Reply to: