summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTing-Wei Lan <lantw44@gmail.com>2013-08-04 15:04:07 +0800
committerLAN-TW <lantw44@gmail.com>2013-08-04 15:10:44 +0800
commit5e5939d1ab9e62f7b7eb33bdf0ce41aa048817a0 (patch)
treec723ef2971c1c61da46cc08d567c27e4e53dfa87
parentfb0cd0fdf0b99c6a9dd76f997585e38bd7c55074 (diff)
downloadgsoc2013-libgnome-autoar-5e5939d1ab9e62f7b7eb33bdf0ce41aa048817a0.tar
gsoc2013-libgnome-autoar-5e5939d1ab9e62f7b7eb33bdf0ce41aa048817a0.tar.gz
gsoc2013-libgnome-autoar-5e5939d1ab9e62f7b7eb33bdf0ce41aa048817a0.tar.bz2
gsoc2013-libgnome-autoar-5e5939d1ab9e62f7b7eb33bdf0ce41aa048817a0.tar.lz
gsoc2013-libgnome-autoar-5e5939d1ab9e62f7b7eb33bdf0ce41aa048817a0.tar.xz
gsoc2013-libgnome-autoar-5e5939d1ab9e62f7b7eb33bdf0ce41aa048817a0.tar.zst
gsoc2013-libgnome-autoar-5e5939d1ab9e62f7b7eb33bdf0ce41aa048817a0.zip
Move local variables into objects or smaller blocks
I hope this will ease the memory management task.
-rw-r--r--configure.ac1
-rw-r--r--gnome-autoar/autoar-common.c20
-rw-r--r--gnome-autoar/autoar-common.h10
-rw-r--r--gnome-autoar/autoar-extract.c778
-rw-r--r--gnome-autoar/autoar-extract.h7
-rw-r--r--tests/test-extract.c2
6 files changed, 449 insertions, 369 deletions
diff --git a/configure.ac b/configure.ac
index 8ce97d3..776df6c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -48,6 +48,7 @@ AC_TYPE_MODE_T
AC_TYPE_OFF_T
AC_TYPE_SIZE_T
AC_TYPE_SSIZE_T
+AC_C_INLINE
# Checks for library functions.
AC_CHECK_FUNCS([getgrnam getpwnam link mkfifo mknod stat])
diff --git a/gnome-autoar/autoar-common.c b/gnome-autoar/autoar-common.c
index b0f87a2..bdb1f7f 100644
--- a/gnome-autoar/autoar-common.c
+++ b/gnome-autoar/autoar-common.c
@@ -107,8 +107,8 @@ autoar_common_g_signal_emit_main_context (void *data)
}
void
-autoar_common_g_signal_emit (gboolean in_thread,
- gpointer instance,
+autoar_common_g_signal_emit (gpointer instance,
+ gboolean in_thread,
guint signal_id,
GQuark detail,
...)
@@ -162,3 +162,19 @@ autoar_common_g_signal_emit (gboolean in_thread,
}
va_end (ap);
}
+
+GError*
+autoar_common_g_error_new_a (GQuark quark,
+ struct archive *a,
+ const char *pathname)
+{
+ GError *newerror;
+ newerror = g_error_new (quark,
+ archive_errno (a),
+ "%s%s%s%s",
+ pathname != NULL ? "\'" : "",
+ pathname != NULL ? pathname : "",
+ pathname != NULL ? "\': " : "",
+ archive_error_string (a));
+ return newerror;
+}
diff --git a/gnome-autoar/autoar-common.h b/gnome-autoar/autoar-common.h
index 888eb08..2867f45 100644
--- a/gnome-autoar/autoar-common.h
+++ b/gnome-autoar/autoar-common.h
@@ -27,15 +27,21 @@
#ifndef AUTOAR_COMMON_H
#define AUTOAR_COMMON_H
+#include <archive.h>
+#include <glib.h>
#include <glib-object.h>
char* autoar_common_get_basename_remove_extension (const char *filename);
char* autoar_common_get_filename_extension (const char *filename);
-void autoar_common_g_signal_emit (gboolean in_thread,
- gpointer instance,
+void autoar_common_g_signal_emit (gpointer instance,
+ gboolean in_thread,
guint signal_id,
GQuark detail,
...);
+GError* autoar_common_g_error_new_a (GQuark quark,
+ struct archive *a,
+ const char *pathname);
+
#endif /* AUTOAR_COMMON_H */
diff --git a/gnome-autoar/autoar-extract.c b/gnome-autoar/autoar-extract.c
index c8bdb9f..ab845ed 100644
--- a/gnome-autoar/autoar-extract.c
+++ b/gnome-autoar/autoar-extract.c
@@ -80,6 +80,18 @@ struct _AutoarExtractPrivate
void *buffer;
gssize buffer_size;
GError *error;
+
+ GCancellable *cancellable;
+
+ GHashTable *userhash;
+ GHashTable *grouphash;
+ GHashTable *bad_filename;
+ GPtrArray *pattern_compiled;
+ GArray *extracted_dir_list;
+ GFile *top_level_dir;
+
+ int in_thread : 1;
+ int use_raw_format : 1;
};
struct _GFileAndInfo
@@ -93,6 +105,7 @@ enum
SCANNED,
DECIDE_DEST,
PROGRESS,
+ CANCELLED,
COMPLETED,
ERROR,
LAST_SIGNAL
@@ -268,11 +281,47 @@ static void
autoar_extract_dispose (GObject *object)
{
AutoarExtract *arextract;
+ AutoarExtractPrivate *priv;
+
arextract = AUTOAR_EXTRACT (object);
+ priv = arextract->priv;
g_debug ("AutoarExtract: dispose");
- g_clear_object (&(arextract->priv->arpref));
+ 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);
+ }
+
+ g_clear_object (&(priv->arpref));
+ g_clear_object (&(priv->top_level_dir));
+
+ if (priv->userhash != NULL) {
+ g_hash_table_unref (priv->userhash);
+ priv->userhash = NULL;
+ }
+
+ if (priv->grouphash != NULL) {
+ g_hash_table_unref (priv->grouphash);
+ priv->grouphash = NULL;
+ }
+
+ if (priv->bad_filename != NULL) {
+ g_hash_table_unref (priv->bad_filename);
+ priv->bad_filename = NULL;
+ }
+
+ if (priv->pattern_compiled != NULL) {
+ g_ptr_array_unref (priv->pattern_compiled);
+ priv->pattern_compiled = NULL;
+ }
+
+ if (priv->extracted_dir_list != NULL) {
+ g_array_unref (priv->extracted_dir_list);
+ priv->extracted_dir_list = NULL;
+ }
G_OBJECT_CLASS (autoar_extract_parent_class)->dispose (object);
}
@@ -294,13 +343,6 @@ autoar_extract_finalize (GObject *object)
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);
- }
-
g_free (priv->buffer);
priv->buffer = NULL;
@@ -471,6 +513,57 @@ g_file_and_info_free (void *g_file_and_info) {
g_object_unref (fi->info);
}
+static inline void
+autoar_extract_signal_scanned (AutoarExtract *arextract)
+{
+ autoar_common_g_signal_emit (arextract, arextract->priv->in_thread,
+ autoar_extract_signals[SCANNED], 0,
+ arextract->priv->files);
+}
+
+static inline void
+autoar_extract_signal_decide_dest (AutoarExtract *arextract)
+{
+ autoar_common_g_signal_emit (arextract, arextract->priv->in_thread,
+ autoar_extract_signals[DECIDE_DEST], 0,
+ arextract->priv->top_level_dir);
+}
+
+static inline void
+autoar_extract_signal_progress (AutoarExtract *arextract)
+{
+ autoar_common_g_signal_emit (arextract, arextract->priv->in_thread,
+ autoar_extract_signals[PROGRESS], 0,
+ ((double)(arextract->priv->completed_size)) /
+ ((double)(arextract->priv->size)),
+ ((double)(arextract->priv->completed_files)) /
+ ((double)(arextract->priv->files)));
+}
+
+static inline void
+autoar_extract_signal_cancelled (AutoarExtract *arextract)
+{
+ autoar_common_g_signal_emit (arextract, arextract->priv->in_thread,
+ autoar_extract_signals[CANCELLED], 0);
+
+}
+
+static inline void
+autoar_extract_signal_completed (AutoarExtract *arextract)
+{
+ autoar_common_g_signal_emit (arextract, arextract->priv->in_thread,
+ autoar_extract_signals[COMPLETED], 0);
+
+}
+
+static inline void
+autoar_extract_signal_error (AutoarExtract *arextract)
+{
+ autoar_common_g_signal_emit (arextract, arextract->priv->in_thread,
+ autoar_extract_signals[ERROR], 0,
+ arextract->priv->error);
+}
+
static GFile*
autoar_extract_do_sanitize_pathname (const char *pathname,
const char *skip_chars,
@@ -554,39 +647,22 @@ autoar_extract_do_write_entry (AutoarExtract *arextract,
struct archive *a,
struct archive_entry *entry,
GFile *dest,
- GFile *hardlink,
- GFile *top_level_dir,
- GHashTable *userhash,
- GHashTable *grouphash,
- GArray *extracted_dir_list,
- gboolean in_thread,
- gboolean use_raw_format)
+ GFile *hardlink)
{
- GOutputStream *ostream;
+ AutoarExtractPrivate *priv;
GFileInfo *info;
- GFile *parent;
mode_t filetype;
- const void *buffer;
- size_t size, written;
- off_t offset;
int r;
-#ifdef HAVE_GETPWNAM
- const char *uname;
-#endif
-
-#ifdef HAVE_GETGRNAM
- const char *gname;
-#endif
-
- guint32 uid, gid;
- char *str, *str2;
- GFileAndInfo fileandinfo;
+ priv = arextract->priv;
- parent = g_file_get_parent (dest);
- if (!g_file_query_exists (parent, NULL))
- g_file_make_directory_with_parents (parent, NULL, NULL);
- g_object_unref (parent);
+ {
+ GFile *parent;
+ parent = g_file_get_parent (dest);
+ if (!g_file_query_exists (parent, NULL))
+ g_file_make_directory_with_parents (parent, NULL, NULL);
+ g_object_unref (parent);
+ }
info = g_file_info_new ();
@@ -626,49 +702,61 @@ autoar_extract_do_write_entry (AutoarExtract *arextract,
}
/* user */
- g_debug ("autoar_extract_do_write_entry: user");
+ {
+ guint32 uid;
+ const char *uname;
+
+ g_debug ("autoar_extract_do_write_entry: user");
#ifdef HAVE_GETPWNAM
- if ((uname = archive_entry_uname (entry)) != NULL) {
- void *got_uid;
- if (g_hash_table_lookup_extended (userhash, uname, NULL, &got_uid) == TRUE) {
- uid = GPOINTER_TO_UINT (got_uid);
- } else {
- struct passwd *pwd = getpwnam (uname);
- if (pwd == NULL) {
- uid = archive_entry_uid (entry);
+ if ((uname = archive_entry_uname (entry)) != NULL) {
+ void *got_uid;
+ if (g_hash_table_lookup_extended (priv->userhash, uname, NULL, &got_uid) == TRUE) {
+ uid = GPOINTER_TO_UINT (got_uid);
} else {
- uid = pwd->pw_uid;
- g_hash_table_insert (userhash, g_strdup (uname), GUINT_TO_POINTER (uid));
+ struct passwd *pwd = getpwnam (uname);
+ if (pwd == NULL) {
+ uid = archive_entry_uid (entry);
+ } else {
+ uid = pwd->pw_uid;
+ g_hash_table_insert (priv->userhash, g_strdup (uname), GUINT_TO_POINTER (uid));
+ }
}
- }
- g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_UID, uid);
- } else
+ g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_UID, uid);
+ } else
#endif
- if ((uid = archive_entry_uid (entry)) != 0) {
- g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_UID, uid);
+
+ if ((uid = archive_entry_uid (entry)) != 0) {
+ g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_UID, uid);
+ }
}
/* group */
- g_debug ("autoar_extract_do_write_entry: group");
+ {
+ guint32 gid;
+ const char *gname;
+
+ g_debug ("autoar_extract_do_write_entry: group");
#ifdef HAVE_GETGRNAM
- if ((gname = archive_entry_gname (entry)) != NULL) {
- void *got_gid;
- if (g_hash_table_lookup_extended (grouphash, gname, NULL, &got_gid) == TRUE) {
- gid = GPOINTER_TO_UINT (got_gid);
- } else {
- struct group *grp = getgrnam (gname);
- if (grp == NULL) {
- gid = archive_entry_gid (entry);
+ if ((gname = archive_entry_gname (entry)) != NULL) {
+ void *got_gid;
+ if (g_hash_table_lookup_extended (priv->grouphash, gname, NULL, &got_gid) == TRUE) {
+ gid = GPOINTER_TO_UINT (got_gid);
} else {
- gid = grp->gr_gid;
- g_hash_table_insert (grouphash, g_strdup (gname), GUINT_TO_POINTER (gid));
+ struct group *grp = getgrnam (gname);
+ if (grp == NULL) {
+ gid = archive_entry_gid (entry);
+ } else {
+ gid = grp->gr_gid;
+ g_hash_table_insert (priv->grouphash, g_strdup (gname), GUINT_TO_POINTER (gid));
+ }
}
- }
- g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_GID, gid);
- } else
+ g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_GID, gid);
+ } else
#endif
- if ((gid = archive_entry_gid (entry)) != 0) {
- g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_GID, gid);
+
+ if ((gid = archive_entry_gid (entry)) != 0) {
+ g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_GID, gid);
+ }
}
/* permissions */
@@ -679,11 +767,13 @@ autoar_extract_do_write_entry (AutoarExtract *arextract,
#ifdef HAVE_LINK
if (hardlink != NULL) {
- r = link (str2 = g_file_get_path (hardlink), str = g_file_get_path (dest));
+ char *hardlink_path, *dest_path;
+ r = link (hardlink_path = g_file_get_path (hardlink),
+ dest_path = g_file_get_path (dest));
g_debug ("autoar_extract_do_write_entry: hard link, %s => %s, %d",
- str, str2, r);
- g_free (str);
- g_free (str2);
+ dest_path, hardlink_path, r);
+ g_free (hardlink_path);
+ g_free (dest_path);
if (r >= 0) {
g_debug ("autoar_extract_do_write_entry: skip file creation");
goto applyinfo;
@@ -696,69 +786,73 @@ autoar_extract_do_write_entry (AutoarExtract *arextract,
switch (filetype = archive_entry_filetype (entry)) {
default:
case AE_IFREG:
- g_debug ("autoar_extract_do_write_entry: case REG");
- ostream = (GOutputStream*)g_file_replace (dest,
- NULL,
- FALSE,
- G_FILE_CREATE_NONE,
- NULL,
- &(arextract->priv->error));
- if (arextract->priv->error != NULL) {
- g_object_unref (info);
- return;
- }
- if (ostream != NULL) {
- /* Archive entry size may be zero if we use raw format. */
- if (archive_entry_size(entry) > 0 || use_raw_format) {
- while (archive_read_data_block (a, &buffer, &size, &offset) == ARCHIVE_OK) {
- /* buffer == NULL occurs in some zip archives when an entry is
- * completely read. We just skip this situation to prevent GIO
- * warnings. */
- if (buffer == NULL)
- continue;
- g_output_stream_write_all (ostream,
- buffer,
- size,
- &written,
- NULL,
- &(arextract->priv->error));
- if (arextract->priv->error != NULL) {
- g_output_stream_close (ostream, NULL, NULL);
- g_object_unref (ostream);
- g_object_unref (info);
- return;
+ {
+ GOutputStream *ostream;
+ const void *buffer;
+ size_t size, written;
+ off_t offset;
+
+ g_debug ("autoar_extract_do_write_entry: case REG");
+ ostream = (GOutputStream*)g_file_replace (dest,
+ NULL,
+ FALSE,
+ G_FILE_CREATE_NONE,
+ NULL,
+ &(arextract->priv->error));
+ if (arextract->priv->error != NULL) {
+ g_object_unref (info);
+ return;
+ }
+ if (ostream != NULL) {
+ /* Archive entry size may be zero if we use raw format. */
+ if (archive_entry_size(entry) > 0 || priv->use_raw_format) {
+ while (archive_read_data_block (a, &buffer, &size, &offset) == ARCHIVE_OK) {
+ /* buffer == NULL occurs in some zip archives when an entry is
+ * completely read. We just skip this situation to prevent GIO
+ * warnings. */
+ if (buffer == NULL)
+ continue;
+ g_output_stream_write_all (ostream,
+ buffer,
+ size,
+ &written,
+ NULL,
+ &(arextract->priv->error));
+ if (arextract->priv->error != NULL) {
+ g_output_stream_close (ostream, NULL, NULL);
+ g_object_unref (ostream);
+ g_object_unref (info);
+ return;
+ }
+ arextract->priv->completed_size += written;
+ autoar_extract_signal_progress (arextract);
}
- arextract->priv->completed_size += written;
- autoar_common_g_signal_emit (in_thread,
- arextract,
- autoar_extract_signals[PROGRESS],
- 0,
- ((double)(arextract->priv->completed_size)) /
- ((double)(arextract->priv->size)),
- ((double)(arextract->priv->completed_files)) /
- ((double)(arextract->priv->files)));
}
+ g_output_stream_close (ostream, NULL, NULL);
+ g_object_unref (ostream);
}
- g_output_stream_close (ostream, NULL, NULL);
- g_object_unref (ostream);
}
break;
case AE_IFDIR:
- g_debug ("autoar_extract_do_write_entry: case DIR");
- g_file_make_directory_with_parents (dest, NULL, &(arextract->priv->error));
- if (arextract->priv->error != NULL) {
- /* "File exists" is not a fatal error */
- if (arextract->priv->error->code == G_IO_ERROR_EXISTS) {
- g_error_free (arextract->priv->error);
- arextract->priv->error = NULL;
- } else {
- g_object_unref (info);
- return;
+ {
+ GFileAndInfo fileandinfo;
+
+ g_debug ("autoar_extract_do_write_entry: case DIR");
+ g_file_make_directory_with_parents (dest, NULL, &(arextract->priv->error));
+ if (arextract->priv->error != NULL) {
+ /* "File exists" is not a fatal error */
+ if (arextract->priv->error->code == G_IO_ERROR_EXISTS) {
+ g_error_free (arextract->priv->error);
+ arextract->priv->error = NULL;
+ } else {
+ g_object_unref (info);
+ return;
+ }
}
+ fileandinfo.file = g_object_ref (dest);
+ fileandinfo.info = g_object_ref (info);
+ g_array_append_val (priv->extracted_dir_list, fileandinfo);
}
- fileandinfo.file = g_object_ref (dest);
- fileandinfo.info = g_object_ref (info);
- g_array_append_val (extracted_dir_list, fileandinfo);
break;
case AE_IFLNK:
g_debug ("autoar_extract_do_write_entry: case LNK");
@@ -771,39 +865,50 @@ autoar_extract_do_write_entry (AutoarExtract *arextract,
* in the regular archives, so errors are not fatal. */
#if defined HAVE_MKFIFO || defined HAVE_MKNOD
case AE_IFIFO:
- g_debug ("autoar_extract_do_write_entry: case FIFO");
+ {
+ char *path;
+ g_debug ("autoar_extract_do_write_entry: case FIFO");
# ifdef HAVE_MKFIFO
- r = mkfifo (str = g_file_get_path (dest), archive_entry_perm (entry));
- g_free (str);
+ r = mkfifo (path = g_file_get_path (dest), archive_entry_perm (entry));
# else
- r = mknod (str = g_file_get_path (dest),
- S_IFIFO | archive_entry_perm (entry),
- 0);
- g_free (str);
+ r = mknod (path = g_file_get_path (dest),
+ S_IFIFO | archive_entry_perm (entry),
+ 0);
# endif
+ g_free (path);
+ }
break;
#endif
#ifdef HAVE_MKNOD
case AE_IFSOCK:
- g_debug ("autoar_extract_do_write_entry: case SOCK");
- r = mknod (str = g_file_get_path (dest),
- S_IFSOCK | archive_entry_perm (entry),
- 0);
- g_free (str);
+ {
+ char *path;
+ g_debug ("autoar_extract_do_write_entry: case SOCK");
+ r = mknod (path = g_file_get_path (dest),
+ S_IFSOCK | archive_entry_perm (entry),
+ 0);
+ g_free (path);
+ }
break;
case AE_IFBLK:
- g_debug ("autoar_extract_do_write_entry: case BLK");
- r = mknod (str = g_file_get_path (dest),
- S_IFBLK | archive_entry_perm (entry),
- archive_entry_rdev (entry));
- g_free (str);
+ {
+ char *path;
+ g_debug ("autoar_extract_do_write_entry: case BLK");
+ r = mknod (path = g_file_get_path (dest),
+ S_IFBLK | archive_entry_perm (entry),
+ archive_entry_rdev (entry));
+ g_free (path);
+ }
break;
case AE_IFCHR:
- g_debug ("autoar_extract_do_write_entry: case CHR");
- r = mknod (str = g_file_get_path (dest),
- S_IFCHR | archive_entry_perm (entry),
- archive_entry_rdev (entry));
- g_free (str);
+ {
+ char *path;
+ g_debug ("autoar_extract_do_write_entry: case CHR");
+ r = mknod (path = g_file_get_path (dest),
+ S_IFCHR | archive_entry_perm (entry),
+ archive_entry_rdev (entry));
+ g_free (path);
+ }
break;
#endif
}
@@ -814,6 +919,7 @@ autoar_extract_do_write_entry (AutoarExtract *arextract,
filetype == AE_IFSOCK ||
filetype == AE_IFBLK ||
filetype == AE_IFCHR)) {
+ GOutputStream *ostream;
ostream = (GOutputStream*)g_file_append_to (dest, G_FILE_CREATE_NONE, NULL, NULL);
if (ostream != NULL) {
g_output_stream_close (ostream, NULL, NULL);
@@ -953,6 +1059,16 @@ autoar_extract_class_init (AutoarExtractClass *klass)
G_TYPE_DOUBLE,
G_TYPE_DOUBLE);
+ autoar_extract_signals[CANCELLED] =
+ g_signal_new ("cancelled",
+ type,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (AutoarExtractClass, cancelled),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+
autoar_extract_signals[COMPLETED] =
g_signal_new ("completed",
type,
@@ -998,6 +1114,19 @@ autoar_extract_init (AutoarExtract *arextract)
priv->buffer_size = BUFFER_SIZE;
priv->buffer = g_new (char, priv->buffer_size);
priv->error = NULL;
+
+ priv->cancellable = NULL;
+
+ priv->userhash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+ priv->grouphash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+ priv->bad_filename = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+ priv->pattern_compiled = g_ptr_array_new_with_free_func (g_pattern_spec_free_safe);
+ priv->extracted_dir_list = g_array_new (FALSE, FALSE, sizeof (GFileAndInfo));
+ g_array_set_clear_func (priv->extracted_dir_list, g_file_and_info_free);
+ priv->top_level_dir = NULL;
+
+ priv->in_thread = FALSE;
+ priv->use_raw_format = FALSE;
}
AutoarExtract*
@@ -1020,65 +1149,51 @@ autoar_extract_new (const char *source,
}
static void
-autoar_extract_run (AutoarExtract *arextract,
- gboolean in_thread)
+autoar_extract_run (AutoarExtract *arextract)
{
struct archive *a;
struct archive_entry *entry;
char *pathname_basename;
- char *pathname_extension;
char *pathname_prefix;
int pathname_prefix_len;
gboolean has_top_level_dir;
gboolean has_only_one_file;
- gboolean use_raw_format;
- char *top_level_dir_basename;
- char *top_level_dir_basename_modified;
- GFile *top_level_parent_dir;
- GFile *top_level_dir;
-
- GHashTable *userhash;
- GHashTable *grouphash;
- GHashTable *bad_filename;
-
- const char **pattern;
- GPtrArray *pattern_compiled;
- GArray *extracted_dir_list;
-
- GFile *source;
- char *source_basename;
+ AutoarExtractPrivate *priv;
int i, r;
g_return_if_fail (AUTOAR_IS_EXTRACT (arextract));
- g_return_if_fail (arextract->priv->source != NULL);
- g_return_if_fail (arextract->priv->output != NULL);
+ priv = arextract->priv;
+
+ g_return_if_fail (priv->source != NULL);
+ g_return_if_fail (priv->output != NULL);
a = archive_read_new ();
archive_read_support_filter_all (a);
archive_read_support_format_all (a);
/* Reset all counter variables */
- arextract->priv->size = 0;
- arextract->priv->completed_size = 0;
- arextract->priv->files = 0;
- arextract->priv->completed_files = 0;
-
- pattern = autoar_pref_get_pattern_to_ignore (arextract->priv->arpref);
- pattern_compiled = g_ptr_array_new_with_free_func (g_pattern_spec_free_safe);
- if (pattern != NULL) {
- for (i = 0; pattern[i] != NULL; i++)
- g_ptr_array_add (pattern_compiled, g_pattern_spec_new (pattern[i]));
+ priv->size = 0;
+ priv->completed_size = 0;
+ priv->files = 0;
+ priv->completed_files = 0;
+
+ {
+ const char **pattern = autoar_pref_get_pattern_to_ignore (priv->arpref);
+ priv->pattern_compiled = g_ptr_array_new_with_free_func (g_pattern_spec_free_safe);
+ if (pattern != NULL) {
+ for (i = 0; pattern[i] != NULL; i++)
+ g_ptr_array_add (priv->pattern_compiled, g_pattern_spec_new (pattern[i]));
+ }
+ g_ptr_array_add (priv->pattern_compiled, NULL);
}
- g_ptr_array_add (pattern_compiled, NULL);
pathname_prefix = NULL;
pathname_prefix_len = 0;
has_top_level_dir = TRUE;
has_only_one_file = TRUE;
- use_raw_format = FALSE;
/* Step 1: Scan all file names in the archive
* We have to check whether the archive contains a top-level directory
@@ -1108,51 +1223,40 @@ autoar_extract_run (AutoarExtract *arextract,
archive_read_set_callback_data (a, arextract);
r = archive_read_open1 (a);
if (r != ARCHIVE_OK || archive_filter_count (a) <= 1) {
- if (arextract->priv->error == NULL) {
+ if (priv->error == NULL) {
if (r != ARCHIVE_OK) {
- arextract->priv->error = g_error_new (autoar_extract_quark,
- archive_errno (a),
- "\'%s\': %s",
- arextract->priv->source,
- archive_error_string (a));
+ priv->error = autoar_common_g_error_new_a (autoar_extract_quark, a, priv->source);
} else {
/* If we only use raw format and filter count is one, libarchive will
* not do anything except for just copying the source file. We do not
* want this thing to happen because it does unnecesssary copying. */
- arextract->priv->error = g_error_new (autoar_extract_quark,
- NOT_AN_ARCHIVE_ERRNO,
- "\'%s\': %s",
- arextract->priv->source,
- "not an archive");
+ priv->error = g_error_new (autoar_extract_quark,
+ NOT_AN_ARCHIVE_ERRNO,
+ "\'%s\': %s",
+ priv->source,
+ "not an archive");
}
}
- autoar_common_g_signal_emit (in_thread, arextract,
- autoar_extract_signals[ERROR],
- 0, arextract->priv->error);
+ autoar_extract_signal_error (arextract);
archive_read_free (a);
- g_ptr_array_unref (pattern_compiled);
return;
}
- use_raw_format = TRUE;
+ priv->use_raw_format = TRUE;
}
- bad_filename = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
pathname_basename = NULL;
while ((r = archive_read_next_header (a, &entry)) == ARCHIVE_OK) {
const char *pathname, *dir_sep_location;
size_t skip_len, prefix_len;
pathname = archive_entry_pathname (entry);
- g_debug ("autoar_extract_run: %d: pathname = %s",
- arextract->priv->files,
- pathname);
+ g_debug ("autoar_extract_run: %d: pathname = %s", priv->files, pathname);
- if (!use_raw_format && !autoar_extract_do_pattern_check (pathname, pattern_compiled)) {
- g_hash_table_insert (bad_filename, g_strdup (pathname), GUINT_TO_POINTER (TRUE));
+ if (!priv->use_raw_format && !autoar_extract_do_pattern_check (pathname, priv->pattern_compiled)) {
+ g_hash_table_insert (priv->bad_filename, g_strdup (pathname), GUINT_TO_POINTER (TRUE));
continue;
}
- g_debug ("autoar_extract_run: %d: pattern check passed",
- arextract->priv->files);
+ g_debug ("autoar_extract_run: %d: pattern check passed", priv->files);
if (pathname_prefix == NULL) {
pathname_basename = g_path_get_basename (pathname);
@@ -1172,115 +1276,109 @@ autoar_extract_run (AutoarExtract *arextract,
has_top_level_dir = FALSE;
}
}
- arextract->priv->files++;
- arextract->priv->size += archive_entry_size (entry);
+ priv->files++;
+ 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));
+ if (priv->error == NULL) {
+ priv->error = autoar_common_g_error_new_a (autoar_extract_quark, a, priv->source);
}
- autoar_common_g_signal_emit (in_thread, arextract,
- autoar_extract_signals[ERROR],
- 0, arextract->priv->error);
+ autoar_extract_signal_error (arextract);
g_free (pathname_prefix);
g_free (pathname_basename);
- 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);
- if (arextract->priv->error != NULL) {
- autoar_common_g_signal_emit (in_thread, arextract,
- autoar_extract_signals[ERROR],
- 0, arextract->priv->error);
- g_hash_table_unref (bad_filename);
+ if (priv->error != NULL) {
+ g_free (pathname_basename);
+ autoar_extract_signal_error (arextract);
return;
}
g_debug ("autoar_extract_run: has_top_level_dir = %s",
has_top_level_dir ? "TRUE" : "FALSE");
- autoar_common_g_signal_emit (in_thread, arextract,
- autoar_extract_signals[SCANNED],
- 0, arextract->priv->files);
+ autoar_extract_signal_scanned (arextract);
/* Step 2: Create necessary directories
* If the archive contains only one file, we don't create the directory */
g_debug ("autoar_extract_run: Step 2, Mkdir-p");
- source = g_file_new_for_commandline_arg (arextract->priv->source);
- source_basename = g_file_get_basename (source);
- g_object_unref (source);
- top_level_dir_basename = autoar_common_get_basename_remove_extension (source_basename);
- top_level_parent_dir = g_file_new_for_commandline_arg (arextract->priv->output);
-
- pathname_extension = autoar_common_get_filename_extension (pathname_basename);
- if (has_only_one_file && (pathname_extension != pathname_basename)) {
- /* If we only have one file, we have to add the file extension.
- * Although we use the variable `top_level_dir', it may be a regular
- * file, so the extension is important. */
- char *new_filename;
- new_filename = g_strconcat (top_level_dir_basename, pathname_extension, NULL);
- top_level_dir = g_file_get_child (top_level_parent_dir, new_filename);
- g_free (new_filename);
- } else {
- top_level_dir = g_file_get_child (top_level_parent_dir, top_level_dir_basename);
- pathname_extension = "";
- }
+ {
+ GFile *top_level_parent_dir;
+ char *top_level_dir_basename;
+ const char *pathname_extension;
+
+ {
+ GFile *source;
+ char *source_basename;
+ source = g_file_new_for_commandline_arg (priv->source);
+ source_basename = g_file_get_basename (source);
+ top_level_dir_basename = autoar_common_get_basename_remove_extension (source_basename);
+ top_level_parent_dir = g_file_new_for_commandline_arg (priv->output);
+ g_object_unref (source);
+ g_free (source_basename);
+ }
- top_level_dir_basename_modified = NULL;
- 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);
- if (has_only_one_file) {
- top_level_dir_basename_modified = g_strdup_printf ("%s(%d)%s",
- top_level_dir_basename,
- i,
- pathname_extension);
+ pathname_extension = autoar_common_get_filename_extension (pathname_basename);
+ if (has_only_one_file && (pathname_extension != pathname_basename)) {
+ /* If we only have one file, we have to add the file extension.
+ * Although we use the variable `top_level_dir', it may be a regular
+ * file, so the extension is important. */
+ char *new_filename;
+ new_filename = g_strconcat (top_level_dir_basename, pathname_extension, NULL);
+ priv->top_level_dir = g_file_get_child (top_level_parent_dir, new_filename);
+ g_free (new_filename);
} else {
- top_level_dir_basename_modified = g_strdup_printf ("%s(%d)",
- top_level_dir_basename,
- i);
+ priv->top_level_dir = g_file_get_child (top_level_parent_dir, top_level_dir_basename);
+ pathname_extension = "";
}
- top_level_dir = g_file_get_child (top_level_parent_dir,
- top_level_dir_basename_modified);
- }
- if (!has_only_one_file)
- g_file_make_directory_with_parents (top_level_dir, NULL, &(arextract->priv->error));
+ {
+ char *top_level_dir_basename_modified = NULL;
+ for (i = 1; g_file_query_exists (priv->top_level_dir, NULL); i++) {
+ g_free (top_level_dir_basename_modified);
+ g_object_unref (priv->top_level_dir);
+ if (has_only_one_file) {
+ top_level_dir_basename_modified = g_strdup_printf ("%s(%d)%s",
+ top_level_dir_basename,
+ i,
+ pathname_extension);
+ } else {
+ top_level_dir_basename_modified = g_strdup_printf ("%s(%d)",
+ top_level_dir_basename,
+ i);
+ }
+ priv->top_level_dir = g_file_get_child (top_level_parent_dir,
+ top_level_dir_basename_modified);
+ }
+ g_free (top_level_dir_basename_modified);
+ }
- g_free (pathname_basename);
- g_free (top_level_dir_basename);
- g_free (top_level_dir_basename_modified);
- g_object_unref (top_level_parent_dir);
+ if (!has_only_one_file)
+ g_file_make_directory_with_parents (priv->top_level_dir, NULL, &(priv->error));
- if (arextract->priv->error != NULL) {
- autoar_common_g_signal_emit (in_thread, arextract,
- autoar_extract_signals[ERROR],
- 0, arextract->priv->error);
- g_object_unref (top_level_dir);
- g_hash_table_unref (bad_filename);
- return;
- }
+ g_free (pathname_basename);
+ g_free (top_level_dir_basename);
+ g_object_unref (top_level_parent_dir);
+
+ if (priv->error != NULL) {
+ autoar_extract_signal_error (arextract);
+ return;
+ }
- autoar_common_g_signal_emit (in_thread, arextract,
- autoar_extract_signals[DECIDE_DEST],
- 0, top_level_dir);
+ autoar_extract_signal_decide_dest (arextract);
+ }
/* Step 3: Extract files
* We have to re-open the archive to extract files */
g_debug ("autoar_extract_run: Step 3, Extract");
a = archive_read_new ();
archive_read_support_filter_all (a);
- if (use_raw_format)
+ if (priv->use_raw_format)
archive_read_support_format_raw (a);
else
archive_read_support_format_all (a);
@@ -1292,25 +1390,13 @@ autoar_extract_run (AutoarExtract *arextract,
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,
- archive_errno (a),
- "\'%s\': %s",
- arextract->priv->source,
- archive_error_string (a));
+ if (priv->error == NULL) {
+ priv->error = autoar_common_g_error_new_a (autoar_extract_quark, a, priv->source);
}
- autoar_common_g_signal_emit (in_thread, arextract,
- autoar_extract_signals[ERROR],
- 0, arextract->priv->error);
- g_object_unref (top_level_dir);
- g_hash_table_unref (bad_filename);
+ autoar_extract_signal_error (arextract);
archive_read_free (a);
return;
}
- 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);
- extracted_dir_list = g_array_new (FALSE, FALSE, sizeof (GFileAndInfo));
- g_array_set_clear_func (extracted_dir_list, g_file_and_info_free);
while ((r = archive_read_next_header (a, &entry)) == ARCHIVE_OK) {
const char *pathname;
const char *hardlink;
@@ -1320,132 +1406,97 @@ autoar_extract_run (AutoarExtract *arextract,
pathname = archive_entry_pathname (entry);
hardlink = archive_entry_hardlink (entry);
hardlink_filename = NULL;
- if (GPOINTER_TO_UINT (g_hash_table_lookup (bad_filename, pathname)))
+ if (GPOINTER_TO_UINT (g_hash_table_lookup (priv->bad_filename, pathname)))
continue;
if (!has_only_one_file) {
if (has_top_level_dir) {
extracted_filename =
autoar_extract_do_sanitize_pathname (pathname + pathname_prefix_len,
- NULL, top_level_dir);
+ NULL, priv->top_level_dir);
if (hardlink != NULL)
hardlink_filename =
autoar_extract_do_sanitize_pathname (hardlink + pathname_prefix_len,
- NULL, top_level_dir);
+ NULL, priv->top_level_dir);
} else {
extracted_filename =
- autoar_extract_do_sanitize_pathname (pathname, "./", top_level_dir);
+ autoar_extract_do_sanitize_pathname (pathname, "./", priv->top_level_dir);
if (hardlink != NULL)
hardlink_filename =
- autoar_extract_do_sanitize_pathname (pathname, "./", top_level_dir);
+ autoar_extract_do_sanitize_pathname (pathname, "./", priv->top_level_dir);
}
} else {
- extracted_filename = g_object_ref (top_level_dir);
+ extracted_filename = g_object_ref (priv->top_level_dir);
}
autoar_extract_do_write_entry (arextract,
a,
entry,
extracted_filename,
- hardlink_filename,
- top_level_dir,
- userhash,
- grouphash,
- extracted_dir_list,
- in_thread,
- use_raw_format);
+ hardlink_filename);
g_object_unref (extracted_filename);
if (hardlink_filename != NULL)
g_object_unref (hardlink_filename);
- if (arextract->priv->error != NULL) {
- autoar_common_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);
- g_array_unref (extracted_dir_list);
+ if (priv->error != NULL) {
+ autoar_extract_signal_error (arextract);
archive_read_close (a);
archive_read_free (a);
return;
}
- arextract->priv->completed_files++;
- autoar_common_g_signal_emit (in_thread,
- arextract,
- autoar_extract_signals[PROGRESS],
- 0,
- ((double)(arextract->priv->completed_size)) /
- ((double)(arextract->priv->size)),
- ((double)(arextract->priv->completed_files)) /
- ((double)(arextract->priv->files)));
+ priv->completed_files++;
+ autoar_extract_signal_progress (arextract);
}
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));
+ if (priv->error == NULL) {
+ priv->error = autoar_common_g_error_new_a (autoar_extract_quark, a, priv->source);
}
- autoar_common_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);
- g_array_unref (extracted_dir_list);
+ autoar_extract_signal_error (arextract);
archive_read_close (a);
archive_read_free (a);
return;
}
- for (i = 0; i < extracted_dir_list->len; i++) {
- GFile *file = g_array_index (extracted_dir_list, GFileAndInfo, i).file;
- GFileInfo *info = g_array_index (extracted_dir_list, GFileAndInfo, i).info;
+ for (i = 0; i < priv->extracted_dir_list->len; i++) {
+ GFile *file = g_array_index (priv->extracted_dir_list, GFileAndInfo, i).file;
+ GFileInfo *info = g_array_index (priv->extracted_dir_list, GFileAndInfo, i).info;
g_file_set_attributes_from_info (file, info,
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
NULL, NULL);
}
- g_object_unref (top_level_dir);
- g_hash_table_unref (userhash);
- g_hash_table_unref (grouphash);
- g_hash_table_unref (bad_filename);
- g_array_unref (extracted_dir_list);
archive_read_close (a);
archive_read_free (a);
- if (arextract->priv->error != NULL) {
- autoar_common_g_signal_emit (in_thread, arextract,
- autoar_extract_signals[ERROR],
- 0, arextract->priv->error);
+ if (priv->error != NULL) {
+ autoar_extract_signal_error (arextract);
return;
}
/* If the extraction is completed successfully, remove the source file.
* Errors are not fatal because we have completed our work. */
- autoar_common_g_signal_emit (in_thread, arextract,
- autoar_extract_signals[PROGRESS],
- 0, 1.0, 1.0);
+ priv->completed_size = priv->size;
+ priv->completed_files = priv->files;
+ autoar_extract_signal_progress (arextract);
g_debug ("autoar_extract_run: Finalize");
- if (autoar_pref_get_delete_if_succeed (arextract->priv->arpref)) {
+ if (autoar_pref_get_delete_if_succeed (priv->arpref)) {
+ GFile *source;
g_debug ("autoar_extract_run: Delete");
- source = g_file_new_for_commandline_arg (arextract->priv->source);
+ source = g_file_new_for_commandline_arg (priv->source);
g_file_delete (source, NULL, NULL);
g_object_unref (source);
}
- autoar_common_g_signal_emit (in_thread, arextract,
- autoar_extract_signals[COMPLETED], 0);
+ autoar_extract_signal_completed (arextract);
}
void
-autoar_extract_start (AutoarExtract *arextract)
+autoar_extract_start (AutoarExtract *arextract,
+ GCancellable *cancellable)
{
- autoar_extract_run (arextract, FALSE);
+ arextract->priv->cancellable = cancellable;
+ arextract->priv->in_thread = FALSE;
+ autoar_extract_run (arextract);
}
static void
@@ -1455,7 +1506,7 @@ autoar_extract_start_async_thread (GTask *task,
GCancellable *cancellable)
{
AutoarExtract *arextract = source_object;
- autoar_extract_run (arextract, TRUE);
+ autoar_extract_run (arextract);
g_task_return_pointer (task, NULL, g_free);
g_object_unref (arextract);
g_object_unref (task);
@@ -1463,11 +1514,14 @@ autoar_extract_start_async_thread (GTask *task,
void
-autoar_extract_start_async (AutoarExtract *arextract)
+autoar_extract_start_async (AutoarExtract *arextract,
+ GCancellable *cancellable)
{
GTask *task;
g_object_ref (arextract);
+ arextract->priv->cancellable = cancellable;
+ arextract->priv->in_thread = TRUE;
task = g_task_new (arextract, NULL, NULL, NULL);
g_task_set_task_data (task, NULL, NULL);
diff --git a/gnome-autoar/autoar-extract.h b/gnome-autoar/autoar-extract.h
index 8e2df64..ef504fd 100644
--- a/gnome-autoar/autoar-extract.h
+++ b/gnome-autoar/autoar-extract.h
@@ -62,6 +62,7 @@ struct _AutoarExtractClass
void (* progress) (AutoarExtract *arextract,
gdouble fraction_size,
gdouble fraction_files);
+ void (* cancelled) (AutoarExtract *arextract);
void (* completed) (AutoarExtract *arextract);
void (* error) (AutoarExtract *arextract,
GError *error);
@@ -73,8 +74,10 @@ AutoarExtract *autoar_extract_new (const char *source,
const char *output,
AutoarPref *arpref);
-void autoar_extract_start (AutoarExtract *arextract);
-void autoar_extract_start_async (AutoarExtract *arextract);
+void autoar_extract_start (AutoarExtract *arextract,
+ GCancellable *cancellable);
+void autoar_extract_start_async (AutoarExtract *arextract,
+ GCancellable *cancellable);
char *autoar_extract_get_source (AutoarExtract *arextract);
char *autoar_extract_get_output (AutoarExtract *arextract);
diff --git a/tests/test-extract.c b/tests/test-extract.c
index 689ba0e..a592dd8 100644
--- a/tests/test-extract.c
+++ b/tests/test-extract.c
@@ -81,7 +81,7 @@ main (int argc,
g_signal_connect (arextract, "error", G_CALLBACK (my_handler_error), NULL);
g_signal_connect (arextract, "completed", G_CALLBACK (my_handler_completed), NULL);
- autoar_extract_start (arextract);
+ autoar_extract_start (arextract, NULL);
g_object_unref (arextract);
g_object_unref (arpref);