File file-roller-drop-workspace-backup-files.patch of Package file-roller.36885

--- a/src/fr-archive-libarchive.c.orig
+++ b/src/fr-archive-libarchive.c.orig
@@ -1,2198 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/*
- *  File-Roller
- *
- *  Copyright (C) 2012 Free Software Foundation, Inc.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <config.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <pwd.h>
-#include <grp.h>
-#include <glib.h>
-#include <glib/gi18n.h>
-#include <gio/gio.h>
-#include <archive.h>
-#include <archive_entry.h>
-#include "file-data.h"
-#include "file-utils.h"
-#include "fr-error.h"
-#include "fr-archive-libarchive.h"
-#include "gio-utils.h"
-#include "glib-utils.h"
-#include "typedefs.h"
-
-
-#define BUFFER_SIZE (64 * 1024)
-#define FILE_ATTRIBUTES_NEEDED_BY_ARCHIVE_ENTRY ("standard::*,time::*,access::*,unix::*")
-
-
-G_DEFINE_TYPE (FrArchiveLibarchive, fr_archive_libarchive, FR_TYPE_ARCHIVE)
-
-
-struct _FrArchiveLibarchivePrivate {
-	gssize compressed_size;
-	gssize uncompressed_size;
-};
-
-
-static void
-fr_archive_libarchive_finalize (GObject *object)
-{
-	/*FrArchiveLibarchive *self;*/
-
-	g_return_if_fail (object != NULL);
-	g_return_if_fail (FR_IS_ARCHIVE_LIBARCHIVE (object));
-
-	/*self = FR_ARCHIVE_LIBARCHIVE (object);*/
-
-	if (G_OBJECT_CLASS (fr_archive_libarchive_parent_class)->finalize)
-		G_OBJECT_CLASS (fr_archive_libarchive_parent_class)->finalize (object);
-}
-
-
-const char *libarchiver_mime_types[] = {
-		"application/vnd.debian.binary-package",
-		"application/vnd.ms-cab-compressed",
-		"application/x-7z-compressed",
-		"application/x-ar",
-		"application/x-bzip-compressed-tar",
-		"application/x-cbr",
-		"application/x-cbz",
-		"application/x-cd-image",
-		"application/x-compressed-tar",
-		"application/x-cpio",
-		"application/x-deb",
-		"application/x-lha",
-		"application/x-lrzip-compressed-tar",
-		"application/x-lzip-compressed-tar",
-		"application/x-lzma-compressed-tar",
-		"application/x-lzop-compressed-tar",
-		"application/x-rar",
-		"application/x-rpm",
-		"application/x-tar",
-		"application/x-tarz",
-		"application/x-xar",
-		"application/x-xz-compressed-tar",
-		"application/zip",
-		NULL };
-
-
-static const char **
-fr_archive_libarchive_get_mime_types (FrArchive *archive)
-{
-	return libarchiver_mime_types;
-}
-
-
-static FrArchiveCap
-fr_archive_libarchive_get_capabilities (FrArchive  *archive,
-					const char *mime_type,
-					gboolean    check_command)
-{
-	FrArchiveCap capabilities;
-
-	capabilities = FR_ARCHIVE_CAN_STORE_MANY_FILES;
-
-	/* write-only formats */
-	if (strcmp (mime_type, "application/x-7z-compressed") == 0) {
-		capabilities |= FR_ARCHIVE_CAN_WRITE;
-		return capabilities;
-	}
-
-	/* give priority to 7za that supports CAB files better. */
-	if ((strcmp (mime_type, "application/vnd.ms-cab-compressed") == 0)
-	    && _g_program_is_available ("7za", check_command))
-	{
-		return capabilities;
-	}
-
-	/* give priority to 7z, unzip and zip that supports ZIP files better. */
-	if ((strcmp (mime_type, "application/zip") == 0)
-	    || (strcmp (mime_type, "application/x-cbz") == 0))
-	{
-		if (_g_program_is_available ("7z", check_command)) {
-			return capabilities;
-		}
-		if (!_g_program_is_available ("unzip", check_command)) {
-			capabilities |= FR_ARCHIVE_CAN_READ;
-		}
-		if (!_g_program_is_available ("zip", check_command)) {
-			capabilities |= FR_ARCHIVE_CAN_WRITE;
-		}
-		return capabilities;
-	}
-
-	/* give priority to utilities that support RAR files better. */
-	if ((strcmp (mime_type, "application/x-rar") == 0)
-	    || (strcmp (mime_type, "application/x-cbr") == 0))
-	{
-		if (_g_program_is_available ("rar", check_command)
-		    || _g_program_is_available ("unrar", check_command)
-		    || _g_program_is_available ("unar", check_command)) {
-			return capabilities;
-		}
-	}
-
-	/* tar.lrz format requires external lrzip */
-	if (strcmp (mime_type, "application/x-lrzip-compressed-tar") == 0) {
-		if (!_g_program_is_available ("lrzip", check_command))
-			return capabilities;
-	}
-
-	capabilities |= FR_ARCHIVE_CAN_READ;
-
-	/* read-only formats */
-	if ((strcmp (mime_type, "application/vnd.ms-cab-compressed") == 0)
-	    || (strcmp (mime_type, "application/x-cbr") == 0)
-	    || (strcmp (mime_type, "application/x-deb") == 0)
-	    || (strcmp (mime_type, "application/vnd.debian.binary-package") == 0)
-	    || (strcmp (mime_type, "application/x-lha") == 0)
-	    || (strcmp (mime_type, "application/x-rar") == 0)
-	    || (strcmp (mime_type, "application/x-rpm") == 0)
-	    || (strcmp (mime_type, "application/x-xar") == 0))
-	{
-		return capabilities;
-	}
-
-	/* all other formats can be read and written */
-	capabilities |= FR_ARCHIVE_CAN_WRITE;
-
-	return capabilities;
-}
-
-
-static const char *
-fr_archive_libarchive_get_packages (FrArchive  *archive,
-				    const char *mime_type)
-{
-	return NULL;
-}
-
-
-/* LoadData */
-
-
-#define LOAD_DATA(x) ((LoadData *)(x))
-
-
-typedef struct {
-	FrArchive          *archive;
-	GCancellable       *cancellable;
-	GSimpleAsyncResult *result;
-	GInputStream       *istream;
-	void               *buffer;
-	gssize              buffer_size;
-	GError             *error;
-} LoadData;
-
-
-static void
-load_data_init (LoadData *load_data)
-{
-	load_data->buffer_size = BUFFER_SIZE;
-	load_data->buffer = g_new (char, load_data->buffer_size);
-}
-
-
-static void
-load_data_free (LoadData *load_data)
-{
-	_g_object_unref (load_data->archive);
-	_g_object_unref (load_data->cancellable);
-	_g_object_unref (load_data->result);
-	_g_object_unref (load_data->istream);
-	g_free (load_data->buffer);
-	g_free (load_data);
-}
-
-
-static int
-load_data_open (struct archive *a,
-		void           *client_data)
-{
-	LoadData *load_data = client_data;
-
-	if (load_data->error != NULL)
-		return ARCHIVE_FATAL;
-
-	if (g_simple_async_result_get_source_tag (load_data->result) == fr_archive_list) {
-		FR_ARCHIVE_LIBARCHIVE (load_data->archive)->priv->compressed_size = 0;
-		FR_ARCHIVE_LIBARCHIVE (load_data->archive)->priv->uncompressed_size = 0;
-	}
-
-	load_data->istream = (GInputStream *) g_file_read (fr_archive_get_file (load_data->archive),
-							   load_data->cancellable,
-							   &load_data->error);
-	return (load_data->error == NULL) ? ARCHIVE_OK : ARCHIVE_FATAL;
-}
-
-
-static ssize_t
-load_data_read (struct archive  *a,
-		void            *client_data,
-		const void     **buff)
-{
-	LoadData *load_data = client_data;
-	gssize    bytes;
-
-	if (load_data->error != NULL)
-		return -1;
-
-	*buff = load_data->buffer;
-	bytes = g_input_stream_read (load_data->istream,
-				     load_data->buffer,
-				     load_data->buffer_size,
-				     load_data->cancellable,
-				     &load_data->error);
-
-	/* update the progress only if listing the content */
-	if (g_simple_async_result_get_source_tag (load_data->result) == fr_archive_list) {
-		fr_archive_progress_set_completed_bytes (load_data->archive,
-							 g_seekable_tell (G_SEEKABLE (load_data->istream)));
-		FR_ARCHIVE_LIBARCHIVE (load_data->archive)->priv->compressed_size += bytes;
-	}
-
-	return bytes;
-}
-
-
-static int
-load_data_close (struct archive *a,
-		 void           *client_data)
-{
-	LoadData *load_data = client_data;
-
-	if (load_data->error != NULL)
-		return ARCHIVE_FATAL;
-
-	if (load_data->istream != NULL) {
-		_g_object_unref (load_data->istream);
-		load_data->istream = NULL;
-	}
-
-	return ARCHIVE_OK;
-}
-
-
-/* -- list -- */
-
-
-static goffset
-_g_file_get_size (GFile        *file,
-		  GCancellable *cancellable)
-{
-	GFileInfo *info;
-	goffset    size;
-
-	info = g_file_query_info (file,
-				  G_FILE_ATTRIBUTE_STANDARD_SIZE,
-				  G_FILE_QUERY_INFO_NONE,
-				  cancellable,
-				  NULL);
-	if (info == NULL)
-		return 0;
-
-	size = g_file_info_get_size (info);
-	g_object_unref (info);
-
-	return size;
-}
-
-
-static GError *
-_g_error_new_from_archive_error (const char *s)
-{
-	char   *msg;
-	GError *error;
-
-	msg = g_locale_to_utf8 (s, -1, NULL, NULL, NULL);
-	if (msg == NULL)
-		msg = g_strdup ("Fatal error");
-	error = g_error_new_literal (FR_ERROR, FR_ERROR_COMMAND_ERROR, msg);
-
-	g_free (msg);
-
-	return error;
-}
-
-
-static void
-list_archive_thread (GSimpleAsyncResult *result,
-		     GObject            *object,
-		     GCancellable       *cancellable)
-{
-	LoadData             *load_data;
-	struct archive       *a;
-	struct archive_entry *entry;
-	int                   r;
-
-	load_data = g_simple_async_result_get_op_res_gpointer (result);
-
-	fr_archive_progress_set_total_bytes (load_data->archive,
-					     _g_file_get_size (fr_archive_get_file (load_data->archive), cancellable));
-
-	a = archive_read_new ();
-	archive_read_support_filter_all (a);
-	archive_read_support_format_all (a);
-	archive_read_open (a, load_data, load_data_open, load_data_read, load_data_close);
-	while ((r = archive_read_next_header (a, &entry)) == ARCHIVE_OK) {
-		FileData   *file_data;
-		const char *pathname;
-
-		if (g_cancellable_is_cancelled (cancellable))
-			break;
-
-		file_data = file_data_new ();
-
-		if (archive_entry_size_is_set (entry)) {
-			file_data->size = archive_entry_size (entry);
-			FR_ARCHIVE_LIBARCHIVE (load_data->archive)->priv->uncompressed_size += file_data->size;
-		}
-
-		if (archive_entry_mtime_is_set (entry))
-			file_data->modified =  archive_entry_mtime (entry);
-
-		if (archive_entry_filetype (entry) == AE_IFLNK)
-			file_data->link = g_strdup (archive_entry_symlink (entry));
-
-		pathname = archive_entry_pathname (entry);
-		if (*pathname == '/') {
-			file_data->full_path = g_strdup (pathname);
-			file_data->original_path = file_data->full_path;
-		}
-		else {
-			file_data->full_path = g_strconcat ("/", pathname, NULL);
-			file_data->original_path = file_data->full_path + 1;
-		}
-
-		file_data->dir = (archive_entry_filetype (entry) == AE_IFDIR);
-		if (file_data->dir)
-			file_data->name = _g_path_get_dir_name (file_data->full_path);
-		else
-			file_data->name = g_strdup (_g_path_get_basename (file_data->full_path));
-		file_data->path = _g_path_remove_level (file_data->full_path);
-
-		/*
-		g_print ("%s\n", archive_entry_pathname (entry));
-		g_print ("\tfull_path: %s\n", file_data->full_path);
-		g_print ("\toriginal_path: %s\n", file_data->original_path);
-		g_print ("\tname: %s\n", file_data->name);
-		g_print ("\tpath: %s\n", file_data->path);
-		*/
-
-		fr_archive_add_file (load_data->archive, file_data);
-
-		archive_read_data_skip (a);
-	}
-	archive_read_free (a);
-
-	if ((load_data->error == NULL) && (r != ARCHIVE_EOF) && (archive_error_string (a) != NULL))
-		load_data->error = _g_error_new_from_archive_error (archive_error_string (a));
-	if (load_data->error == NULL)
-		g_cancellable_set_error_if_cancelled (cancellable, &load_data->error);
-	if (load_data->error != NULL)
-		g_simple_async_result_set_from_error (result, load_data->error);
-
-	load_data_free (load_data);
-}
-
-
-static void
-fr_archive_libarchive_list (FrArchive           *archive,
-			    const char          *password,
-			    GCancellable        *cancellable,
-			    GAsyncReadyCallback  callback,
-			    gpointer             user_data)
-{
-	LoadData *load_data;
-
-	load_data = g_new0 (LoadData, 1);
-	load_data_init (load_data);
-
-	load_data->archive = g_object_ref (archive);
-	load_data->cancellable = _g_object_ref (cancellable);
-	load_data->result = g_simple_async_result_new (G_OBJECT (archive),
-						       callback,
-						       user_data,
-						       fr_archive_list);
-
-	g_simple_async_result_set_op_res_gpointer (load_data->result, load_data, NULL);
-	g_simple_async_result_run_in_thread (load_data->result,
-					     list_archive_thread,
-					     G_PRIORITY_DEFAULT,
-					     cancellable);
-}
-
-
-/* -- extract -- */
-
-
-#define NULL_BUFFER_SIZE (16 * 1024)
-
-
-typedef struct {
-	LoadData    parent;
-	GList      *file_list;
-	GFile      *destination;
-	char       *base_dir;
-	gboolean    skip_older;
-	gboolean    overwrite;
-	gboolean    junk_paths;
-	GHashTable *files_to_extract;
-	int         n_files_to_extract;
-	GHashTable *usernames;
-	GHashTable *groupnames;
-	char       *null_buffer;
-} ExtractData;
-
-
-static void
-extract_data_free (ExtractData *extract_data)
-{
-	g_free (extract_data->base_dir);
-	_g_object_unref (extract_data->destination);
-	_g_string_list_free (extract_data->file_list);
-	g_hash_table_unref (extract_data->files_to_extract);
-	g_hash_table_unref (extract_data->usernames);
-	g_hash_table_unref (extract_data->groupnames);
-	g_free (extract_data->null_buffer);
-	load_data_free (LOAD_DATA (extract_data));
-}
-
-
-static gboolean
-extract_data_get_extraction_requested (ExtractData *extract_data,
-				       const char  *pathname)
-{
-	if (extract_data->file_list != NULL)
-		return g_hash_table_lookup (extract_data->files_to_extract, pathname) != NULL;
-	else
-		return TRUE;
-}
-
-
-static GFileInfo *
-_g_file_info_create_from_entry (struct archive_entry *entry,
-			        ExtractData          *extract_data)
-{
-	GFileInfo *info;
-
-	info = g_file_info_new ();
-
-	/* times */
-
-	if (archive_entry_mtime_is_set (entry))
-		g_file_info_set_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_MODIFIED, archive_entry_mtime (entry));
-
-	/* username */
-
-	if (archive_entry_uname (entry) != NULL) {
-		guint32 uid;
-
-		uid = GPOINTER_TO_INT (g_hash_table_lookup (extract_data->usernames, archive_entry_uname (entry)));
-		if (uid == 0) {
-			struct passwd *pwd = getpwnam (archive_entry_uname (entry));
-			if (pwd != NULL) {
-				uid = pwd->pw_uid;
-				g_hash_table_insert (extract_data->usernames, g_strdup (archive_entry_uname (entry)), GINT_TO_POINTER (uid));
-			}
-		}
-		if (uid != 0)
-			g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_UID, uid);
-	}
-
-	/* groupname */
-
-	if (archive_entry_gname (entry) != NULL) {
-		guint32 gid;
-
-		gid = GPOINTER_TO_INT (g_hash_table_lookup (extract_data->groupnames, archive_entry_gname (entry)));
-		if (gid == 0) {
-			struct group *grp = getgrnam (archive_entry_gname (entry));
-			if (grp != NULL) {
-				gid = grp->gr_gid;
-				g_hash_table_insert (extract_data->groupnames, g_strdup (archive_entry_gname (entry)), GINT_TO_POINTER (gid));
-			}
-		}
-		if (gid != 0)
-			g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_GID, gid);
-	}
-
-	/* permsissions */
-
-	g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_MODE, archive_entry_mode (entry));
-
-	return info;
-}
-
-
-static gboolean
-_g_file_set_attributes_from_info (GFile         *file,
-				  GFileInfo     *info,
-				  GCancellable  *cancellable,
-				  GError       **error)
-{
-	return g_file_set_attributes_from_info (file, info, G_FILE_QUERY_INFO_NONE, cancellable, error);
-}
-
-
-static void
-restore_original_file_attributes (GHashTable    *created_files,
-				  GCancellable  *cancellable)
-{
-	GHashTableIter iter;
-	gpointer       key, value;
-
-	g_hash_table_iter_init (&iter, created_files);
-	while (g_hash_table_iter_next (&iter, &key, &value)) {
-		GFile     *file = key;
-		GFileInfo *info = value;
-
-		_g_file_set_attributes_from_info (file, info, cancellable, NULL);
-	}
-}
-
-
-static gboolean
-_g_output_stream_add_padding (ExtractData    *extract_data,
-			      GOutputStream  *ostream,
-			      gssize          target_offset,
-			      gssize          actual_offset,
-			      GCancellable   *cancellable,
-			      GError        **error)
-{
-	gboolean success = TRUE;
-	gsize    count;
-	gsize    bytes_written;
-
-	if (extract_data->null_buffer == NULL)
-		extract_data->null_buffer = g_malloc0 (NULL_BUFFER_SIZE);
-
-	while (target_offset > actual_offset) {
-		count = NULL_BUFFER_SIZE;
-		if (target_offset < actual_offset + NULL_BUFFER_SIZE)
-			count = target_offset - actual_offset;
-
-		success = g_output_stream_write_all (ostream, extract_data->null_buffer, count, &bytes_written, cancellable, error);
-		if (! success)
-			break;
-
-		actual_offset += bytes_written;
-	}
-
-	return success;
-}
-
-
-static void
-extract_archive_thread (GSimpleAsyncResult *result,
-			GObject            *object,
-			GCancellable       *cancellable)
-{
-	ExtractData          *extract_data;
-	LoadData             *load_data;
-	GHashTable           *checked_folders;
-	GHashTable           *created_files;
-	GHashTable           *folders_created_during_extraction;
-	struct archive       *a;
-	struct archive_entry *entry;
-	int                   r;
-
-	extract_data = g_simple_async_result_get_op_res_gpointer (result);
-	load_data = LOAD_DATA (extract_data);
-
-	checked_folders = g_hash_table_new_full (g_file_hash, (GEqualFunc) g_file_equal, g_object_unref, NULL);
-	created_files = g_hash_table_new_full (g_file_hash, (GEqualFunc) g_file_equal, g_object_unref, g_object_unref);
-	folders_created_during_extraction = g_hash_table_new_full (g_file_hash, (GEqualFunc) g_file_equal, g_object_unref, NULL);
-	fr_archive_progress_set_total_files (load_data->archive, extract_data->n_files_to_extract);
-
-	a = archive_read_new ();
-	archive_read_support_filter_all (a);
-	archive_read_support_format_all (a);
-	archive_read_open (a, load_data, load_data_open, load_data_read, load_data_close);
-	while ((r = archive_read_next_header (a, &entry)) == ARCHIVE_OK) {
-		const char    *pathname;
-		char          *fullpath;
-		const char    *relative_path;
-		GFile         *file;
-		GFile         *parent;
-		GOutputStream *ostream;
-		const void    *buffer;
-		size_t         buffer_size;
-		int64_t        target_offset, actual_offset;
-		GError        *local_error = NULL;
-		__LA_MODE_T    filetype;
-
-		if (g_cancellable_is_cancelled (cancellable))
-			break;
-
-		pathname = archive_entry_pathname (entry);
-		if (! extract_data_get_extraction_requested (extract_data, pathname)) {
-			archive_read_data_skip (a);
-			continue;
-		}
-
-		fullpath = (*pathname == '/') ? g_strdup (pathname) : g_strconcat ("/", pathname, NULL);
-		relative_path = _g_path_get_relative_basename_safe (fullpath, extract_data->base_dir, extract_data->junk_paths);
-		if (relative_path == NULL) {
-			archive_read_data_skip (a);
-			continue;
-		}
-
-		file = g_file_get_child (extract_data->destination, relative_path);
-
-		/* honor the skip_older and overwrite options */
-
-		if ((g_hash_table_lookup (folders_created_during_extraction, file) == NULL)
-		    && (extract_data->skip_older || ! extract_data->overwrite))
-		{
-			GFileInfo *info;
-
-			info = g_file_query_info (file,
-						  G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME "," G_FILE_ATTRIBUTE_TIME_MODIFIED,
-						  G_FILE_QUERY_INFO_NONE,
-						  cancellable,
-						  &local_error);
-			if (info != NULL) {
-				gboolean skip = FALSE;
-
-				if (! extract_data->overwrite) {
-					skip = TRUE;
-				}
-				else if (extract_data->skip_older) {
-					GTimeVal modification_time;
-
-					g_file_info_get_modification_time (info, &modification_time);
-					if (archive_entry_mtime (entry) < modification_time.tv_sec)
-						skip = TRUE;
-				}
-
-				g_object_unref (info);
-
-				if (skip) {
-					g_object_unref (file);
-
-					archive_read_data_skip (a);
-					fr_archive_progress_inc_completed_bytes (load_data->archive, archive_entry_size_is_set (entry) ? archive_entry_size (entry) : 0);
-
-					if ((extract_data->file_list != NULL) && (--extract_data->n_files_to_extract == 0)) {
-						r = ARCHIVE_EOF;
-						break;
-					}
-
-					continue;
-				}
-			}
-			else {
-				if (! g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) {
-					load_data->error = local_error;
-					g_object_unref (info);
-					break;
-				}
-				g_clear_error (&local_error);
-			}
-		}
-
-		fr_archive_progress_inc_completed_files (load_data->archive, 1);
-
-		/* create the file parents */
-
-		parent = g_file_get_parent (file);
-
-		if ((parent != NULL)
-		    && (g_hash_table_lookup (checked_folders, parent) == NULL)
-		    && ! g_file_query_exists (parent, cancellable))
-		{
-			if (! _g_file_make_directory_with_parents (parent,
-								   folders_created_during_extraction,
-								   cancellable,
-								   &local_error))
-			{
-				if (! g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_EXISTS))
-					load_data->error = local_error;
-				else
-					g_clear_error (&local_error);
-			}
-
-			if (load_data->error == NULL) {
-				GFile *grandparent;
-
-				grandparent = g_object_ref (parent);
-				while (grandparent != NULL) {
-					if (g_hash_table_lookup (checked_folders, grandparent) == NULL)
-						g_hash_table_insert (checked_folders, grandparent, GINT_TO_POINTER (1));
-					grandparent = g_file_get_parent (grandparent);
-				}
-			}
-		}
-		g_object_unref (parent);
-
-		/* create the file */
-
-		filetype = archive_entry_filetype (entry);
-
-		if (load_data->error == NULL) {
-			const char  *linkname;
-
-			linkname = archive_entry_hardlink (entry);
-			if (linkname != NULL) {
-				char        *link_fullpath;
-				const char  *relative_path;
-				GFile       *link_file;
-				char        *oldname;
-				char        *newname;
-				int          r;
-
-				link_fullpath = (*linkname == '/') ? g_strdup (linkname) : g_strconcat ("/", linkname, NULL);
-				relative_path = _g_path_get_relative_basename_safe (link_fullpath, extract_data->base_dir, extract_data->junk_paths);
-				if (relative_path == NULL) {
-					g_free (link_fullpath);
-					archive_read_data_skip (a);
-					continue;
-				}
-
-				link_file = g_file_get_child (extract_data->destination, relative_path);
-				oldname = g_file_get_path (link_file);
-				newname = g_file_get_path (file);
-
-				if ((oldname != NULL) && (newname != NULL))
-					r = link (oldname, newname);
-				else
-					r = -1;
-
-				if (r == 0) {
-					__LA_INT64_T filesize;
-
-					if (archive_entry_size_is_set (entry))
-						filesize = archive_entry_size (entry);
-					else
-						filesize = -1;
-
-					if (filesize > 0)
-						filetype = AE_IFREG; /* treat as a regular file to save the data */
-				}
-				else {
-					char *uri;
-					char *msg;
-
-					uri = g_file_get_uri (file);
-					msg = g_strdup_printf ("Could not create the hard link %s", uri);
-					load_data->error = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_FAILED, msg);
-
-					g_free (msg);
-					g_free (uri);
-				}
-
-				g_free (newname);
-				g_free (oldname);
-				g_object_unref (link_file);
-				g_free (link_fullpath);
-			}
-		}
-
-		if (load_data->error == NULL) {
-			switch (filetype) {
-			case AE_IFDIR:
-				if (! g_file_make_directory (file, cancellable, &local_error)) {
-					if (! g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_EXISTS))
-						load_data->error = g_error_copy (local_error);
-					g_clear_error (&local_error);
-				}
-				if (load_data->error == NULL)
-					g_hash_table_insert (created_files, g_object_ref (file), _g_file_info_create_from_entry (entry, extract_data));
-				archive_read_data_skip (a);
-				break;
-
-			case AE_IFREG:
-				ostream = (GOutputStream *) g_file_replace (file, NULL, FALSE, G_FILE_CREATE_REPLACE_DESTINATION, cancellable, &load_data->error);
-				if (ostream == NULL)
-					break;
-
-				actual_offset = 0;
-				while ((r = archive_read_data_block (a, &buffer, &buffer_size, &target_offset)) == ARCHIVE_OK) {
-					gsize bytes_written;
-
-					if (target_offset > actual_offset) {
-						if (! _g_output_stream_add_padding (extract_data, ostream, target_offset, actual_offset, cancellable, &load_data->error))
-							break;
-						fr_archive_progress_inc_completed_bytes (load_data->archive, target_offset - actual_offset);
-						actual_offset = target_offset;
-					}
-
-					if (! g_output_stream_write_all (ostream, buffer, buffer_size, &bytes_written, cancellable, &load_data->error))
-						break;
-
-					actual_offset += bytes_written;
-					fr_archive_progress_inc_completed_bytes (load_data->archive, bytes_written);
-				}
-
-				if ((r == ARCHIVE_EOF) && (target_offset > actual_offset))
-					_g_output_stream_add_padding (extract_data, ostream, target_offset, actual_offset, cancellable, &load_data->error);
-
-				_g_object_unref (ostream);
-
-				if (r != ARCHIVE_EOF)
-					load_data->error = _g_error_new_from_archive_error (archive_error_string (a));
-				else
-					g_hash_table_insert (created_files, g_object_ref (file), _g_file_info_create_from_entry (entry, extract_data));
-				break;
-
-			case AE_IFLNK:
-				if (! g_file_make_symbolic_link (file, archive_entry_symlink (entry), cancellable, &local_error)) {
-					if (! g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_EXISTS))
-						load_data->error = g_error_copy (local_error);
-					g_clear_error (&local_error);
-				}
-				archive_read_data_skip (a);
-				break;
-
-			default:
-				archive_read_data_skip (a);
-				break;
-			}
-		}
-
-		g_object_unref (file);
-		g_free (fullpath);
-
-		if (load_data->error != NULL)
-			break;
-
-		if ((extract_data->file_list != NULL) && (--extract_data->n_files_to_extract == 0)) {
-			r = ARCHIVE_EOF;
-			break;
-		}
-	}
-
-	if (load_data->error == NULL)
-		restore_original_file_attributes (created_files, cancellable);
-
-	if ((load_data->error == NULL) && (r != ARCHIVE_EOF))
-		load_data->error = _g_error_new_from_archive_error (archive_error_string (a));
-	if (load_data->error == NULL)
-		g_cancellable_set_error_if_cancelled (cancellable, &load_data->error);
-	if (load_data->error != NULL)
-		g_simple_async_result_set_from_error (result, load_data->error);
-
-	g_hash_table_unref (folders_created_during_extraction);
-	g_hash_table_unref (created_files);
-	g_hash_table_unref (checked_folders);
-	archive_read_free (a);
-	extract_data_free (extract_data);
-}
-
-
-static void
-fr_archive_libarchive_extract_files (FrArchive           *archive,
-				     GList               *file_list,
-				     GFile               *destination,
-				     const char          *base_dir,
-				     gboolean             skip_older,
-				     gboolean             overwrite,
-				     gboolean             junk_paths,
-				     const char          *password,
-				     GCancellable        *cancellable,
-				     GAsyncReadyCallback  callback,
-				     gpointer             user_data)
-{
-	ExtractData *extract_data;
-	LoadData    *load_data;
-	GList       *scan;
-
-	extract_data = g_new0 (ExtractData, 1);
-
-	load_data = LOAD_DATA (extract_data);
-	load_data->archive = g_object_ref (archive);
-	load_data->cancellable = _g_object_ref (cancellable);
-	load_data->result = g_simple_async_result_new (G_OBJECT (archive),
-						       callback,
-						       user_data,
-						       fr_archive_extract);
-	load_data->buffer_size = BUFFER_SIZE;
-	load_data->buffer = g_new (char, load_data->buffer_size);
-
-	extract_data->file_list = _g_string_list_dup (file_list);
-	extract_data->destination = g_object_ref (destination);
-	extract_data->base_dir = g_strdup (base_dir);
-	extract_data->skip_older = skip_older;
-	extract_data->overwrite = overwrite;
-	extract_data->junk_paths = junk_paths;
-	extract_data->files_to_extract = g_hash_table_new (g_str_hash, g_str_equal);
-	extract_data->n_files_to_extract = 0;
-	extract_data->usernames = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
-	extract_data->groupnames = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
-
-	for (scan = extract_data->file_list; scan; scan = scan->next) {
-		g_hash_table_insert (extract_data->files_to_extract, scan->data, GINT_TO_POINTER (1));
-		extract_data->n_files_to_extract++;
-	}
-
-	g_simple_async_result_set_op_res_gpointer (load_data->result, extract_data, NULL);
-	g_simple_async_result_run_in_thread (load_data->result,
-					     extract_archive_thread,
-					     G_PRIORITY_DEFAULT,
-					     cancellable);
-}
-
-
-/* --  AddFile -- */
-
-
-typedef struct {
-	GFile *file;
-	char  *pathname;
-} AddFile;
-
-
-static AddFile *
-add_file_new (GFile      *file,
-	      const char *archive_pathname)
-{
-	AddFile *add_file;
-
-	add_file = g_new (AddFile, 1);
-	add_file->file = g_object_ref (file);
-	add_file->pathname = g_strdup (archive_pathname);
-
-	return add_file;
-}
-
-
-static void
-add_file_free (AddFile *add_file)
-{
-	g_object_unref (add_file->file);
-	g_free (add_file->pathname);
-	g_free (add_file);
-}
-
-
-/* -- _fr_archive_libarchive_save -- */
-
-
-#define SAVE_DATA(x) ((SaveData *)(x))
-
-
-typedef enum {
-	WRITE_ACTION_ABORT,
-	WRITE_ACTION_SKIP_ENTRY,
-	WRITE_ACTION_WRITE_ENTRY
-} WriteAction;
-
-
-typedef struct      _SaveData SaveData;
-typedef void        (*SaveDataFunc)    (SaveData *, gpointer user_data);
-typedef WriteAction (*EntryActionFunc) (SaveData *, struct archive_entry *, gpointer user_data);
-
-
-struct _SaveData {
-	LoadData         parent;
-	GFile           *tmp_file;
-	GOutputStream   *ostream;
-	GHashTable      *usernames;
-	GHashTable      *groupnames;
-	gboolean         update;
-	char            *password;
-	gboolean         encrypt_header;
-	FrCompression    compression;
-	guint            volume_size;
-	void            *buffer;
-	gsize            buffer_size;
-	SaveDataFunc     begin_operation;
-	SaveDataFunc     end_operation;
-	EntryActionFunc  entry_action;
-	gpointer         user_data;
-	GDestroyNotify   user_data_notify;
-	struct archive  *b;
-};
-
-
-static void
-save_data_init (SaveData *save_data)
-{
-	load_data_init (LOAD_DATA (save_data));
-	save_data->buffer_size = BUFFER_SIZE;
-	save_data->buffer = g_new (char, save_data->buffer_size);
-	save_data->usernames = g_hash_table_new_full (g_int64_hash, g_int64_equal, g_free, g_free);
-	save_data->groupnames = g_hash_table_new_full (g_int64_hash, g_int64_equal, g_free, g_free);
-}
-
-
-static void
-save_data_free (SaveData *save_data)
-{
-	if (save_data->user_data_notify != NULL)
-		save_data->user_data_notify (save_data->user_data);
-	g_free (save_data->buffer);
-	g_free (save_data->password);
-	g_hash_table_unref (save_data->groupnames);
-	g_hash_table_unref (save_data->usernames);
-	_g_object_unref (save_data->ostream);
-	_g_object_unref (save_data->tmp_file);
-	load_data_free (LOAD_DATA (save_data));
-}
-
-
-static int
-save_data_open (struct archive *a,
-	        void           *client_data)
-{
-	SaveData *save_data = client_data;
-	LoadData *load_data = LOAD_DATA (save_data);
-	GFile    *parent;
-	char     *basename;
-	char     *tmpname;
-
-	if (load_data->error != NULL)
-		return ARCHIVE_FATAL;
-
-	parent = g_file_get_parent (fr_archive_get_file (load_data->archive));
-	basename = g_file_get_basename (fr_archive_get_file (load_data->archive));
-	tmpname = _g_filename_get_random (16, basename);
-	save_data->tmp_file = g_file_get_child (parent, tmpname);
-	save_data->ostream = (GOutputStream *) g_file_create (save_data->tmp_file, G_FILE_CREATE_NONE, load_data->cancellable, &load_data->error);
-
-	g_free (tmpname);
-	g_free (basename);
-	g_object_unref (parent);
-
-	return (save_data->ostream != NULL) ? ARCHIVE_OK : ARCHIVE_FATAL;
-}
-
-
-static ssize_t
-save_data_write (struct archive *a,
-		 void           *client_data,
-		 const void     *buff,
-		 size_t          n)
-{
-	SaveData *save_data = client_data;
-	LoadData *load_data = LOAD_DATA (save_data);
-
-	if (load_data->error != NULL)
-		return -1;
-
-	return g_output_stream_write (save_data->ostream, buff, n, load_data->cancellable, &load_data->error);
-}
-
-
-static int
-save_data_close (struct archive *a,
-		 void           *client_data)
-{
-	SaveData *save_data = client_data;
-	LoadData *load_data = LOAD_DATA (save_data);
-
-	if (save_data->ostream != NULL) {
-		GError *error = NULL;
-
-		g_output_stream_close (save_data->ostream, load_data->cancellable, &error);
-		if (load_data->error == NULL && error != NULL)
-			load_data->error = g_error_copy (error);
-
-		_g_error_free (error);
-	}
-
-	if (load_data->error == NULL)
-		g_file_move (save_data->tmp_file,
-			     fr_archive_get_file (load_data->archive),
-			     G_FILE_COPY_OVERWRITE | G_FILE_COPY_TARGET_DEFAULT_PERMS,
-			     load_data->cancellable,
-			     NULL,
-			     NULL,
-			     &load_data->error);
-	else
-		g_file_delete (save_data->tmp_file, NULL, NULL);
-
-	return ARCHIVE_OK;
-}
-
-
-static void
-_archive_write_set_format_from_context (struct archive *a,
-					SaveData       *save_data)
-{
-	const char *mime_type;
-	int         archive_filter;
-
-	/* set format and filter from the mime type */
-
-	mime_type = fr_archive_get_mime_type (LOAD_DATA (save_data)->archive);
-	archive_filter = ARCHIVE_FILTER_NONE;
-
-	if (_g_str_equal (mime_type, "application/x-bzip-compressed-tar")) {
-		archive_write_set_format_pax_restricted (a);
-		archive_filter = ARCHIVE_FILTER_BZIP2;
-	}
-	else if (_g_str_equal (mime_type, "application/x-tarz")) {
-		archive_write_set_format_pax_restricted (a);
-		archive_filter = ARCHIVE_FILTER_COMPRESS;
-	}
-	else if (_g_str_equal (mime_type, "application/x-compressed-tar")) {
-		archive_write_set_format_pax_restricted (a);
-		archive_filter = ARCHIVE_FILTER_GZIP;
-	}
-	else if (_g_str_equal (mime_type, "application/x-lrzip-compressed-tar")) {
-		archive_write_set_format_pax_restricted (a);
-		archive_filter = ARCHIVE_FILTER_LRZIP;
-	}
-	else if (_g_str_equal (mime_type, "application/x-lzip-compressed-tar")) {
-		archive_write_set_format_pax_restricted (a);
-		archive_filter = ARCHIVE_FILTER_LZIP;
-	}
-	else if (_g_str_equal (mime_type, "application/x-lzma-compressed-tar")) {
-		archive_write_set_format_pax_restricted (a);
-		archive_filter = ARCHIVE_FILTER_LZMA;
-	}
-	else if (_g_str_equal (mime_type, "application/x-lzop-compressed-tar")) {
-		archive_write_set_format_pax_restricted (a);
-		archive_filter = ARCHIVE_FILTER_LZOP;
-	}
-	else if (_g_str_equal (mime_type, "application/x-xz-compressed-tar")) {
-		archive_write_set_format_pax_restricted (a);
-		archive_filter = ARCHIVE_FILTER_XZ;
-	}
-	else if (_g_str_equal (mime_type, "application/x-tar")) {
-		archive_write_add_filter_none (a);
-		archive_write_set_format_pax_restricted (a);
-	}
-	else if (_g_str_equal (mime_type, "application/x-cd-image")) {
-		archive_write_set_format_iso9660 (a);
-	}
-	else if (_g_str_equal (mime_type, "application/x-cpio")) {
-		archive_write_set_format_cpio (a);
-	}
-	else if (_g_str_equal (mime_type, "application/x-xar")) {
-		archive_write_set_format_xar (a);
-	}
-	else if (_g_str_equal (mime_type, "application/x-ar")) {
-		archive_write_set_format_ar_svr4 (a);
-	}
-	else if (_g_str_equal (mime_type, "application/x-7z-compressed")) {
-		archive_write_set_format_7zip (a);
-	}
-	else if (_g_str_equal (mime_type, "application/zip")
-	    || _g_str_equal (mime_type, "application/x-cbz")) {
-		archive_write_set_format_zip (a);
-	}
-
-	/* set the filter */
-
-	if (archive_filter != ARCHIVE_FILTER_NONE) {
-		char *compression_level = NULL;
-
-		switch (archive_filter) {
-		case ARCHIVE_FILTER_BZIP2:
-			archive_write_add_filter_bzip2 (a);
-			break;
-		case ARCHIVE_FILTER_COMPRESS:
-			archive_write_add_filter_compress (a);
-			break;
-		case ARCHIVE_FILTER_GZIP:
-			archive_write_add_filter_gzip (a);
-			break;
-		case ARCHIVE_FILTER_LRZIP:
-			archive_write_add_filter_lrzip (a);
-			break;
-		case ARCHIVE_FILTER_LZIP:
-			archive_write_add_filter_lzip (a);
-			break;
-		case ARCHIVE_FILTER_LZMA:
-			archive_write_add_filter_lzma (a);
-			break;
-		case ARCHIVE_FILTER_LZOP:
-			archive_write_add_filter_lzop (a);
-			break;
-		case ARCHIVE_FILTER_XZ:
-			archive_write_add_filter_xz (a);
-			break;
-		default:
-			break;
-		}
-
-		/* set the compression level */
-
-		compression_level = NULL;
-		switch (save_data->compression) {
-		case FR_COMPRESSION_VERY_FAST:
-			compression_level = "1";
-			break;
-		case FR_COMPRESSION_FAST:
-			compression_level = "3";
-			break;
-		case FR_COMPRESSION_NORMAL:
-			compression_level = "6";
-			break;
-		case FR_COMPRESSION_MAXIMUM:
-			compression_level = "9";
-			break;
-		}
-		if (compression_level != NULL)
-			archive_write_set_filter_option (a, NULL, "compression-level", compression_level);
-	}
-}
-
-
-/* -- _archive_write_file -- */
-
-
-static gint64 *
-_g_int64_pointer_new (gint64 i)
-{
-	gint64 *p;
-
-	p = g_new (gint64, 1);
-	*p = i;
-
-	return p;
-}
-
-
-static gboolean
-_archive_entry_copy_file_info (struct archive_entry *entry,
-			       GFileInfo            *info,
-			       SaveData             *save_data)
-{
-	int     filetype;
-	char   *username;
-	char   *groupname;
-	gint64  id;
-
-	switch (g_file_info_get_file_type (info)) {
-	case G_FILE_TYPE_REGULAR:
-		filetype = AE_IFREG;
-		break;
-	case G_FILE_TYPE_DIRECTORY:
-		filetype = AE_IFDIR;
-		break;
-	case G_FILE_TYPE_SYMBOLIC_LINK:
-		filetype = AE_IFLNK;
-		break;
-	default:
-		return FALSE;
-		break;
-	}
-	archive_entry_set_filetype (entry, filetype);
-
-	archive_entry_set_atime (entry,
-				 g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_ACCESS),
-				 g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_TIME_ACCESS_USEC) * 1000);
-	archive_entry_set_ctime (entry,
-				 g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_CREATED),
-				 g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_TIME_CREATED_USEC) * 1000);
-	archive_entry_set_mtime (entry,
-				 g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_MODIFIED),
-				 g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC) * 1000);
-	archive_entry_unset_birthtime (entry);
-	archive_entry_set_dev (entry, g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_DEVICE));
-	archive_entry_set_gid (entry, g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_GID));
-	archive_entry_set_uid (entry, g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_UID));
-	archive_entry_set_ino64 (entry, g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_UNIX_INODE));
-	archive_entry_set_mode (entry, g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_MODE));
-	archive_entry_set_nlink (entry, g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_NLINK));
-	archive_entry_set_rdev (entry, g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_RDEV));
-	archive_entry_set_size (entry, g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_STANDARD_SIZE));
-	if (filetype == AE_IFLNK)
-		archive_entry_set_symlink (entry, g_file_info_get_attribute_byte_string (info, G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET));
-
-	/* username */
-
-	id = archive_entry_uid (entry);
-	username = g_hash_table_lookup (save_data->usernames, &id);
-	if (username == NULL) {
-		struct passwd *pwd = getpwuid (id);
-		if (pwd != NULL) {
-			username = g_strdup (pwd->pw_name);
-			g_hash_table_insert (save_data->usernames, _g_int64_pointer_new (id), username);
-		}
-	}
-	if (username != NULL)
-		archive_entry_set_uname (entry, username);
-
-	/* groupname */
-
-	id = archive_entry_gid (entry);
-	groupname = g_hash_table_lookup (save_data->groupnames, &id);
-	if (groupname == NULL) {
-		struct group *grp = getgrgid (id);
-		if (grp != NULL) {
-			groupname = g_strdup (grp->gr_name);
-			g_hash_table_insert (save_data->groupnames, _g_int64_pointer_new (id), groupname);
-		}
-	}
-	if (groupname != NULL)
-		archive_entry_set_gname (entry, groupname);
-
-	return TRUE;
-}
-
-
-static WriteAction
-_archive_write_file (struct archive       *b,
-		     SaveData             *save_data,
-		     AddFile              *add_file,
-		     gboolean              follow_link,
-		     struct archive_entry *r_entry,
-		     GCancellable         *cancellable)
-{
-	LoadData             *load_data = LOAD_DATA (save_data);
-	GFileInfo            *info;
-	struct archive_entry *w_entry;
-	int                   rb;
-
-	/* write the file header */
-
-	info = g_file_query_info (add_file->file,
-				  FILE_ATTRIBUTES_NEEDED_BY_ARCHIVE_ENTRY,
-				  (! follow_link ? G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS : 0),
-				  cancellable,
-				  &load_data->error);
-	if (info == NULL)
-		return WRITE_ACTION_ABORT;
-
-	w_entry = archive_entry_new ();
-	if (! _archive_entry_copy_file_info (w_entry, info, save_data)) {
-		archive_entry_free (w_entry);
-		g_object_unref (info);
-		return WRITE_ACTION_SKIP_ENTRY;
-	}
-
-	/* honor the update flag */
-
-	if (save_data->update && (r_entry != NULL) && (archive_entry_mtime (w_entry) < archive_entry_mtime (r_entry))) {
-		archive_entry_free (w_entry);
-		g_object_unref (info);
-		return WRITE_ACTION_WRITE_ENTRY;
-	}
-
-	archive_entry_set_pathname (w_entry, add_file->pathname);
-	rb = archive_write_header (b, w_entry);
-
-	/* write the file data */
-
-	if (g_file_info_get_file_type (info) == G_FILE_TYPE_REGULAR) {
-		GInputStream *istream;
-
-		istream = (GInputStream *) g_file_read (add_file->file, cancellable, &load_data->error);
-		if (istream != NULL) {
-			gssize bytes_read;
-
-			while ((bytes_read = g_input_stream_read (istream, save_data->buffer, save_data->buffer_size, cancellable, &load_data->error)) > 0) {
-				archive_write_data (b, save_data->buffer, bytes_read);
-				fr_archive_progress_inc_completed_bytes (load_data->archive, bytes_read);
-			}
-
-			g_object_unref (istream);
-		}
-	}
-
-	rb = archive_write_finish_entry (b);
-
-	if ((load_data->error == NULL) && (rb <= ARCHIVE_FAILED))
-		load_data->error = g_error_new_literal (FR_ERROR, FR_ERROR_COMMAND_ERROR, archive_error_string (b));
-
-	archive_entry_free (w_entry);
-	g_object_unref (info);
-
-	return (load_data->error == NULL) ? WRITE_ACTION_SKIP_ENTRY : WRITE_ACTION_ABORT;
-}
-
-
-static void
-save_archive_thread (GSimpleAsyncResult *result,
-		     GObject            *object,
-		     GCancellable       *cancellable)
-{
-	SaveData             *save_data;
-	LoadData             *load_data;
-	struct archive       *a, *b;
-	struct archive_entry *r_entry;
-	int                   ra = ARCHIVE_OK, rb = ARCHIVE_OK;
-
-	save_data = g_simple_async_result_get_op_res_gpointer (result);
-	load_data = LOAD_DATA (save_data);
-
-	save_data->b = b = archive_write_new ();
-	_archive_write_set_format_from_context (b, save_data);
-	archive_write_open (b, save_data, save_data_open, save_data_write, save_data_close);
-	archive_write_set_bytes_in_last_block (b, 1);
-
-	a = archive_read_new ();
-	archive_read_support_filter_all (a);
-	archive_read_support_format_all (a);
-	archive_read_open (a, load_data, load_data_open, load_data_read, load_data_close);
-
-	if (save_data->begin_operation != NULL)
-		save_data->begin_operation (save_data, save_data->user_data);
-
-	while ((load_data->error == NULL) && (ra = archive_read_next_header (a, &r_entry)) == ARCHIVE_OK) {
-		struct archive_entry *w_entry;
-		WriteAction           action;
-
-		if (g_cancellable_is_cancelled (cancellable))
-			break;
-
-		action = WRITE_ACTION_WRITE_ENTRY;
-		w_entry = archive_entry_clone (r_entry);
-		if (save_data->entry_action != NULL)
-			action = save_data->entry_action (save_data, w_entry, save_data->user_data);
-
-		if (action == WRITE_ACTION_WRITE_ENTRY) {
-			const void   *buffer;
-			size_t        buffer_size;
-			__LA_INT64_T  offset;
-
-			rb = archive_write_header (b, w_entry);
-			if (rb <= ARCHIVE_FAILED) {
-				load_data->error = _g_error_new_from_archive_error (archive_error_string (b));
-				break;
-			}
-
-			switch (archive_entry_filetype (r_entry)) {
-			case AE_IFREG:
-				while ((ra = archive_read_data_block (a, &buffer, &buffer_size, &offset)) == ARCHIVE_OK) {
-					archive_write_data (b, buffer, buffer_size);
-					fr_archive_progress_inc_completed_bytes (load_data->archive, buffer_size);
-				}
-
-				if (ra <= ARCHIVE_FAILED) {
-					load_data->error = _g_error_new_from_archive_error (archive_error_string (a));
-					break;
-				}
-				break;
-
-			default:
-				break;
-			}
-
-			rb = archive_write_finish_entry (b);
-		}
-		else if (action == WRITE_ACTION_SKIP_ENTRY)
-			fr_archive_progress_inc_completed_bytes (load_data->archive, archive_entry_size (r_entry));
-
-		archive_entry_free (w_entry);
-	}
-
-	if (g_error_matches (load_data->error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
-		ra = ARCHIVE_EOF;
-
-	if (save_data->end_operation != NULL)
-		save_data->end_operation (save_data, save_data->user_data);
-
-	rb = archive_write_close (b);
-
-	if ((load_data->error == NULL) && (ra != ARCHIVE_EOF))
-		load_data->error = _g_error_new_from_archive_error (archive_error_string (a));
-	if ((load_data->error == NULL) && (rb <= ARCHIVE_FAILED))
-		load_data->error =  _g_error_new_from_archive_error (archive_error_string (b));
-	if (load_data->error == NULL)
-		g_cancellable_set_error_if_cancelled (cancellable, &load_data->error);
-	if (load_data->error != NULL)
-		g_simple_async_result_set_from_error (result, load_data->error);
-
-	archive_read_free (a);
-	archive_write_free (b);
-	save_data_free (save_data);
-}
-
-
-static void
-_fr_archive_libarchive_save (FrArchive          *archive,
-			     gboolean            update,
-			     const char         *password,
-			     gboolean            encrypt_header,
-			     FrCompression       compression,
-			     guint               volume_size,
-			     GCancellable       *cancellable,
-			     GSimpleAsyncResult *result,
-			     SaveDataFunc        begin_operation,
-			     SaveDataFunc        end_operation,
-			     EntryActionFunc     entry_action,
-			     gpointer            user_data,
-			     GDestroyNotify      notify)
-{
-	SaveData *save_data;
-	LoadData *load_data;
-
-	save_data = g_new0 (SaveData, 1);
-	save_data_init (SAVE_DATA (save_data));
-
-	load_data = LOAD_DATA (save_data);
-	load_data->archive = g_object_ref (archive);
-	load_data->cancellable = _g_object_ref (cancellable);
-	load_data->result = result;
-
-	save_data->update = update;
-	save_data->password = g_strdup (password);
-	save_data->encrypt_header = encrypt_header;
-	save_data->compression = compression;
-	save_data->volume_size = volume_size;
-	save_data->begin_operation = begin_operation;
-	save_data->end_operation = end_operation;
-	save_data->entry_action = entry_action;
-	save_data->user_data = user_data;
-	save_data->user_data_notify = notify;
-
-	g_simple_async_result_set_op_res_gpointer (load_data->result, save_data, NULL);
-	g_simple_async_result_run_in_thread (load_data->result,
-					     save_archive_thread,
-					     G_PRIORITY_DEFAULT,
-					     cancellable);
-}
-
-
-/* -- add_files -- */
-
-
-typedef struct {
-	gboolean    follow_links;
-	GHashTable *files_to_add;
-	int         n_files_to_add;
-} AddData;
-
-
-static AddData *
-add_data_new (void)
-{
-	AddData *add_data;
-
-	add_data = g_new0 (AddData, 1);
-	add_data->files_to_add = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) add_file_free);
-	add_data->n_files_to_add = 0;
-	add_data->follow_links = TRUE;
-
-	return add_data;
-}
-
-
-static void
-add_data_free (AddData *add_data)
-{
-	g_hash_table_unref (add_data->files_to_add);
-	g_free (add_data);
-}
-
-
-static void
-_add_files_begin (SaveData *save_data,
-		  gpointer  user_data)
-{
-	AddData  *add_data = user_data;
-	LoadData *load_data = LOAD_DATA (save_data);
-
-	fr_archive_progress_set_total_files (load_data->archive, add_data->n_files_to_add);
-
-	if (load_data->archive->files_to_add_size == 0) {
-		GList *files_to_add;
-		GList *scan;
-
-		files_to_add = g_hash_table_get_values (add_data->files_to_add);
-		for (scan = files_to_add; scan; scan = scan->next) {
-			AddFile *add_file = scan->data;
-
-			if (g_cancellable_is_cancelled (load_data->cancellable))
-				break;
-
-			load_data->archive->files_to_add_size += _g_file_get_size (add_file->file, load_data->cancellable);
-		}
-
-		g_list_free (files_to_add);
-	}
-
-	fr_archive_progress_set_total_bytes (load_data->archive,
-			FR_ARCHIVE_LIBARCHIVE (load_data->archive)->priv->uncompressed_size + load_data->archive->files_to_add_size);
-}
-
-
-static WriteAction
-_add_files_entry_action (SaveData             *save_data,
-			 struct archive_entry *w_entry,
-			 gpointer              user_data)
-{
-	AddData     *add_data = user_data;
-	LoadData    *load_data = LOAD_DATA (save_data);
-	WriteAction  action;
-	const char  *pathname;
-	AddFile     *add_file;
-
-	action = WRITE_ACTION_WRITE_ENTRY;
-	pathname = archive_entry_pathname (w_entry);
-	add_file = g_hash_table_lookup (add_data->files_to_add, pathname);
-	if (add_file != NULL) {
-		action = _archive_write_file (save_data->b,
-					      save_data,
-					      add_file,
-					      add_data->follow_links,
-					      w_entry,
-					      load_data->cancellable);
-		fr_archive_progress_inc_completed_files (load_data->archive, 1);
-		add_data->n_files_to_add--;
-		g_hash_table_remove (add_data->files_to_add, pathname);
-	}
-
-	return action;
-}
-
-
-static void
-_add_files_end (SaveData *save_data,
-		gpointer  user_data)
-{
-	AddData  *add_data = user_data;
-	LoadData *load_data = LOAD_DATA (save_data);
-	GList    *remaining_files;
-	GList    *scan;
-
-	/* allow to add files to a new archive */
-
-	if (g_error_matches (load_data->error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
-		g_clear_error (&load_data->error);
-
-	/* add the files that weren't present in the archive already */
-
-	remaining_files = g_hash_table_get_values (add_data->files_to_add);
-	for (scan = remaining_files; (load_data->error == NULL) && scan; scan = scan->next) {
-		AddFile *add_file = scan->data;
-
-		if (g_cancellable_is_cancelled (load_data->cancellable))
-			break;
-
-		if (_archive_write_file (save_data->b,
-					 save_data,
-					 add_file,
-					 add_data->follow_links,
-					 NULL,
-					 load_data->cancellable) == WRITE_ACTION_ABORT)
-		{
-			break;
-		}
-
-		fr_archive_progress_inc_completed_files (load_data->archive, 1);
-	}
-
-	g_list_free (remaining_files);
-}
-
-
-static void
-fr_archive_libarchive_add_files (FrArchive           *archive,
-				 GList               *file_list,
-				 GFile               *base_dir,
-				 const char          *dest_dir,
-				 gboolean             update,
-				 gboolean             follow_links,
-				 const char          *password,
-				 gboolean             encrypt_header,
-				 FrCompression        compression,
-				 guint                volume_size,
-				 GCancellable        *cancellable,
-				 GAsyncReadyCallback  callback,
-				 gpointer             user_data)
-{
-	AddData *add_data;
-	GList   *scan;
-
-	g_return_if_fail (base_dir != NULL);
-
-	add_data = add_data_new ();
-	add_data->follow_links = follow_links;
-
-	if (dest_dir != NULL)
-		dest_dir = (dest_dir[0] == '/' ? dest_dir + 1 : dest_dir);
-	else
-		dest_dir = "";
-
-	for (scan = file_list; scan; scan = scan->next) {
-		GFile *file = G_FILE (scan->data);
-		char  *relative_pathname;
-		char  *archive_pathname;
-
-		relative_pathname = g_file_get_relative_path (base_dir, file);
-		archive_pathname = g_build_filename (dest_dir, relative_pathname, NULL);
-		g_hash_table_insert (add_data->files_to_add,
-				     g_strdup (archive_pathname),
-				     add_file_new (file, archive_pathname));
-		add_data->n_files_to_add++;
-
-		g_free (archive_pathname);
-		g_free (relative_pathname);
-	}
-
-	_fr_archive_libarchive_save (archive,
-				     update,
-				     password,
-				     encrypt_header,
-				     compression,
-				     volume_size,
-				     cancellable,
-				     g_simple_async_result_new (G_OBJECT (archive),
-				     				callback,
-				     				user_data,
-				     				fr_archive_add_files),
-				     _add_files_begin,
-				     _add_files_end,
-				     _add_files_entry_action,
-				     add_data,
-				     (GDestroyNotify) add_data_free);
-}
-
-
-/* -- remove -- */
-
-
-typedef struct {
-	GHashTable *files_to_remove;
-	gboolean    remove_all_files;
-	int         n_files_to_remove;
-} RemoveData;
-
-
-static void
-remove_data_free (RemoveData *remove_data)
-{
-	if (remove_data->files_to_remove != NULL)
-		g_hash_table_unref (remove_data->files_to_remove);
-	g_free (remove_data);
-}
-
-
-static void
-_remove_files_begin (SaveData *save_data,
-		     gpointer  user_data)
-{
-	LoadData   *load_data = LOAD_DATA (save_data);
-	RemoveData *remove_data = user_data;
-
-	fr_archive_progress_set_total_files (load_data->archive, remove_data->n_files_to_remove);
-	fr_archive_progress_set_total_bytes (load_data->archive,
-					     FR_ARCHIVE_LIBARCHIVE (load_data->archive)->priv->uncompressed_size);
-}
-
-
-static WriteAction
-_remove_files_entry_action (SaveData             *save_data,
-			    struct archive_entry *w_entry,
-			    gpointer              user_data)
-{
-	RemoveData  *remove_data = user_data;
-	LoadData    *load_data = LOAD_DATA (save_data);
-	WriteAction  action;
-	const char  *pathname;
-
-	if (remove_data->remove_all_files)
-		return WRITE_ACTION_SKIP_ENTRY;
-
-	action = WRITE_ACTION_WRITE_ENTRY;
-	pathname = archive_entry_pathname (w_entry);
-	if (g_hash_table_lookup (remove_data->files_to_remove, pathname) != NULL) {
-		action = WRITE_ACTION_SKIP_ENTRY;
-		remove_data->n_files_to_remove--;
-		fr_archive_progress_inc_completed_files (load_data->archive, 1);
-		g_hash_table_remove (remove_data->files_to_remove, pathname);
-	}
-
-	return action;
-}
-
-
-static void
-fr_archive_libarchive_remove_files (FrArchive           *archive,
-				    GList               *file_list,
-				    FrCompression        compression,
-				    GCancellable        *cancellable,
-				    GAsyncReadyCallback  callback,
-				    gpointer             user_data)
-{
-	RemoveData *remove_data;
-	GList      *scan;
-
-	remove_data = g_new0 (RemoveData, 1);
-	remove_data->remove_all_files = (file_list == NULL);
-	if (! remove_data->remove_all_files) {
-		remove_data->files_to_remove = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
-		remove_data->n_files_to_remove = 0;
-		for (scan = file_list; scan; scan = scan->next) {
-			g_hash_table_insert (remove_data->files_to_remove, g_strdup (scan->data), GINT_TO_POINTER (1));
-			remove_data->n_files_to_remove++;
-		}
-	}
-	else
-		remove_data->n_files_to_remove = archive->files->len;
-
-	_fr_archive_libarchive_save (archive,
-				     FALSE,
-				     archive->password,
-				     archive->encrypt_header,
-				     compression,
-				     0,
-				     cancellable,
-				     g_simple_async_result_new (G_OBJECT (archive),
-				     				callback,
-				     				user_data,
-				     				fr_archive_remove),
-     				     _remove_files_begin,
-				     NULL,
-				     _remove_files_entry_action,
-				     remove_data,
-				     (GDestroyNotify) remove_data_free);
-}
-
-
-/* -- fr_archive_libarchive_rename -- */
-
-
-typedef struct {
-	GHashTable *files_to_rename;
-	int         n_files_to_rename;
-} RenameData;
-
-
-static void
-rename_data_free (RenameData *rename_data)
-{
-	g_hash_table_unref (rename_data->files_to_rename);
-	g_free (rename_data);
-}
-
-
-static void
-_rename_files_begin (SaveData *save_data,
-		     gpointer  user_data)
-{
-	LoadData   *load_data = LOAD_DATA (save_data);
-	RenameData *rename_data = user_data;
-
-	fr_archive_progress_set_total_files (load_data->archive, rename_data->n_files_to_rename);
-	fr_archive_progress_set_total_bytes (load_data->archive,
-				FR_ARCHIVE_LIBARCHIVE (load_data->archive)->priv->uncompressed_size);
-}
-
-
-static WriteAction
-_rename_files_entry_action (SaveData             *save_data,
-			    struct archive_entry *w_entry,
-			    gpointer              user_data)
-{
-	LoadData    *load_data = LOAD_DATA (save_data);
-	RenameData  *rename_data = user_data;
-	WriteAction  action;
-	const char  *pathname;
-	char        *new_pathname;
-
-	action = WRITE_ACTION_WRITE_ENTRY;
-	pathname = archive_entry_pathname (w_entry);
-	new_pathname = g_hash_table_lookup (rename_data->files_to_rename, pathname);
-	if (new_pathname != NULL) {
-		archive_entry_set_pathname (w_entry, new_pathname);
-		rename_data->n_files_to_rename--;
-		g_hash_table_remove (rename_data->files_to_rename, pathname);
-		fr_archive_progress_inc_completed_files (load_data->archive, 1);
-	}
-
-	return action;
-}
-
-
-static void
-fr_archive_libarchive_rename (FrArchive           *archive,
-			      GList               *file_list,
-			      const char          *old_name,
-			      const char          *new_name,
-			      const char          *current_dir,
-			      gboolean             is_dir,
-			      gboolean             dir_in_archive,
-			      const char          *original_path,
-			      GCancellable        *cancellable,
-			      GAsyncReadyCallback  callback,
-			      gpointer             user_data)
-{
-	RenameData *rename_data;
-
-	rename_data = g_new0 (RenameData, 1);
-	rename_data->files_to_rename = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
-	rename_data->n_files_to_rename = 0;
-
-	if (is_dir) {
-		char  *old_dirname;
-		char  *new_dirname;
-		int    old_dirname_len;
-		GList *scan;
-
-		old_dirname = g_build_filename (current_dir + 1, old_name, "/", NULL);
-		old_dirname_len = strlen (old_dirname);
-		new_dirname = g_build_filename (current_dir + 1, new_name, "/", NULL);
-
-		for (scan = file_list; scan; scan = scan->next) {
-			char *old_pathname = scan->data;
-			char *new_pathname;
-
-			new_pathname = g_build_filename (new_dirname, old_pathname + old_dirname_len, NULL);
-			g_hash_table_insert (rename_data->files_to_rename, g_strdup (old_pathname), new_pathname);
-			rename_data->n_files_to_rename++;
-		}
-
-		g_free (new_dirname);
-		g_free (old_dirname);
-	}
-	else {
-		char *old_pathname = (char *) file_list->data;
-		char *new_pathname;
-
-		new_pathname = g_build_filename (current_dir + 1, new_name, NULL);
-		g_hash_table_insert (rename_data->files_to_rename,
-				     g_strdup (old_pathname),
-				     new_pathname);
-		rename_data->n_files_to_rename = 1;
-	}
-
-	_fr_archive_libarchive_save (archive,
-				     FALSE,
-				     archive->password,
-				     archive->encrypt_header,
-				     archive->compression,
-				     0,
-				     cancellable,
-				     g_simple_async_result_new (G_OBJECT (archive),
-				     				callback,
-				     				user_data,
-				     				fr_archive_rename),
-     				     _rename_files_begin,
-				     NULL,
-				     _rename_files_entry_action,
-				     rename_data,
-				     (GDestroyNotify) rename_data_free);
-}
-
-
-/* -- fr_archive_libarchive_paste_clipboard -- */
-
-
-static void
-fr_archive_libarchive_paste_clipboard (FrArchive           *archive,
-				       GFile               *archive_file,
-				       char                *password,
-				       gboolean             encrypt_header,
-				       FrCompression        compression,
-				       guint                volume_size,
-				       FrClipboardOp        op,
-				       char                *base_dir,
-				       GList               *files,
-				       GFile               *tmp_dir,
-				       char                *current_dir,
-				       GCancellable        *cancellable,
-				       GAsyncReadyCallback  callback,
-				       gpointer             user_data)
-{
-	AddData *add_data;
-	GList   *scan;
-
-	g_return_if_fail (base_dir != NULL);
-
-	add_data = add_data_new ();
-
-	current_dir = current_dir + 1;
-	for (scan = files; scan; scan = scan->next) {
-		const char *old_name = (char *) scan->data;
-		char       *new_name;
-		GFile      *file;
-
-		new_name = g_build_filename (current_dir, old_name + strlen (base_dir) - 1, NULL);
-		file = _g_file_append_path (tmp_dir, old_name, NULL);
-		g_hash_table_insert (add_data->files_to_add, new_name, add_file_new (file, new_name));
-		add_data->n_files_to_add++;
-
-		g_object_unref (file);
-	}
-
-	_fr_archive_libarchive_save (archive,
-				     FALSE,
-				     password,
-				     encrypt_header,
-				     compression,
-				     volume_size,
-				     cancellable,
-				     g_simple_async_result_new (G_OBJECT (archive),
-				     				callback,
-				     				user_data,
-				     				fr_archive_paste_clipboard),
-				     _add_files_begin,
-				     _add_files_end,
-				     _add_files_entry_action,
-				     add_data,
-				     (GDestroyNotify) add_data_free);
-}
-
-
-/* -- fr_archive_libarchive_add_dropped_files -- */
-
-
-static void
-fr_archive_libarchive_add_dropped_files (FrArchive           *archive,
-					 GList               *file_list,
-					 const char          *dest_dir,
-					 const char          *password,
-					 gboolean             encrypt_header,
-					 FrCompression        compression,
-					 guint                volume_size,
-					 GCancellable        *cancellable,
-					 GAsyncReadyCallback  callback,
-					 gpointer             user_data)
-{
-	AddData *add_data;
-	GList   *scan;
-
-	add_data = add_data_new ();
-
-	if (dest_dir[0] == '/')
-		dest_dir += 1;
-
-	for (scan = file_list; scan; scan = scan->next) {
-		GFile *file = G_FILE (scan->data);
-		char  *basename;
-		char  *archive_pathname;
-
-		basename = g_file_get_basename (file);
-		archive_pathname = g_build_filename (dest_dir, basename, NULL);
-		g_hash_table_insert (add_data->files_to_add,
-				     g_strdup (archive_pathname),
-				     add_file_new (file, archive_pathname));
-
-		g_free (archive_pathname);
-		g_free (basename);
-	}
-
-	_fr_archive_libarchive_save (archive,
-				     FALSE,
-				     password,
-				     encrypt_header,
-				     compression,
-				     volume_size,
-				     cancellable,
-				     g_simple_async_result_new (G_OBJECT (archive),
-				     				callback,
-				     				user_data,
-				     				fr_archive_add_dropped_items),
-				     _add_files_begin,
-				     _add_files_end,
-				     _add_files_entry_action,
-				     add_data,
-				     (GDestroyNotify) add_data_free);
-}
-
-
-/* -- fr_archive_libarchive_update_open_files -- */
-
-
-static void
-fr_archive_libarchive_update_open_files (FrArchive           *archive,
-					 GList               *file_list,
-					 GList               *dir_list,
-					 const char          *password,
-					 gboolean             encrypt_header,
-					 FrCompression        compression,
-					 guint                volume_size,
-					 GCancellable        *cancellable,
-					 GAsyncReadyCallback  callback,
-					 gpointer             user_data)
-{
-	AddData *add_data;
-	GList   *scan_file;
-	GList   *scan_dir;
-
-	add_data = add_data_new ();
-
-	for (scan_file = file_list, scan_dir = dir_list;
-	     scan_file && scan_dir;
-	     scan_file = scan_file->next, scan_dir = scan_dir->next)
-	{
-		GFile *temp_dir = G_FILE (scan_dir->data);
-		GFile *extracted_file = G_FILE (scan_file->data);
-		char  *archive_pathname;
-
-		archive_pathname = g_file_get_relative_path (temp_dir, extracted_file);
-		g_hash_table_insert (add_data->files_to_add, g_strdup (archive_pathname), add_file_new (extracted_file, archive_pathname));
-		add_data->n_files_to_add++;
-
-		g_free (archive_pathname);
-	}
-
-	_fr_archive_libarchive_save (archive,
-				     FALSE,
-				     password,
-				     encrypt_header,
-				     compression,
-				     volume_size,
-				     cancellable,
-				     g_simple_async_result_new (G_OBJECT (archive),
-				     				callback,
-				     				user_data,
-				     				fr_archive_update_open_files),
-				     _add_files_begin,
-				     _add_files_end,
-				     _add_files_entry_action,
-				     add_data,
-				     (GDestroyNotify) add_data_free);
-}
-
-
-static void
-fr_archive_libarchive_class_init (FrArchiveLibarchiveClass *klass)
-{
-	GObjectClass   *gobject_class;
-	FrArchiveClass *archive_class;
-
-	fr_archive_libarchive_parent_class = g_type_class_peek_parent (klass);
-	g_type_class_add_private (klass, sizeof (FrArchiveLibarchivePrivate));
-
-	gobject_class = G_OBJECT_CLASS (klass);
-	gobject_class->finalize = fr_archive_libarchive_finalize;
-
-	archive_class = FR_ARCHIVE_CLASS (klass);
-	archive_class->get_mime_types = fr_archive_libarchive_get_mime_types;
-	archive_class->get_capabilities = fr_archive_libarchive_get_capabilities;
-	archive_class->get_packages = fr_archive_libarchive_get_packages;
-	archive_class->list = fr_archive_libarchive_list;
-	archive_class->extract_files = fr_archive_libarchive_extract_files;
-	archive_class->add_files = fr_archive_libarchive_add_files;
-	archive_class->remove_files = fr_archive_libarchive_remove_files;
-	archive_class->rename = fr_archive_libarchive_rename;
-	archive_class->paste_clipboard = fr_archive_libarchive_paste_clipboard;
-	archive_class->add_dropped_files = fr_archive_libarchive_add_dropped_files;
-	archive_class->update_open_files = fr_archive_libarchive_update_open_files;
-}
-
-
-static void
-fr_archive_libarchive_init (FrArchiveLibarchive *self)
-{
-	FrArchive *base = FR_ARCHIVE (self);
-
-	self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, FR_TYPE_ARCHIVE_LIBARCHIVE, FrArchiveLibarchivePrivate);
-
-	base->propAddCanReplace = TRUE;
-	base->propAddCanUpdate = TRUE;
-	base->propAddCanStoreFolders = TRUE;
-	base->propAddCanStoreLinks = TRUE;
-	base->propExtractCanAvoidOverwrite = TRUE;
-	base->propExtractCanSkipOlder = TRUE;
-	base->propExtractCanJunkPaths = TRUE;
-	base->propCanExtractAll = TRUE;
-	base->propCanDeleteNonEmptyFolders = TRUE;
-	base->propCanExtractNonEmptyFolders = TRUE;
-}

--- a/src/fr-init.c.orig
+++ b/src/fr-init.c.orig
@@ -1,667 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/*
- *  File-Roller
- *
- *  Copyright (C) 2010 Free Software Foundation, Inc.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <config.h>
-#include <stdlib.h>
-#include <glib/gi18n.h>
-#include "file-data.h"
-#include "file-utils.h"
-#include "glib-utils.h"
-#if ENABLE_LIBARCHIVE
-# include "fr-archive-libarchive.h"
-#endif
-#include "fr-command.h"
-#include "fr-command-ace.h"
-#include "fr-command-alz.h"
-#include "fr-command-ar.h"
-#include "fr-command-arj.h"
-#include "fr-command-cfile.h"
-#include "fr-command-cpio.h"
-#include "fr-command-dpkg.h"
-#include "fr-command-iso.h"
-#include "fr-command-jar.h"
-#include "fr-command-lha.h"
-#include "fr-command-lrzip.h"
-#include "fr-command-rar.h"
-#include "fr-command-rpm.h"
-#include "fr-command-tar.h"
-#if HAVE_JSON_GLIB
-  #include "fr-command-unarchiver.h"
-#endif
-#include "fr-command-unstuff.h"
-#include "fr-command-zip.h"
-#include "fr-command-zoo.h"
-#include "fr-command-7z.h"
-#include "fr-init.h"
-#include "fr-process.h"
-#include "fr-window.h"
-#include "typedefs.h"
-#include "preferences.h"
-
-
-/* The capabilities are computed automatically in
- * compute_supported_archive_types() so it's correct to initialize to 0 here. */
-FrMimeTypeDescription mime_type_desc[] = {
-	{ "application/x-7z-compressed",        ".7z",       0 },
-	{ "application/x-7z-compressed-tar",    ".tar.7z",   0 },
-	{ "application/x-ace",                  ".ace",      0 },
-	{ "application/x-alz",                  ".alz",      0 },
-	{ "application/x-ar",                   ".ar",       0 },
-	{ "application/x-arj",                  ".arj",      0 },
-	{ "application/x-bzip",                 ".bz2",      0 },
-	{ "application/x-bzip-compressed-tar",  ".tar.bz2",  0 },
-	{ "application/x-bzip1",                ".bz",       0 },
-	{ "application/x-bzip1-compressed-tar", ".tar.bz",   0 },
-	{ "application/vnd.ms-cab-compressed",  ".cab",      0 },
-	{ "application/x-cbr",                  ".cbr",      0 },
-	{ "application/x-cbz",                  ".cbz",      0 },
-	{ "application/x-cd-image",             ".iso",      0 },
-	{ "application/x-compress",             ".Z",        0 },
-	{ "application/x-compressed-tar",       ".tar.gz",   0 },
-	{ "application/x-cpio",                 ".cpio",     0 },
-	{ "application/x-deb",                  ".deb",      0 },
-	{ "application/x-debian-package",	".deb",      0 },
-	{ "application/vnd.debian.binary-package",	".deb",      0 },
-	{ "application/x-ear",                  ".ear",      0 },
-	{ "application/x-ms-dos-executable",    ".exe",      0 },
-	{ "application/x-gzip",                 ".gz",       0 },
-	{ "application/x-java-archive",         ".jar",      0 },
-	{ "application/x-lha",                  ".lzh",      0 },
-	{ "application/x-lrzip",                ".lrz",      0 },
-	{ "application/x-lrzip-compressed-tar", ".tar.lrz",  0 },
-	{ "application/x-lzip",                 ".lz",       0 },
-	{ "application/x-lzip-compressed-tar",  ".tar.lz",   0 },
-	{ "application/x-lzma",                 ".lzma",     0 },
-	{ "application/x-lzma-compressed-tar",  ".tar.lzma", 0 },
-	{ "application/x-lzop",                 ".lzo",      0 },
-	{ "application/x-lzop-compressed-tar",  ".tar.lzo",  0 },
-	{ "application/x-ms-wim",               ".wim",      0 },
-	{ "application/x-rar",                  ".rar",      0 },
-	{ "application/x-rpm",                  ".rpm",      0 },
-	{ "application/x-rzip",                 ".rz",       0 },
-	{ "application/x-rzip-compressed-tar",  ".tar.rz",   0 },
-	{ "application/x-tar",                  ".tar",      0 },
-	{ "application/x-tarz",                 ".tar.Z",    0 },
-	{ "application/x-stuffit",              ".sit",      0 },
-	{ "application/x-war",                  ".war",      0 },
-	{ "application/x-xar",                  ".xar",      0 },
-	{ "application/x-xz",                   ".xz",       0 },
-	{ "application/x-xz-compressed-tar",    ".tar.xz",   0 },
-	{ "application/x-zoo",                  ".zoo",      0 },
-	{ "application/zip",                    ".zip",      0 },
-	{ NULL, NULL, 0 }
-};
-
-FrExtensionType file_ext_type[] = {
-	{ ".7z", "application/x-7z-compressed" },
-	{ ".ace", "application/x-ace" },
-	{ ".alz", "application/x-alz" },
-	{ ".ar", "application/x-ar" },
-	{ ".arj", "application/x-arj" },
-	{ ".bin", "application/x-stuffit" },
-	{ ".bz", "application/x-bzip" },
-	{ ".bz2", "application/x-bzip" },
-	{ ".cab", "application/vnd.ms-cab-compressed" },
-	{ ".cbr", "application/x-cbr" },
-	{ ".cbz", "application/x-cbz" },
-	{ ".click", "application/x-deb" },
-	{ ".cpio", "application/x-cpio" },
-	{ ".deb", "application/x-deb" },
-	{ ".ear", "application/x-ear" },
-	{ ".exe", "application/x-ms-dos-executable" },
-	{ ".gz", "application/x-gzip" },
-	{ ".iso", "application/x-cd-image" },
-	{ ".jar", "application/x-java-archive" },
-	{ ".lha", "application/x-lha" },
-	{ ".lrz", "application/x-lrzip" },
-	{ ".lzh", "application/x-lha" },
-	{ ".lz", "application/x-lzip" },
-	{ ".lzma", "application/x-lzma" },
-	{ ".lzo", "application/x-lzop" },
-	{ ".rar", "application/x-rar" },
-	{ ".rpm", "application/x-rpm" },
-	{ ".rz", "application/x-rzip" },
-	{ ".sit", "application/x-stuffit" },
-	{ ".swm", "application/x-ms-wim" },
-	{ ".tar", "application/x-tar" },
-	{ ".tar.bz", "application/x-bzip-compressed-tar" },
-	{ ".tar.bz2", "application/x-bzip-compressed-tar" },
-	{ ".tar.gz", "application/x-compressed-tar" },
-	{ ".tar.lrz", "application/x-lrzip-compressed-tar" },
-	{ ".tar.lz", "application/x-lzip-compressed-tar" },
-	{ ".tar.lzma", "application/x-lzma-compressed-tar" },
-	{ ".tar.lzo", "application/x-lzop-compressed-tar" },
-	{ ".tar.7z", "application/x-7z-compressed-tar" },
-	{ ".tar.rz", "application/x-rzip-compressed-tar" },
-	{ ".tar.xz", "application/x-xz-compressed-tar" },
-	{ ".tar.Z", "application/x-tarz" },
-	{ ".taz", "application/x-tarz" },
-	{ ".tbz", "application/x-bzip-compressed-tar" },
-	{ ".tbz2", "application/x-bzip-compressed-tar" },
-	{ ".tgz", "application/x-compressed-tar" },
-	{ ".txz", "application/x-xz-compressed-tar" },
-	{ ".tlz", "application/x-lzip-compressed-tar" },
-	{ ".tzma", "application/x-lzma-compressed-tar" },
-	{ ".tzo", "application/x-lzop-compressed-tar" },
-	{ ".war", "application/x-war" },
-	{ ".wim", "application/x-ms-wim" },
-	{ ".xar", "application/x-xar" },
-	{ ".xz", "application/x-xz" },
-	{ ".z", "application/x-gzip" },
-	{ ".Z", "application/x-compress" },
-	{ ".zip", "application/zip" },
-	{ ".zoo", "application/x-zoo" },
-	{ NULL, NULL }
-};
-
-
-GList        *CommandList;
-gint          ForceDirectoryCreation;
-GHashTable   *ProgramsCache;
-GPtrArray    *Registered_Archives;
-int           single_file_save_type[64];
-int           save_type[64];
-int           open_type[64];
-int           create_type[64];
-
-
-static void
-migrate_options_directory (void)
-{
-	char *old_directory_path;
-	GFile *old_directory;
-	GFile *new_directory;
-
-	old_directory_path = get_home_relative_path (".gnome2/file-roller/options");
-	old_directory = g_file_new_for_path (old_directory_path);
-	new_directory = _g_file_new_user_config_subdir (ADD_FOLDER_OPTIONS_DIR, FALSE);
-	if (g_file_query_exists (old_directory, NULL) && ! g_file_query_exists (new_directory, NULL)) {
-		GFile *parent;
-
-		parent = g_file_get_parent (new_directory);
-		if (_g_file_make_directory_tree (parent, 0700, NULL))
-			g_file_move (old_directory, new_directory, 0, NULL, NULL, NULL, NULL);
-
-		g_object_unref (parent);
-	}
-
-	g_object_unref (new_directory);
-	g_object_unref (old_directory);
-	g_free (old_directory_path);
-}
-
-
-/* -- FrRegisteredArchive -- */
-
-
-static FrRegisteredArchive *
-fr_registered_archive_new (GType command_type)
-{
-	FrRegisteredArchive  *reg_com;
-	FrArchive            *archive;
-	const char          **mime_types;
-	int                   i;
-
-	reg_com = g_new0 (FrRegisteredArchive, 1);
-	reg_com->ref = 1;
-	reg_com->type = command_type;
-	reg_com->caps = g_ptr_array_new ();
-	reg_com->packages = g_ptr_array_new ();
-
-	archive = (FrArchive*) g_object_new (reg_com->type, NULL);
-	mime_types = fr_archive_get_supported_types (archive);
-	for (i = 0; mime_types[i] != NULL; i++) {
-		const char         *mime_type;
-		FrMimeTypeCap      *cap;
-		FrMimeTypePackages *packages;
-
-		mime_type = _g_str_get_static (mime_types[i]);
-
-		cap = g_new0 (FrMimeTypeCap, 1);
-		cap->mime_type = mime_type;
-		cap->current_capabilities = fr_archive_get_capabilities (archive, mime_type, TRUE);
-		cap->potential_capabilities = fr_archive_get_capabilities (archive, mime_type, FALSE);
-		g_ptr_array_add (reg_com->caps, cap);
-
-		packages = g_new0 (FrMimeTypePackages, 1);
-		packages->mime_type = mime_type;
-		packages->packages = fr_archive_get_packages (archive, mime_type);
-		g_ptr_array_add (reg_com->packages, packages);
-	}
-
-	g_object_unref (archive);
-
-	return reg_com;
-}
-
-
-G_GNUC_UNUSED static void
-fr_registered_command_ref (FrRegisteredArchive *reg_com)
-{
-	reg_com->ref++;
-}
-
-
-static void
-fr_registered_archive_unref (FrRegisteredArchive *reg_com)
-{
-	if (--(reg_com->ref) != 0)
-		return;
-
-	g_ptr_array_foreach (reg_com->caps, (GFunc) g_free, NULL);
-	g_ptr_array_free (reg_com->caps, TRUE);
-	g_free (reg_com);
-}
-
-
-static FrArchiveCaps
-fr_registered_archive_get_capabilities (FrRegisteredArchive *reg_com,
-				        const char          *mime_type)
-{
-	int i;
-
-	for (i = 0; i < reg_com->caps->len; i++) {
-		FrMimeTypeCap *cap;
-
-		cap = g_ptr_array_index (reg_com->caps, i);
-		if (strcmp (mime_type, cap->mime_type) == 0)
-			return cap->current_capabilities;
-	}
-
-	return FR_ARCHIVE_CAN_DO_NOTHING;
-}
-
-
-static FrArchiveCaps
-fr_registered_archive_get_potential_capabilities (FrRegisteredArchive *reg_com,
-						  const char          *mime_type)
-{
-	int i;
-
-	if (mime_type == NULL)
-		return FR_ARCHIVE_CAN_DO_NOTHING;
-
-	for (i = 0; i < reg_com->caps->len; i++) {
-		FrMimeTypeCap *cap;
-
-		cap = g_ptr_array_index (reg_com->caps, i);
-		if ((cap->mime_type != NULL) && (strcmp (mime_type, cap->mime_type) == 0))
-			return cap->potential_capabilities;
-	}
-
-	return FR_ARCHIVE_CAN_DO_NOTHING;
-}
-
-
-static void
-register_archive (GType command_type)
-{
-	if (Registered_Archives == NULL)
-		Registered_Archives = g_ptr_array_sized_new (5);
-	g_ptr_array_add (Registered_Archives, fr_registered_archive_new (command_type));
-}
-
-
-G_GNUC_UNUSED static gboolean
-unregister_archive (GType command_type)
-{
-	int i;
-
-	for (i = 0; i < Registered_Archives->len; i++) {
-		FrRegisteredArchive *archive;
-
-		archive = g_ptr_array_index (Registered_Archives, i);
-		if (archive->type == command_type) {
-			g_ptr_array_remove_index (Registered_Archives, i);
-			fr_registered_archive_unref (archive);
-			return TRUE;
-		}
-	}
-
-	return FALSE;
-}
-
-
-static void
-register_archives (void)
-{
-	/* The order here is important. Commands registered earlier have higher
-	 * priority.  However commands that can read and write a file format
-	 * have higher priority over commands that can only read the same
-	 * format, regardless of the registration order. */
-
-#if ENABLE_LIBARCHIVE
-	register_archive (FR_TYPE_ARCHIVE_LIBARCHIVE);
-#endif
-
-	register_archive (FR_TYPE_COMMAND_TAR);
-	register_archive (FR_TYPE_COMMAND_CFILE);
-	register_archive (FR_TYPE_COMMAND_7Z);
-	register_archive (FR_TYPE_COMMAND_DPKG);
-
-	register_archive (FR_TYPE_COMMAND_ACE);
-	register_archive (FR_TYPE_COMMAND_ALZ);
-	register_archive (FR_TYPE_COMMAND_AR);
-	register_archive (FR_TYPE_COMMAND_ARJ);
-	register_archive (FR_TYPE_COMMAND_CPIO);
-	register_archive (FR_TYPE_COMMAND_ISO);
-	register_archive (FR_TYPE_COMMAND_JAR);
-	register_archive (FR_TYPE_COMMAND_LHA);
-	register_archive (FR_TYPE_COMMAND_RAR);
-	register_archive (FR_TYPE_COMMAND_RPM);
-	register_archive (FR_TYPE_COMMAND_UNSTUFF);
-	register_archive (FR_TYPE_COMMAND_ZIP);
-	register_archive (FR_TYPE_COMMAND_LRZIP);
-	register_archive (FR_TYPE_COMMAND_ZOO);
-#if HAVE_JSON_GLIB
-	register_archive (FR_TYPE_COMMAND_UNARCHIVER);
-#endif
-}
-
-
-GType
-get_archive_type_from_mime_type (const char    *mime_type,
-				 FrArchiveCaps  requested_capabilities)
-{
-	int i;
-
-	if (mime_type == NULL)
-		return 0;
-
-	for (i = 0; i < Registered_Archives->len; i++) {
-		FrRegisteredArchive *command;
-		FrArchiveCaps        capabilities;
-
-		command = g_ptr_array_index (Registered_Archives, i);
-		capabilities = fr_registered_archive_get_capabilities (command, mime_type);
-
-		/* the command must support all the requested capabilities */
-		if (((capabilities ^ requested_capabilities) & requested_capabilities) == 0)
-			return command->type;
-	}
-
-	return 0;
-}
-
-
-GType
-get_preferred_archive_for_mime_type (const char    *mime_type,
-				     FrArchiveCaps  requested_capabilities)
-{
-	int i;
-
-	for (i = 0; i < Registered_Archives->len; i++) {
-		FrRegisteredArchive *archive;
-		FrArchiveCaps        capabilities;
-
-		archive = g_ptr_array_index (Registered_Archives, i);
-		capabilities = fr_registered_archive_get_potential_capabilities (archive, mime_type);
-
-		/* the archive must support all the requested capabilities */
-		if (((capabilities ^ requested_capabilities) & requested_capabilities) == 0)
-			return archive->type;
-	}
-
-	return 0;
-}
-
-
-void
-update_registered_archives_capabilities (void)
-{
-	int i;
-
-	g_hash_table_remove_all (ProgramsCache);
-
-	for (i = 0; i < Registered_Archives->len; i++) {
-		FrRegisteredArchive *reg_com;
-		FrArchive           *archive;
-		int                  j;
-
-		reg_com = g_ptr_array_index (Registered_Archives, i);
-		archive = g_object_new (reg_com->type, NULL);
-		for (j = 0; j < reg_com->caps->len; j++) {
-			FrMimeTypeCap *cap = g_ptr_array_index (reg_com->caps, j);
-
-			cap->current_capabilities = fr_archive_get_capabilities (archive, cap->mime_type, TRUE);
-			cap->potential_capabilities = fr_archive_get_capabilities (archive, cap->mime_type, FALSE);
-		}
-
-		g_object_unref (archive);
-	}
-}
-
-
-const char *
-_g_mime_type_get_from_extension (const char *ext)
-{
-	int i;
-
-	if (ext == NULL)
-		return NULL;
-
-	for (i = G_N_ELEMENTS (file_ext_type) - 1; i >= 0; i--) {
-		if (file_ext_type[i].ext == NULL)
-			continue;
-		if (strcasecmp (ext, file_ext_type[i].ext) == 0)
-			return _g_str_get_static (file_ext_type[i].mime_type);
-	}
-
-	return NULL;
-}
-
-
-const char *
-_g_mime_type_get_from_filename (GFile *file)
-{
-	const char *mime_type = NULL;
-	char       *uri;
-
-	if (file == NULL)
-		return NULL;
-
-	uri = g_file_get_uri (file);
-	mime_type = _g_mime_type_get_from_extension (_g_filename_get_extension (uri));
-
-	g_free (uri);
-
-	return mime_type;
-}
-
-
-const char *
-get_archive_filename_extension (const char *filename)
-{
-	const char *ext;
-	int         i;
-
-	if (filename == NULL)
-		return NULL;
-
-	ext = _g_filename_get_extension (filename);
-	if (ext == NULL)
-		return NULL;
-
-	for (i = G_N_ELEMENTS (file_ext_type) - 1; i >= 0; i--) {
-		if (file_ext_type[i].ext == NULL)
-			continue;
-		if (strcasecmp (ext, file_ext_type[i].ext) == 0)
-			return ext;
-	}
-
-	return NULL;
-}
-
-
-int
-get_mime_type_index (const char *mime_type)
-{
-	int i;
-
-	for (i = 0; mime_type_desc[i].mime_type != NULL; i++)
-		if (strcmp (mime_type_desc[i].mime_type, mime_type) == 0)
-			return i;
-	return -1;
-}
-
-
-static void
-add_if_non_present (int *a,
-	            int *n,
-	            int  o)
-{
-	int i;
-
-	for (i = 0; i < *n; i++) {
-		if (a[i] == o)
-			return;
-	}
-	a[*n] = o;
-	*n = *n + 1;
-}
-
-
-static int
-cmp_mime_type_by_extension (const void *p1,
-			    const void *p2)
-{
-	int i1 = * (int*) p1;
-	int i2 = * (int*) p2;
-
-	return strcmp (mime_type_desc[i1].default_ext, mime_type_desc[i2].default_ext);
-}
-
-
-static void
-sort_mime_types (int *a,
-                 int(*compar)(const void *, const void *))
-{
-	int n = 0;
-
-	while (a[n] != -1)
-		n++;
-	qsort (a, n, sizeof (int), compar);
-}
-
-
-void
-sort_mime_types_by_extension (int *a)
-{
-	sort_mime_types (a, cmp_mime_type_by_extension);
-}
-
-
-static void
-compute_supported_archive_types (void)
-{
-	int sf_i = 0, s_i = 0, o_i = 0, c_i = 0;
-	int i;
-
-	for (i = 0; i < Registered_Archives->len; i++) {
-		FrRegisteredArchive *reg_com;
-		int                  j;
-
-		reg_com = g_ptr_array_index (Registered_Archives, i);
-		for (j = 0; j < reg_com->caps->len; j++) {
-			FrMimeTypeCap *cap;
-			int            idx;
-
-			cap = g_ptr_array_index (reg_com->caps, j);
-			idx = get_mime_type_index (cap->mime_type);
-			if (idx < 0) {
-				g_warning ("mime type not recognized: %s", cap->mime_type);
-				continue;
-			}
-			mime_type_desc[idx].capabilities |= cap->current_capabilities;
-			if (cap->current_capabilities & FR_ARCHIVE_CAN_READ)
-				add_if_non_present (open_type, &o_i, idx);
-			if (cap->current_capabilities & FR_ARCHIVE_CAN_WRITE) {
-				if (cap->current_capabilities & FR_ARCHIVE_CAN_STORE_MANY_FILES) {
-					add_if_non_present (save_type, &s_i, idx);
-					if (cap->current_capabilities & FR_ARCHIVE_CAN_WRITE)
-						add_if_non_present (create_type, &c_i, idx);
-				}
-				add_if_non_present (single_file_save_type, &sf_i, idx);
-			}
-		}
-	}
-
-	open_type[o_i] = -1;
-	save_type[s_i] = -1;
-	single_file_save_type[sf_i] = -1;
-	create_type[c_i] = -1;
-}
-
-
-static gboolean initialized = FALSE;
-
-
-void
-initialize_data (void)
-{
-	if (initialized)
-		return;
-	initialized = TRUE;
-
-	ProgramsCache = g_hash_table_new_full (g_str_hash,
-					       g_str_equal,
-					       g_free,
-					       NULL);
-
-	gtk_icon_theme_append_search_path (gtk_icon_theme_get_default (),
-					   PKG_DATA_DIR G_DIR_SEPARATOR_S "icons");
-
-	migrate_options_directory ();
-	register_archives ();
-	compute_supported_archive_types ();
-}
-
-
-static void
-command_done (CommandData *cdata)
-{
-	if (cdata == NULL)
-		return;
-
-	_g_file_remove_directory (cdata->temp_dir, NULL, NULL);
-
-	g_free (cdata->command);
-	_g_object_unref (cdata->app);
-	_g_object_list_unref (cdata->file_list);
-	_g_object_unref (cdata->temp_dir);
-	_g_object_unref (cdata->process);
-
-	CommandList = g_list_remove (CommandList, cdata);
-	g_free (cdata);
-}
-
-
-void
-release_data (void)
-{
-	if (! initialized)
-		return;
-
-	while (CommandList != NULL) {
-		CommandData *cdata = CommandList->data;
-		command_done (cdata);
-	}
-}

--- a/src/glib-utils.c.orig
+++ b/src/glib-utils.c.orig
@@ -1,1589 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-
-/*
- *  File-Roller
- *
- *  Copyright (C) 2005 Free Software Foundation, Inc.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <config.h>
-#include <ctype.h>
-#include <string.h>
-#include <stdio.h>
-#include <glib.h>
-#include <glib/gi18n.h>
-#include <glib/gprintf.h>
-#include <glib-object.h>
-#include "glib-utils.h"
-#if ENABLE_MAGIC
-#  include <magic.h>
-#endif
-
-
-#define MAX_PATTERNS 128
-
-
-/* gobject utils*/
-
-
-gpointer
-_g_object_ref (gpointer object)
-{
-	return (object != NULL) ? g_object_ref (object) : NULL;
-}
-
-
-void
-_g_object_unref (gpointer object)
-{
-	if (object != NULL)
-		g_object_unref (object);
-}
-
-
-void
-_g_clear_object (gpointer p)
-{
-	g_clear_object ((GObject **) p);
-}
-
-
-GList *
-_g_object_list_ref (GList *list)
-{
-	GList *new_list;
-
-	if (list == NULL)
-		return NULL;
-
-	new_list = g_list_copy (list);
-	g_list_foreach (new_list, (GFunc) g_object_ref, NULL);
-
-	return new_list;
-}
-
-
-void
-_g_object_list_unref (GList *list)
-{
-	g_list_foreach (list, (GFunc) g_object_unref, NULL);
-	g_list_free (list);
-}
-
-/* enum */
-
-
-GEnumValue *
-_g_enum_type_get_value (GType enum_type,
-			int   value)
-{
-	GEnumClass *class;
-	GEnumValue *enum_value;
-
-	class = G_ENUM_CLASS (g_type_class_ref (enum_type));
-	enum_value = g_enum_get_value (class, value);
-	g_type_class_unref (class);
-
-	return enum_value;
-}
-
-
-GEnumValue *
-_g_enum_type_get_value_by_nick (GType       enum_type,
-				const char *nick)
-{
-	GEnumClass *class;
-	GEnumValue *enum_value;
-
-	class = G_ENUM_CLASS (g_type_class_ref (enum_type));
-	enum_value = g_enum_get_value_by_nick (class, nick);
-	g_type_class_unref (class);
-
-	return enum_value;
-}
-
-
-/* error */
-
-
-void
-_g_error_free (GError *error)
-{
-	if (error != NULL)
-		g_error_free (error);
-}
-
-
-/* string */
-
-
-gboolean
-_g_strchrs (const char *str,
-	    const char *chars)
-{
-	const char *c;
-	for (c = chars; *c != '\0'; c++)
-		if (strchr (str, *c) != NULL)
-			return TRUE;
-	return FALSE;
-}
-
-
-char *
-_g_str_substitute (const char *str,
-		   const char *from_str,
-		   const char *to_str)
-{
-	char    **tokens;
-	int       i;
-	GString  *gstr;
-
-	if (str == NULL)
-		return NULL;
-
-	if (from_str == NULL)
-		return g_strdup (str);
-
-	if (strcmp (str, from_str) == 0)
-		return g_strdup (to_str);
-
-	tokens = g_strsplit (str, from_str, -1);
-
-	gstr = g_string_new (NULL);
-	for (i = 0; tokens[i] != NULL; i++) {
-		gstr = g_string_append (gstr, tokens[i]);
-		if ((to_str != NULL) && (tokens[i+1] != NULL))
-			gstr = g_string_append (gstr, to_str);
-	}
-
-	return g_string_free (gstr, FALSE);
-}
-
-
-gboolean
-_g_str_equal (const char *s1,
-	      const char *s2)
-{
-	return g_strcmp0 (s1, s2) == 0;
-}
-
-
-/* -- _g_str_escape_full -- */
-
-
-/* counts how many characters to escape in @str. */
-static int
-count_chars_to_escape (const char *str,
-		       const char *meta_chars)
-{
-	int         meta_chars_n = strlen (meta_chars);
-	const char *s;
-	int         n = 0;
-
-	for (s = str; *s != 0; s++) {
-		int i;
-		for (i = 0; i < meta_chars_n; i++)
-			if (*s == meta_chars[i]) {
-				n++;
-				break;
-			}
-	}
-
-	return n;
-}
-
-
-char *
-_g_str_escape_full (const char *str,
-		    const char *meta_chars,
-		    const char  prefix,
-		    const char  postfix)
-{
-	int         meta_chars_n = strlen (meta_chars);
-	char       *escaped;
-	int         i, new_l, extra_chars = 0;
-	const char *s;
-	char       *t;
-
-	if (str == NULL)
-		return NULL;
-
-	if (prefix)
-		extra_chars++;
-	if (postfix)
-		extra_chars++;
-
-	new_l = strlen (str) + (count_chars_to_escape (str, meta_chars) * extra_chars);
-	escaped = g_malloc (new_l + 1);
-
-	s = str;
-	t = escaped;
-	while (*s) {
-		gboolean is_bad = FALSE;
-		for (i = 0; (i < meta_chars_n) && !is_bad; i++)
-			is_bad = (*s == meta_chars[i]);
-		if (is_bad && prefix)
-			*t++ = prefix;
-		*t++ = *s++;
-		if (is_bad && postfix)
-			*t++ = postfix;
-	}
-	*t = 0;
-
-	return escaped;
-}
-
-
-/* escape with backslash the string @str. */
-char *
-_g_str_escape (const char *str,
-	       const char *meta_chars)
-{
-	return _g_str_escape_full (str, meta_chars, '\\', 0);
-}
-
-
-/* escape with backslash the file name. */
-char *
-_g_str_shell_escape (const char *filename)
-{
-	return _g_str_escape (filename, "$'`\"\\!?* ()[]&|:;<>#");
-}
-
-
-char *
-_g_strdup_with_max_size (const char *s,
-			 int         max_size)
-{
-	char *result;
-	int   l = strlen (s);
-
-	if (l > max_size) {
-		char *first_half;
-		char *second_half;
-		int   offset;
-		int   half_max_size = max_size / 2 + 1;
-
-		first_half = g_strndup (s, half_max_size);
-		offset = half_max_size + l - max_size;
-		second_half = g_strndup (s + offset, half_max_size);
-
-		result = g_strconcat (first_half, "...", second_half, NULL);
-
-		g_free (first_half);
-		g_free (second_half);
-	} else
-		result = g_strdup (s);
-
-	return result;
-}
-
-
-const char *
-_g_str_eat_spaces (const char *line)
-{
-	if (line == NULL)
-		return NULL;
-	while ((*line == ' ') && (*line != 0))
-		line++;
-	return line;
-}
-
-
-const char *
-_g_str_eat_void_chars (const char *line)
-{
-	if (line == NULL)
-		return NULL;
-	while (((*line == ' ') || (*line == '\t')) && (*line != 0))
-		line++;
-	return line;
-}
-
-
-char **
-_g_str_split_line (const char *line,
-		   int         n_fields)
-{
-	char       **fields;
-	const char  *scan, *field_end;
-	int          i;
-
-	fields = g_new0 (char *, n_fields + 1);
-	fields[n_fields] = NULL;
-
-	scan = _g_str_eat_spaces (line);
-	for (i = 0; i < n_fields; i++) {
-		if (scan == NULL) {
-			fields[i] = NULL;
-			continue;
-		}
-		field_end = strchr (scan, ' ');
-		if (field_end != NULL) {
-			fields[i] = g_strndup (scan, field_end - scan);
-			scan = _g_str_eat_spaces (field_end);
-		}
-	}
-
-	return fields;
-}
-
-
-const char *
-_g_str_get_last_field (const char *line,
-		       int         last_field)
-{
-	const char *field;
-	int         i;
-
-	if (line == NULL)
-		return NULL;
-
-	last_field--;
-	field = _g_str_eat_spaces (line);
-	for (i = 0; i < last_field; i++) {
-		if (field == NULL)
-			return NULL;
-		field = strchr (field, ' ');
-		field = _g_str_eat_spaces (field);
-	}
-
-	return field;
-}
-
-
-GHashTable *static_strings = NULL;
-
-
-const char *
-_g_str_get_static (const char *s)
-{
-        const char *result;
-
-        if (s == NULL)
-                return NULL;
-
-        if (static_strings == NULL)
-                static_strings = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
-
-        if (! g_hash_table_lookup_extended (static_strings, s, (gpointer*) &result, NULL)) {
-                result = g_strdup (s);
-                g_hash_table_insert (static_strings,
-                                     (gpointer) result,
-                                     GINT_TO_POINTER (1));
-        }
-
-        return result;
-}
-
-
-/* string vector */
-
-
-char **
-_g_strv_prepend (char       **str_array,
-		 const char  *str)
-{
-	char **result;
-	int    i;
-	int    j;
-
-	result = g_new (char *, g_strv_length (str_array) + 1);
-	i = 0;
-	result[i++] = g_strdup (str);
-	for (j = 0; str_array[j] != NULL; j++)
-		result[i++] = g_strdup (str_array[j]);
-	result[i] = NULL;
-
-	return result;
-}
-
-
-gboolean
-_g_strv_remove (char       **str_array,
-		const char  *str)
-{
-	int i;
-	int j;
-
-	if (str == NULL)
-		return FALSE;
-
-	for (i = 0; str_array[i] != NULL; i++)
-		if (strcmp (str_array[i], str) == 0)
-			break;
-
-	if (str_array[i] == NULL)
-		return FALSE;
-
-	for (j = i; str_array[j] != NULL; j++)
-		str_array[j] = str_array[j + 1];
-
-	return TRUE;
-}
-
-
-/* string list */
-
-
-void
-_g_string_list_free (GList *path_list)
-{
-	if (path_list == NULL)
-		return;
-	g_list_foreach (path_list, (GFunc) g_free, NULL);
-	g_list_free (path_list);
-}
-
-
-GList *
-_g_string_list_dup (GList *path_list)
-{
-	GList *new_list = NULL;
-	GList *scan;
-
-	for (scan = path_list; scan; scan = scan->next)
-		new_list = g_list_prepend (new_list, g_strdup (scan->data));
-
-	return g_list_reverse (new_list);
-}
-
-
-/* GPtrArray */
-
-
-GPtrArray *
-_g_ptr_array_copy (GPtrArray *array)
-{
-	GPtrArray *new_array;
-
-	if (array == NULL)
-		return NULL;
-
-	new_array = g_ptr_array_sized_new (array->len);
-	memcpy (new_array->pdata, array->pdata, array->len * sizeof (gpointer));
-	new_array->len = array->len;
-
-	return new_array;
-}
-
-
-void
-_g_ptr_array_free_full (GPtrArray *array,
-                        GFunc      free_func,
-                        gpointer   user_data)
-{
-	g_ptr_array_foreach (array, free_func, user_data);
-	g_ptr_array_free (array, TRUE);
-}
-
-
-void
-_g_ptr_array_reverse (GPtrArray *array)
-{
-	int      i, j;
-	gpointer tmp;
-
-	for (i = 0; i < array->len / 2; i++) {
-		j = array->len - i - 1;
-		tmp = g_ptr_array_index (array, i);
-		g_ptr_array_index (array, i) = g_ptr_array_index (array, j);
-		g_ptr_array_index (array, j) = tmp;
-	}
-}
-
-
-int
-_g_ptr_array_binary_search (GPtrArray    *array,
-			   gpointer      value,
-			   GCompareFunc  func)
-{
-	int l, r, p, cmp = -1;
-
-	l = 0;
-	r = array->len;
-	while (l < r) {
-		p = l + ((r - l) / 2);
-		cmp = func(value, &g_ptr_array_index (array, p));
-		if (cmp == 0)
-			return p;
-		else if (cmp < 0)
-			r = p;
-		else
-			l = p + 1;
-	}
-
-	return -1;
-}
-
-
-/* GRegex */
-
-
-gboolean
-_g_regexp_matchv (GRegex           **regexps,
-	          const char        *string,
-	          GRegexMatchFlags   match_options)
-{
-	gboolean matched;
-	int      i;
-
-	if ((regexps == NULL) || (regexps[0] == NULL))
-		return TRUE;
-
-	if (string == NULL)
-		return FALSE;
-
-	matched = FALSE;
-	for (i = 0; regexps[i] != NULL; i++)
-		if (g_regex_match (regexps[i], string, match_options, NULL)) {
-			matched = TRUE;
-			break;
-		}
-
-	return matched;
-}
-
-
-void
-_g_regexp_freev (GRegex **regexps)
-{
-	int i;
-
-	if (regexps == NULL)
-		return;
-
-	for (i = 0; regexps[i] != NULL; i++)
-		g_regex_unref (regexps[i]);
-	g_free (regexps);
-}
-
-
-/* -- _g_regexp_get_patternv -- */
-
-
-static const char *
-_g_utf8_strstr (const char *haystack,
-		const char *needle)
-{
-	const char *s;
-	gsize       i;
-	gsize       haystack_len = g_utf8_strlen (haystack, -1);
-	gsize       needle_len = g_utf8_strlen (needle, -1);
-	int         needle_size = strlen (needle);
-
-	s = haystack;
-	for (i = 0; i <= haystack_len - needle_len; i++) {
-		if (strncmp (s, needle, needle_size) == 0)
-			return s;
-		s = g_utf8_next_char(s);
-	}
-
-	return NULL;
-}
-
-
-static char **
-_g_utf8_strsplit (const char *string,
-		  const char *delimiter,
-		  int         max_tokens)
-{
-	GSList      *string_list = NULL, *slist;
-	char       **str_array;
-	const char  *s;
-	guint        n = 0;
-	const char  *remainder;
-
-	g_return_val_if_fail (string != NULL, NULL);
-	g_return_val_if_fail (delimiter != NULL, NULL);
-	g_return_val_if_fail (delimiter[0] != '\0', NULL);
-
-	if (max_tokens < 1)
-		max_tokens = G_MAXINT;
-
-	remainder = string;
-	s = _g_utf8_strstr (remainder, delimiter);
-	if (s != NULL) {
-		gsize delimiter_size = strlen (delimiter);
-
-		while (--max_tokens && (s != NULL)) {
-			gsize  size = s - remainder;
-			char  *new_string;
-
-			new_string = g_new (char, size + 1);
-			strncpy (new_string, remainder, size);
-			new_string[size] = 0;
-
-			string_list = g_slist_prepend (string_list, new_string);
-			n++;
-			remainder = s + delimiter_size;
-			s = _g_utf8_strstr (remainder, delimiter);
-		}
-	}
-	if (*string) {
-		n++;
-		string_list = g_slist_prepend (string_list, g_strdup (remainder));
-	}
-
-	str_array = g_new (char*, n + 1);
-
-	str_array[n--] = NULL;
-	for (slist = string_list; slist; slist = slist->next)
-		str_array[n--] = slist->data;
-
-	g_slist_free (string_list);
-
-	return str_array;
-}
-
-
-static char*
-g_utf8_strchug (char *string)
-{
-	char     *scan;
-	gunichar  c;
-
-	g_return_val_if_fail (string != NULL, NULL);
-
-	scan = string;
-	c = g_utf8_get_char (scan);
-	while (g_unichar_isspace (c)) {
-		scan = g_utf8_next_char (scan);
-		c = g_utf8_get_char (scan);
-	}
-
-	memmove (string, scan, strlen (scan) + 1);
-
-	return string;
-}
-
-
-static char*
-g_utf8_strchomp (char *string)
-{
-	char   *scan;
-	gsize   len;
-
-	g_return_val_if_fail (string != NULL, NULL);
-
-	len = g_utf8_strlen (string, -1);
-
-	if (len == 0)
-		return string;
-
-	scan = g_utf8_offset_to_pointer (string, len - 1);
-
-	while (len--) {
-		gunichar c = g_utf8_get_char (scan);
-		if (g_unichar_isspace (c))
-			*scan = '\0';
-		else
-			break;
-		scan = g_utf8_find_prev_char (string, scan);
-	}
-
-	return string;
-}
-
-
-#define g_utf8_strstrip(string) g_utf8_strchomp (g_utf8_strchug (string))
-
-
-char **
-_g_regexp_get_patternv (const char *pattern_string)
-{
-	char **patterns;
-	int    i;
-
-	if (pattern_string == NULL)
-		return NULL;
-
-	patterns = _g_utf8_strsplit (pattern_string, ";", MAX_PATTERNS);
-	for (i = 0; patterns[i] != NULL; i++) {
-		char *p1, *p2;
-
-		p1 = g_utf8_strstrip (patterns[i]);
-		p2 = _g_str_substitute (p1, ".", "\\.");
-		patterns[i] = _g_str_substitute (p2, "*", ".*");
-
-		g_free (p2);
-		g_free (p1);
-	}
-
-	return patterns;
-}
-
-
-GRegex **
-_g_regexp_split_from_patterns (const char         *pattern_string,
-			       GRegexCompileFlags  compile_options)
-{
-	char   **patterns;
-	GRegex **regexps;
-	int      i;
-
-	patterns = _g_regexp_get_patternv (pattern_string);
-	if (patterns == NULL)
-		return NULL;
-
-	regexps = g_new0 (GRegex*, g_strv_length (patterns) + 1);
-	for (i = 0; patterns[i] != NULL; i++)
-		regexps[i] = g_regex_new (patterns[i],
-					  G_REGEX_OPTIMIZE | compile_options,
-					  G_REGEX_MATCH_NOTEMPTY,
-					  NULL);
-	g_strfreev (patterns);
-
-	return regexps;
-}
-
-
-/* time */
-
-
-char *
-_g_time_to_string (time_t time)
-{
-	struct tm *tm;
-	char       s_time[256];
-	char      *locale_format = NULL;
-	char      *time_utf8;
-
-	tm = localtime (&time);
-	/* This is the time format used in the "Date Modified" column and
-	 * in the Properties dialog.  See the man page of strftime for an
-	 * explanation of the values. */
-	locale_format = g_locale_from_utf8 (_("%d %B %Y, %H:%M"), -1, NULL, NULL, NULL);
-	strftime (s_time, sizeof (s_time) - 1, locale_format, tm);
-	g_free (locale_format);
-	time_utf8 = g_locale_to_utf8 (s_time, -1, NULL, NULL, NULL);
-
-	return time_utf8;
-}
-
-
-/* uri/path/filename */
-
-
-const char *
-_g_uri_get_home (void)
-{
-	static char *home_uri = NULL;
-	if (home_uri == NULL)
-		home_uri = g_filename_to_uri (g_get_home_dir (), NULL, NULL);
-	return home_uri;
-}
-
-
-char *
-_g_uri_get_home_relative (const char *partial_uri)
-{
-	return g_strconcat (_g_uri_get_home (),
-			    "/",
-			    partial_uri,
-			    NULL);
-}
-
-
-const char *
-_g_uri_remove_host (const char *uri)
-{
-        const char *idx, *sep;
-
-        if (uri == NULL)
-                return NULL;
-
-        idx = strstr (uri, "://");
-        if (idx == NULL)
-                return uri;
-        idx += 3;
-        if (*idx == '\0')
-                return "/";
-        sep = strstr (idx, "/");
-        if (sep == NULL)
-                return idx;
-        return sep;
-}
-
-
-char *
-_g_uri_get_host (const char *uri)
-{
-	const char *idx;
-
-	idx = strstr (uri, "://");
-	if (idx == NULL)
-		return NULL;
-	idx = strstr (idx + 3, "/");
-	if (idx == NULL)
-		return NULL;
-	return g_strndup (uri, (idx - uri));
-}
-
-
-char *
-_g_uri_get_root (const char *uri)
-{
-	char *host;
-	char *root;
-
-	host = _g_uri_get_host (uri);
-	if (host == NULL)
-		return NULL;
-	root = g_strconcat (host, "/", NULL);
-	g_free (host);
-
-	return root;
-}
-
-
-int
-_g_uri_cmp (const char *uri1,
-	    const char *uri2)
-{
-	return g_strcmp0 (uri1, uri2);
-}
-
-
-/* like g_path_get_basename but does not warn about NULL and does not
- * alloc a new string. */
-const gchar *
-_g_path_get_basename (const gchar *file_name)
-{
-	register char   *base;
-	register gssize  last_char;
-
-	if (file_name == NULL)
-		return NULL;
-
-	if (file_name[0] == '\0')
-		return "";
-
-	last_char = strlen (file_name) - 1;
-
-	if (file_name [last_char] == G_DIR_SEPARATOR)
-		return "";
-
-	base = g_utf8_strrchr (file_name, -1, G_DIR_SEPARATOR);
-	if (! base)
-		return file_name;
-
-	return base + 1;
-}
-
-
-char *
-_g_path_get_dir_name (const gchar *path)
-{
-	register gssize base;
-	register gssize last_char;
-
-	if (path == NULL)
-		return NULL;
-
-	if (path[0] == '\0')
-		return g_strdup ("");
-
-	last_char = strlen (path) - 1;
-	if (path[last_char] == G_DIR_SEPARATOR)
-		last_char--;
-
-	base = last_char;
-	while ((base >= 0) && (path[base] != G_DIR_SEPARATOR))
-		base--;
-
-	return g_strndup (path + base + 1, last_char - base);
-}
-
-
-gchar *
-_g_path_remove_level (const gchar *path)
-{
-	int         p;
-	const char *ptr = path;
-	char       *new_path;
-
-	if (path == NULL)
-		return NULL;
-
-	p = strlen (path) - 1;
-	if (p < 0)
-		return NULL;
-
-	/* ignore the first slash if it's the last character,
-	 * this way /a/b/ is treated as /a/b */
-
-	if ((ptr[p] == '/') && (p > 0))
-		p--;
-
-	while ((p > 0) && (ptr[p] != '/'))
-		p--;
-	if ((p == 0) && (ptr[p] == '/'))
-		p++;
-	new_path = g_strndup (path, (guint)p);
-
-	return new_path;
-}
-
-
-char *
-_g_path_remove_ending_separator (const char *path)
-{
-	gint len, copy_len;
-
-	if (path == NULL)
-		return NULL;
-
-	copy_len = len = strlen (path);
-	if ((len > 1) && (path[len - 1] == '/'))
-		copy_len--;
-
-	return g_strndup (path, copy_len);
-}
-
-
-char *
-_g_path_remove_extension (const gchar *path)
-{
-	const char *ext;
-
-	if (path == NULL)
-		return NULL;
-
-	ext = _g_filename_get_extension (path);
-	if (ext == NULL)
-		return g_strdup (path);
-	else
-		return g_strndup (path, strlen (path) - strlen (ext));
-}
-
-
-char *
-_g_path_remove_first_extension (const gchar *path)
-{
-	const char *ext;
-
-	if (path == NULL)
-		return NULL;
-
-	ext = strrchr (path, '.');
-	if (ext == NULL)
-		return g_strdup (path);
-	else
-		return g_strndup (path, strlen (path) - strlen (ext));
-}
-
-
-/* Check whether the dirname is contained in filename */
-gboolean
-_g_path_is_parent_of (const char *dirname,
-		      const char *filename)
-{
-	int dirname_l, filename_l, separator_position;
-
-	if ((dirname == NULL) || (filename == NULL))
-		return FALSE;
-
-	dirname_l = strlen (dirname);
-	filename_l = strlen (filename);
-
-	if ((dirname_l == filename_l + 1)
-	     && (dirname[dirname_l - 1] == '/'))
-		return FALSE;
-
-	if ((filename_l == dirname_l + 1)
-	     && (filename[filename_l - 1] == '/'))
-		return FALSE;
-
-	if (dirname[dirname_l - 1] == '/')
-		separator_position = dirname_l - 1;
-	else
-		separator_position = dirname_l;
-
-	return ((filename_l > dirname_l)
-		&& (strncmp (dirname, filename, dirname_l) == 0)
-		&& (filename[separator_position] == '/'));
-}
-
-
-const char *
-_g_path_get_relative_basename (const char *path,
-			       const char *base_dir,
-			       gboolean    junk_paths)
-{
-	int         base_dir_len;
-	const char *base_path;
-
-	if (junk_paths)
-		return _g_path_get_basename (path);
-
-	if (base_dir == NULL)
-		return (path[0] == '/') ? path + 1 : path;
-
-	base_dir_len = strlen (base_dir);
-	if (strlen (path) < base_dir_len)
-		return NULL;
-
-	base_path = path + base_dir_len;
-	if (path[0] != '/')
-		base_path -= 1;
-
-	return base_path;
-}
-
-
-#define ISDOT(c) ((c) == '.')
-#define ISSLASH(c) ((c) == '/')
-
-
-static const char *
-sanitize_filename (const char *file_name)
-{
-	size_t      prefix_len;
-	char const *p;
-
-	if (file_name == NULL)
-		return NULL;
-
-	prefix_len = 0;
-	for (p = file_name; *p; ) {
-		if (ISDOT (p[0]) && ISDOT (p[1]) && (ISSLASH (p[2]) || !p[2]))
-			prefix_len = p + 2 - file_name;
-
-		do {
-			char c = *p++;
-			if (ISSLASH (c))
-				break;
-		}
-		while (*p);
-	}
-
-	p = file_name + prefix_len;
-	while (ISSLASH (*p))
-		p++;
-
-	return p;
-}
-
-
-const char *
-_g_path_get_relative_basename_safe (const char *path,
-				    const char *base_dir,
-				    gboolean    junk_paths)
-{
-	return sanitize_filename (_g_path_get_relative_basename (path, base_dir, junk_paths));
-}
-
-
-gboolean
-_g_filename_is_hidden (const gchar *name)
-{
-	if (name[0] != '.') return FALSE;
-	if (name[1] == '\0') return FALSE;
-	if ((name[1] == '.') && (name[2] == '\0')) return FALSE;
-
-	return TRUE;
-}
-
-
-const char *
-_g_filename_get_extension (const char *filename)
-{
-	const char *ptr = filename;
-	int         len;
-	int         p;
-	const char *ext;
-
-	if (filename == NULL)
-		return NULL;
-
-	len = strlen (filename);
-	if (len <= 1)
-		return NULL;
-
-	p = len - 1;
-	while ((p >= 0) && (ptr[p] != '.'))
-		p--;
-	if (p < 0)
-		return NULL;
-
-	ext = filename + p;
-	if (ext - 4 > filename) {
-		const char *test = ext - 4;
-		/* .tar.rz cannot be uncompressed in one step */
-		if ((strncmp (test, ".tar", 4) == 0) && (strncmp (ext, ".rz", 2) != 0))
-			ext = ext - 4;
-	}
-	return ext;
-}
-
-
-gboolean
-_g_filename_has_extension (const char *filename,
-		   const char *ext)
-{
-	int filename_l, ext_l;
-
-	filename_l = strlen (filename);
-	ext_l = strlen (ext);
-
-	if (filename_l < ext_l)
-		return FALSE;
-	return strcasecmp (filename + filename_l - ext_l, ext) == 0;
-}
-
-
-char *
-_g_filename_get_random (int         random_part_len,
-		        const char *suffix)
-{
-	const char *letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
-	const int   n_letters = strlen (letters);
-	int         suffix_len;
-	char       *result, *c;
-	GRand      *rand;
-	int         i;
-
-	suffix_len = suffix != NULL ? strlen (suffix) + 1 : 0;
-	result = g_new (char, suffix_len + random_part_len + 1);
-
-	rand = g_rand_new ();
-	for (i = 0, c = result; i < random_part_len; i++, c++)
-		*c = letters[g_rand_int_range (rand, 0, n_letters)];
-	*c = '\0';
-	g_rand_free (rand);
-
-	if (suffix != NULL) {
-		strcpy (c, ".");
-		strcpy (c + 1, suffix);
-	}
-
-	return result;
-}
-
-
-gboolean
-_g_mime_type_matches (const char *mime_type,
-		      const char *pattern)
-{
-	return (strcasecmp (mime_type, pattern) == 0);
-}
-
-
-const char *
-_g_mime_type_get_from_content (char  *buffer,
-			       gsize  buffer_size)
-{
-#if ENABLE_MAGIC
-
-	static magic_t magic = NULL;
-
-	if (magic == NULL) {
-		magic = magic_open (MAGIC_MIME_TYPE);
-		if (magic != NULL)
-			magic_load (magic, NULL);
-		else
-			g_warning ("unable to open magic database");
-	}
-
-	if (magic != NULL) {
-		const char * mime_type;
-
-		mime_type = magic_buffer (magic, buffer, buffer_size);
-		if ((mime_type != NULL) && (strcmp (mime_type, "application/octet-stream") == 0))
-			return NULL;
-
-		if (mime_type != NULL)
-			return mime_type;
-
-		g_warning ("unable to detect filetype from magic: %s", magic_error (magic));
-	}
-
-#else
-
-	static const struct magic {
-		const unsigned int off;
-		const unsigned int len;
-		const char * const id;
-		const char * const mime_type;
-	}
-	magic_ids [] = {
-		/* magic ids taken from magic/Magdir/archive from the file-4.21 tarball */
-		{ 0,  6, "7z\274\257\047\034",                   "application/x-7z-compressed" },
-		{ 7,  7, "**ACE**",                              "application/x-ace"           },
-		{ 0,  2, "\x60\xea",                             "application/x-arj"           },
-		{ 0,  3, "BZh",                                  "application/x-bzip2"         },
-		{ 0,  2, "\037\213",                             "application/x-gzip"          },
-		{ 0,  4, "LZIP",                                 "application/x-lzip"          },
-		{ 0,  9, "\x89\x4c\x5a\x4f\x00\x0d\x0a\x1a\x0a", "application/x-lzop",         },
-		{ 0,  4, "Rar!",                                 "application/x-rar"           },
-		{ 0,  4, "RZIP",                                 "application/x-rzip"          },
-		{ 0,  6, "\3757zXZ\000",                         "application/x-xz"            },
-		{ 20, 4, "\xdc\xa7\xc4\xfd",                     "application/x-zoo",          },
-		{ 0,  4, "PK\003\004",                           "application/zip"             },
-		{ 0,  8, "PK00PK\003\004",                       "application/zip"             },
-		{ 0,  4, "LRZI",                                 "application/x-lrzip"         },
-	};
-
-	int  i;
-
-	for (i = 0; i < G_N_ELEMENTS (magic_ids); i++) {
-		const struct magic * const magic = &magic_ids[i];
-
-		if ((magic->off + magic->len) > buffer_size)
-			g_warning ("buffer underrun for mime-type '%s' magic", magic->mime_type);
-		else if (! memcmp (buffer + magic->off, magic->id, magic->len))
-			return magic->mime_type;
-	}
-
-#endif
-
-	return NULL;
-}
-
-
-/* GFile */
-
-
-int
-_g_file_cmp_uris (GFile *a,
-                  GFile *b)
-{
-	char *uri_a;
-	char *uri_b;
-	int   result;
-
-	uri_a = g_file_get_uri (a);
-	uri_b = g_file_get_uri (b);
-	result = g_strcmp0 (uri_a, uri_b);
-
-	g_free (uri_b);
-	g_free (uri_a);
-
-	return result;
-}
-
-
-gboolean
-_g_file_is_local (GFile *file)
-{
-	char     *scheme;
-	gboolean  is_local;
-
-	scheme = g_file_get_uri_scheme (file);
-	is_local = strcmp (scheme, "file") == 0;
-
-	g_free (scheme);
-
-	return is_local;
-}
-
-
-GFile *
-_g_file_get_home (void)
-{
-	static GFile *file = NULL;
-
-	if (file != NULL)
-		return file;
-
-	file = g_file_new_for_path (g_get_home_dir ());
-
-	return file;
-}
-
-
-char *
-_g_file_get_display_basename (GFile *file)
-{
-	char *uri, *e_name, *name;
-
-	uri = g_file_get_uri (file);
-	e_name = g_filename_display_basename (uri);
-	name = g_uri_unescape_string (e_name, "");
-
-	g_free (e_name);
-	g_free (uri);
-
-	return name;
-}
-
-
-GFile *
-_g_file_new_home_relative (const char *partial_uri)
-{
-	GFile *file;
-	char  *uri;
-
-	uri = g_strconcat (_g_uri_get_home (), "/", partial_uri, NULL);
-	file = g_file_new_for_uri (uri);
-	g_free (uri);
-
-	return file;
-}
-
-
-GList *
-_g_file_list_dup (GList *l)
-{
-	GList *r = NULL, *scan;
-	for (scan = l; scan; scan = scan->next)
-		r = g_list_prepend (r, g_file_dup ((GFile*) scan->data));
-	return g_list_reverse (r);
-}
-
-
-void
-_g_file_list_free (GList *l)
-{
-	GList *scan;
-	for (scan = l; scan; scan = scan->next)
-		g_object_unref (scan->data);
-	g_list_free (l);
-}
-
-
-GList *
-_g_file_list_new_from_uri_list (GList *uris)
-{
-	GList *r = NULL, *scan;
-	for (scan = uris; scan; scan = scan->next)
-		r = g_list_prepend (r, g_file_new_for_uri ((char*)scan->data));
-	return g_list_reverse (r);
-}
-
-
-GFile *
-_g_file_append_path (GFile  *file,
-		     ...)
-{
-	char       *uri;
-	const char *path;
-	va_list     args;
-	GFile      *new_file;
-
-	uri = g_file_get_uri (file);
-
-	va_start (args, file);
-	while ((path = va_arg (args, const char *)) != NULL) {
-		char *escaped;
-		char *new_uri;
-
-		escaped = g_uri_escape_string (path, G_URI_RESERVED_CHARS_ALLOWED_IN_PATH, FALSE);
-		new_uri = g_build_filename (uri, escaped, NULL);
-		g_free (uri);
-		uri = new_uri;
-
-		g_free (escaped);
-	}
-	va_end (args);
-	new_file = g_file_new_for_uri (uri);
-
-	g_free (uri);
-
-	return new_file;
-}
-
-
-/* GKeyFile */
-
-
-GList *
-_g_key_file_get_string_list (GKeyFile    *key_file,
-			     const char  *group_name,
-			     const char  *key,
-			     GError    **error)
-{
-	char  **strv;
-	GList  *list;
-	int     i;
-
-	strv = g_key_file_get_string_list (key_file, group_name, key, NULL, error);
-	if (strv == NULL)
-		return NULL;
-
-	list = NULL;
-	for (i = 0; strv[i] != NULL; i++)
-		list = g_list_prepend (list, strv[i]);
-
-	g_free (strv);
-
-	return g_list_reverse (list);
-}
-
-
-/* GSettings utils */
-
-
-GSettings *
-_g_settings_new_if_schema_installed (const char *schema_id)
-{
-	GSettingsSchema *schema;
-
-	schema = g_settings_schema_source_lookup (g_settings_schema_source_get_default (),
-						  schema_id,
-						  TRUE);
-	if (schema == NULL)
-		return NULL;
-
-	g_settings_schema_unref (schema);
-
-	return g_settings_new (schema_id);
-}
-
-
-/* line parser */
-
-
-gboolean
-_g_line_matches_pattern (const char *line,
-			 const char *pattern)
-{
-	const char *l = line, *p = pattern;
-
-	for (/* void */; (*p != 0) && (*l != 0); p++, l++) {
-		if (*p != '%') {
-			if (*p != *l)
-				return FALSE;
-		}
-		else {
-			p++;
-			switch (*p) {
-			case 'a':
-				break;
-			case 'n':
-				if (!isdigit (*l))
-					return FALSE;
-				break;
-			case 'c':
-				if (!isalpha (*l))
-					return FALSE;
-				break;
-			default:
-				return FALSE;
-			}
-		}
-	}
-
-	return (*p == 0);
-}
-
-
-int
-_g_line_get_index_from_pattern (const char *line,
-				const char *pattern)
-{
-	int         line_l, pattern_l;
-	const char *l;
-
-	line_l = strlen (line);
-	pattern_l = strlen (pattern);
-
-	if ((pattern_l == 0) || (line_l == 0))
-		return -1;
-
-	for (l = line; *l != 0; l++)
-		if (_g_line_matches_pattern (l, pattern))
-			return (l - line);
-
-	return -1;
-}
-
-
-char*
-_g_line_get_next_field (const char *line,
-			int         start_from,
-			int         field_n)
-{
-	const char *f_start, *f_end;
-
-	line = line + start_from;
-
-	f_start = line;
-	while ((*f_start == ' ') && (*f_start != *line))
-		f_start++;
-	f_end = f_start;
-
-	while ((field_n > 0) && (*f_end != 0)) {
-		if (*f_end == ' ') {
-			field_n--;
-			if (field_n != 0) {
-				while ((*f_end == ' ') && (*f_end != *line))
-					f_end++;
-				f_start = f_end;
-			}
-		}
-		else
-			f_end++;
-	}
-
-	return g_strndup (f_start, f_end - f_start);
-}
-
-
-char*
-_g_line_get_prev_field (const char *line,
-			int         start_from,
-			int         field_n)
-{
-	const char *f_start, *f_end;
-
-	f_start = line + start_from - 1;
-	while ((*f_start == ' ') && (*f_start != *line))
-		f_start--;
-	f_end = f_start;
-
-	while ((field_n > 0) && (*f_start != *line)) {
-		if (*f_start == ' ') {
-			field_n--;
-			if (field_n != 0) {
-				while ((*f_start == ' ') && (*f_start != *line))
-					f_start--;
-				f_end = f_start;
-			}
-		}
-		else
-			f_start--;
-	}
-
-	return g_strndup (f_start + 1, f_end - f_start);
-}
-
-
-/* debug */
-
-void
-debug (const char *file,
-       int         line,
-       const char *function,
-       const char *format, ...)
-{
-#ifdef DEBUG
-	va_list  args;
-	char    *str;
-
-	g_return_if_fail (format != NULL);
-
-	va_start (args, format);
-	str = g_strdup_vprintf (format, args);
-	va_end (args);
-
-	g_fprintf (stderr, "[FR] %s:%d (%s):\n\t%s\n", file, line, function, str);
-
-	g_free (str);
-#else /* ! DEBUG */
-#endif
-}
openSUSE Build Service is sponsored by