summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/dpkg/arch.c107
-rw-r--r--lib/dpkg/arch.h5
-rw-r--r--lib/dpkg/libdpkg.map4
3 files changed, 116 insertions, 0 deletions
diff --git a/lib/dpkg/arch.c b/lib/dpkg/arch.c
index 9a9c56c..856158f 100644
--- a/lib/dpkg/arch.c
+++ b/lib/dpkg/arch.c
@@ -24,15 +24,23 @@
#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);
+}
diff --git a/lib/dpkg/arch.h b/lib/dpkg/arch.h
index fbb9268..23f532e 100644
--- a/lib/dpkg/arch.h
+++ b/lib/dpkg/arch.h
@@ -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
diff --git a/lib/dpkg/libdpkg.map b/lib/dpkg/libdpkg.map
index 41d3ad5..9f80069 100644
--- a/lib/dpkg/libdpkg.map
+++ b/lib/dpkg/libdpkg.map
@@ -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;