[virt-tools-list] [libosinfo 3/4] Add osinfo_media_new_from_location()

Zeeshan Ali (Khattak) zeeshanak at gnome.org
Mon Aug 22 21:31:25 UTC 2011


From: "Zeeshan Ali (Khattak)" <zeeshanak at gnome.org>

Add API to create a OsinfoMedia object, given an installation media
location. This includes moving of installation media errors to
osinfo_media module and rename from OsinfoInstallMediaError to
OsinfoMediaError.

Some application/libraries will want to be able to get basic information
about an installation media without having to load the whole metadata DB.
---
 osinfo/libosinfo.syms |    3 +-
 osinfo/osinfo_db.c    |  148 +++++------------------------------------
 osinfo/osinfo_db.h    |   24 -------
 osinfo/osinfo_media.c |  176 +++++++++++++++++++++++++++++++++++++++++++++++++
 osinfo/osinfo_media.h |   28 ++++++++
 5 files changed, 224 insertions(+), 155 deletions(-)

diff --git a/osinfo/libosinfo.syms b/osinfo/libosinfo.syms
index 2b2a03e..e64156a 100644
--- a/osinfo/libosinfo.syms
+++ b/osinfo/libosinfo.syms
@@ -1,7 +1,6 @@
 LIBOSINFO_0.0.1 {
     global:
 	osinfo_db_get_type;
-	osinfo_install_media_error_quark;
 	osinfo_db_new;
 	osinfo_db_get_platform;
 	osinfo_db_get_device;
@@ -142,7 +141,9 @@ LIBOSINFO_0.0.1 {
 	osinfo_deploymentlist_new_intersection;
 	osinfo_deploymentlist_new_union;
 	osinfo_media_get_type;
+	osinfo_media_error_quark;
 	osinfo_media_new;
+	osinfo_media_new_from_location;
 	osinfo_media_get_architecture;
 	osinfo_media_get_url;
 	osinfo_media_get_volume_id;
diff --git a/osinfo/osinfo_db.c b/osinfo/osinfo_db.c
index d8e6b7c..42ca7eb 100644
--- a/osinfo/osinfo_db.c
+++ b/osinfo/osinfo_db.c
@@ -25,43 +25,6 @@
 #include <osinfo/osinfo.h>
 #include <gio/gio.h>
 #include <string.h>
-#include <stdlib.h>
-
-#define MAX_VOLUME 32
-#define MAX_SYSTEM 32
-#define MAX_PUBLISHER 128
-
-#define PVD_OFFSET 0x00008000
-#define BOOTABLE_TAG "EL TORITO SPECIFICATION"
-
-typedef struct _PrimaryVolumeDescriptor PrimaryVolumeDescriptor;
-
-struct _PrimaryVolumeDescriptor {
-    guint8 ignored[8];
-    gchar  system[MAX_SYSTEM];       /* System ID */
-    gchar  volume[MAX_VOLUME];       /* Volume ID */
-    guint8 ignored2[246];
-    gchar  publisher[MAX_PUBLISHER]; /* Publisher ID */
-    guint8 ignored3[1602];
-};
-
-typedef struct _SupplementaryVolumeDescriptor SupplementaryVolumeDescriptor;
-
-struct _SupplementaryVolumeDescriptor {
-    guint8 ignored[7];
-    gchar  system[MAX_SYSTEM]; /* System ID */
-};
-
-GQuark
-osinfo_install_media_error_quark (void)
-{
-    static GQuark quark = 0;
-
-    if (!quark)
-        quark = g_quark_from_static_string ("osinfo-install-media-error");
-
-    return quark;
-}
 
 G_DEFINE_TYPE (OsinfoDb, osinfo_db, G_TYPE_OBJECT);
 
@@ -377,98 +340,24 @@ OsinfoOs *osinfo_db_guess_os_from_location(OsinfoDb *db,
                                            GError **error)
 {
     OsinfoOs *ret = NULL;
-    PrimaryVolumeDescriptor pvd;
-    SupplementaryVolumeDescriptor svd;
-    GFile *file;
-    GFileInputStream *stream;
+    OsinfoMedia *media;
     GList *oss = NULL;
     GList *os_iter;
+    const gchar *media_volume;
+    const gchar *media_system;
+    const gchar *media_publisher;
 
     g_return_val_if_fail(OSINFO_IS_DB(db), NULL);
     g_return_val_if_fail(location != NULL, NULL);
     g_return_val_if_fail(error == NULL || *error == NULL, NULL);
 
-    file = g_file_new_for_commandline_arg(location);
-    stream = g_file_read(file, NULL, error);
-    if (error != NULL && *error != NULL) {
-        g_prefix_error(error, "Failed to open file");
-
-        goto EXIT;
-    }
-
-    memset(&pvd, 0, sizeof(pvd));
-    if (g_input_stream_skip(G_INPUT_STREAM(stream),
-                            PVD_OFFSET,
-                            cancellable,
-                            error) < sizeof(pvd)) {
-        if (*error)
-            g_prefix_error(error, "Failed to skip %d bytes", PVD_OFFSET);
-        else
-            g_set_error(error,
-                         OSINFO_INSTALL_MEDIA_ERROR,
-                         OSINFO_INSTALL_MEDIA_ERROR_NO_DESCRIPTORS,
-                         "No volume descriptors");
-
+    media = osinfo_media_new_from_location (location, cancellable, error);
+    if (*error != NULL)
         goto EXIT;
-    }
-
-    if (g_input_stream_read(G_INPUT_STREAM(stream),
-                            &pvd,
-                            sizeof(pvd),
-                            cancellable,
-                            error) < sizeof(pvd)) {
-        if (*error)
-            g_prefix_error(error, "Failed to read primary volume descriptor");
-        else
-            g_set_error(error,
-                        OSINFO_INSTALL_MEDIA_ERROR,
-                        OSINFO_INSTALL_MEDIA_ERROR_NO_PVD,
-                        "Primary volume descriptor unavailable");
-
-        goto EXIT;
-    }
-
-    pvd.volume[MAX_VOLUME - 1] = 0;
-    pvd.system[MAX_SYSTEM - 1] = 0;
-    pvd.publisher[MAX_PUBLISHER - 1] = 0;
-
-    if (pvd.volume[0] && (pvd.system[0] == 0 && pvd.publisher[0] == 0)) {
-        g_set_error(error,
-                    OSINFO_INSTALL_MEDIA_ERROR,
-                    OSINFO_INSTALL_MEDIA_ERROR_INSUFFIENT_METADATA,
-                    "Insufficient metadata on installation media");
-
-        goto EXIT;
-    }
-
-    memset(&svd, 0, sizeof(svd));
-    if (g_input_stream_read(G_INPUT_STREAM(stream),
-                            &svd,
-                            sizeof(svd),
-                            cancellable,
-                            error) < sizeof(svd)) {
-        if (*error)
-            g_prefix_error(error,
-                           "Failed to read supplementary volume descriptor");
-        else
-            g_set_error(error,
-                        OSINFO_INSTALL_MEDIA_ERROR,
-                        OSINFO_INSTALL_MEDIA_ERROR_NO_SVD,
-                        "Supplementary volume descriptor unavailable");
-
-        goto EXIT;
-    }
 
-    svd.system[MAX_SYSTEM - 1] = 0;
-
-    if (strncmp(BOOTABLE_TAG, svd.system, sizeof(BOOTABLE_TAG) != 0)) {
-        g_set_error(error,
-                    OSINFO_INSTALL_MEDIA_ERROR,
-                    OSINFO_INSTALL_MEDIA_ERROR_NOT_BOOTABLE,
-                    "Install media is not bootable");
-
-        goto EXIT;
-    }
+    media_volume = osinfo_media_get_volume_id(media);
+    media_system = osinfo_media_get_system_id(media);
+    media_publisher = osinfo_media_get_publisher_id(media);
 
     oss = osinfo_list_get_elements(OSINFO_LIST(db->priv->oses));
     for (os_iter = oss; os_iter; os_iter = os_iter->next) {
@@ -478,14 +367,14 @@ OsinfoOs *osinfo_db_guess_os_from_location(OsinfoDb *db,
         GList *media_iter;
 
         for (media_iter = medias; media_iter; media_iter = media_iter->next) {
-            OsinfoMedia *media = OSINFO_MEDIA(media_iter->data);
-            const gchar *media_volume = osinfo_media_get_volume_id(media);
-            const gchar *media_system = osinfo_media_get_system_id(media);
-            const gchar *media_publisher = osinfo_media_get_publisher_id(media);
-
-            if (str_contains(pvd.volume, media_volume) &&
-                (str_contains(pvd.system, media_system) ||
-                 str_contains(pvd.publisher, media_publisher))) {
+            OsinfoMedia *os_media = OSINFO_MEDIA(media_iter->data);
+            const gchar *os_volume = osinfo_media_get_volume_id(os_media);
+            const gchar *os_system = osinfo_media_get_system_id(os_media);
+            const gchar *os_publisher = osinfo_media_get_publisher_id(os_media);
+
+            if (str_contains(media_volume, os_volume) &&
+                (str_contains(media_system, os_system) ||
+                 str_contains(media_publisher, os_publisher))) {
                 ret = os;
                 break;
             }
@@ -500,8 +389,7 @@ OsinfoOs *osinfo_db_guess_os_from_location(OsinfoDb *db,
 
 EXIT:
     g_list_free(oss);
-    g_object_unref(stream);
-    g_object_unref(file);
+    g_clear_object(&media);
 
     return ret;
 }
diff --git a/osinfo/osinfo_db.h b/osinfo/osinfo_db.h
index 3f56de1..f3ba37e 100644
--- a/osinfo/osinfo_db.h
+++ b/osinfo/osinfo_db.h
@@ -34,30 +34,6 @@
 #ifndef __OSINFO_DB_H__
 #define __OSINFO_DB_H__
 
-GQuark
-osinfo_install_media_error_quark (void) G_GNUC_CONST;
-
-#define OSINFO_INSTALL_MEDIA_ERROR (osinfo_install_media_error_quark ())
-
-/**
- * OsinfoInstallMediaError:
- * @OSINFO_INSTALL_MEDIA_ERROR_NO_DESCRIPTORS: No descriptors.
- * @OSINFO_INSTALL_MEDIA_ERROR_INSUFFIENT_METADATA: Not enough metadata.
- * @OSINFO_INSTALL_MEDIA_ERROR_NOT_BOOTABLE: Install media not bootable.
- * @OSINFO_INSTALL_MEDIA_ERROR_NO_PVD: No Primary volume descriptor.
- * @OSINFO_INSTALL_MEDIA_ERROR_NO_SVD: No supplementary volume descriptor.
- *
- * #GError codes used for errors in the #OSINFO_INSTALL_MEDIA_ERROR domain, during
- * reading of data from install media for detection of OS.
- */
-typedef enum {
-    OSINFO_INSTALL_MEDIA_ERROR_NO_DESCRIPTORS,
-    OSINFO_INSTALL_MEDIA_ERROR_NO_PVD,
-    OSINFO_INSTALL_MEDIA_ERROR_NO_SVD,
-    OSINFO_INSTALL_MEDIA_ERROR_INSUFFIENT_METADATA,
-    OSINFO_INSTALL_MEDIA_ERROR_NOT_BOOTABLE
-} OsinfoInstallMediaError;
-
 /*
  * Type macros.
  */
diff --git a/osinfo/osinfo_media.c b/osinfo/osinfo_media.c
index 5af6d67..9f44806 100644
--- a/osinfo/osinfo_media.c
+++ b/osinfo/osinfo_media.c
@@ -24,6 +24,45 @@
  */
 
 #include <osinfo/osinfo.h>
+#include <gio/gio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define MAX_VOLUME 32
+#define MAX_SYSTEM 32
+#define MAX_PUBLISHER 128
+
+#define PVD_OFFSET 0x00008000
+#define BOOTABLE_TAG "EL TORITO SPECIFICATION"
+
+typedef struct _PrimaryVolumeDescriptor PrimaryVolumeDescriptor;
+
+struct _PrimaryVolumeDescriptor {
+    guint8 ignored[8];
+    gchar  system[MAX_SYSTEM];       /* System ID */
+    gchar  volume[MAX_VOLUME];       /* Volume ID */
+    guint8 ignored2[246];
+    gchar  publisher[MAX_PUBLISHER]; /* Publisher ID */
+    guint8 ignored3[1602];
+};
+
+typedef struct _SupplementaryVolumeDescriptor SupplementaryVolumeDescriptor;
+
+struct _SupplementaryVolumeDescriptor {
+    guint8 ignored[7];
+    gchar  system[MAX_SYSTEM]; /* System ID */
+};
+
+GQuark
+osinfo_media_error_quark (void)
+{
+    static GQuark quark = 0;
+
+    if (!quark)
+        quark = g_quark_from_static_string ("osinfo-media-error");
+
+    return quark;
+}
 
 G_DEFINE_TYPE (OsinfoMedia, osinfo_media, OSINFO_TYPE_ENTITY);
 
@@ -88,6 +127,143 @@ OsinfoMedia *osinfo_media_new(const gchar *id,
 }
 
 /**
+ * osinfo_media_new_from_location:
+ * @location: the location of an installation media
+ * @cancellable (allow-none): a #GCancellable, or %NULL
+ * @error: The location where to store any error, or %NULL
+ *
+ * Creates a new #OsinfoMedia for installation media at @location. The @location
+ * could be any URI that GIO can handle or a local path.
+ *
+ * NOTE: Currently this only works for ISO images/devices.
+ *
+ * Returns: (transfer full): a new #OsinfoMedia , or NULL on error
+ */
+OsinfoMedia *osinfo_media_new_from_location(const gchar *location,
+                                            GCancellable *cancellable,
+                                            GError **error)
+{
+    OsinfoMedia *ret = NULL;
+    PrimaryVolumeDescriptor pvd;
+    SupplementaryVolumeDescriptor svd;
+    GFile *file;
+    GFileInputStream *stream;
+    gchar *uri;
+
+    g_return_val_if_fail(location != NULL, NULL);
+    g_return_val_if_fail(error == NULL || *error == NULL, NULL);
+
+    file = g_file_new_for_commandline_arg(location);
+    stream = g_file_read(file, NULL, error);
+    if (error != NULL && *error != NULL) {
+        g_prefix_error(error, "Failed to open file");
+
+        goto EXIT;
+    }
+
+    memset(&pvd, 0, sizeof(pvd));
+    if (g_input_stream_skip(G_INPUT_STREAM(stream),
+                            PVD_OFFSET,
+                            cancellable,
+                            error) < sizeof(pvd)) {
+        if (*error)
+            g_prefix_error(error, "Failed to skip %d bytes", PVD_OFFSET);
+        else
+            g_set_error(error,
+                         OSINFO_MEDIA_ERROR,
+                         OSINFO_MEDIA_ERROR_NO_DESCRIPTORS,
+                         "No volume descriptors");
+
+        goto EXIT;
+    }
+
+    if (g_input_stream_read(G_INPUT_STREAM(stream),
+                            &pvd,
+                            sizeof(pvd),
+                            cancellable,
+                            error) < sizeof(pvd)) {
+        if (*error)
+            g_prefix_error(error, "Failed to read primary volume descriptor");
+        else
+            g_set_error(error,
+                        OSINFO_MEDIA_ERROR,
+                        OSINFO_MEDIA_ERROR_NO_PVD,
+                        "Primary volume descriptor unavailable");
+
+        goto EXIT;
+    }
+
+    pvd.volume[MAX_VOLUME - 1] = 0;
+    pvd.system[MAX_SYSTEM - 1] = 0;
+    pvd.publisher[MAX_PUBLISHER - 1] = 0;
+
+    if (pvd.volume[0] && (pvd.system[0] == 0 && pvd.publisher[0] == 0)) {
+        g_set_error(error,
+                    OSINFO_MEDIA_ERROR,
+                    OSINFO_MEDIA_ERROR_INSUFFIENT_METADATA,
+                    "Insufficient metadata on installation media");
+
+        goto EXIT;
+    }
+
+    memset(&svd, 0, sizeof(svd));
+    if (g_input_stream_read(G_INPUT_STREAM(stream),
+                            &svd,
+                            sizeof(svd),
+                            cancellable,
+                            error) < sizeof(svd)) {
+        if (*error)
+            g_prefix_error(error,
+                           "Failed to read supplementary volume descriptor");
+        else
+            g_set_error(error,
+                        OSINFO_MEDIA_ERROR,
+                        OSINFO_MEDIA_ERROR_NO_SVD,
+                        "Supplementary volume descriptor unavailable");
+
+        goto EXIT;
+    }
+
+    svd.system[MAX_SYSTEM - 1] = 0;
+
+    if (strncmp(BOOTABLE_TAG, svd.system, sizeof(BOOTABLE_TAG) != 0)) {
+        g_set_error(error,
+                    OSINFO_MEDIA_ERROR,
+                    OSINFO_MEDIA_ERROR_NOT_BOOTABLE,
+                    "Install media is not bootable");
+
+        goto EXIT;
+    }
+
+    uri = g_file_get_uri(file);
+    ret = g_object_new(OSINFO_TYPE_MEDIA,
+                       "id", uri,
+                       NULL);
+    osinfo_entity_set_param(OSINFO_ENTITY(ret),
+                            OSINFO_MEDIA_PROP_URL,
+                            uri);
+    g_free(uri);
+    if (pvd.volume[0] != 0)
+        osinfo_entity_set_param(OSINFO_ENTITY(ret),
+                                OSINFO_MEDIA_PROP_VOLUME_ID,
+                                pvd.volume);
+    if (pvd.system[0] != 0)
+        osinfo_entity_set_param(OSINFO_ENTITY(ret),
+                                OSINFO_MEDIA_PROP_SYSTEM_ID,
+                                pvd.system);
+    if (pvd.publisher[0] != 0)
+        osinfo_entity_set_param(OSINFO_ENTITY(ret),
+                                OSINFO_MEDIA_PROP_PUBLISHER_ID,
+                                pvd.publisher);
+
+EXIT:
+    g_object_unref(stream);
+    g_object_unref(file);
+
+    return ret;
+}
+
+/**
  * osinfo_entity_get_architecture:
  * @media: a #OsinfoMedia instance
  *
diff --git a/osinfo/osinfo_media.h b/osinfo/osinfo_media.h
index 4552da9..9d68c6e 100644
--- a/osinfo/osinfo_media.h
+++ b/osinfo/osinfo_media.h
@@ -24,11 +24,36 @@
  */
 
 #include <glib-object.h>
+#include <gio/gio.h>
 #include <osinfo/osinfo_entity.h>
 
 #ifndef __OSINFO_MEDIA_H__
 #define __OSINFO_MEDIA_H__
 
+GQuark
+osinfo_media_error_quark (void) G_GNUC_CONST;
+
+#define OSINFO_MEDIA_ERROR (osinfo_media_error_quark ())
+
+/**
+ * OsinfoMediaError:
+ * @OSINFO_MEDIA_ERROR_NO_DESCRIPTORS: No descriptors.
+ * @OSINFO_MEDIA_ERROR_INSUFFIENT_METADATA: Not enough metadata.
+ * @OSINFO_MEDIA_ERROR_NOT_BOOTABLE: Install media not bootable.
+ * @OSINFO_MEDIA_ERROR_NO_PVD: No Primary volume descriptor.
+ * @OSINFO_MEDIA_ERROR_NO_SVD: No supplementary volume descriptor.
+ *
+ * #GError codes used for errors in the #OSINFO_MEDIA_ERROR domain, during
+ * reading of data from install media location.
+ */
+typedef enum {
+    OSINFO_MEDIA_ERROR_NO_DESCRIPTORS,
+    OSINFO_MEDIA_ERROR_NO_PVD,
+    OSINFO_MEDIA_ERROR_NO_SVD,
+    OSINFO_MEDIA_ERROR_INSUFFIENT_METADATA,
+    OSINFO_MEDIA_ERROR_NOT_BOOTABLE
+} OsinfoMediaError;
+
 /*
  * Type macros.
  */
@@ -73,6 +98,9 @@ struct _OsinfoMediaClass
 GType osinfo_media_get_type(void);
 
 OsinfoMedia *osinfo_media_new(const gchar *id, const gchar *architecture);
+OsinfoMedia *osinfo_media_new_from_location(const gchar *location,
+                                            GCancellable *cancellable,
+                                            GError **error);
 
 const gchar *osinfo_media_get_architecture(OsinfoMedia *media);
 const gchar *osinfo_media_get_url(OsinfoMedia *media);
-- 
1.7.6




More information about the virt-tools-list mailing list