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

[PATCH 1/4] Allow pkg:arch syntax in package relationship fields



Implement support for the packagename:archname syntax in package
relationships, required for multiarch.

FIXME: do we want the architecture to be a string, or an enum of known
architectures?

Also, the only architecture value currently allowed is 'any', consistent
with round one of <https://wiki.ubuntu.com/MultiarchSpec>.  This may be
relaxed before the squeeze release to allow for arch-specific cross
dependencies in the next release, but should probably not be relaxed for
package generation in order to avoid accidental archive uploads of
uninstallable packages.
---
 lib/dpkg/dpkg-db.h   |    1 +
 lib/dpkg/dump.c      |    9 +++++++++
 lib/dpkg/fields.c    |   38 ++++++++++++++++++++++++++++++++++----
 lib/dpkg/parse.c     |   10 ++++++++++
 lib/dpkg/parsehelp.c |   36 ++++++++++++++++++++++++++++++++++++
 src/processarc.c     |    1 +
 6 files changed, 91 insertions(+), 4 deletions(-)

diff --git a/lib/dpkg/dpkg-db.h b/lib/dpkg/dpkg-db.h
index c31b4d1..3f31512 100644
--- a/lib/dpkg/dpkg-db.h
+++ b/lib/dpkg/dpkg-db.h
@@ -75,6 +75,7 @@ struct deppossi {
   struct deppossi *next, *nextrev, *backrev;
   struct versionrevision version;
   enum depverrel verrel;
+  char *arch;
   int cyclebreak;
 };
 
