[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

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: