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

[PATCH 2/4] Implement architecture checking of package relationships in the resolver



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  |   24 ++++++++++++++++++++++++
 src/archives.c     |    1 +
 src/depcon.c       |   37 +++++++++++++++++++++++++++++--------
 src/enquiry.c      |    4 +++-
 src/packages.c     |   11 +++++++++++
 6 files changed, 70 insertions(+), 9 deletions(-)

diff --git a/lib/dpkg/dpkg-db.h b/lib/dpkg/dpkg-db.h
index 3f31512..93b7061 100644
--- a/lib/dpkg/dpkg-db.h
+++ b/lib/dpkg/dpkg-db.h
@@ -443,6 +443,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..67076ba 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,26 @@ 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)
+    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..26520b3 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"),
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


Reply to: