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