Преглед на файлове

libdpkg: Add new dpkg_arch database interface

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.
Guillem Jover преди 14 години
родител
ревизия
1c1c2f7dc4
променени са 3 файла, в които са добавени 116 реда и са изтрити 0 реда
  1. 107 0
      lib/dpkg/arch.c
  2. 5 0
      lib/dpkg/arch.h
  3. 4 0
      lib/dpkg/libdpkg.map

+ 107 - 0
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);
+}

+ 5 - 0
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

+ 4 - 0
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;