[virt-tools-list] [PATCH libosinfo 1/3] Add support for install tree metadata

Daniel P. Berrange berrange at redhat.com
Thu Feb 23 12:23:59 UTC 2012


From: "Daniel P. Berrange" <berrange at redhat.com>

The <media> element and OsinfoMedia class can be used to identify
install media, ie ISO images.

The <tree> element and OsinfoTree class are the same concept but
used to identify installation trees.
---
 docs/reference/Libosinfo.types |    2 +
 osinfo/Makefile.am             |   10 +-
 osinfo/libosinfo.syms          |   28 ++
 osinfo/osinfo.h                |    2 +
 osinfo/osinfo_db.c             |   81 ++++-
 osinfo/osinfo_db.h             |    4 +
 osinfo/osinfo_loader.c         |   77 ++++
 osinfo/osinfo_os.c             |   38 ++
 osinfo/osinfo_os.h             |    4 +
 osinfo/osinfo_tree.c           |  870 ++++++++++++++++++++++++++++++++++++++++
 osinfo/osinfo_tree.h           |  117 ++++++
 osinfo/osinfo_treelist.c       |  167 ++++++++
 osinfo/osinfo_treelist.h       |   82 ++++
 tools/osinfo-detect.c          |  127 +++++-
 14 files changed, 1585 insertions(+), 24 deletions(-)
 create mode 100644 osinfo/osinfo_tree.c
 create mode 100644 osinfo/osinfo_tree.h
 create mode 100644 osinfo/osinfo_treelist.c
 create mode 100644 osinfo/osinfo_treelist.h

diff --git a/docs/reference/Libosinfo.types b/docs/reference/Libosinfo.types
index 2342f68..2cf0934 100644
--- a/docs/reference/Libosinfo.types
+++ b/docs/reference/Libosinfo.types
@@ -21,3 +21,5 @@ osinfo_productfilter_get_type
 osinfo_productlist_get_type
 osinfo_resources_get_type
 osinfo_resourceslist_get_type
+osinfo_tree_get_type
+osinfo_treelist_get_type
diff --git a/osinfo/Makefile.am b/osinfo/Makefile.am
index 4bf12ed..98e2365 100644
--- a/osinfo/Makefile.am
+++ b/osinfo/Makefile.am
@@ -65,7 +65,10 @@ libosinfo_1_0_include_HEADERS = \
   osinfo_media.h		\
   osinfo_medialist.h		\
   osinfo_resources.h		\
-  osinfo_resourceslist.h
+  osinfo_resourceslist.h	\
+  osinfo_tree.h			\
+  osinfo_treelist.h		\
+  $(NULL)
 
 libosinfo_1_0_la_SOURCES =	\
   osinfo_entity.c		\
@@ -89,8 +92,11 @@ libosinfo_1_0_la_SOURCES =	\
   osinfo_medialist.c		\
   osinfo_resources.c		\
   osinfo_resourceslist.c	\
+  osinfo_tree.c			\
+  osinfo_treelist.c		\
   osinfo_db.c			\
-  osinfo_loader.c
+  osinfo_loader.c		\
+  $(NULL)
 
 if WITH_GOBJECT_INTROSPECTION
 
