From bb257548a99b9027cef90e5acdefb3b7da9769fa Mon Sep 17 00:00:00 2001 From: Ting-Wei Lan Date: Fri, 12 Jul 2013 14:55:36 +0800 Subject: Implement callback functions for archive_read_open --- autoarchive/autoar-extract.c | 144 ++++++++++++++++++++++++++++++++++++------- autoarchive/autoar-extract.h | 2 +- 2 files changed, 122 insertions(+), 24 deletions(-) diff --git a/autoarchive/autoar-extract.c b/autoarchive/autoar-extract.c index 2943058c6..ecaf20d8a 100644 --- a/autoarchive/autoar-extract.c +++ b/autoarchive/autoar-extract.c @@ -27,6 +27,8 @@ #include "autoar-extract.h" +#include +#include #include #include @@ -35,18 +37,23 @@ G_DEFINE_TYPE (AutoarExtract, autoar_extract, G_TYPE_OBJECT) #define AUTOAR_EXTRACT_GET_PRIVATE(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), AUTOAR_TYPE_EXTRACT, AutoarExtractPrivate)) +#define BUFFER_SIZE (64 * 1024) + struct _AutoarExtractPrivate { char *source; char *output; - struct archive* ar_read; - guint64 size; guint64 completed_size; guint files; guint completed_files; + + GInputStream *istream; + void *buffer; + gssize buffer_size; + GError *error; }; enum @@ -221,24 +228,109 @@ autoar_extract_finalize (GObject *object) arextract = AUTOAR_EXTRACT (object); priv = arextract->priv; - if (priv->source != NULL) { - g_free (priv->source); - priv->source = NULL; - } + g_free (priv->source); + priv->source = NULL; - if (priv->output != NULL) { - g_free (priv->output); - priv->output = NULL; + g_free (priv->output); + priv->output = NULL; + + if (priv->istream != NULL) { + if (!g_input_stream_is_closed (priv->istream)) { + g_input_stream_close (priv->istream, NULL, NULL); + } + g_object_unref (priv->istream); } - if (priv->ar_read != NULL) { - archive_read_free (priv->ar_read); - priv->ar_read = NULL; + g_free (priv->buffer); + priv->buffer = NULL; + + if (priv->error != NULL) { + g_error_free (priv->error); + priv->error = NULL; } G_OBJECT_CLASS (autoar_extract_parent_class)->finalize (object); } +static int +libarchive_read_open_cb (struct archive *ar_read, + void *client_data) +{ + AutoarExtract *arextract; + GFile *file; + GFileInfo *fileinfo; + + arextract = (AutoarExtract*)client_data; + if (arextract->priv->error != NULL) { + return ARCHIVE_FATAL; + } + + file = g_file_new_for_commandline_arg (arextract->priv->source); + + fileinfo = g_file_query_info (file, + G_FILE_ATTRIBUTE_STANDARD_SIZE, + G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, + NULL, + &(arextract->priv->error)); + g_return_val_if_fail (arextract->priv->error == NULL, ARCHIVE_FATAL); + + arextract->priv->size = g_file_info_get_size (fileinfo); + g_object_unref (fileinfo); + + arextract->priv->istream = (GInputStream*)g_file_read (file, + NULL, + &(arextract->priv->error)); + g_return_val_if_fail (arextract->priv->error == NULL, ARCHIVE_FATAL); + + return ARCHIVE_OK; +} + +static int +libarchive_read_close_cb (struct archive *ar_read, + void *client_data) +{ + AutoarExtract *arextract; + + arextract = (AutoarExtract*)client_data; + if (arextract->priv->error != NULL) { + return ARCHIVE_FATAL; + } + + if (arextract->priv->istream != NULL) { + g_input_stream_close (arextract->priv->istream, NULL, NULL); + g_object_unref (arextract->priv->istream); + arextract->priv->istream = NULL; + } + + return ARCHIVE_OK; +} + +static ssize_t +libarchive_read_read_cb (struct archive *ar_read, + void *client_data, + const void **buffer) +{ + AutoarExtract *arextract; + gssize read_size; + + arextract = (AutoarExtract*)client_data; + if (arextract->priv->error != NULL) { + return -1; + } + + *buffer = &(arextract->priv->buffer); + read_size = g_input_stream_read (arextract->priv->istream, + arextract->priv->buffer, + arextract->priv->buffer_size, + NULL, + &(arextract->priv->error)); + g_return_val_if_fail (arextract->priv->error == NULL, -1); + + arextract->priv->completed_size += read_size; + + return read_size; +} + /* Additional marshaller generated by glib-genmarshal * Command: echo "VOID:DOUBLE,DOUBLE" | glib-genmarshal --header */ @@ -439,10 +531,10 @@ autoar_extract_class_init (AutoarExtractClass *klass) G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (AutoarExtractClass, error), NULL, NULL, - g_cclosure_marshal_VOID__INT, + g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, - G_TYPE_INT); + G_TYPE_POINTER); } static void @@ -456,23 +548,29 @@ autoar_extract_init (AutoarExtract *arextract) priv->source = NULL; priv->output = NULL; - priv->ar_read = NULL; - priv->size = 0; priv->completed_size = 0; + priv->files = 0; priv->completed_files = 0; + + priv->istream = NULL; + priv->buffer_size = BUFFER_SIZE; + priv->buffer = g_new (char, priv->buffer_size); + priv->error = NULL; } AutoarExtract* autoar_extract_new (const char *source, const char *output) { - AutoarExtract *arextract = g_object_new (AUTOAR_TYPE_EXTRACT, - "source", - source, - "output", - output, - NULL); - return arextract; + g_return_val_if_fail (source != NULL, NULL); + g_return_val_if_fail (output != NULL, NULL); + + return g_object_new (AUTOAR_TYPE_EXTRACT, + "source", + source, + "output", + output, + NULL); } diff --git a/autoarchive/autoar-extract.h b/autoarchive/autoar-extract.h index c76853107..2d93228f2 100644 --- a/autoarchive/autoar-extract.h +++ b/autoarchive/autoar-extract.h @@ -59,7 +59,7 @@ struct _AutoarExtractClass gdouble fraction_files); void (* completed) (AutoarExtract *arextract); void (* error) (AutoarExtract *arextract, - gint error_code); + GError* error); }; GType autoar_extract_get_type (void) G_GNUC_CONST; -- cgit v1.2.3