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