diff --git a/osinfo/libosinfo.syms b/osinfo/libosinfo.syms
index 2f801af..1f1a161 100644
--- a/osinfo/libosinfo.syms
+++ b/osinfo/libosinfo.syms
@@ -16,6 +16,7 @@ LIBOSINFO_0.0.1 {
 	osinfo_db_add_device;
 	osinfo_db_add_deployment;
 	osinfo_db_guess_os_from_media;
+	osinfo_db_guess_os_from_tree;
 	osinfo_db_unique_values_for_property_in_os;
 	osinfo_db_unique_values_for_property_in_platform;
 	osinfo_db_unique_values_for_property_in_device;
@@ -115,6 +116,8 @@ LIBOSINFO_0.0.1 {
 	osinfo_os_get_family;
 	osinfo_os_get_media_list;
 	osinfo_os_add_media;
+	osinfo_os_get_tree_list;
+	osinfo_os_add_tree;
         osinfo_os_get_minimum_resources;
         osinfo_os_get_recommended_resources;
         osinfo_os_add_minimum_resources;
@@ -204,6 +207,31 @@ LIBOSINFO_0.0.6 {
 	osinfo_os_get_devices_by_property;
 } LIBOSINFO_0.0.5;
 
+LIBOSINFO_0.1.0 {
+    global:
+	osinfo_tree_new;
+	osinfo_tree_create_from_location;
+	osinfo_tree_create_from_location_async;
+	osinfo_tree_create_from_location_finish;
+	osinfo_tree_error_quark;
+	osinfo_tree_get_architecture;
+	osinfo_tree_get_boot_iso_path;
+	osinfo_tree_get_initrd_path;
+	osinfo_tree_get_kernel_path;
+	osinfo_tree_get_treeinfo_family;
+	osinfo_tree_get_treeinfo_variant;
+	osinfo_tree_get_treeinfo_version;
+	osinfo_tree_get_treeinfo_arch;
+	osinfo_tree_get_type;
+	osinfo_tree_get_url;
+	osinfo_treelist_get_type;
+	osinfo_treelist_new;
+	osinfo_treelist_new_copy;
+	osinfo_treelist_new_filtered;
+	osinfo_treelist_new_intersection;
+	osinfo_treelist_new_union;
+} LIBOSINFO_0.0.6;
+
 /* Symbols in next release...
 
   LIBOSINFO_0.0.2 {
diff --git a/osinfo/osinfo.h b/osinfo/osinfo.h
index 3d2acfe..0ec055b 100644
--- a/osinfo/osinfo.h
+++ b/osinfo/osinfo.h
@@ -46,6 +46,8 @@
 #include <osinfo/osinfo_medialist.h>
 #include <osinfo/osinfo_resources.h>
 #include <osinfo/osinfo_resourceslist.h>
+#include <osinfo/osinfo_tree.h>
+#include <osinfo/osinfo_treelist.h>
 #include <osinfo/osinfo_db.h>
 #include <osinfo/osinfo_loader.h>
 
diff --git a/osinfo/osinfo_db.c b/osinfo/osinfo_db.c
index ecc8fbd..986e7c9 100644
--- a/osinfo/osinfo_db.c
+++ b/osinfo/osinfo_db.c
@@ -31,6 +31,7 @@ G_DEFINE_TYPE (OsinfoDb, osinfo_db, G_TYPE_OBJECT);
 #define OSINFO_DB_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), OSINFO_TYPE_DB, OsinfoDbPrivate))
 
 #define match_regex(pattern, str) (((pattern) == NULL && (str) == NULL) || \
+                                   ((pattern) == NULL) ||               \
                                    ((pattern) != NULL && (str) != NULL && \
                                     g_regex_match_simple((pattern), (str), 0, 0)))
 
@@ -386,11 +387,10 @@ OsinfoOs *osinfo_db_guess_os_from_media(OsinfoDb *db,
             const gchar *os_publisher = osinfo_media_get_publisher_id(os_media);
             const gchar *os_application = osinfo_media_get_application_id(os_media);
 
-            if ((match_regex (os_volume, media_volume) ||
-                 match_regex (os_application, media_application))
-                 &&
-                (match_regex (os_system, media_system) ||
-                 match_regex (os_publisher, media_publisher))) {
+            if (match_regex (os_volume, media_volume) &&
+                match_regex (os_application, media_application) &&
+                match_regex (os_system, media_system) &&
+                match_regex (os_publisher, media_publisher)) {
                 ret = os;
                 if (matched_media != NULL)
                     *matched_media = os_media;
@@ -410,6 +410,77 @@ OsinfoOs *osinfo_db_guess_os_from_media(OsinfoDb *db,
     return ret;
 }
 
+
+/**
+ * osinfo_db_guess_os_from_tree:
+ * @db: the database
+ * @tree: the installation tree
+ * @matched_tree: (out) (transfer none) (allow-none): the matched operating
+ * system tree
+ *
+ * Guess operating system given a #OsinfoTree object.
+ *
+ * Returns: (transfer none): the operating system, or NULL if guessing failed
+ */
+OsinfoOs *osinfo_db_guess_os_from_tree(OsinfoDb *db,
+                                       OsinfoTree *tree,
+                                       OsinfoTree **matched_tree)
+{
+    OsinfoOs *ret = NULL;
+    GList *oss = NULL;
+    GList *os_iter;
+    const gchar *tree_family;
+    const gchar *tree_variant;
+    const gchar *tree_version;
+    const gchar *tree_arch;
+
+    g_return_val_if_fail(OSINFO_IS_DB(db), NULL);
+    g_return_val_if_fail(tree != NULL, NULL);
+
+    tree_family = osinfo_tree_get_treeinfo_family(tree);
+    tree_variant = osinfo_tree_get_treeinfo_variant(tree);
+    tree_version = osinfo_tree_get_treeinfo_version(tree);
+    tree_arch = osinfo_tree_get_treeinfo_arch(tree);
+
+    oss = osinfo_list_get_elements(OSINFO_LIST(db->priv->oses));
+    for (os_iter = oss; os_iter; os_iter = os_iter->next) {
+        OsinfoOs *os = OSINFO_OS(os_iter->data);
+        OsinfoTreeList *tree_list = osinfo_os_get_tree_list(os);
+        GList *trees = osinfo_list_get_elements(OSINFO_LIST(tree_list));
+        GList *tree_iter;
+
+        //trees = g_list_sort(trees, tree_family_compare);
+
+        for (tree_iter = trees; tree_iter; tree_iter = tree_iter->next) {
+            OsinfoTree *os_tree = OSINFO_TREE(tree_iter->data);
+            const gchar *os_family = osinfo_tree_get_treeinfo_family(os_tree);
+            const gchar *os_variant = osinfo_tree_get_treeinfo_variant(os_tree);
+            const gchar *os_version = osinfo_tree_get_treeinfo_version(os_tree);
+            const gchar *os_arch = osinfo_tree_get_treeinfo_arch(os_tree);
+
+            if (match_regex (os_family, tree_family) &&
+                match_regex (os_variant, tree_variant) &&
+                match_regex (os_version, tree_version) &&
+                match_regex (os_arch, tree_arch)) {
+                ret = os;
+                if (matched_tree != NULL)
+                    *matched_tree = os_tree;
+                break;
+            }
+        }
+
+        g_list_free(trees);
+        g_object_unref(tree_list);
+
+        if (ret)
+            break;
+    }
+
+    g_list_free(oss);
+
+    return ret;
+}
+
 struct osinfo_db_populate_values_args {
     GHashTable *values;
     const gchar *property;
diff --git a/osinfo/osinfo_db.h b/osinfo/osinfo_db.h
index 79075d0..2edfee0 100644
--- a/osinfo/osinfo_db.h
+++ b/osinfo/osinfo_db.h
@@ -97,6 +97,10 @@ OsinfoOs *osinfo_db_guess_os_from_media(OsinfoDb *db,
                                         OsinfoMedia *media,
                                         OsinfoMedia **matched_media);
 
+OsinfoOs *osinfo_db_guess_os_from_tree(OsinfoDb *db,
+                                       OsinfoTree *tree,
+                                       OsinfoTree **matched_tree);
+
 // Get me all unique values for property "vendor" among operating systems
 GList *osinfo_db_unique_values_for_property_in_os(OsinfoDb *db, const gchar *propName);
 
diff --git a/osinfo/osinfo_loader.c b/osinfo/osinfo_loader.c
index cb3f19e..9517ec9 100644
--- a/osinfo/osinfo_loader.c
+++ b/osinfo/osinfo_loader.c
@@ -548,6 +548,64 @@ static OsinfoMedia *osinfo_loader_media (OsinfoLoader *loader,
     return media;
 }
 
+static OsinfoTree *osinfo_loader_tree (OsinfoLoader *loader,
+                                         xmlXPathContextPtr ctxt,
+                                         xmlNodePtr root,
+                                         const gchar *id,
+                                         GError **err)
+{
+    xmlNodePtr *nodes = NULL;
+    guint i;
+
+    gchar *arch = (gchar *)xmlGetProp(root, BAD_CAST "arch");
+    const gchar *const keys[] = {
+        OSINFO_TREE_PROP_URL,
+        OSINFO_TREE_PROP_KERNEL,
+        OSINFO_TREE_PROP_INITRD,
+        OSINFO_TREE_PROP_BOOT_ISO,
+        NULL
+    };
+
+    OsinfoTree *tree = osinfo_tree_new(id, arch);
+
+    osinfo_loader_entity(loader, OSINFO_ENTITY(tree), keys, ctxt, root, err);
+
+    gint nnodes = osinfo_loader_nodeset("./treeinfo/*", ctxt, &nodes, err);
+    if (error_is_set(err))
+        return NULL;
+
+    for (i = 0 ; i < nnodes ; i++) {
+        if (!nodes[i]->children ||
+            nodes[i]->children->type != XML_TEXT_NODE)
+            continue;
+
+        if (strcmp((const gchar *)nodes[i]->name,
+                   OSINFO_TREE_PROP_TREEINFO_FAMILY + 9) == 0)
+            osinfo_entity_set_param(OSINFO_ENTITY(tree),
+                                    OSINFO_TREE_PROP_TREEINFO_FAMILY,
+                                    (const gchar *)nodes[i]->children->content);
+        else if (strcmp((const gchar *)nodes[i]->name,
+                        OSINFO_TREE_PROP_TREEINFO_VARIANT + 9) == 0)
+            osinfo_entity_set_param(OSINFO_ENTITY(tree),
+                                    OSINFO_TREE_PROP_TREEINFO_VARIANT,
+                                    (const gchar *)nodes[i]->children->content);
+        else if (strcmp((const gchar *)nodes[i]->name,
+                        OSINFO_TREE_PROP_TREEINFO_VERSION + 9) == 0)
+            osinfo_entity_set_param(OSINFO_ENTITY(tree),
+                                    OSINFO_TREE_PROP_TREEINFO_VERSION,
+                                    (const gchar *)nodes[i]->children->content);
+        else if (strcmp((const gchar *)nodes[i]->name,
+                        OSINFO_TREE_PROP_TREEINFO_ARCH + 9) == 0)
+            osinfo_entity_set_param(OSINFO_ENTITY(tree),
+                                    OSINFO_TREE_PROP_TREEINFO_ARCH,
+                                    (const gchar *)nodes[i]->children->content);
+    }
+
+    g_free(nodes);
+
+    return tree;
+}
+
 static OsinfoResources *osinfo_loader_resources(OsinfoLoader *loader,
                                                 xmlXPathContextPtr ctxt,
                                                 xmlNodePtr root,
@@ -672,6 +730,25 @@ static void osinfo_loader_os(OsinfoLoader *loader,
 
     g_free(nodes);
 
+    nnodes = osinfo_loader_nodeset("./tree", ctxt, &nodes, err);
+    if (error_is_set(err))
+        goto cleanup;
+
+    for (i = 0 ; i < nnodes ; i++) {
+        xmlNodePtr saved = ctxt->node;
+        ctxt->node = nodes[i];
+        gchar *tree_id = g_strdup_printf ("%s:%u", id, i);
+        OsinfoTree *tree = osinfo_loader_tree(loader, ctxt, nodes[i], tree_id, err);
+        g_free (tree_id);
+        ctxt->node = saved;
+        if (error_is_set(err))
+            break;
+
+        osinfo_os_add_tree (os, tree);
+    }
+
+    g_free(nodes);
+
     nnodes = osinfo_loader_nodeset("./resources", ctxt, &nodes, err);
     if (error_is_set(err))
         goto cleanup;
diff --git a/osinfo/osinfo_os.c b/osinfo/osinfo_os.c
index 39806d9..4954024 100644
--- a/osinfo/osinfo_os.c
+++ b/osinfo/osinfo_os.c
@@ -46,6 +46,7 @@ struct _OsinfoOsPrivate
     GList *deviceLinks;
 
     OsinfoMediaList *medias;
+    OsinfoTreeList *trees;
     OsinfoResourcesList *minimum;
     OsinfoResourcesList *recommended;
 };
@@ -97,6 +98,8 @@ osinfo_os_finalize (GObject *object)
 
     g_list_foreach(os->priv->deviceLinks, osinfo_device_link_free, NULL);
     g_list_free(os->priv->deviceLinks);
+    g_object_unref(os->priv->medias);
+    g_object_unref(os->priv->trees);
 
     /* Chain up to the parent class */
     G_OBJECT_CLASS (osinfo_os_parent_class)->finalize (object);
@@ -141,6 +144,7 @@ osinfo_os_init (OsinfoOs *os)
 
     os->priv->deviceLinks = NULL;
     os->priv->medias = osinfo_medialist_new ();
+    os->priv->trees = osinfo_treelist_new ();
     os->priv->minimum = osinfo_resourceslist_new ();
     os->priv->recommended = osinfo_resourceslist_new ();
 }
@@ -377,6 +381,40 @@ void osinfo_os_add_media(OsinfoOs *os, OsinfoMedia *media)
 }
 
 /**
+ * osinfo_os_get_tree_list:
+ * @os: an operating system
+ *
+ * Get all installation trees associated with operating system @os.
+ *
+ * Returns: (transfer full): A list of trees
+ */
+OsinfoTreeList *osinfo_os_get_tree_list(OsinfoOs *os)
+{
+    g_return_val_if_fail(OSINFO_IS_OS(os), NULL);
+
+    OsinfoTreeList *newList = osinfo_treelist_new();
+
+    osinfo_list_add_all(OSINFO_LIST(newList), OSINFO_LIST(os->priv->trees));
+
+    return newList;
+}
+
+/**
+ * osinfo_os_add_tree:
+ * @os: an operating system
+ * @tree: (transfer none): the tree to add
+ *
+ * Adds installation tree @tree to operating system @os.
+ */
+void osinfo_os_add_tree(OsinfoOs *os, OsinfoTree *tree)
+{
+    g_return_if_fail(OSINFO_IS_OS(os));
+    g_return_if_fail(OSINFO_IS_TREE(tree));
+
+    osinfo_list_add(OSINFO_LIST(os->priv->trees), OSINFO_ENTITY(tree));
+}
+
+/**
  * osinfo_os_get_minimum_resources:
  * @os: an operating system
  *
diff --git a/osinfo/osinfo_os.h b/osinfo/osinfo_os.h
index 13c1aba..d4af9e8 100644
--- a/osinfo/osinfo_os.h
+++ b/osinfo/osinfo_os.h
@@ -28,6 +28,8 @@
 #include <osinfo/osinfo_devicelist.h>
 #include <osinfo/osinfo_medialist.h>
 #include <osinfo/osinfo_media.h>
+#include <osinfo/osinfo_treelist.h>
+#include <osinfo/osinfo_tree.h>
 #include <osinfo/osinfo_resources.h>
 #include <osinfo/osinfo_resourceslist.h>
 
@@ -87,6 +89,8 @@ OsinfoDeviceLink *osinfo_os_add_device(OsinfoOs *os, OsinfoDevice *dev);
 const gchar *osinfo_os_get_family(OsinfoOs *os);
 OsinfoMediaList *osinfo_os_get_media_list(OsinfoOs *os);
 void osinfo_os_add_media(OsinfoOs *os, OsinfoMedia *media);
+OsinfoTreeList *osinfo_os_get_tree_list(OsinfoOs *os);
+void osinfo_os_add_tree(OsinfoOs *os, OsinfoTree *tree);
 OsinfoResourcesList *osinfo_os_get_minimum_resources(OsinfoOs *os);
 OsinfoResourcesList *osinfo_os_get_recommended_resources(OsinfoOs *os);
 void osinfo_os_add_minimum_resources(OsinfoOs *os, OsinfoResources *resources);
diff --git a/osinfo/osinfo_tree.c b/osinfo/osinfo_tree.c
new file mode 100644
index 0000000..0ec4f5b
--- /dev/null
+++ b/osinfo/osinfo_tree.c
@@ -0,0 +1,870 @@
+/*
+ * libosinfo: An installation tree for a (guest) OS
+ *
+ * Copyright (C) 2009-2011 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.1 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
+ *
+ * Authors:
+ *   Zeeshan Ali <zeenix at redhat.com>
+ *   Arjun Roy <arroy at redhat.com>
+ *   Daniel P. Berrange <berrange at redhat.com>
+ */
+
+#include <osinfo/osinfo.h>
+#include <gio/gio.h>
+#include <stdlib.h>
+#include <string.h>
+
+typedef struct _CreateFromLocationAsyncData CreateFromLocationAsyncData;
+struct _CreateFromLocationAsyncData {
+    GFile *file;
+    gchar *location;
+
+    gint priority;
+    GCancellable *cancellable;
+
+    GSimpleAsyncResult *res;
+
+    OsinfoTree *tree;
+};
+
+static void create_from_location_async_data_free(CreateFromLocationAsyncData *data)
+{
+    if (data->tree)
+    g_object_unref(data->tree);
+    g_object_unref(data->file);
+    g_clear_object(&data->cancellable);
+    g_object_unref(data->res);
+
+    g_slice_free(CreateFromLocationAsyncData, data);
+}
+
+typedef struct _CreateFromLocationData CreateFromLocationData;
+struct _CreateFromLocationData {
+    GMainLoop *main_loop;
+
+    GAsyncResult *res;
+};
+
+static void create_from_location_data_free(CreateFromLocationData *data)
+{
+    g_object_unref(data->res);
+    g_main_loop_unref(data->main_loop);
+
+    g_slice_free(CreateFromLocationData, data);
+}
+
+GQuark
+osinfo_tree_error_quark (void)
+{
+    static GQuark quark = 0;
+
+    if (!quark)
+        quark = g_quark_from_static_string ("osinfo-tree-error");
+
+    return quark;
+}
+
+G_DEFINE_TYPE (OsinfoTree, osinfo_tree, OSINFO_TYPE_ENTITY);
+
+#define OSINFO_TREE_GET_PRIVATE(obj)                    \
+    (G_TYPE_INSTANCE_GET_PRIVATE ((obj),                \
+                                  OSINFO_TYPE_TREE,     \
+                                  OsinfoTreePrivate))
+
+/**
+ * SECTION:osinfo_tree
+ * @short_description: An installation tree for a (guest) OS
+ * @see_also: #OsinfoOs
+ *
+ * #OsinfoTree is an entity representing an installation tree
+ * a (guest) operating system.
+ */
+
+struct _OsinfoTreePrivate
+{
+    gboolean unused;
+};
+
+enum {
+    PROP_0,
+
+    PROP_ARCHITECTURE,
+    PROP_URL,
+    PROP_TREEINFO_FAMILY,
+    PROP_TREEINFO_VARIANT,
+    PROP_TREEINFO_VERSION,
+    PROP_TREEINFO_ARCH,
+    PROP_KERNEL_PATH,
+    PROP_INITRD_PATH,
+    PROP_BOOT_ISO_PATH,
+};
+
+static void
+osinfo_tree_get_property(GObject *object,
+                         guint property_id,
+                         GValue *value,
+                         GParamSpec *pspec)
+{
+    OsinfoTree *tree = OSINFO_TREE(object);
+
+    switch (property_id) {
+    case PROP_ARCHITECTURE:
+        g_value_set_string(value,
+                           osinfo_tree_get_architecture(tree));
+        break;
+
+    case PROP_URL:
+        g_value_set_string(value,
+                           osinfo_tree_get_url(tree));
+        break;
+
+    case PROP_TREEINFO_FAMILY:
+        g_value_set_string(value,
+                           osinfo_tree_get_treeinfo_family(tree));
+        break;
+
+    case PROP_TREEINFO_VARIANT:
+        g_value_set_string(value,
+                           osinfo_tree_get_treeinfo_variant(tree));
+        break;
+
+    case PROP_TREEINFO_VERSION:
+        g_value_set_string(value,
+                           osinfo_tree_get_treeinfo_version(tree));
+        break;
+
+    case PROP_TREEINFO_ARCH:
+        g_value_set_string(value,
+                           osinfo_tree_get_treeinfo_arch(tree));
+        break;
+
+    case PROP_KERNEL_PATH:
+        g_value_set_string(value,
+                           osinfo_tree_get_kernel_path(tree));
+        break;
+
+    case PROP_INITRD_PATH:
+        g_value_set_string(value,
+                           osinfo_tree_get_initrd_path(tree));
+        break;
+
+    case PROP_BOOT_ISO_PATH:
+        g_value_set_string(value,
+                           osinfo_tree_get_boot_iso_path(tree));
+        break;
+
+    default:
+        /* We don't have any other property... */
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
+        break;
+    }
+}
+
+
+static void
+osinfo_tree_set_property(GObject      *object,
+                         guint         property_id,
+                         const GValue *value,
+                         GParamSpec   *pspec)
+{
+    OsinfoTree *tree = OSINFO_TREE(object);
+
+    switch (property_id) {
+    case PROP_ARCHITECTURE:
+        osinfo_entity_set_param(OSINFO_ENTITY(tree),
+                                OSINFO_TREE_PROP_ARCHITECTURE,
+                                g_value_get_string(value));
+        break;
+
+    case PROP_URL:
+        osinfo_entity_set_param(OSINFO_ENTITY(tree),
+                                OSINFO_TREE_PROP_URL,
+                                g_value_get_string(value));
+        break;
+
+    case PROP_TREEINFO_FAMILY:
+        osinfo_entity_set_param(OSINFO_ENTITY(tree),
+                                OSINFO_TREE_PROP_TREEINFO_FAMILY,
+                                g_value_get_string(value));
+        break;
+
+    case PROP_TREEINFO_VARIANT:
+        osinfo_entity_set_param(OSINFO_ENTITY(tree),
+                                OSINFO_TREE_PROP_TREEINFO_VARIANT,
+                                g_value_get_string(value));
+        break;
+
+    case PROP_TREEINFO_VERSION:
+        osinfo_entity_set_param(OSINFO_ENTITY(tree),
+                                OSINFO_TREE_PROP_TREEINFO_VERSION,
+                                g_value_get_string(value));
+        break;
+
+    case PROP_TREEINFO_ARCH:
+        osinfo_entity_set_param(OSINFO_ENTITY(tree),
+                                OSINFO_TREE_PROP_TREEINFO_ARCH,
+                                g_value_get_string(value));
+        break;
+
+    case PROP_KERNEL_PATH:
+        osinfo_entity_set_param(OSINFO_ENTITY(tree),
+                                OSINFO_TREE_PROP_KERNEL,
+                                g_value_get_string(value));
+        break;
+
+    case PROP_INITRD_PATH:
+        osinfo_entity_set_param(OSINFO_ENTITY(tree),
+                                OSINFO_TREE_PROP_INITRD,
+                                g_value_get_string(value));
+        break;
+
+    case PROP_BOOT_ISO_PATH:
+        osinfo_entity_set_param(OSINFO_ENTITY(tree),
+                                OSINFO_TREE_PROP_BOOT_ISO,
+                                g_value_get_string(value));
+        break;
+
+    default:
+        /* We don't have any other property... */
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
+        break;
+    }
+}
+
+static void
+osinfo_tree_finalize(GObject *object)
+{
+    /* Chain up to the parent class */
+    G_OBJECT_CLASS(osinfo_tree_parent_class)->finalize(object);
+}
+
+/* Init functions */
+static void
+osinfo_tree_class_init(OsinfoTreeClass *klass)
+{
+    GObjectClass *g_klass = G_OBJECT_CLASS(klass);
+    GParamSpec *pspec;
+
+    g_klass->finalize = osinfo_tree_finalize;
+    g_klass->get_property = osinfo_tree_get_property;
+    g_klass->set_property = osinfo_tree_set_property;
+    g_type_class_add_private(klass, sizeof(OsinfoTreePrivate));
+
+    /**
+     * OsinfoTree::architecture:
+     *
+     * The target hardware architecture of this tree.
+     */
+    pspec = g_param_spec_string("architecture",
+                                "ARCHITECTURE",
+                                "CPU Architecture",
+                                NULL /* default value */,
+                                G_PARAM_READWRITE |
+                                G_PARAM_STATIC_NAME |
+                                G_PARAM_STATIC_NICK |
+                                G_PARAM_STATIC_BLURB);
+    g_object_class_install_property(g_klass, PROP_ARCHITECTURE, pspec);
+
+    /**
+     * OsinfoTree::url
+     *
+     * The URL to this tree.
+     */
+    pspec = g_param_spec_string("url",
+                                "URL",
+                                "The URL to this tree",
+                                NULL /* default value */,
+                                G_PARAM_READWRITE |
+                                G_PARAM_STATIC_NAME |
+                                G_PARAM_STATIC_NICK |
+                                G_PARAM_STATIC_BLURB);
+    g_object_class_install_property(g_klass, PROP_URL, pspec);
+
+    /**
+     * OsinfoTree::volume-id
+     *
+     * Expected volume ID (regular expression) for ISO9660 image/device.
+     */
+    pspec = g_param_spec_string("volume-id",
+                                "VolumeID",
+                                "Expected ISO9660 volume ID",
+                                NULL /* default value */,
+                                G_PARAM_READWRITE |
+                                G_PARAM_STATIC_NAME |
+                                G_PARAM_STATIC_NICK |
+                                G_PARAM_STATIC_BLURB);
+    g_object_class_install_property(g_klass, PROP_TREEINFO_FAMILY, pspec);
+
+    /**
+     * OsinfoTree::publisher-id
+     *
+     * Expected publisher ID (regular expression) for ISO9660 image/device.
+     */
+    pspec = g_param_spec_string("publisher-id",
+                                "PublisherID",
+                                "Expected ISO9660 publisher ID",
+                                NULL /* default value */,
+                                G_PARAM_READWRITE |
+                                G_PARAM_STATIC_NAME |
+                                G_PARAM_STATIC_NICK |
+                                G_PARAM_STATIC_BLURB);
+    g_object_class_install_property(g_klass, PROP_TREEINFO_VARIANT, pspec);
+
+    /**
+     * OsinfoTree::application-id
+     *
+     * Expected application ID (regular expression) for ISO9660 image/device.
+     */
+    pspec = g_param_spec_string("application-id",
+                                "ApplicationID",
+                                "Expected ISO9660 application ID",
+                                NULL /* default value */,
+                                G_PARAM_READWRITE |
+                                G_PARAM_STATIC_NAME |
+                                G_PARAM_STATIC_NICK |
+                                G_PARAM_STATIC_BLURB);
+    g_object_class_install_property(g_klass, PROP_TREEINFO_VERSION, pspec);
+
+    /**
+     * OsinfoTree::system-id
+     *
+     * Expected system ID (regular expression) for ISO9660 image/device.
+     */
+    pspec = g_param_spec_string("system-id",
+                                "SystemID",
+                                "Expected ISO9660 system ID",
+                                NULL /* default value */,
+                                G_PARAM_READWRITE |
+                                G_PARAM_STATIC_NAME |
+                                G_PARAM_STATIC_NICK |
+                                G_PARAM_STATIC_BLURB);
+    g_object_class_install_property(g_klass, PROP_TREEINFO_ARCH, pspec);
+
+    /**
+     * OsinfoTree::kernel-path
+     *
+     * The path to the kernel image in the install tree.
+     */
+    pspec = g_param_spec_string("kernel-path",
+                                "KernelPath",
+                                "The path to the kernel image",
+                                NULL /* default value */,
+                                G_PARAM_READWRITE |
+                                G_PARAM_STATIC_NAME |
+                                G_PARAM_STATIC_NICK |
+                                G_PARAM_STATIC_BLURB);
+    g_object_class_install_property(g_klass, PROP_KERNEL_PATH, pspec);
+
+    /**
+     * OsinfoTree::initrd-path
+     *
+     * The path to the initrd image in the install tree.
+     */
+    pspec = g_param_spec_string("initrd-path",
+                                "InitrdPath",
+                                "The path to the inirtd image",
+                                NULL /* default value */,
+                                G_PARAM_READWRITE |
+                                G_PARAM_STATIC_NAME |
+                                G_PARAM_STATIC_NICK |
+                                G_PARAM_STATIC_BLURB);
+    g_object_class_install_property(g_klass, PROP_INITRD_PATH, pspec);
+
+    /**
+     * OsinfoTree::boot-iso-path
+     *
+     * The path to the boot ISO in the install tree
+     */
+    pspec = g_param_spec_string("boot-iso-path",
+                                "BootISOPath",
+                                "The path to the bootable ISO image",
+                                NULL /* default value */,
+                                G_PARAM_READWRITE |
+                                G_PARAM_STATIC_NAME |
+                                G_PARAM_STATIC_NICK |
+                                G_PARAM_STATIC_BLURB);
+    g_object_class_install_property(g_klass, PROP_BOOT_ISO_PATH, pspec);
+
+}
+
+static void
+osinfo_tree_init(OsinfoTree *tree)
+{
+    OsinfoTreePrivate *priv;
+    tree->priv = priv = OSINFO_TREE_GET_PRIVATE(tree);
+}
+
+OsinfoTree *osinfo_tree_new(const gchar *id,
+                            const gchar *architecture)
+{
+    OsinfoTree *tree;
+
+    tree = g_object_new(OSINFO_TYPE_TREE,
+                        "id", id,
+                        NULL);
+
+    osinfo_entity_set_param(OSINFO_ENTITY(tree),
+                            OSINFO_TREE_PROP_ARCHITECTURE,
+                            architecture);
+
+    return tree;
+}
+
+static void on_tree_create_from_location_ready(GObject *source_object,
+                                               GAsyncResult *res,
+                                               gpointer user_data)
+{
+    CreateFromLocationData *data = (CreateFromLocationData *)user_data;
+
+    data->res = g_object_ref(res);
+
+    g_main_loop_quit(data->main_loop);
+}
+
+/**
+ * osinfo_tree_create_from_location:
+ * @location: the location of an installation tree
+ * @cancellable: (allow-none): a #GCancellable, or %NULL
+ * @error: The location where to store any error, or %NULL
+ *
+ * Creates a new #OsinfoTree for installation tree at @location. The @location
+ * could be any URI that GIO can handle or a local path.
+ *
+ * NOTE: Currently this only works for trees with a .treeinfo file
+ *
+ * Returns: (transfer full): a new #OsinfoTree , or NULL on error
+ */
+OsinfoTree *osinfo_tree_create_from_location(const gchar *location,
+                                             GCancellable *cancellable,
+                                             GError **error)
+{
+    CreateFromLocationData *data;
+    OsinfoTree *ret;
+
+    data = g_slice_new0(CreateFromLocationData);
+    data->main_loop = g_main_loop_new(g_main_context_get_thread_default(),
+                                      TRUE);
+
+    osinfo_tree_create_from_location_async(location,
+                                           G_PRIORITY_DEFAULT,
+                                           cancellable,
+                                           on_tree_create_from_location_ready,
+                                           data);
+
+    /* Loop till we get a reply (or time out) */
+    if (g_main_loop_is_running(data->main_loop))
+        g_main_loop_run(data->main_loop);
+
+    ret = osinfo_tree_create_from_location_finish(data->res, error);
+    create_from_location_data_free(data);
+
+    return ret;
+}
+
+static gboolean is_str_empty(const gchar *str) {
+    guint8 i;
+    gboolean ret = TRUE;
+
+    if ((str == NULL) || (*str == 0))
+        return TRUE;
+
+    for (i = 0; i < strlen(str); i++)
+        if (!g_ascii_isspace(str[i])) {
+            ret = FALSE;
+
+            break;
+        }
+
+    return ret;
+}
+
+
+static OsinfoTree *load_keyinfo(const gchar *location,
+                                const gchar *content,
+                                gsize length,
+                                GError **error)
+{
+    GKeyFile *file = g_key_file_new();
+    OsinfoTree *tree = NULL;
+    gchar *family = NULL;
+    gchar *variant = NULL;
+    gchar *version = NULL;
+    gchar *arch = NULL;
+    gchar *kernel = NULL;
+    gchar *initrd = NULL;
+    gchar *bootiso = NULL;
+    gchar *group = NULL;
+
+    if (!g_key_file_load_from_data(file, content, length,
+                                   G_KEY_FILE_NONE, error))
+        goto cleanup;
+
+    if (!(family = g_key_file_get_string(file, "general", "family", error)) &&
+        (*error && (*error)->code != G_KEY_FILE_ERROR_KEY_NOT_FOUND &&
+         (*error)->code != G_KEY_FILE_ERROR_GROUP_NOT_FOUND))
+        goto cleanup;
+
+    if (!(variant = g_key_file_get_string(file, "general", "variant", error)) &&
+        (*error && (*error)->code != G_KEY_FILE_ERROR_KEY_NOT_FOUND &&
+         (*error)->code != G_KEY_FILE_ERROR_GROUP_NOT_FOUND))
+        goto cleanup;
+
+    if (!(version = g_key_file_get_string(file, "general", "version", error)) &&
+        (*error && (*error)->code != G_KEY_FILE_ERROR_KEY_NOT_FOUND &&
+         (*error)->code != G_KEY_FILE_ERROR_GROUP_NOT_FOUND))
+        goto cleanup;
+
+    if (!(arch = g_key_file_get_string(file, "general", "arch", error)) &&
+        (*error && (*error)->code != G_KEY_FILE_ERROR_KEY_NOT_FOUND &&
+         (*error)->code != G_KEY_FILE_ERROR_GROUP_NOT_FOUND))
+        goto cleanup;
+
+
+    if (arch) {
+        group = g_strdup_printf("images-%s", arch);
+
+        if (!(kernel = g_key_file_get_string(file, group, "kernel", error)) &&
+            (*error && (*error)->code != G_KEY_FILE_ERROR_KEY_NOT_FOUND &&
+             (*error)->code != G_KEY_FILE_ERROR_GROUP_NOT_FOUND))
+            goto cleanup;
+
+        if (!(initrd = g_key_file_get_string(file, group, "initrd", error)) &&
+            (*error && (*error)->code != G_KEY_FILE_ERROR_KEY_NOT_FOUND &&
+             (*error)->code != G_KEY_FILE_ERROR_GROUP_NOT_FOUND))
+            goto cleanup;
+
+        if (!(bootiso = g_key_file_get_string(file, group, "boot.iso", error)) &&
+            (*error && (*error)->code != G_KEY_FILE_ERROR_KEY_NOT_FOUND &&
+             (*error)->code != G_KEY_FILE_ERROR_GROUP_NOT_FOUND))
+            goto cleanup;
+    }
+
+    tree = osinfo_tree_new(location, arch ? arch : "i386");
+
+    osinfo_entity_set_param(OSINFO_ENTITY(tree),
+                            OSINFO_TREE_PROP_URL,
+                            location);
+
+    if (!is_str_empty(family))
+        osinfo_entity_set_param(OSINFO_ENTITY(tree),
+                                OSINFO_TREE_PROP_TREEINFO_FAMILY,
+                                family);
+    if (!is_str_empty(variant))
+        osinfo_entity_set_param(OSINFO_ENTITY(tree),
+                                OSINFO_TREE_PROP_TREEINFO_VARIANT,
+                                variant);
+    if (!is_str_empty(version))
+        osinfo_entity_set_param(OSINFO_ENTITY(tree),
+                                OSINFO_TREE_PROP_TREEINFO_VERSION,
+                                version);
+    if (!is_str_empty(arch))
+        osinfo_entity_set_param(OSINFO_ENTITY(tree),
+                                OSINFO_TREE_PROP_TREEINFO_ARCH,
+                                arch);
+    if (!is_str_empty(kernel))
+        osinfo_entity_set_param(OSINFO_ENTITY(tree),
+                                OSINFO_TREE_PROP_KERNEL,
+                                kernel);
+    if (!is_str_empty(initrd))
+        osinfo_entity_set_param(OSINFO_ENTITY(tree),
+                                OSINFO_TREE_PROP_INITRD,
+                                initrd);
+    if (!is_str_empty(bootiso))
+        osinfo_entity_set_param(OSINFO_ENTITY(tree),
+                                OSINFO_TREE_PROP_BOOT_ISO,
+                                bootiso);
+
+ cleanup:
+    g_free(family);
+    g_free(variant);
+    g_free(version);
+    g_free(arch);
+    g_free(kernel);
+    g_free(initrd);
+    g_free(bootiso);
+    g_key_file_free(file);
+    return tree;
+}
+
+
+static void on_location_read(GObject *source,
+                             GAsyncResult *res,
+                             gpointer user_data)
+{
+    CreateFromLocationAsyncData *data;
+    GError *error = NULL;
+    gchar *content = NULL;
+    gsize length = 0;
+    OsinfoTree *ret = NULL;
+
+    data = (CreateFromLocationAsyncData *)user_data;
+
+    if (!g_file_load_contents_finish(G_FILE(source),
+                                     res,
+                                     &content,
+                                     &length,
+                                     NULL,
+                                     &error)) {
+        g_prefix_error(&error, "Failed to load .treeinfo file: ");
+        g_simple_async_result_take_error(data->res, error);
+        g_simple_async_result_complete(data->res);
+        create_from_location_async_data_free(data);
+        return;
+    }
+
+    if (!(ret = load_keyinfo(data->location,
+                             content,
+                             length,
+                             &error))) {
+        g_prefix_error(&error, "Failed to process keyinfo file: ");
+        g_simple_async_result_take_error(data->res, error);
+        goto cleanup;
+    }
+
+    g_simple_async_result_set_op_res_gpointer(data->res, ret, NULL);
+
+ cleanup:
+    g_simple_async_result_complete (data->res);
+    create_from_location_async_data_free(data);
+    g_free(content);
+}
+
+/**
+ * osinfo_tree_create_from_location_async:
+ * @location: the location of an installation tree
+ * @priority: the I/O priority of the request
+ * @cancellable: (allow-none): a #GCancellable, or %NULL
+ * @callback: Function to call when result of this call is ready
+ * @user_data: The user data to pass to @callback, or %NULL
+ *
+ * Asynchronous variant of #osinfo_tree_create_from_location.
+ */
+void osinfo_tree_create_from_location_async(const gchar *location,
+                                            gint priority,
+                                            GCancellable *cancellable,
+                                            GAsyncReadyCallback callback,
+                                            gpointer user_data)
+{
+    CreateFromLocationAsyncData *data;
+    gchar *treeinfo;
+
+    g_return_if_fail(location != NULL);
+
+    treeinfo = g_strdup_printf("%s/.treeinfo", location);
+
+    data = g_slice_new0(CreateFromLocationAsyncData);
+    data->res = g_simple_async_result_new
+        (NULL,
+         callback,
+         user_data,
+         osinfo_tree_create_from_location_async);
+    data->file = g_file_new_for_uri(treeinfo);
+    data->location = g_strdup(location);
+    data->priority = priority;
+    data->cancellable = cancellable;
+
+    /* XXX priority ? */
+    /* XXX probe other things besides just tree info */
+    g_file_load_contents_async(data->file,
+                               cancellable,
+                               on_location_read,
+                               data);
+
+    g_free(treeinfo);
+}
+
+
+/**
+ * osinfo_tree_create_from_location_finish:
+ * @res: a #GAsyncResult
+ * @error: The location where to store any error, or %NULL
+ *
+ * Finishes an asynchronous tree object creation process started with
+ * #osinfo_tree_create_from_location_async.
+ *
+ * Returns: (transfer full): a new #OsinfoTree , or NULL on error
+ */
+OsinfoTree *osinfo_tree_create_from_location_finish(GAsyncResult *res,
+                                                    GError **error)
+{
+    GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT(res);
+
+    g_return_val_if_fail(error == NULL || *error == NULL, NULL);
+
+    if (g_simple_async_result_propagate_error(simple, error))
+        return NULL;
+
+    return g_simple_async_result_get_op_res_gpointer(simple);
+}
+
+/**
+ * osinfo_tree_get_architecture:
+ * @tree: a #OsinfoTree instance
+ *
+ * Retrieves the target hardware architecture of the OS @tree provides.
+ *
+ * Returns: (transfer none): the hardware architecture, or NULL
+ */
+const gchar *osinfo_tree_get_architecture(OsinfoTree *tree)
+{
+    return osinfo_entity_get_param_value(OSINFO_ENTITY(tree),
+                                         OSINFO_TREE_PROP_ARCHITECTURE);
+}
+
+/**
+ * osinfo_tree_get_url:
+ * @tree: a #OsinfoTree instance
+ *
+ * The URL to the @tree
+ *
+ * Returns: (transfer none): the URL, or NULL
+ */
+const gchar *osinfo_tree_get_url(OsinfoTree *tree)
+{
+    return osinfo_entity_get_param_value(OSINFO_ENTITY(tree),
+                                         OSINFO_TREE_PROP_URL);
+}
+
+/**
+ * osinfo_tree_get_treeinfo_family:
+ * @tree: a #OsinfoTree instance
+ *
+ * If @tree is an ISO9660 image/device, this function retrieves the expected
+ * volume ID.
+ *
+ * Note: In practice, this will usually not be the exact copy of the volume ID
+ * string on the ISO image/device but rather a regular expression that matches
+ * it.
+ *
+ * Returns: (transfer none): the volume id, or NULL
+ */
+const gchar *osinfo_tree_get_treeinfo_family(OsinfoTree *tree)
+{
+    return osinfo_entity_get_param_value(OSINFO_ENTITY(tree),
+                                         OSINFO_TREE_PROP_TREEINFO_FAMILY);
+}
+
+/**
+ * osinfo_tree_get_treeinfo_arch:
+ * @tree: a #OsinfoTree instance
+ *
+ * If @tree is an ISO9660 image/device, this function retrieves the expected
+ * system ID.
+ *
+ * Note: In practice, this will usually not be the exact copy of the system ID
+ * string on the ISO image/device but rather a regular expression that matches
+ * it.
+ *
+ * Returns: (transfer none): the system id, or NULL
+ */
+const gchar *osinfo_tree_get_treeinfo_arch(OsinfoTree *tree)
+{
+    return osinfo_entity_get_param_value(OSINFO_ENTITY(tree),
+                                         OSINFO_TREE_PROP_TREEINFO_ARCH);
+}
+
+/**
+ * osinfo_tree_get_treeinfo_variant:
+ * @tree: a #OsinfoTree instance
+ *
+ * If @tree is an ISO9660 image/device, this function retrieves the expected
+ * publisher ID.
+ *
+ * Note: In practice, this will usually not be the exact copy of the publisher
+ * ID string on the ISO image/device but rather a regular expression that
+ * matches it.
+ *
+ * Returns: (transfer none): the publisher id, or NULL
+ */
+const gchar *osinfo_tree_get_treeinfo_variant(OsinfoTree *tree)
+{
+    return osinfo_entity_get_param_value(OSINFO_ENTITY(tree),
+                                         OSINFO_TREE_PROP_TREEINFO_VARIANT);
+}
+
+/**
+ * osinfo_tree_get_treeinfo_version:
+ * @tree: a #OsinfoTree instance
+ *
+ * If @tree is an ISO9660 image/device, this function retrieves the expected
+ * application ID.
+ *
+ * Note: In practice, this will usually not be the exact copy of the application
+ * ID string on the ISO image/device but rather a regular expression that
+ * matches it.
+ *
+ * Returns: (transfer none): the application id, or NULL
+ */
+const gchar *osinfo_tree_get_treeinfo_version(OsinfoTree *tree)
+{
+    return osinfo_entity_get_param_value(OSINFO_ENTITY(tree),
+                                         OSINFO_TREE_PROP_TREEINFO_VERSION);
+}
+
+/**
+ * osinfo_tree_get_boot_iso_path:
+ * @tree: a #OsinfoTree instance
+ *
+ * Retrieves the path to the boot_iso image in the install tree.
+ *
+ * Returns: (transfer none): the path to boot_iso image, or NULL
+ */
+const gchar *osinfo_tree_get_boot_iso_path(OsinfoTree *tree)
+{
+    return osinfo_entity_get_param_value(OSINFO_ENTITY(tree),
+                                         OSINFO_TREE_PROP_BOOT_ISO);
+}
+
+/**
+ * osinfo_tree_get_kernel_path:
+ * @tree: a #OsinfoTree instance
+ *
+ * Retrieves the path to the kernel image in the install tree.
+ *
+ * Note: This only applies to installer trees of 'Linux' OS family.
+ *
+ * Returns: (transfer none): the path to kernel image, or NULL
+ */
+const gchar *osinfo_tree_get_kernel_path(OsinfoTree *tree)
+{
+    return osinfo_entity_get_param_value(OSINFO_ENTITY(tree),
+                                         OSINFO_TREE_PROP_KERNEL);
+}
+
+/**
+ * osinfo_tree_get_initrd_path:
+ * @tree: a #OsinfoTree instance
+ *
+ * Retrieves the path to the initrd image in the install tree.
+ *
+ * Note: This only applies to installer trees of 'Linux' OS family.
+ *
+ * Returns: (transfer none): the path to initrd image, or NULL
+ */
+const gchar *osinfo_tree_get_initrd_path(OsinfoTree *tree)
+{
+    return osinfo_entity_get_param_value(OSINFO_ENTITY(tree),
+                                         OSINFO_TREE_PROP_INITRD);
+}
+
+/*
+ * Local variables:
+ *  indent-tabs-mode: nil
+ *  c-indent-level: 4
+ *  c-basic-offset: 4
+ * End:
+ */
diff --git a/osinfo/osinfo_tree.h b/osinfo/osinfo_tree.h
new file mode 100644
index 0000000..2cbdca8
--- /dev/null
+++ b/osinfo/osinfo_tree.h
@@ -0,0 +1,117 @@
+/*
+ * libosinfo: An installation tree for a (guest) OS
+ *
+ * Copyright (C) 2009-2011 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.1 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
+ *
+ * Authors:
+ *   Zeeshan Ali <zeenix at redhat.com>
+ *   Arjun Roy <arroy at redhat.com>
+ *   Daniel P. Berrange <berrange at redhat.com>
+ */
+
+#include <glib-object.h>
+#include <gio/gio.h>
+#include <osinfo/osinfo_entity.h>
+
+#ifndef __OSINFO_TREE_H__
+#define __OSINFO_TREE_H__
+
+GQuark
+osinfo_tree_error_quark (void) G_GNUC_CONST;
+
+#define OSINFO_TREE_ERROR (osinfo_tree_error_quark ())
+
+
+/*
+ * Type macros.
+ */
+#define OSINFO_TYPE_TREE                  (osinfo_tree_get_type ())
+#define OSINFO_TREE(obj)                  (G_TYPE_CHECK_INSTANCE_CAST ((obj), OSINFO_TYPE_TREE, OsinfoTree))
+#define OSINFO_IS_TREE(obj)               (G_TYPE_CHECK_INSTANCE_TYPE ((obj), OSINFO_TYPE_TREE))
+#define OSINFO_TREE_CLASS(klass)          (G_TYPE_CHECK_CLASS_CAST ((klass), OSINFO_TYPE_TREE, OsinfoTreeClass))
+#define OSINFO_IS_TREE_CLASS(klass)       (G_TYPE_CHECK_CLASS_TYPE ((klass), OSINFO_TYPE_TREE))
+#define OSINFO_TREE_GET_CLASS(obj)        (G_TYPE_INSTANCE_GET_CLASS ((obj), OSINFO_TYPE_TREE, OsinfoTreeClass))
+
+typedef struct _OsinfoTree        OsinfoTree;
+
+typedef struct _OsinfoTreeClass   OsinfoTreeClass;
+
+typedef struct _OsinfoTreePrivate OsinfoTreePrivate;
+
+#define OSINFO_TREE_PROP_ARCHITECTURE     "architecture"
+#define OSINFO_TREE_PROP_URL              "url"
+#define OSINFO_TREE_PROP_TREEINFO_FAMILY  "treeinfo-family"
+#define OSINFO_TREE_PROP_TREEINFO_VARIANT "treeinfo-variant"
+#define OSINFO_TREE_PROP_TREEINFO_VERSION "treeinfo-version"
+#define OSINFO_TREE_PROP_TREEINFO_ARCH    "treeinfo-arch"
+#define OSINFO_TREE_PROP_BOOT_ISO         "boot-iso"
+#define OSINFO_TREE_PROP_KERNEL           "kernel"
+#define OSINFO_TREE_PROP_INITRD           "initrd"
+
+/* object */
+struct _OsinfoTree
+{
+    OsinfoEntity parent_instance;
+
+    /* public */
+
+    /* private */
+    OsinfoTreePrivate *priv;
+};
+
+/* class */
+struct _OsinfoTreeClass
+{
+    OsinfoEntityClass parent_class;
+
+    /* class members */
+};
+
+GType osinfo_tree_get_type(void);
+
+OsinfoTree *osinfo_tree_new(const gchar *id, const gchar *architecture);
+OsinfoTree *osinfo_tree_create_from_location(const gchar *location,
+                                             GCancellable *cancellable,
+                                             GError **error);
+void osinfo_tree_create_from_location_async(const gchar *location,
+                                            gint priority,
+                                            GCancellable *cancellable,
+                                            GAsyncReadyCallback callback,
+                                            gpointer user_data);
+OsinfoTree *osinfo_tree_create_from_location_finish(GAsyncResult *res,
+                                                    GError **error);
+
+const gchar *osinfo_tree_get_architecture(OsinfoTree *tree);
+const gchar *osinfo_tree_get_url(OsinfoTree *tree);
+const gchar *osinfo_tree_get_treeinfo_family(OsinfoTree *tree);
+const gchar *osinfo_tree_get_treeinfo_variant(OsinfoTree *tree);
+const gchar *osinfo_tree_get_treeinfo_version(OsinfoTree *tree);
+const gchar *osinfo_tree_get_treeinfo_arch(OsinfoTree *tree);
+/* XXX list of files to probe for in absence of treeinfo ?  see virtinst isValidStore */
+const gchar *osinfo_tree_get_boot_iso_path(OsinfoTree *tree);
+const gchar *osinfo_tree_get_kernel_path(OsinfoTree *tree);
+const gchar *osinfo_tree_get_initrd_path(OsinfoTree *tree);
+/* XXX Xen kernel/initrd paths ? */
+
+#endif /* __OSINFO_TREE_H__ */
+/*
+ * Local variables:
+ *  indent-tabs-mode: nil
+ *  c-indent-level: 4
+ *  c-basic-offset: 4
+ * End:
+ */
diff --git a/osinfo/osinfo_treelist.c b/osinfo/osinfo_treelist.c
new file mode 100644
index 0000000..22dda16
--- /dev/null
+++ b/osinfo/osinfo_treelist.c
@@ -0,0 +1,167 @@
+/*
+ * libosinfo:
+ *
+ * Copyright (C) 2009-2011 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.1 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
+ *
+ * Authors:
+ *   Arjun Roy <arroy at redhat.com>
+ *   Daniel P. Berrange <berrange at redhat.com>
+ */
+
+#include <osinfo/osinfo.h>
+
+G_DEFINE_TYPE (OsinfoTreeList, osinfo_treelist, OSINFO_TYPE_LIST);
+
+#define OSINFO_TREELIST_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), OSINFO_TYPE_TREELIST, OsinfoTreeListPrivate))
+
+/**
+ * SECTION:osinfo_treelist
+ * @short_description: A list of installation tree
+ * @see_also: #OsinfoList, #OsinfoTree
+ *
+ * #OsinfoTreeList is a list specialization that stores
+ * only #OsinfoTree objects.
+ */
+
+struct _OsinfoTreeListPrivate
+{
+    gboolean unused;
+};
+
+static void
+osinfo_treelist_finalize (GObject *object)
+{
+    /* Chain up to the parent class */
+    G_OBJECT_CLASS (osinfo_treelist_parent_class)->finalize (object);
+}
+
+/* Init functions */
+static void
+osinfo_treelist_class_init (OsinfoTreeListClass *klass)
+{
+    GObjectClass *g_klass = G_OBJECT_CLASS (klass);
+
+    g_klass->finalize = osinfo_treelist_finalize;
+    g_type_class_add_private (klass, sizeof (OsinfoTreeListPrivate));
+}
+
+static void
+osinfo_treelist_init (OsinfoTreeList *list)
+{
+    OsinfoTreeListPrivate *priv;
+    list->priv = priv = OSINFO_TREELIST_GET_PRIVATE(list);
+
+}
+
+/**
+ * osinfo_treelist_new:
+ *
+ * Construct a new tree list that is initially empty.
+ *
+ * Returns: (transfer full): an empty tree list
+ */
+OsinfoTreeList *osinfo_treelist_new(void)
+{
+    return g_object_new(OSINFO_TYPE_TREELIST,
+                        "element-type", OSINFO_TYPE_TREE,
+                        NULL);
+}
+
+/**
+ * osinfo_treelist_new_copy:
+ * @source: the tree list to copy
+ *
+ * Construct a new tree list that is filled with trees
+ * from @source
+ *
+ * Returns: (transfer full): a copy of the tree list
+ */
+OsinfoTreeList *osinfo_treelist_new_copy(OsinfoTreeList *source)
+{
+    OsinfoTreeList *newList = osinfo_treelist_new();
+    osinfo_list_add_all(OSINFO_LIST(newList),
+                        OSINFO_LIST(source));
+    return newList;
+}
+
+/**
+ * osinfo_treelist_new_filtered:
+ * @source: the tree list to copy
+ * @filter: the filter to apply
+ *
+ * Construct a new tree list that is filled with trees
+ * from @source that match @filter
+ *
+ * Returns: (transfer full): a filtered copy of the tree list
+ */
+OsinfoTreeList *osinfo_treelist_new_filtered(OsinfoTreeList *source,
+                                               OsinfoFilter *filter)
+{
+    OsinfoTreeList *newList = osinfo_treelist_new();
+    osinfo_list_add_filtered(OSINFO_LIST(newList),
+                             OSINFO_LIST(source),
+                             filter);
+    return newList;
+}
+
+/**
+ * osinfo_treelist_new_intersection:
+ * @sourceOne: the first tree list to copy
+ * @sourceTwo: the second tree list to copy
+ *
+ * Construct a new tree list that is filled with only the
+ * trees that are present in both @sourceOne and @sourceTwo.
+ *
+ * Returns: (transfer full): an intersection of the two tree lists
+ */
+OsinfoTreeList *osinfo_treelist_new_intersection(OsinfoTreeList *sourceOne,
+                                                   OsinfoTreeList *sourceTwo)
+{
+    OsinfoTreeList *newList = osinfo_treelist_new();
+    osinfo_list_add_intersection(OSINFO_LIST(newList),
+                                 OSINFO_LIST(sourceOne),
+                                 OSINFO_LIST(sourceTwo));
+    return newList;
+}
+
+/**
+ * osinfo_treelist_new_union:
+ * @sourceOne: the first tree list to copy
+ * @sourceTwo: the second tree list to copy
+ *
+ * Construct a new tree list that is filled with all the
+ * trees that are present in either @sourceOne and @sourceTwo.
+ *
+ * Returns: (transfer full): a union of the two tree lists
+ */
+OsinfoTreeList *osinfo_treelist_new_union(OsinfoTreeList *sourceOne,
+					  OsinfoTreeList *sourceTwo)
+{
+    OsinfoTreeList *newList = osinfo_treelist_new();
+    osinfo_list_add_union(OSINFO_LIST(newList),
+                          OSINFO_LIST(sourceOne),
+                          OSINFO_LIST(sourceTwo));
+    return newList;
+}
+
+/*
+ * Local variables:
+ *  indent-tabs-mode: nil
+ *  c-indent-level: 4
+ *  c-basic-offset: 4
+ * End:
+ */
diff --git a/osinfo/osinfo_treelist.h b/osinfo/osinfo_treelist.h
new file mode 100644
index 0000000..702c4aa
--- /dev/null
+++ b/osinfo/osinfo_treelist.h
@@ -0,0 +1,82 @@
+/*
+ * libosinfo: a list of installation tree
+ *
+ * Copyright (C) 2009-2011 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.1 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
+ *
+ * Authors:
+ *   Zeeshan Ali <zeenix at redhat.com>
+ *   Arjun Roy <arroy at redhat.com>
+ *   Daniel P. Berrange <berrange at redhat.com>
+ */
+
+#include <glib-object.h>
+#include <osinfo/osinfo_list.h>
+
+#ifndef __OSINFO_TREELIST_H__
+#define __OSINFO_TREELIST_H__
+
+/*
+ * Type macros.
+ */
+#define OSINFO_TYPE_TREELIST                  (osinfo_treelist_get_type ())
+#define OSINFO_TREELIST(obj)                  (G_TYPE_CHECK_INSTANCE_CAST ((obj), OSINFO_TYPE_TREELIST, OsinfoTreeList))
+#define OSINFO_IS_TREELIST(obj)               (G_TYPE_CHECK_INSTANCE_TYPE ((obj), OSINFO_TYPE_TREELIST))
+#define OSINFO_TREELIST_CLASS(klass)          (G_TYPE_CHECK_CLASS_CAST ((klass), OSINFO_TYPE_TREELIST, OsinfoTreeListClass))
+#define OSINFO_IS_TREELIST_CLASS(klass)       (G_TYPE_CHECK_CLASS_TYPE ((klass), OSINFO_TYPE_TREELIST))
+#define OSINFO_TREELIST_GET_CLASS(obj)        (G_TYPE_INSTANCE_GET_CLASS ((obj), OSINFO_TYPE_TREELIST, OsinfoTreeListClass))
+
+typedef struct _OsinfoTreeList        OsinfoTreeList;
+
+typedef struct _OsinfoTreeListClass   OsinfoTreeListClass;
+
+typedef struct _OsinfoTreeListPrivate OsinfoTreeListPrivate;
+
+/* object */
+struct _OsinfoTreeList
+{
+    OsinfoList parent_instance;
+
+    /* public */
+
+    /* private */
+    OsinfoTreeListPrivate *priv;
+};
+
+/* class */
+struct _OsinfoTreeListClass
+{
+    OsinfoListClass parent_class;
+
+    /* class members */
+};
+
+GType osinfo_treelist_get_type(void);
+
+OsinfoTreeList *osinfo_treelist_new(void);
+OsinfoTreeList *osinfo_treelist_new_copy(OsinfoTreeList *source);
+OsinfoTreeList *osinfo_treelist_new_filtered(OsinfoTreeList *source, OsinfoFilter *filter);
+OsinfoTreeList *osinfo_treelist_new_intersection(OsinfoTreeList *sourceOne, OsinfoTreeList *sourceTwo);
+OsinfoTreeList *osinfo_treelist_new_union(OsinfoTreeList *sourceOne, OsinfoTreeList *sourceTwo);
+
+#endif /* __OSINFO_TREELIST_H__ */
+/*
+ * Local variables:
+ *  indent-tabs-mode: nil
+ *  c-indent-level: 4
+ *  c-basic-offset: 4
+ * End:
+ */
diff --git a/tools/osinfo-detect.c b/tools/osinfo-detect.c
index 5413dec..b9ce7ba 100644
--- a/tools/osinfo-detect.c
+++ b/tools/osinfo-detect.c
@@ -35,6 +35,16 @@ typedef enum {
 
 static OutputFormat format = OUTPUT_FORMAT_PLAIN;
 
+#define TYPE_STR_MEDIA "media"
+#define TYPE_STR_TREE "tree"
+
+typedef enum {
+    URL_TYPE_MEDIA,
+    URL_TYPE_TREE
+} OutputType;
+
+static OutputType type = URL_TYPE_MEDIA;
+
 static gboolean parse_format_str(const gchar *option_name,
                                  const gchar *value,
                                  gpointer data,
@@ -56,12 +66,37 @@ static gboolean parse_format_str(const gchar *option_name,
     return TRUE;
 }
 
+static gboolean parse_type_str(const gchar *option_name,
+				const gchar *value,
+				gpointer data,
+				GError **error)
+{
+    if (strcmp(value, TYPE_STR_MEDIA) == 0)
+        type = URL_TYPE_MEDIA;
+    else if (strcmp(value, TYPE_STR_TREE) == 0)
+        type = URL_TYPE_TREE;
+    else {
+        g_set_error(error,
+                    G_OPTION_ERROR,
+                    G_OPTION_ERROR_FAILED,
+                    "Invalid value '%s'", value);
+
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
 static GOptionEntry entries[] =
 {
     { "format", 'f', 0,
       G_OPTION_ARG_CALLBACK, parse_format_str,
       "Output format. Default: plain",
       "plain|env." },
+    { "type", 't', 0,
+      G_OPTION_ARG_CALLBACK, parse_type_str,
+      "URL type. Default: media",
+      "media|tree." },
     { NULL }
 };
 
@@ -79,7 +114,7 @@ static void print_bootable(gboolean bootable)
             g_print("Media is not bootable.\n");
 }
 
-static void print_os(OsinfoOs *os, OsinfoMedia *media)
+static void print_os_media(OsinfoOs *os, OsinfoMedia *media)
 {
     if (os == NULL)
         return;
@@ -103,12 +138,44 @@ static void print_os(OsinfoOs *os, OsinfoMedia *media)
     }
 }
 
+static void print_os_tree(OsinfoOs *os, OsinfoTree *tree, OsinfoTree *matched_tree)
+{
+    if (os == NULL)
+        return;
+
+    if (format == OUTPUT_FORMAT_ENV) {
+        const gchar *id = osinfo_entity_get_id(OSINFO_ENTITY(os));
+        const gchar *kernel = osinfo_tree_get_kernel_path(tree);
+        const gchar *initrd = osinfo_tree_get_initrd_path(tree);
+        const gchar *bootiso = osinfo_tree_get_boot_iso_path(tree);
+
+        if (!kernel)
+            kernel = osinfo_tree_get_kernel_path(matched_tree);
+        if (!initrd)
+            initrd = osinfo_tree_get_initrd_path(matched_tree);
+        if (!bootiso)
+            bootiso = osinfo_tree_get_boot_iso_path(matched_tree);
+
+        g_print("OSINFO_INSTALLER=%s\n", id);
+        g_print("OSINFO_TREE=%s\n",
+                osinfo_entity_get_id(OSINFO_ENTITY(matched_tree)));
+        if (kernel)
+            g_print("OSINFO_TREE_KERNEL=%s\n", kernel);
+        if (initrd)
+            g_print("OSINFO_TREE_INITRD=%s\n", initrd);
+        if (bootiso)
+            g_print("OSINFO_TREE_BOOT_ISO=%s\n", bootiso);
+    } else {
+        const gchar *name = osinfo_product_get_name(OSINFO_PRODUCT(os));
+
+        g_print("Tree is an installer for OS '%s'\n", name);
+    }
+}
+
 gint main(gint argc, gchar **argv)
 {
     GOptionContext *context;
     GError *error = NULL;
-    OsinfoMedia *media = NULL;
-    OsinfoMedia *matched_media = NULL;
     OsinfoLoader *loader = NULL;
     OsinfoDb *db = NULL;
     OsinfoOs *os = NULL;
@@ -135,18 +202,6 @@ gint main(gint argc, gchar **argv)
 
     g_type_init();
 
-    media = osinfo_media_create_from_location(argv[1], NULL, &error);
-    if (error != NULL) {
-        if (error->code != OSINFO_MEDIA_ERROR_NOT_BOOTABLE) {
-            g_printerr("Error parsing media: %s\n", error->message);
-
-            ret = -3;
-            goto EXIT;
-        } else
-            print_bootable(FALSE);
-    } else
-        print_bootable(TRUE);
-
     loader = osinfo_loader_new();
     osinfo_loader_process_default_path(loader, &error);
     if (error != NULL) {
@@ -157,9 +212,39 @@ gint main(gint argc, gchar **argv)
     }
 
     db = osinfo_loader_get_db(loader);
-    os = osinfo_db_guess_os_from_media(db, media, &matched_media);
 
-    print_os(os, matched_media);
+    if (type == URL_TYPE_MEDIA) {
+        OsinfoMedia *media = NULL;
+        OsinfoMedia *matched_media = NULL;
+        media = osinfo_media_create_from_location(argv[1], NULL, &error);
+        if (error != NULL) {
+            if (error->code != OSINFO_MEDIA_ERROR_NOT_BOOTABLE) {
+                g_printerr("Error parsing media: %s\n", error->message);
+
+                ret = -3;
+                goto EXIT;
+            } else {
+                print_bootable(FALSE);
+            }
+        } else {
+            print_bootable(TRUE);
+        }
+        os = osinfo_db_guess_os_from_media(db, media, &matched_media);
+        print_os_media(os, matched_media);
+    } else if (type == URL_TYPE_TREE) {
+        OsinfoTree *tree = NULL;
+        OsinfoTree *matched_tree = NULL;
+        tree = osinfo_tree_create_from_location(argv[1], NULL, &error);
+        if (error != NULL) {
+            g_printerr("Error parsing tree: %s\n", error->message);
+
+            ret = -3;
+            goto EXIT;
+        }
+        os = osinfo_db_guess_os_from_tree(db, tree, &matched_tree);
+        print_os_tree(os, tree, matched_tree);
+    }
+
 
 EXIT:
     g_clear_error(&error);
@@ -168,3 +253,11 @@ EXIT:
 
     return ret;
 }
+
+/*
+ * Local variables:
+ *  indent-tabs-mode: nil
+ *  c-indent-level: 4
+ *  c-basic-offset: 4
+ * End:
+ */
-- 
1.7.7.6




More information about the virt-tools-list mailing list