From: "Daniel P. Berrange" <berrange@xxxxxxxxxx> 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@xxxxxxxxxx> + * Arjun Roy <arroy@xxxxxxxxxx> + * Daniel P. Berrange <berrange@xxxxxxxxxx> + */ + +#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@xxxxxxxxxx> + * Arjun Roy <arroy@xxxxxxxxxx> + * Daniel P. Berrange <berrange@xxxxxxxxxx> + */ + +#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@xxxxxxxxxx> + * Daniel P. Berrange <berrange@xxxxxxxxxx> + */ + +#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@xxxxxxxxxx> + * Arjun Roy <arroy@xxxxxxxxxx> + * Daniel P. Berrange <berrange@xxxxxxxxxx> + */ + +#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