Sfoglia il codice sorgente

dpkg: Switch from foreign arch option to add and remove commands

The --foreign-architecture option is not a good interface, the problem
with it comes from the fact that the architectures supported by the
database are not configuration, they are state. This shows up in several
ways.

When a front-end needs to load the list of architectures, it needs to
get someone to parse dpkg.cfg files, this is currently done by dpkg
itself, and the list can be retrieved with --print-foreign-architectures,
the problem appears when wanting a front-end to load them through libdpkg.
Making the latter have to execute «dpkg --print-foreign-architectures»
would be suboptimal, and making libdpkg have to load dpkg.cfg would be
distasteful. Another issue is that if the list of foreign architectures
is on the configuration files it makes it slightly more tricky to
cross-grade dpkg, and it makes it fairly easy to accidentally remove
architectures required by the database.

Replace the option with two new commands --add-architecture and
--remove-architecture which will perform sanity checks and store and
load the architecture list (including the native arch) in an internal
db file under /var/lib/dpkg/.
Guillem Jover 14 anni fa
parent
commit
61b3201ddb
5 ha cambiato i file con 88 aggiunte e 22 eliminazioni
  1. 2 0
      lib/dpkg/dbmodify.c
  2. 13 6
      man/dpkg.1
  3. 2 0
      src/enquiry.c
  4. 69 16
      src/main.c
  5. 2 0
      src/main.h

+ 2 - 0
lib/dpkg/dbmodify.c

@@ -276,6 +276,8 @@ modstatdb_open(enum modstatdb_rw readwritereq)
     internerr("unknown modstatdb_rw '%d'", readwritereq);
   }
 
+  dpkg_arch_load_list();
+
   if (cstatus != msdbrw_needsuperuserlockonly) {
     cleanupdates();
     if (cflags >= msdbrw_available_readonly)

+ 13 - 6
man/dpkg.1

@@ -231,6 +231,19 @@ deinstall any packages not in list given to \-\-set\-selections.
 Searches for packages selected for installation, but which for some
 reason still haven't been installed.
 .TP
+.B \-\-add\-architecture \fIarchitecture\fP
+Add \fIarchitecture\fP to the list of architectures for which packages can
+be installed without using \fB\-\-force\-architecture\fP. The architecture
+\fBdpkg\fP is built for (i.e. the output of \fB\-\-print\-architecture\fP)
+is always part of that list.
+.TP
+.B \-\-remove\-architecture \fIarchitecture\fP
+Remove \fIarchitecture\fP from the list of architectures for which packages
+can be installed without using \fB\-\-force\-architecture\fP. If the
+architecture is currently in use in the database then the operation will
+be refused, except if \fB\-\-force\-architecture\fP is specified. The
+architecture \fBdpkg\fP is built for (i.e. the output of
+\fB\-\-print\-architecture\fP) can never be removed from that list.
 .TP
 .B \-\-print\-architecture
 Print architecture of packages \fBdpkg\fP installs (for example, "i386").
@@ -572,12 +585,6 @@ each other. Both are processed in the given order, with the last rule that
 matches a file name making the decision.
 .RE
 .TP
-.B \-\-foreign\-architecture \fIarchitecture\fP
-Add \fIarchitecture\fP to the list of architectures for which packages can
-be installed without using \fB\-\-force\-architecture\fP, in addition to
-the architecture \fBdpkg\fP is built for (i.e.: the output of
-\fB\-\-print\-architecture\fP).
-.TP
 \fB\-\-status\-fd \fR\fIn\fR
 Send machine-readable package status and progress information to file
 descriptor \fIn\fP. This option can be specified multiple times. The

+ 2 - 0
src/enquiry.c

@@ -484,6 +484,8 @@ print_foreign_arches(const char *const *argv)
   if (*argv)
     badusage(_("--%s takes no arguments"), cipaction->olong);
 
+  dpkg_arch_load_list();
+
   for (arch = dpkg_arch_get_list(); arch; arch = arch->next) {
     if (arch->type != arch_foreign)
       continue;

+ 69 - 16
src/main.c

@@ -104,6 +104,8 @@ usage(const struct cmdinfo *ci, const char *value)
 "  -l|--list [<pattern> ...]        List packages concisely.\n"
 "  -S|--search <pattern> ...        Find package(s) owning file(s).\n"
 "  -C|--audit                       Check for broken package(s).\n"
+"  --add-architecture <arch>        Add <arch> to the list of architectures.\n"
+"  --remove-architecture <arch>     Remove <arch> from the list of architectures.\n"
 "  --print-architecture             Print dpkg architecture.\n"
 "  --print-foreign-architectures    Print allowed foreign architectures.\n"
 "  --compare-versions <a> <op> <b>  Compare version numbers - see below.\n"
@@ -133,8 +135,6 @@ usage(const struct cmdinfo *ci, const char *value)
 "  --instdir=<directory>      Change installation dir without changing admin dir.\n"
 "  --path-exclude=<pattern>   Do not install paths which match a shell pattern.\n"
 "  --path-include=<pattern>   Re-include a pattern after a previous exclusion.\n"
-"  --foreign-architecture=<arch>\n"
-"                             Add <arch> to the list of foreign architectures.\n"
 "  -O|--selected-only         Skip packages not selected for install/upgrade.\n"
 "  -E|--skip-same-version     Skip packages whose same version is installed.\n"
 "  -G|--refuse-downgrade      Skip packages with earlier version than installed.\n"
@@ -473,22 +473,74 @@ run_status_loggers(struct invoke_hook *hook_head)
   }
 }
 
