Browse Source

Switch deb format version handling to use the new deb-version module

This simplifies the parsing and checking and avoids having to treat the
format versions as floats, which can cause parse errors depending on the
locale (this only affected the old deb format).
Guillem Jover 12 years ago
parent
commit
c13a013fd8
6 changed files with 62 additions and 41 deletions
  1. 0 1
      TODO
  2. 3 0
      debian/changelog
  3. 39 32
      dpkg-deb/extract.c
  4. 4 1
      dpkg-split/dpkg-split.h
  5. 11 6
      dpkg-split/info.c
  6. 5 1
      dpkg-split/queue.c

+ 0 - 1
TODO

@@ -40,7 +40,6 @@ TODO
    - Add needed includes to all header files.
    - Get rid of unuseful "unsigned" modifiers.
    - Use internerr instead of assert, and print more meaninful messages.
-   - Make deb build version a version instead of doing checks over a string.
    - Use enums for currently hardcoded literals (replacingfilesandsaid,
      saidread, rok, filetriggers_edited, etc).
    - Do not use nfmalloc (and friends) for non in-core db memory.

+ 3 - 0
debian/changelog

@@ -22,6 +22,9 @@ dpkg (1.16.3) UNRELEASED; urgency=low
   * Change start-stop-daemon --name on GNU/Hurd to check the process' argv[1]
     in addition to argv[0], to handle both binaries and interpreted scripts.
     Reported by Mats Erik Andersson <mats.andersson@gisladisker.se>.
+  * Handle deb format versions as major.minor integers instead of strings or
+    floats, the latter being susceptible to parsing errors depending on the
+    current locale (although this was only affecting the old deb format).
 
   [ Helge Kreutzmann ]
   * Fix a typo in man/dpkg-buildflags.1.

+ 39 - 32
dpkg-deb/extract.c

@@ -3,6 +3,7 @@
  * extract.c - extracting archives
  *
  * Copyright © 1994,1995 Ian Jackson <ian@chiark.greenend.org.uk>
+ * Copyright © 2006-2012 Guillem Jover <guillem@debian.org>
  *
  * This is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -47,6 +48,7 @@
 #include <dpkg/command.h>
 #include <dpkg/compress.h>
 #include <dpkg/ar.h>
+#include <dpkg/deb-version.h>
 #include <dpkg/options.h>
 
 #include "dpkg-deb.h"
