Procházet zdrojové kódy

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 před 14 roky
rodič
revize
c13a013fd8
6 změnil soubory, kde provedl 62 přidání a 41 odebrání
  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.
    - Add needed includes to all header files.
    - Get rid of unuseful "unsigned" modifiers.
    - Get rid of unuseful "unsigned" modifiers.
    - Use internerr instead of assert, and print more meaninful messages.
    - 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,
    - Use enums for currently hardcoded literals (replacingfilesandsaid,
      saidread, rok, filetriggers_edited, etc).
      saidread, rok, filetriggers_edited, etc).
    - Do not use nfmalloc (and friends) for non in-core db memory.
    - 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]
   * 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.
     in addition to argv[0], to handle both binaries and interpreted scripts.
     Reported by Mats Erik Andersson <mats.andersson@gisladisker.se>.
     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 ]
   [ Helge Kreutzmann ]
   * Fix a typo in man/dpkg-buildflags.1.
   * Fix a typo in man/dpkg-buildflags.1.

+ 39 - 32
dpkg-deb/extract.c

@@ -3,6 +3,7 @@
  * extract.c - extracting archives
  * extract.c - extracting archives
  *
  *
  * Copyright © 1994,1995 Ian Jackson <ian@chiark.greenend.org.uk>
  * 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
  * This is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * it under the terms of the GNU General Public License as published by
@@ -47,6 +48,7 @@
 #include <dpkg/command.h>
 #include <dpkg/command.h>
 #include <dpkg/compress.h>
 #include <dpkg/compress.h>
 #include <dpkg/ar.h>
 #include <dpkg/ar.h>
+#include <dpkg/deb-version.h>
 #include <dpkg/options.h>
 #include <dpkg/options.h>
 
 
 #include "dpkg-deb.h"
 #include "dpkg-deb.h"
@@ -105,8 +107,9 @@ void
 extracthalf(const char *debar, const char *dir, const char *taroption,
 extracthalf(const char *debar, const char *dir, const char *taroption,
             int admininfo)
             int admininfo)
 {
 {
+  const char *err;
   char versionbuf[40];
   char versionbuf[40];
-  float versionnum;
+  struct deb_version version;
   off_t ctrllennum, memberlen = 0;
   off_t ctrllennum, memberlen = 0;
   ssize_t r;
   ssize_t r;
   int dummy;
   int dummy;
@@ -117,7 +120,7 @@ extracthalf(const char *debar, const char *dir, const char *taroption,
   struct stat stab;
   struct stat stab;
   char nlc;
   char nlc;
   int adminmember;
   int adminmember;
-  bool oldformat, header_done;
+  bool header_done;
   enum compressor_type decompressor = compressor_type_gzip;
   enum compressor_type decompressor = compressor_type_gzip;
 
 
   arfd = open(debar, O_RDONLY);
   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"));
     read_fail(r, debar, _("archive magic version number"));
 
 
   if (strcmp(versionbuf, DPKG_AR_MAGIC) == 0) {
   if (strcmp(versionbuf, DPKG_AR_MAGIC) == 0) {
-    oldformat = false;
-
     ctrllennum= 0;
     ctrllennum= 0;
     header_done = false;
     header_done = false;
     for (;;) {
     for (;;) {
@@ -149,7 +150,6 @@ extracthalf(const char *debar, const char *dir, const char *taroption,
       memberlen = dpkg_ar_member_get_size(debar, &arh);
       memberlen = dpkg_ar_member_get_size(debar, &arh);
       if (!header_done) {
       if (!header_done) {
         char *infobuf;
         char *infobuf;
-        char *cur;
 
 
         if (strncmp(arh.ar_name, DEBMAGIC, sizeof(arh.ar_name)) != 0)
         if (strncmp(arh.ar_name, DEBMAGIC, sizeof(arh.ar_name)) != 0)
           ohshit(_("file `%.250s' is not a debian binary archive (try dpkg-split?)"),debar);
           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)))
         if (r != (memberlen + (memberlen & 1)))
           read_fail(r, debar, _("archive information header member"));
           read_fail(r, debar, _("archive information header member"));
         infobuf[memberlen] = '\0';
         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);
         free(infobuf);
 
 
         header_done = true;
         header_done = true;
@@ -211,21 +210,23 @@ extracthalf(const char *debar, const char *dir, const char *taroption,
     }
     }
 
 
     if (admininfo >= 2) {
     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>"));
       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];
     char ctrllenbuf[40];
     int l = 0;
     int l = 0;
 
 
-    oldformat = true;
     l = strlen(versionbuf);
     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));
     r = read_line(arfd, ctrllenbuf, 1, sizeof(ctrllenbuf));
     if (r < 0)
     if (r < 0)
@@ -243,9 +244,10 @@ extracthalf(const char *debar, const char *dir, const char *taroption,
     }
     }
 
 
     if (admininfo >= 2) {
     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));
              (intmax_t)(stab.st_size - ctrllennum - strlen(ctrllenbuf) - l));
       m_output(stdout, _("<standard output>"));
       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);
   subproc_wait_check(c2, _("<decompress>"), PROCPIPE);
   if (c1 != -1)
   if (c1 != -1)
     subproc_wait_check(c1, _("paste"), 0);
     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);
       movecontrolfiles(OLDOLDDEBDIR);
-    } else if (versionnum == 0.932F || versionnum == 0.933F) {
+    else if (version.minor == 932 || version.minor == 933)
       movecontrolfiles(OLDDEBDIR);
       movecontrolfiles(OLDDEBDIR);
-    }
   }
   }
 }
 }
 
 

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

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

+ 11 - 6
dpkg-split/info.c

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

+ 5 - 1
dpkg-split/queue.c

@@ -3,6 +3,7 @@
  * queue.c - queue management
  * queue.c - queue management
  *
  *
  * Copyright © 1995 Ian Jackson <ian@chiark.greenend.org.uk>
  * 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
  * This is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * 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;
     if (de->d_name[0] == '.') continue;
     pq= nfmalloc(sizeof(struct partqueue));
     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.arch = NULL;
     pq->info.orglength= pq->info.thispartoffset= pq->info.thispartlen= 0;
     pq->info.orglength= pq->info.thispartoffset= pq->info.thispartlen= 0;
     pq->info.headerlen= 0;
     pq->info.headerlen= 0;