libdpkg: Add new dpkg_arch database interface
authorGuillem Jover <guillem@debian.org>
Tue, 15 Nov 2011 20:59:17 +0000 (21:59 +0100)
committerGuillem Jover <guillem@debian.org>
Mon, 2 Jan 2012 08:13:07 +0000 (09:13 +0100)
The arch database will store all known architectures in the file
«/var/lib/dpkg/arch», this includes the native architecture dpkg
was built for, and all registered foreign architectures.

lib/dpkg/arch.c
lib/dpkg/arch.h
lib/dpkg/libdpkg.map

index 9a9c56c..856158f 100644 (file)
 #include <compat.h>
 
 #include <assert.h>
+#include <limits.h>
 #include <ctype.h>
 #include <string.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
 
 #include <dpkg/i18n.h>
 #include <dpkg/ehandle.h>
+#include <dpkg/dpkg.h>
 #include <dpkg/dpkg-db.h>
+#include <dpkg/dir.h>
 #include <dpkg/varbuf.h>
 #include <dpkg/arch.h>
 
+#define DPKG_DB_ARCH_FILE "arch"
+
 /**
  * Verify if the architecture name is valid.
  *
@@ -98,6 +106,7 @@ static struct dpkg_arch arch_item_native = {
 };
 static struct dpkg_arch *arch_head = &arch_item_native;
 static struct dpkg_arch *arch_builtin_tail = &arch_item_any;
+static bool arch_list_dirty;
 
 static struct dpkg_arch *
 dpkg_arch_new(const char *name, enum dpkg_arch_type type)
@@ -202,6 +211,7 @@ void
 dpkg_arch_reset_list(void)
 {
        arch_builtin_tail->next = NULL;
+       arch_list_dirty = false;
 }
 
 void
@@ -213,3 +223,100 @@ varbuf_add_archqual(struct varbuf *vb, const struct dpkg_arch *arch)
        varbuf_add_char(vb, ':');
        varbuf_add_str(vb, arch->name);
 }
+
+/**
+ * Add a new foreign dpkg_arch architecture.
+ */
+struct dpkg_arch *
+dpkg_arch_add(const char *name)
+{
+       struct dpkg_arch *arch;
+
+       arch = dpkg_arch_find(name);
+       if (arch->type == arch_unknown) {
+               arch->type = arch_foreign;
+               arch_list_dirty = true;
+       }
+
+       return arch;
+}
+
+/**
+ * Remove a foreign dpkg_arch architecture.
+ */
+void
+dpkg_arch_remove(struct dpkg_arch *arch_remove)
+{
+       struct dpkg_arch *arch;
+
+       for (arch = arch_builtin_tail; arch->next; arch = arch->next) {
+               if (arch->next->type != arch_foreign)
+                       continue;
+
+               if (arch->next == arch_remove) {
+                       arch->next = arch->next->next;
+                       arch_list_dirty = true;
+               }
+       }
+}
+
+/**
+ * Load the architecture database.
+ */
+void
+dpkg_arch_load_list(void)
+{
+       FILE *fp;
+       char *archfile;
+       char archname[_POSIX2_LINE_MAX];
+
+       archfile = dpkg_db_get_path(DPKG_DB_ARCH_FILE);
+       fp = fopen(archfile, "r");
+       free(archfile);
+       if (fp == NULL) {
+               arch_list_dirty = true;
+               return;
+       }
+
+       while (fgets_checked(archname, sizeof(archname), fp, archfile) >= 0)
+               dpkg_arch_add(archname);
+
+       fclose(fp);
+}
+
+/**
+ * Save the architecture database.
+ */
+void
+dpkg_arch_save_list(void)
+{
+       struct atomic_file *file;
+       struct dpkg_arch *arch;
+       char *archfile;
+
+       if (!arch_list_dirty)
+               return;
+
+       archfile = dpkg_db_get_path(DPKG_DB_ARCH_FILE);
+       file = atomic_file_new(archfile, 0);
+       atomic_file_open(file);
+
+       for (arch = arch_head; arch; arch = arch->next) {
+               if (arch->type != arch_foreign && arch->type != arch_native)
+                       continue;
+
+               if (fprintf(file->fp, "%s\n", arch->name) < 0)
+                       ohshite(_("error writing to architecture list"));
+       }
+
+       atomic_file_sync(file);
+       atomic_file_close(file);
+       atomic_file_commit(file);
+       atomic_file_free(file);
+
+       dir_sync_path(dpkg_db_get_dir());
+
+       arch_list_dirty = false;
+
+       free(archfile);
+}
index fbb9268..23f532e 100644 (file)
@@ -51,6 +51,11 @@ struct dpkg_arch *dpkg_arch_get(enum dpkg_arch_type type);
 struct dpkg_arch *dpkg_arch_get_list(void);
 void dpkg_arch_reset_list(void);
 
+struct dpkg_arch *dpkg_arch_add(const char *name);
+void dpkg_arch_remove(struct dpkg_arch *arch);
+void dpkg_arch_load_list(void);
+void dpkg_arch_save_list(void);
+
 void varbuf_add_archqual(struct varbuf *vb, const struct dpkg_arch *arch);
 
 DPKG_END_DECLS
index 41d3ad5..9f80069 100644 (file)
@@ -191,6 +191,10 @@ LIBDPKG_PRIVATE {
        dpkg_arch_get;
        dpkg_arch_get_list;
        dpkg_arch_reset_list;
+       dpkg_arch_add;
+       dpkg_arch_remove;
+       dpkg_arch_load_list;
+       dpkg_arch_save_list;
 
        # Package struct handling
        pkg_blank;