[gnome-software] appstream: don't use gzip to decompress the zip file
- From: Giovanni Campagna <gcampagna src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-software] appstream: don't use gzip to decompress the zip file
- Date: Sun, 1 Sep 2013 20:22:35 +0000 (UTC)
commit da40e50c8a2dc0776bf9044b1b200625a5ea17f3
Author: Giovanni Campagna <gcampagna src gnome org>
Date: Sun Sep 1 19:38:08 2013 +0200
appstream: don't use gzip to decompress the zip file
It's a terrible idea to use predictable names in /tmp, and in
general we don't need to spawn an external binary, we can use
GIO for the same.
Also, improve the thread safety with GOnce instead of GMutex.
https://bugzilla.gnome.org/show_bug.cgi?id=707185
src/plugins/gs-plugin-appstream.c | 141 ++++++++++++-------------------------
1 files changed, 45 insertions(+), 96 deletions(-)
---
diff --git a/src/plugins/gs-plugin-appstream.c b/src/plugins/gs-plugin-appstream.c
index 95cf783..a59f643 100644
--- a/src/plugins/gs-plugin-appstream.c
+++ b/src/plugins/gs-plugin-appstream.c
@@ -46,14 +46,13 @@ typedef struct {
} GsAppstreamItem;
struct GsPluginPrivate {
- GMutex mutex;
gchar *cachedir;
GsAppstreamXmlSection section;
GsAppstreamItem *item_temp;
GPtrArray *array; /* of GsAppstreamItem */
GHashTable *hash_id; /* of GsAppstreamItem{id} */
GHashTable *hash_pkgname; /* of GsAppstreamItem{pkgname} */
- gboolean done_init;
+ gsize done_init;
};
/**
@@ -139,67 +138,6 @@ out:
}
/**
- * gs_plugin_decompress_xml:
- */
-static gboolean
-gs_plugin_decompress_xml (GsPlugin *plugin, GError **error)
-{
- const gchar *argv[6];
- const gchar *tmpdir = "/tmp";
- gboolean ret = TRUE;
- gint exit_status = 0;
- gchar *data = NULL;
- gsize len;
-
- /* already exists */
- if (g_file_test ("/tmp/appstream.xml.gz", G_FILE_TEST_EXISTS))
- goto out;
-
- /* copy to /tmp */
- ret = g_file_get_contents (DATADIR "/gnome-software/appstream.xml.gz",
- &data,
- &len,
- error);
- if (!ret)
- goto out;
- ret = g_file_set_contents ("/tmp/appstream.xml.gz",
- data,
- len,
- error);
- if (!ret)
- goto out;
-
- /* decompress */
- argv[0] = "gunzip";
- argv[1] = "/tmp/appstream.xml.gz";
- argv[2] = NULL;
- g_debug ("Decompressing %s to %s", argv[2], tmpdir);
- ret = g_spawn_sync (tmpdir,
- (gchar **) argv,
- NULL,
- G_SPAWN_SEARCH_PATH,
- NULL, NULL,
- NULL,
- NULL,
- &exit_status,
- error);
- if (!ret)
- goto out;
- if (exit_status != 0) {
- ret = FALSE;
- g_set_error (error,
- GS_PLUGIN_ERROR,
- GS_PLUGIN_ERROR_FAILED,
- "Failed to unzip XML data to %s [%i]",
- tmpdir, exit_status);
- goto out;
- }
-out:
- g_free (data);
- return ret;
-}
-
-/**
* gs_appstream_selection_from_text:
*/
static GsAppstreamXmlSection
@@ -454,26 +392,55 @@ gs_plugin_parse_xml (GsPlugin *plugin, GError **error)
gboolean ret;
GMarkupParseContext *ctx;
gchar *data;
- gsize len;
+ gssize len;
+ GFile *file;
+ GConverter *converter;
+ GInputStream *file_stream;
+ GInputStream *converter_stream;
const GMarkupParser parser = {
gs_appstream_start_element_cb,
gs_appstream_end_element_cb,
gs_appstream_text_cb,
NULL /* passthrough */,
NULL /* error */ };
+
+ file = g_file_new_for_path (DATADIR "/gnome-software/appstream.xml.gz");
+ file_stream = G_INPUT_STREAM (g_file_read (file, NULL, error));
+ g_object_unref (file);
+ if (!file_stream)
+ return FALSE;
+
+ converter = G_CONVERTER (g_zlib_decompressor_new (G_ZLIB_COMPRESSOR_FORMAT_GZIP));
+ converter_stream = g_converter_input_stream_new (file_stream, converter);
+
ctx = g_markup_parse_context_new (&parser,
G_MARKUP_PREFIX_ERROR_POSITION,
plugin,
NULL);
- ret = g_file_get_contents ("/tmp/appstream.xml", &data, &len, error);
- if (!ret)
- goto out;
- ret = g_markup_parse_context_parse (ctx, data, len, error);
- if (!ret)
- goto out;
-out:
+
+ ret = TRUE;
+ data = g_malloc (32 * 1024);
+ while ((len = g_input_stream_read (converter_stream, data, 32 * 1024, NULL, error)) > 0) {
+ ret = g_markup_parse_context_parse (ctx, data, len, error);
+ if (!ret)
+ goto out;
+ }
+
+ if (len < 0)
+ ret = FALSE;
+
+ out:
+ /* Reset in case we failed parsing */
+ if (plugin->priv->item_temp) {
+ gs_appstream_item_free (plugin->priv->item_temp);
+ plugin->priv->item_temp = NULL;
+ }
+
g_markup_parse_context_free (ctx);
g_free (data);
+ g_object_unref (converter_stream);
+ g_object_unref (file_stream);
+ g_object_unref (converter);
return ret;
}
@@ -499,9 +466,6 @@ gs_plugin_initialize (GsPlugin *plugin)
plugin->priv->cachedir = g_build_filename (g_get_user_cache_dir(),
"gnome-software",
NULL);
-
- /* can only load from one thread */
- g_mutex_init (&plugin->priv->mutex);
}
/**
@@ -523,7 +487,6 @@ gs_plugin_destroy (GsPlugin *plugin)
g_ptr_array_unref (plugin->priv->array);
g_hash_table_unref (plugin->priv->hash_id);
g_hash_table_unref (plugin->priv->hash_pkgname);
- g_mutex_clear (&plugin->priv->mutex);
}
@@ -536,13 +499,6 @@ gs_plugin_startup (GsPlugin *plugin, GError **error)
gboolean ret = TRUE;
GTimer *timer = NULL;
- /* protect */
- g_mutex_lock (&plugin->priv->mutex);
-
- /* already done */
- if (plugin->priv->done_init)
- goto out;
-
/* get the icons ready for use */
timer = g_timer_new ();
ret = gs_plugin_decompress_icons (plugin, error);
@@ -550,14 +506,6 @@ gs_plugin_startup (GsPlugin *plugin, GError **error)
goto out;
g_debug ("Decompressing icons\t:%.1fms", g_timer_elapsed (timer, NULL) * 1000);
- /* Decompress the XML ready for use */
- g_timer_reset (timer);
- ret = gs_plugin_decompress_xml (plugin, error);
- if (!ret)
- goto out;
- g_debug ("Decompressing XML\t:%.1fms",
- g_timer_elapsed (timer, NULL) * 1000);
-
/* Parse the XML */
g_timer_reset (timer);
ret = gs_plugin_parse_xml (plugin, error);
@@ -567,12 +515,9 @@ gs_plugin_startup (GsPlugin *plugin, GError **error)
plugin->priv->array->len,
g_timer_elapsed (timer, NULL) * 1000);
- /* done */
- plugin->priv->done_init = TRUE;
out:
if (timer != NULL)
g_timer_destroy (timer);
- g_mutex_unlock (&plugin->priv->mutex);
return ret;
}
@@ -708,9 +653,13 @@ gs_plugin_refine (GsPlugin *plugin,
GsApp *app;
/* load XML files */
- ret = gs_plugin_startup (plugin, error);
- if (!ret)
- goto out;
+ if (g_once_init_enter (&plugin->priv->done_init)) {
+ ret = gs_plugin_startup (plugin, error);
+ g_once_init_leave (&plugin->priv->done_init, TRUE);
+
+ if (!ret)
+ goto out;
+ }
for (l = list; l != NULL; l = l->next) {
app = GS_APP (l->data);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]