diff --git a/lib/dpkg/dump.c b/lib/dpkg/dump.c
index 241be90..a02242d 100644
--- a/lib/dpkg/dump.c
+++ b/lib/dpkg/dump.c
@@ -236,6 +236,15 @@ void varbufdependency(struct varbuf *vb, struct dependency *dep) {
     assert(dop->up == dep);
     varbufaddstr(vb,possdel); possdel= " | ";
     varbufaddstr(vb,dop->ed->name);
+    /* FIXME: eventually we need to be able to output other :arch values, but
+       we only want to do this when the value isn't implicit, which means
+       changing the varbufdependency API */
+    if (strcmp(dop->arch, "any") == 0 && dep->type != dep_conflicts &&
+        dep->type != dep_breaks && dep->type != dep_replaces)
+    {
+      varbufaddc(vb, ':');
+      varbufaddstr(vb, dop->arch);
+    }
     if (dop->verrel != dvr_none) {
       varbufaddstr(vb," (");
       switch (dop->verrel) {
diff --git a/lib/dpkg/fields.c b/lib/dpkg/fields.c
index fcd5e19..2723e40 100644
--- a/lib/dpkg/fields.c
+++ b/lib/dpkg/fields.c
@@ -4,6 +4,7 @@
  *
  * Copyright © 1995 Ian Jackson <ian@chiark.greenend.org.uk>
  * Copyright © 2001 Wichert Akkerman
+ * Copyright © 2009 Canonical Ltd.
  *
  * This is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as
@@ -314,8 +315,8 @@ void f_dependency(struct pkginfo *pigp, struct pkginfoperfile *pifp,
                   const char *value, const struct fieldinfo *fip) {
   char c1, c2;
   const char *p, *emsg;
-  const char *depnamestart, *versionstart;
-  int depnamelength, versionlength;
+  const char *depnamestart, *versionstart, *archstart;
+  int depnamelength, versionlength, archlength;
   static int depnameused= 0, versionused= 0;
   static char *depname= NULL, *version= NULL;
 
@@ -336,8 +337,10 @@ void f_dependency(struct pkginfo *pigp, struct pkginfoperfile *pifp,
     for (;;) { /* loop creating new struct deppossi's */
       depnamestart= p;
 /* skip over package name characters */
-      while (*p && !isspace(*p) && *p != '(' && *p != ',' && *p != '|') {
-	p++;
+      while (*p && !isspace(*p) && *p != ':' && *p != '(' && *p != ',' &&
+             *p != '|')
+      {
+        p++;
       }
       depnamelength= p - depnamestart ;
       if (depnamelength >= depnameused) {
@@ -367,6 +370,33 @@ void f_dependency(struct pkginfo *pigp, struct pkginfoperfile *pifp,
                         * links from the depended on packages to dop are left undone.
                         */
       dop->cyclebreak= 0;
+      if (*p == ':') {			/* if we have an architecture spec */
+        p++;
+        archstart= p;
+        while (*p && !isspace(*p) && *p != '(' && *p != ',' && *p != '|') {
+          p++;
+        }
+        archlength= p - archstart ;
+        dop->arch = m_malloc(archlength + 1);
+        strncpy(dop->arch, archstart, archlength);
+        *(dop->arch + archlength) = '\0';
+        if (!*dop->arch)
+          parse_error(ps, pigp,
+                      _("`%s' field, missing architecture name, or garbage "
+                        "where architecture name expected"), fip->name);
+        emsg= illegal_archname(dop->arch, NULL);
+        if (emsg)
+          parse_error(ps, pigp,
+                      _("`%s' field, reference to `%.255s': "
+                        "invalid architecture name `%.255s': %s"),
+                      fip->name, depname, dop->arch, emsg);
+      } else if (fip->integer == dep_conflicts || fip->integer == dep_breaks ||
+                 fip->integer == dep_replaces)
+      {
+        dop->arch = m_strdup("any");
+      } else {
+        dop->arch = NULL;
+      }
 /* skip whitespace after packagename */
       while (isspace(*p)) p++;
       if (*p == '(') {			/* if we have a versioned relation */
diff --git a/lib/dpkg/parse.c b/lib/dpkg/parse.c
index e74222c..7928d23 100644
--- a/lib/dpkg/parse.c
+++ b/lib/dpkg/parse.c
@@ -263,6 +263,16 @@ int parsedb(const char *filename, enum parsedbflags flags,
       parse_ensure_have_field(&ps, &newpig,
                               &newpifp->architecture, "architecture");
 
+    if (newpifp->architecture) {
+      struct dependency *dyp;
+      struct deppossi *dop;
+
+      for (dyp = newpifp->depends; dyp; dyp = dyp->next)
+        for (dop = dyp->list; dop; dop = dop->next)
+          if (!dop->arch)
+            dop->arch = (char *)newpifp->architecture;
+    }
+
     /* Check the Config-Version information:
      * If there is a Config-Version it is definitely to be used, but
      * there shouldn't be one if the package is `installed' (in which case
diff --git a/lib/dpkg/parsehelp.c b/lib/dpkg/parsehelp.c
index c9f9a67..3f0b09d 100644
--- a/lib/dpkg/parsehelp.c
+++ b/lib/dpkg/parsehelp.c
@@ -3,6 +3,7 @@
  * parsehelp.c - helpful routines for parsing and writing
  *
  * Copyright © 1995 Ian Jackson <ian@chiark.greenend.org.uk>
+ * Copyright © 2009 Canonical Ltd.
  *
  * This is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as
@@ -159,6 +160,41 @@ const char *illegal_packagename(const char *p, const char **ep) {
   return buf;
 }
 
+/* currently all valid architectures match the pattern [a-z0-9][a-z0-9]+;
+   for the moment, as a first pass, use this pattern to check for arch
+   validity. */
+const char *illegal_archname(const char *p, const char **ep) {
+  static char buf[150];
+  int c;
+  
+  if (!*p)
+    return _("may not be empty string");
+  /* But for now, only one value is allowed. */
+  if (strcmp(p,"any") == 0)
+    return NULL;
+  else {
+    snprintf(buf, sizeof(buf), _("value `%s' not permitted)"), p);
+    return buf;
+  }
+  if (!isalnum(*p))
+    return _("must start with an alphanumeric");
+  while ((c = *p++) != '\0')
+    if (!isalnum(c) && c != '-')
+      break;
+  if (!c)
+    return NULL;
+  if (isspace(c) && ep) {
+    while (isspace(*p))
+      p++;
+    *ep= p;
+    return NULL;
+  }
+  snprintf(buf, sizeof(buf), _(
+	   "character `%c' not allowed (only letters, digits and the character `-')"),
+	   c);
+  return buf;
+}
+
 const struct nickname nicknames[]= {
   /* NB: capitalisation of these strings is important. */
   { "Recommended",       "Recommends"  },
diff --git a/src/processarc.c b/src/processarc.c
index 313f2f3..762d3f6 100644
--- a/src/processarc.c
+++ b/src/processarc.c
@@ -916,6 +916,7 @@ void process_archive(const char *filename) {
       else
         blankversion(&newpossi->version);
       newpossi->cyclebreak= 0;
+      newpossi->arch = possi->arch;
       *newpossilastp= newpossi;
       newpossilastp= &newpossi->next;
     }
-- 
1.6.3.3


-- 
Steve Langasek                   Give me a lever long enough and a Free OS
Debian Developer                   to set it on, and I can move the world.
Ubuntu Developer                                    http://www.debian.org/
slangasek@ubuntu.com                                     vorlon@debian.org

Attachment: signature.asc
Description: Digital signature


Reply to: