Split lib/osinfo.c to provide an API for other pieces of code (namely
mllib) to reuse it. The ISO-related processing is thus moved into a
lib/osinfo-iso.c file.
---
lib/Makefile.am | 2 +
lib/osinfo-iso.c | 462 +++
lib/osinfo.c | 420 +-
lib/osinfo.h | 27
4 files changed, 493 insertions(+), 418 deletions(-)
create mode 100644 lib/osinfo-iso.c
create mode 100644 lib/osinfo.h
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 360ce9c92..2cb83f2bb 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -113,7 +113,9 @@ libguestfs_la_SOURCES = \
lpj.c \
match.c \
mountable.c \
+ osinfo.h \
osinfo.c \
+ osinfo-iso.c \
private-data.c \
proto.c \
qemu.c \
diff --git a/lib/osinfo-iso.c b/lib/osinfo-iso.c
new file mode 100644
index 0..059d72def
--- /dev/null
+++ b/lib/osinfo-iso.c
@@ -0,0 +1,462 @@
+/* libguestfs
+ * Copyright (C) 2012 Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/* Read libosinfo XML files to parse out just the
+ * os/media/iso/system-id and os/media/iso/volume-id fields, which we
+ * can then use to map install media to operating systems.
+ *
+ * Note some assumptions here:
+ *
+ * (1) We have to do some translation of the distro names and versions
+ * stored in the libosinfo files and the standard names returned by
+ * libguestfs.
+ *
+ * (2) Media detection is only part of the story. We may still need
+ * to inspect inside the image.
+ *
+ * (3) We only read the XML database files (at most) once per process,
+ * and keep them cached. They are only read at all if someone tries
+ * to inspect a CD/DVD/ISO.
+ *
+ * XXX Currently the database is not freed when the program exits /
+ * library is unloaded, although we should probably do that.
+ */
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+#include "ignore-value.h"
+#include "glthread/lock.h"
+#include "c-ctype.h"
+
+#include "guestfs.h"
+#include "guestfs-internal.h"
+
+#include "osinfo.h"
+
+gl_lock_define_initialized (static, osinfo_db_lock);
+static ssize_t osinfo_db_size = 0; /* 0 = unread, -1 = error, >= 1 = #records
*/
+static struct osinfo *osinfo_db = NULL;
+
+static void free_osinfo_db_entry (struct osinfo *);
+
+#define XMLSTREQ(a,b) (xmlStrEqual((a),(b)) == 1)
+
+static int read_osinfo_db_xml (guestfs_h *g, const char *pathname, void *data);
+
+/* Given one or more fields from the header of a CD/DVD/ISO, look up
+ * the media in the libosinfo database and return our best guess for
+ * the operating system.
+ *
+ * This returns:
+ * -1 => a fatal error ('error' has been called, caller must not ignore it)
+ * 0 => could not locate the OS
+ * 1 => matching OS found, the osinfo_ret pointer has been filled in
+ */
+int
+guestfs_int_osinfo_map (guestfs_h *g, const struct guestfs_isoinfo *isoinfo,
+const struct osinfo **osinfo_ret)
+{
+ size_t i;
+
+ /* We only need to lock the database when reading it for the first time. */
+ gl_lock_lock (osinfo_db_lock);
+ if (osinfo_db_size == 0) {
+if (read_osinfo_db (g, read_osinfo_db_xml, NULL) == -1) {
+ /* Fatal error: free any database entries which have been read, and
+ * mark the database as having a permanent error.
+ */
+ if (osinfo_db_size > 0) {
+for (i = 0; i < (size_t) osinfo_db_size; ++i)
+ free_osinfo_db_entry (_db[i]);
+ }
+ free (osinfo_db);
+ osinfo_db = NULL;
+ osinfo_db_size = -1;
+ gl_lock_unlock (osinfo_db_lock);
+ return -1;
+}
+ }
+ gl_lock_unlock (osinfo_db_lock);
+
+ if (osinfo_db_size <= 0)
+return 0;
+
+ /* Look in the database to see if we can find a match. */
+ for (i = 0; i < (size_t) osinfo_db_size; ++i) {
+if (osinfo_db[i].re_system_id) {
+ if (!isoinfo->iso_system_id ||
+ !match (g, isoinfo->iso_system_id, osinfo_db[i].re_system_id))
+continue;
+}
+
+if (osinfo_db[i].re_volume_id) {
+ if (!isoinfo->iso_volume_id ||
+ !match (g, isoinfo->iso_volume_id, osinfo_db[i].re_volume_id))
+