-static void
-set_foreign_arch(const struct cmdinfo *cip, const char *value)
+static int
+arch_add(const char *const *argv)
 {
   struct dpkg_arch *arch;
+  const char *archname = *argv++;
+
+  if (archname == NULL)
+    badusage(_("--%s takes one argument"), cipaction->olong);
+
+  dpkg_arch_load_list();
+
+  arch = dpkg_arch_add(archname);
+  switch (arch->type) {
+  case arch_native:
+  case arch_foreign:
+    break;
+  case arch_illegal:
+    ohshit(_("architecture '%s' is illegal: %s"), archname,
+           dpkg_arch_name_is_illegal(archname));
+  default:
+    ohshit(_("architecture '%s' is reserved and cannot be added"), archname);
+  }
+
+  dpkg_arch_save_list();
+
+  return 0;
+}
+
+static int
+arch_remove(const char *const *argv)
+{
+  const char *archname = *argv++;
+  struct dpkg_arch *arch;
+  struct pkgiterator *iter;
+  struct pkginfo *pkg;
+
+  if (archname == NULL)
+    badusage(_("--%s takes one argument"), cipaction->olong);
+
+  modstatdb_open(msdbrw_readonly);
+
+  arch = dpkg_arch_find(archname);
+  if (arch->type != arch_foreign) {
+    warning(_("cannot remove non-foreign architecture '%s'"), arch->name);
+    return 0;
+  }
+
+  /* Check if it's safe to remove the architecture from the db. */
+  iter = pkg_db_iter_new();
+  while ((pkg = pkg_db_iter_next_pkg(iter))) {
+    if (pkg->installed.arch == arch) {
+      if (fc_architecture)
+        warning(_("removing architecture '%s' currently in use by database"),
+                arch->name);
+      else
+        ohshit(_("cannot remove architecture '%s' currently in use by the database"),
+               arch->name);
+      break;
+    }
+  }
+  pkg_db_iter_free(iter);
+
+  dpkg_arch_remove(arch);
+  dpkg_arch_save_list();
+
+  modstatdb_shutdown();
 
-  arch = dpkg_arch_find(value);
-  if (arch->type == arch_foreign)
-    return;
-  else if (arch->type == arch_unknown)
-    arch->type = arch_foreign;
-  else if (arch->type == arch_illegal)
-    warning(_("ignoring option --%s=%s: %s"), cip->olong, value,
-            dpkg_arch_name_is_illegal(value));
-  else
-    warning(_("ignoring option --%s=%s: %s"), cip->olong, value,
-            _("this architecture cannot be foreign"));
+  return 0;
 }
 
 static void setforce(const struct cmdinfo *cip, const char *value) {
@@ -574,6 +626,8 @@ static const struct cmdinfo cmdinfos[]= {
   ACTION( "assert-working-epoch",            0,  act_assertepoch,          assertepoch     ),
   ACTION( "assert-long-filenames",           0,  act_assertlongfilenames,  assertlongfilenames ),
   ACTION( "assert-multi-conrep",             0,  act_assertmulticonrep,    assertmulticonrep ),
+  ACTION( "add-architecture",                0,  act_arch_add,             arch_add        ),
+  ACTION( "remove-architecture",             0,  act_arch_remove,          arch_remove     ),
   ACTION( "print-architecture",              0,  act_printarch,            printarch   ),
   ACTION( "print-installation-architecture", 0,  act_printinstarch,        printinstarch  ),
   ACTION( "print-foreign-architectures",     0,  act_printforeignarches,   print_foreign_arches ),
@@ -587,7 +641,6 @@ static const struct cmdinfo cmdinfos[]= {
   { "post-invoke",       0,   1, NULL,          NULL,      set_invoke_hook, 0, &post_invoke_hooks_tail },
   { "path-exclude",      0,   1, NULL,          NULL,      setfilter,     0 },
   { "path-include",      0,   1, NULL,          NULL,      setfilter,     1 },
-  { "foreign-architecture", 0, 1, NULL,         NULL,      set_foreign_arch, 0 },
   { "status-logger",     0,   1, NULL,          NULL,      set_invoke_hook, 0, &status_loggers_tail },
   { "status-fd",         0,   1, NULL,          NULL,      setpipe, 0 },
   { "log",               0,   1, NULL,          &log_file, NULL,    0 },

+ 2 - 0
src/main.h

@@ -78,6 +78,8 @@ enum action {
 
 	act_cmpversions,
 
+	act_arch_add,
+	act_arch_remove,
 	act_printarch,
 	act_printinstarch,
 	act_printforeignarches,