summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTing-Wei Lan <lantw44@gmail.com>2013-07-27 22:41:25 +0800
committerLAN-TW <lantw44@gmail.com>2013-07-27 22:41:25 +0800
commite5c7b85cca2a25342c886372b477ed14fe742920 (patch)
treed5b4104c6c9aa10d1db60164309bb20cc000ce52
parent532d2be27a8a0660c903e941420d999643e7ba29 (diff)
downloadgsoc2013-libgnome-autoar-e5c7b85cca2a25342c886372b477ed14fe742920.tar
gsoc2013-libgnome-autoar-e5c7b85cca2a25342c886372b477ed14fe742920.tar.gz
gsoc2013-libgnome-autoar-e5c7b85cca2a25342c886372b477ed14fe742920.tar.bz2
gsoc2013-libgnome-autoar-e5c7b85cca2a25342c886372b477ed14fe742920.tar.lz
gsoc2013-libgnome-autoar-e5c7b85cca2a25342c886372b477ed14fe742920.tar.xz
gsoc2013-libgnome-autoar-e5c7b85cca2a25342c886372b477ed14fe742920.tar.zst
gsoc2013-libgnome-autoar-e5c7b85cca2a25342c886372b477ed14fe742920.zip
Add seek and skip callback functions for libarchive
Seek callback function is required to extract 7-zip file.
-rw-r--r--autoar-extract.c140
-rw-r--r--test-extract.c5
2 files changed, 126 insertions, 19 deletions
diff --git a/autoar-extract.c b/autoar-extract.c
index f869f16..9be8df7 100644
--- a/autoar-extract.c
+++ b/autoar-extract.c
@@ -268,6 +268,8 @@ autoar_extract_dispose (GObject *object)
AutoarExtract *arextract;
arextract = AUTOAR_EXTRACT (object);
+ g_debug ("AutoarExtract: dispose");
+
g_clear_object (&(arextract->priv->arpref));
G_OBJECT_CLASS (autoar_extract_parent_class)->dispose (object);
@@ -282,6 +284,8 @@ autoar_extract_finalize (GObject *object)
arextract = AUTOAR_EXTRACT (object);
priv = arextract->priv;
+ g_debug ("AutoarExtract: finalize");
+
g_free (priv->source);
priv->source = NULL;
@@ -381,6 +385,76 @@ libarchive_read_read_cb (struct archive *ar_read,
return read_size;
}
+static off_t
+libarchive_read_seek_cb (struct archive *ar_read,
+ void *client_data,
+ off_t request,
+ int whence)
+{
+ AutoarExtract *arextract;
+ GSeekable *seekable;
+ GSeekType seektype;
+ off_t new_offset;
+
+ g_debug ("libarchive_read_seek_cb: called");
+
+ arextract = (AutoarExtract*)client_data;
+ seekable = (GSeekable*)(arextract->priv->istream);
+ if (arextract->priv->error != NULL) {
+ return -1;
+ }
+
+ switch (whence) {
+ case SEEK_SET:
+ seektype = G_SEEK_SET;
+ break;
+ case SEEK_CUR:
+ seektype = G_SEEK_CUR;
+ break;
+ case SEEK_END:
+ seektype = G_SEEK_END;
+ break;
+ default:
+ return -1;
+ }
+
+ g_seekable_seek (seekable,
+ request,
+ seektype,
+ NULL,
+ &(arextract->priv->error));
+ new_offset = g_seekable_tell (seekable);
+ g_return_val_if_fail (arextract->priv->error == NULL, -1);
+
+ g_debug ("libarchive_read_seek_cb: %"G_GOFFSET_FORMAT, (goffset)new_offset);
+ return new_offset;
+}
+
+static off_t
+libarchive_read_skip_cb (struct archive *ar_read,
+ void *client_data,
+ off_t request)
+{
+ AutoarExtract *arextract;
+ GSeekable *seekable;
+ off_t old_offset, new_offset;
+
+ g_debug ("libarchive_read_skip_cb: called");
+
+ arextract = (AutoarExtract*)client_data;
+ seekable = (GSeekable*)(arextract->priv->istream);
+ if (arextract->priv->error != NULL) {
+ return -1;
+ }
+
+ old_offset = g_seekable_tell (seekable);
+ new_offset = libarchive_read_seek_cb (ar_read, client_data, request, SEEK_CUR);
+ if (new_offset > old_offset)
+ return (new_offset - old_offset);
+
+ return 0;
+}
+
static char*
_g_filename_basename_remove_extension (const char *filename)
{
@@ -1017,11 +1091,13 @@ autoar_extract_run (AutoarExtract *arextract,
a = archive_read_new ();
archive_read_support_filter_all (a);
archive_read_support_format_all (a);
- r = archive_read_open (a,
- arextract,
- libarchive_read_open_cb,
- libarchive_read_read_cb,
- libarchive_read_close_cb);
+ archive_read_set_open_callback (a, libarchive_read_open_cb);
+ archive_read_set_read_callback (a, libarchive_read_read_cb);
+ archive_read_set_close_callback (a, libarchive_read_close_cb);
+ archive_read_set_seek_callback (a, libarchive_read_seek_cb);
+ archive_read_set_skip_callback (a, libarchive_read_skip_cb);
+ archive_read_set_callback_data (a, arextract);
+ r = archive_read_open1 (a);
if (r != ARCHIVE_OK) {
if (arextract->priv->error == NULL) {
arextract->priv->error = g_error_new (autoar_extract_quark,
@@ -1076,14 +1152,30 @@ autoar_extract_run (AutoarExtract *arextract,
arextract->priv->size += archive_entry_size (entry);
archive_read_data_skip (a);
}
+ if (r != ARCHIVE_EOF) {
+ if (arextract->priv->error == NULL) {
+ arextract->priv->error = g_error_new (autoar_extract_quark,
+ archive_errno (a),
+ "\'%s\': %s",
+ arextract->priv->source,
+ archive_error_string (a));
+ }
+ _g_signal_emit (in_thread, arextract, autoar_extract_signals[ERROR], 0, arextract->priv->error);
+ g_free (pathname_prefix);
+ g_ptr_array_unref (pattern_compiled);
+ g_hash_table_unref (bad_filename);
+ archive_read_close (a);
+ archive_read_free (a);
+ return;
+ }
+
g_free (pathname_prefix);
+ g_ptr_array_unref (pattern_compiled);
archive_read_close (a);
archive_read_free (a);
- g_ptr_array_unref (pattern_compiled);
if (arextract->priv->error != NULL) {
_g_signal_emit (in_thread, arextract, autoar_extract_signals[ERROR], 0, arextract->priv->error);
g_hash_table_unref (bad_filename);
- archive_read_free (a);
return;
}
g_debug ("autoar_extract_run: has_top_level_dir = %s",
@@ -1100,7 +1192,7 @@ autoar_extract_run (AutoarExtract *arextract,
top_level_dir = g_file_get_child (top_level_parent_dir, top_level_dir_basename);
top_level_dir_basename_modified = NULL;
- for (i=1; g_file_query_exists (top_level_dir, NULL); i++) {
+ for (i = 1; g_file_query_exists (top_level_dir, NULL); i++) {
g_free (top_level_dir_basename_modified);
g_object_unref (top_level_dir);
top_level_dir_basename_modified = g_strdup_printf ("%s (%d)",
@@ -1132,12 +1224,13 @@ autoar_extract_run (AutoarExtract *arextract,
a = archive_read_new ();
archive_read_support_filter_all (a);
archive_read_support_format_all (a);
-
- r = archive_read_open (a,
- arextract,
- libarchive_read_open_cb,
- libarchive_read_read_cb,
- libarchive_read_close_cb);
+ archive_read_set_open_callback (a, libarchive_read_open_cb);
+ archive_read_set_read_callback (a, libarchive_read_read_cb);
+ archive_read_set_close_callback (a, libarchive_read_close_cb);
+ archive_read_set_seek_callback (a, libarchive_read_seek_cb);
+ archive_read_set_skip_callback (a, libarchive_read_skip_cb);
+ archive_read_set_callback_data (a, arextract);
+ r = archive_read_open1 (a);
if (r != ARCHIVE_OK) {
if (arextract->priv->error == NULL) {
arextract->priv->error = g_error_new (autoar_extract_quark,
@@ -1154,7 +1247,7 @@ autoar_extract_run (AutoarExtract *arextract,
}
userhash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
grouphash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
- while (archive_read_next_header (a, &entry) == ARCHIVE_OK) {
+ while ((r = archive_read_next_header (a, &entry)) == ARCHIVE_OK) {
const char *pathname;
const char *pathname_skip_prefix;
char **pathname_chunks;
@@ -1224,6 +1317,23 @@ autoar_extract_run (AutoarExtract *arextract,
((double)(arextract->priv->completed_files)) / ((double)(arextract->priv->files)));
g_object_unref (extracted_filename);
}
+ if (r != ARCHIVE_EOF) {
+ if (arextract->priv->error == NULL) {
+ arextract->priv->error = g_error_new (autoar_extract_quark,
+ archive_errno (a),
+ "\'%s\': %s",
+ arextract->priv->source,
+ archive_error_string (a));
+ }
+ _g_signal_emit (in_thread, arextract, autoar_extract_signals[ERROR], 0, arextract->priv->error);
+ g_object_unref (top_level_dir);
+ g_hash_table_unref (userhash);
+ g_hash_table_unref (grouphash);
+ g_hash_table_unref (bad_filename);
+ archive_read_close (a);
+ archive_read_free (a);
+ return;
+ }
g_object_unref (top_level_dir);
g_hash_table_unref (userhash);
diff --git a/test-extract.c b/test-extract.c
index bf5f6ca..b6721fc 100644
--- a/test-extract.c
+++ b/test-extract.c
@@ -41,9 +41,7 @@ my_handler_error (AutoarExtract *arextract,
GError *error,
gpointer data)
{
- g_printerr ("\nError: %s\n", error->message);
- g_error_free (error);
- exit (1);
+ g_printerr ("\nError %d: %s\n", error->code, error->message);
}
static void
@@ -51,7 +49,6 @@ my_handler_completed (AutoarExtract *arextract,
gpointer data)
{
g_print ("\nCompleted!\n");
- exit (0);
}
int