Explorar o código

dpkg-deb: Use parsedb() instead of an ad-hoc deb822 parser

This makes sure any field fixup and sanity check is performed on
the input, and gets reflected on the output.
Guillem Jover %!s(int64=12) %!d(string=hai) anos
pai
achega
589602c780
Modificáronse 3 ficheiros con 33 adicións e 53 borrados
  1. 3 0
      debian/changelog
  2. 0 1
      dpkg-deb/dpkg-deb.h
  3. 30 52
      dpkg-deb/info.c

+ 3 - 0
debian/changelog

@@ -38,6 +38,9 @@ dpkg (1.17.11) UNRELEASED; urgency=low
     and derivatives, enabled by default. It will fallback to stackprotector
     when the former is not functional or disabled by the user.
     Thanks to Romain Francoise <rfrancoise@debian.org>.
+  * Change «dpkg-deb --field» code to use the libdpkg deb822 parser instead
+    of an ad-hoc one. This makes sure any field fixup and sanity check is
+    performed on the input, and gets reflected on the output.
 
   [ Updated programs translations ]
   * Danish (Joe Dalton). Closes: #754127

+ 0 - 1
dpkg-deb/dpkg-deb.h

@@ -75,7 +75,6 @@ extern struct compress_params compress_params;
 #define DATAMEMBER		"data.tar"
 
 #define MAXFILENAME 2048
-#define MAXFIELDNAME 200
 
 #ifdef PATH_MAX
 # define INTERPRETER_MAX PATH_MAX

+ 30 - 52
dpkg-deb/info.c

@@ -40,6 +40,7 @@
 #include <dpkg/i18n.h>
 #include <dpkg/dpkg.h>
 #include <dpkg/dpkg-db.h>
+#include <dpkg/parsedump.h>
 #include <dpkg/pkg-format.h>
 #include <dpkg/buffer.h>
 #include <dpkg/path.h>
@@ -208,64 +209,41 @@ info_list(const char *debar, const char *dir)
 
 static void
 info_field(const char *debar, const char *dir, const char *const *fields,
-           bool showfieldname)
+           enum fwriteflags fieldflags)
 {
-  FILE *cc;
   char *controlfile;
-  char fieldname[MAXFIELDNAME+1];
-  char *pf;
-  const char *const *fp;
-  int c, lno, fnl;
-  bool doing;
+  struct varbuf str = VARBUF_INIT;
+  struct pkginfo *pkg;
+  int i;
 
   m_asprintf(&controlfile, "%s/%s", dir, CONTROLFILE);
-  cc = fopen(controlfile, "r");
-  if (!cc)
-    ohshite(_("could not open the `control' component"));
-  doing = true;
-  lno = 1;
-  for (;;) {
-    c = getc(cc);
-    if (c == EOF) {
-      doing = false;
-      break;
-    }
-    if (c == '\n') {
-      lno++;
-      doing = true;
-      continue;
-    }
-    if (!isspace(c)) {
-      for (pf=fieldname, fnl=0;
-           fnl <= MAXFIELDNAME && c!=EOF && !isspace(c) && c!=':';
-           c= getc(cc)) { *pf++= c; fnl++; }
-      *pf = '\0';
-      doing= fnl >= MAXFIELDNAME || c=='\n' || c==EOF;
-      for (fp=fields; !doing && *fp; fp++)
-        if (strcasecmp(*fp, fieldname) == 0)
-          doing = true;
-      if (showfieldname) {
-        if (doing)
-          fputs(fieldname,stdout);
-      } else {
-        if (c==':') c= getc(cc);
-        while (c != '\n' && isspace(c)) c= getc(cc);
-      }
-    }
-    for(;;) {
-      if (c == EOF) break;
-      if (doing) putc(c,stdout);
-      if (c == '\n') { lno++; break; }
-      c= getc(cc);
+  parsedb(controlfile, pdb_parse_binary | pdb_ignorefiles, &pkg);
+  free(controlfile);
+
+  for (i = 0; fields[i]; i++) {
+    const struct fieldinfo *field;
+    const struct arbitraryfield *arbfield;
+
+    varbuf_reset(&str);
+    field = find_field_info(fieldinfos, fields[i]);
+    if (field) {
+      field->wcall(&str, pkg, &pkg->available, fieldflags, field);
+    } else {
+      arbfield = find_arbfield_info(pkg->available.arbs, fields[i]);
+      if (arbfield)
+        varbuf_add_arbfield(&str, arbfield, fieldflags);
     }
-    if (c == EOF) break;
+    varbuf_end_str(&str);
+
+    if (fieldflags & fw_printheader)
+      printf("%s", str.buf);
+    else
+      printf("%s\n", str.buf);
   }
-  if (ferror(cc)) ohshite(_("failed during read of `control' component"));
-  if (fclose(cc))
-    ohshite(_("error closing the '%s' component"), CONTROLFILE);
-  if (doing) putc('\n',stdout);
+
   m_output(stdout, _("<standard output>"));
-  free(controlfile);
+
+  varbuf_destroy(&str);
 }
 
 int
@@ -315,7 +293,7 @@ do_field(const char *const *argv)
 
   info_prepare(&argv, &debar, &dir, 1);
   if (*argv) {
-    info_field(debar, dir, argv, argv[1] != NULL);
+    info_field(debar, dir, argv, argv[1] != NULL ? fw_printheader : 0);
   } else {
     static const char *const controlonly[] = { CONTROLFILE, NULL };
     info_spew(debar, dir, controlonly);