Revised patch - an oversight in the previous revision caused
conflicts/replaces/breaks to never match. This one should fix that problem.
As part of multiarch, we enforce architecture affinity of package
relationships:
- unqualified Depends/Pre-Depends/Recommends/Suggests are only satisfied
by a package of a different architecture if the target package is
Multi-Arch: foreign
- Depends/Pre-Depends/Recommends/Suggests on pkg:any are satisfied by a
package of a different architecture if the target package is Multi-Arch:
allowed
- all other Depends/Pre-Depends/Recommends/Suggests are only satisfied by
packages of the same architecture
- Architecture: all packages are treated the same as packages of the native
architecture
- Conflicts/Replaces/Breaks are assumed to apply to packages of any arch
---
lib/dpkg/dpkg-db.h | 2 ++
lib/dpkg/vercmp.c | 28 ++++++++++++++++++++++++++++
src/archives.c | 1 +
src/depcon.c | 40 ++++++++++++++++++++++++++++++++--------
src/enquiry.c | 4 +++-
src/packages.c | 11 +++++++++++
6 files changed, 77 insertions(+), 9 deletions(-)
diff --git a/lib/dpkg/dpkg-db.h b/lib/dpkg/dpkg-db.h
index b6d8602..5cfa453 100644
--- a/lib/dpkg/dpkg-db.h
+++ b/lib/dpkg/dpkg-db.h
@@ -394,6 +394,8 @@ void varbufdependency(struct varbuf *vb, struct dependency *dep);
/*** from vercmp.c ***/
+int archsatisfied(struct pkginfoperfile *it, struct deppossi *against,
+ const char *architecture);
int versionsatisfied(struct pkginfoperfile *it, struct deppossi *against);
int versionsatisfied3(const struct versionrevision *it,
const struct versionrevision *ref,
diff --git a/lib/dpkg/vercmp.c b/lib/dpkg/vercmp.c
index da8fb3e..ab5f605 100644
--- a/lib/dpkg/vercmp.c
+++ b/lib/dpkg/vercmp.c
@@ -3,6 +3,7 @@
* vercmp.c - comparison of version numbers
*
* 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
@@ -97,3 +98,30 @@ int versionsatisfied3(const struct versionrevision *it,
int versionsatisfied(struct pkginfoperfile *it, struct deppossi *against) {
return versionsatisfied3(&it->version,&against->version,against->verrel);
}
+
+int
+archsatisfied(struct pkginfoperfile *it, struct deppossi *against,
+ const char *architecture)
+{
+ const char *srcarch, *tgtarch;
+
+ if (it->multiarch == multiarch_foreign)
+ return 1;
+
+ srcarch = against->arch;
+ if (strcmp(srcarch, "any") == 0 &&
+ (it->multiarch == multiarch_allowed ||
+ against->up->type == dep_conflicts ||
+ against->up->type == dep_replaces ||
+ against->up->type == dep_breaks))
+ return 1;
+
+ if (strcmp(srcarch, "all") == 0)
+ srcarch = architecture;
+
+ tgtarch = it->architecture;
+ if (strcmp(tgtarch, "all") == 0)
+ tgtarch = architecture;
+
+ return (strcmp(srcarch, tgtarch) == 0);
+}
diff --git a/src/archives.c b/src/archives.c
index 2a5765b..3957f05 100644
--- a/src/archives.c
+++ b/src/archives.c
@@ -282,6 +282,7 @@ static int does_replace(struct pkginfo *newpigp,
debug(dbg_depcondetail,"does_replace ... found old, version %s",
versiondescribe(&dep->list->version,vdew_always));
if (!versionsatisfied(&oldpigp->installed,dep->list)) continue;
+ if (!archsatisfied(&oldpigp->installed, dep->list, architecture)) continue;
debug(dbg_depcon,"does_replace ... yes");
return 1;
}
diff --git a/src/depcon.c b/src/depcon.c
index f109384..f72f78b 100644
--- a/src/depcon.c
+++ b/src/depcon.c
@@ -281,19 +281,33 @@ int depisok(struct dependency *dep, struct varbuf *whynot,
sprintf(linebuf,_(" %.250s is to be deconfigured.\n"),possi->ed->name);
break;
case itb_installnew:
- if (versionsatisfied(&possi->ed->available,possi)) return 1;
- sprintf(linebuf,_(" %.250s is to be installed, but is version %.250s.\n"),
- possi->ed->name,
- versiondescribe(&possi->ed->available.version,vdew_nonambig));
+ if (versionsatisfied(&possi->ed->available,possi)) {
+ if (archsatisfied(&possi->ed->available, possi, architecture))
+ return 1;
+ sprintf(linebuf,_(" %.250s is to be installed, but is architecture %.250s.\n"),
+ possi->ed->name,
+ possi->ed->available.architecture);
+ } else {
+ sprintf(linebuf,_(" %.250s is to be installed, but is version %.250s.\n"),
+ possi->ed->name,
+ versiondescribe(&possi->ed->available.version,vdew_nonambig));
+ }
break;
case itb_normal: case itb_preinstall:
switch (possi->ed->status) {
case stat_installed:
case stat_triggerspending:
- if (versionsatisfied(&possi->ed->installed,possi)) return 1;
- sprintf(linebuf,_(" %.250s is installed, but is version %.250s.\n"),
- possi->ed->name,
- versiondescribe(&possi->ed->installed.version,vdew_nonambig));
+ if (versionsatisfied(&possi->ed->installed,possi)) {
+ if (archsatisfied(&possi->ed->installed, possi, architecture))
+ return 1;
+ sprintf(linebuf,_(" %.250s is installed, but is architecture %.250s.\n"),
+ possi->ed->name,
+ possi->ed->installed.architecture);
+ } else {
+ sprintf(linebuf,_(" %.250s is installed, but is version %.250s.\n"),
+ possi->ed->name,
+ versiondescribe(&possi->ed->installed.version,vdew_nonambig));
+ }
break;
case stat_notinstalled:
/* Don't say anything about this yet - it might be a virtual package.
@@ -315,6 +329,13 @@ int depisok(struct dependency *dep, struct varbuf *whynot,
possi->ed->name,
versiondescribe(&possi->ed->available.version,vdew_nonambig));
break;
+ } else if (!archsatisfied(&possi->ed->installed, possi,
+ architecture))
+ {
+ sprintf(linebuf,_(" %.250s is unpacked, but is architecture %.250s.\n"),
+ possi->ed->name,
+ possi->ed->installed.architecture);
+ break;
} else if (!versionsatisfied3(&possi->ed->configversion,
&possi->version,possi->verrel)) {
sprintf(linebuf, _(" %.250s latest configured version is %.250s.\n"),
@@ -418,6 +439,7 @@ int depisok(struct dependency *dep, struct varbuf *whynot,
break;
case itb_installnew:
if (!versionsatisfied(&possi->ed->available, possi)) break;
+ if (!archsatisfied(&possi->ed->available, possi, architecture)) break;
sprintf(linebuf, _(" %.250s (version %.250s) is to be installed.\n"),
possi->ed->name,
versiondescribe(&possi->ed->available.version,vdew_nonambig));
@@ -440,6 +462,8 @@ int depisok(struct dependency *dep, struct varbuf *whynot,
case stat_triggerspending:
case stat_triggersawaited:
if (!versionsatisfied(&possi->ed->installed, possi)) break;
+ if (!archsatisfied(&possi->ed->available, possi, architecture))
+ break;
sprintf(linebuf, _(" %.250s (version %.250s) is present and %s.\n"),
possi->ed->name,
versiondescribe(&possi->ed->installed.version,vdew_nonambig),
diff --git a/src/enquiry.c b/src/enquiry.c
index 02ede15..f5b359f 100644
--- a/src/enquiry.c
+++ b/src/enquiry.c
@@ -344,7 +344,9 @@ void predeppackage(const char *const *argv) {
possi=possi->next) {
trypkg= possi->ed;
if (!trypkg->available.valid) continue;
- if (trypkg->files && versionsatisfied(&trypkg->available,possi)) {
+ if (trypkg->files && versionsatisfied(&trypkg->available, possi) &&
+ archsatisfied(&trypkg->available, possi, architecture))
+ {
if (trypkg->clientdata->istobe == itb_normal) { pkg= trypkg; break; }
}
if (possi->verrel != dvr_none) continue;
diff --git a/src/packages.c b/src/packages.c
index b176581..c677b60 100644
--- a/src/packages.c
+++ b/src/packages.c
@@ -369,6 +369,16 @@ static int deppossi_ok_found(struct pkginfo *possdependee,
(*interestingwarnings)++;
return thisf;
}
+ if (checkversion && !archsatisfied(&possdependee->installed, checkversion,
+ architecture))
+ {
+ varbufprintf(oemsgs, _(" Architecture of %s on system is %s.\n"),
+ possdependee->name, checkversion->arch);
+ if (fc_depends || fc_dependsversion) thisf= (dependtry >= 3) ? 2 : 1;
+ debug(dbg_depcondetail," bad architecture, returning %d",thisf);
+ (*interestingwarnings)++;
+ return thisf;
+ }
if (possdependee->status == stat_installed ||
possdependee->status == stat_triggerspending) {
debug(dbg_depcondetail," is installed, ok and found");
@@ -470,6 +480,7 @@ static void breaks_check_one(struct varbuf *aemsgs, int *ok,
breaker->status == stat_configfiles) return;
if (broken == breaker) return;
if (!versionsatisfied(&broken->installed, breaks)) return;
+ if (!archsatisfied(&broken->installed, breaks, architecture)) return;
if (ignore_depends(breaker)) return;
if (virtbroken && ignore_depends(virtbroken)) return;
--
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