@@ -105,8 +107,9 @@ void
 extracthalf(const char *debar, const char *dir, const char *taroption,
             int admininfo)
 {
+  const char *err;
   char versionbuf[40];
-  float versionnum;
+  struct deb_version version;
   off_t ctrllennum, memberlen = 0;
   ssize_t r;
   int dummy;
@@ -117,7 +120,7 @@ extracthalf(const char *debar, const char *dir, const char *taroption,
   struct stat stab;
   char nlc;
   int adminmember;
-  bool oldformat, header_done;
+  bool header_done;
   enum compressor_type decompressor = compressor_type_gzip;
 
   arfd = open(debar, O_RDONLY);
@@ -131,8 +134,6 @@ extracthalf(const char *debar, const char *dir, const char *taroption,
     read_fail(r, debar, _("archive magic version number"));
 
   if (strcmp(versionbuf, DPKG_AR_MAGIC) == 0) {
-    oldformat = false;
-
     ctrllennum= 0;
     header_done = false;
     for (;;) {
@@ -149,7 +150,6 @@ extracthalf(const char *debar, const char *dir, const char *taroption,
       memberlen = dpkg_ar_member_get_size(debar, &arh);
       if (!header_done) {
         char *infobuf;
-        char *cur;
 
         if (strncmp(arh.ar_name, DEBMAGIC, sizeof(arh.ar_name)) != 0)
           ohshit(_("file `%.250s' is not a debian binary archive (try dpkg-split?)"),debar);
@@ -158,17 +158,16 @@ extracthalf(const char *debar, const char *dir, const char *taroption,
         if (r != (memberlen + (memberlen & 1)))
           read_fail(r, debar, _("archive information header member"));
         infobuf[memberlen] = '\0';
-        cur= strchr(infobuf,'\n');
-        if (!cur) ohshit(_("archive has no newlines in header"));
-        *cur = '\0';
-        cur= strchr(infobuf,'.');
-        if (!cur) ohshit(_("archive has no dot in version number"));
-        *cur = '\0';
-        if (strcmp(infobuf,"2"))
-          ohshit(_("archive version %.250s not understood, get newer dpkg-deb"), infobuf);
-        *cur= '.';
-        strncpy(versionbuf,infobuf,sizeof(versionbuf));
-        versionbuf[sizeof(versionbuf) - 1] = '\0';
+
+        if (strchr(infobuf, '\n') == NULL)
+          ohshit(_("archive has no newlines in header"));
+        err = deb_version_parse(&version, infobuf);
+        if (err)
+          ohshit(_("archive has invalid format version: %s"), err);
+        if (version.major != 2)
+          ohshit(_("archive is format version %d.%d; get a newer dpkg-deb"),
+                 version.major, version.minor);
+
         free(infobuf);
 
         header_done = true;
@@ -211,21 +210,23 @@ extracthalf(const char *debar, const char *dir, const char *taroption,
     }
 
     if (admininfo >= 2) {
-      printf(_(" new debian package, version %s.\n"
-               " size %jd bytes: control archive= %jd bytes.\n"),
-             versionbuf, (intmax_t)stab.st_size, (intmax_t)ctrllennum);
+      printf(_(" new debian package, version %d.%d.\n"
+               " size %jd bytes: control archive=%jd bytes.\n"),
+             version.major, version.minor,
+             (intmax_t)stab.st_size, (intmax_t)ctrllennum);
       m_output(stdout, _("<standard output>"));
     }
-  } else if (strncmp(versionbuf, "0.93", 4) == 0 &&
-             sscanf(versionbuf,"%f%c%d",&versionnum,&nlc,&dummy) == 2 &&
-             nlc == '\n') {
+  } else if (strncmp(versionbuf, "0.93", 4) == 0) {
     char ctrllenbuf[40];
     int l = 0;
 
-    oldformat = true;
     l = strlen(versionbuf);
-    if (l && versionbuf[l - 1] == '\n')
-      versionbuf[l - 1] = '\0';
+
+    if (strchr(versionbuf, '\n') == NULL)
+      ohshit(_("archive has no newlines in header"));
+    err = deb_version_parse(&version, versionbuf);
+    if (err)
+      ohshit(_("archive has invalid format version: %s"), err);
 
     r = read_line(arfd, ctrllenbuf, 1, sizeof(ctrllenbuf));
     if (r < 0)
@@ -243,9 +244,10 @@ extracthalf(const char *debar, const char *dir, const char *taroption,
     }
 
     if (admininfo >= 2) {
-      printf(_(" old debian package, version %s.\n"
-               " size %jd bytes: control archive= %jd, main archive= %jd.\n"),
-             versionbuf, (intmax_t)stab.st_size, (intmax_t)ctrllennum,
+      printf(_(" old debian package, version %d.%d.\n"
+               " size %jd bytes: control archive=%jd, main archive=%jd.\n"),
+             version.major, version.minor,
+             (intmax_t)stab.st_size, (intmax_t)ctrllennum,
              (intmax_t)(stab.st_size - ctrllennum - strlen(ctrllenbuf) - l));
       m_output(stdout, _("<standard output>"));
     }
@@ -323,12 +325,17 @@ extracthalf(const char *debar, const char *dir, const char *taroption,
   subproc_wait_check(c2, _("<decompress>"), PROCPIPE);
   if (c1 != -1)
     subproc_wait_check(c1, _("paste"), 0);
-  if (oldformat && admininfo) {
-    if (versionnum == 0.931F) {
+  if (version.major == 0 && admininfo) {
+    /* Handle the version as a float to preserve the behaviour of old code,
+     * because even if the format is defined to be padded by 0's that might
+     * not have been always true for really ancient versions... */
+    while (version.minor && (version.minor % 10) == 0)
+      version.minor /= 10;
+
+    if (version.minor ==  931)
       movecontrolfiles(OLDOLDDEBDIR);
-    } else if (versionnum == 0.932F || versionnum == 0.933F) {
+    else if (version.minor == 932 || version.minor == 933)
       movecontrolfiles(OLDDEBDIR);
-    }
   }
 }
 

+ 4 - 1
dpkg-split/dpkg-split.h

@@ -3,6 +3,7 @@
  * dpkg-split.h - external definitions for this program
  *
  * Copyright © 1995 Ian Jackson <ian@chiark.greenend.org.uk>
+ * Copyright © 2008-2012 Guillem Jover <guillem@debian.org>
  *
  * This is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -21,6 +22,8 @@
 #ifndef DPKG_SPLIT_H
 #define DPKG_SPLIT_H
 
+#include <dpkg/deb-version.h>
+
 action_func do_split;
 action_func do_join;
 action_func do_info;
@@ -29,8 +32,8 @@ action_func do_queue;
 action_func do_discard;
 
 struct partinfo {
+  struct deb_version fmtversion;
   const char *filename;
-  const char *fmtversion;
   const char *package;
   const char *version;
   const char *arch;

+ 11 - 6
dpkg-split/info.c

@@ -3,6 +3,7 @@
  * info.c - information about split archives
  *
  * Copyright © 1995 Ian Jackson <ian@chiark.greenend.org.uk>
+ * Copyright © 2008-2012 Guillem Jover <guillem@debian.org>
  *
  * This is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -80,6 +81,7 @@ struct partinfo *read_info(FILE *partfile, const char *fn, struct partinfo *ir)
   size_t thisilen;
   intmax_t templong;
   char magicbuf[sizeof(DPKG_AR_MAGIC) - 1], *rip, *partnums, *slash;
+  const char *err;
   struct ar_hdr arh;
   int c;
   struct stat stab;
@@ -119,10 +121,13 @@ struct partinfo *read_info(FILE *partfile, const char *fn, struct partinfo *ir)
   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 dpkg-split"),
-           fn,ir->fmtversion);
+  err = deb_version_parse(&ir->fmtversion,
+                          nextline(&rip, fn, _("format version number")));
+  if (err)
+    ohshit(_("file '%.250s' has invalid format version: %s"), fn, err);
+  if (ir->fmtversion.major != 2 || ir->fmtversion.minor != 1)
+    ohshit(_("file '%.250s' is format version %d.%d; get a newer dpkg-split"),
+           fn, ir->fmtversion.major, ir->fmtversion.minor);
 
   ir->package = nfstrsave(nextline(&rip, fn, _("package name")));
   ir->version = nfstrsave(nextline(&rip, fn, _("package version number")));
@@ -207,7 +212,7 @@ void mustgetpartinfo(const char *filename, struct partinfo *ri) {
 
 void print_info(const struct partinfo *pi) {
   printf(_("%s:\n"
-         "    Part format version:            %s\n"
+         "    Part format version:            %d.%d\n"
          "    Part of package:                %s\n"
          "        ... version:                %s\n"
          "        ... architecture:           %s\n"
@@ -219,7 +224,7 @@ void print_info(const struct partinfo *pi) {
          "    Part offset:                    %jd bytes\n"
          "    Part file size (used portion):  %jd bytes\n\n"),
          pi->filename,
-         pi->fmtversion,
+         pi->fmtversion.major, pi->fmtversion.minor,
          pi->package,
          pi->version,
          pi->arch ? pi->arch : C_("architecture", "<unknown>"),

+ 5 - 1
dpkg-split/queue.c

@@ -3,6 +3,7 @@
  * queue.c - queue management
  *
  * Copyright © 1995 Ian Jackson <ian@chiark.greenend.org.uk>
+ * Copyright © 2008-2012 Guillem Jover <guillem@debian.org>
  *
  * This is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -94,7 +95,10 @@ void scandepot(void) {
 
     if (de->d_name[0] == '.') continue;
     pq= nfmalloc(sizeof(struct partqueue));
-    pq->info.fmtversion= pq->info.package= pq->info.version= NULL;
+    pq->info.fmtversion.major = 0;
+    pq->info.fmtversion.minor = 0;
+    pq->info.package = NULL;
+    pq->info.version = NULL;
     pq->info.arch = NULL;
     pq->info.orglength= pq->info.thispartoffset= pq->info.thispartlen= 0;
     pq->info.headerlen= 0;