[file-roller: 64/123] libarchive: implemented the add_files function
- From: Paolo Bacchilega <paobac src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [file-roller: 64/123] libarchive: implemented the add_files function
- Date: Mon, 6 Aug 2012 13:46:14 +0000 (UTC)
commit cb385203d33ba28a4ca48b756ea9982279149153
Author: Paolo Bacchilega <paobac src gnome org>
Date: Sat Jul 28 20:11:14 2012 +0200
libarchive: implemented the add_files function
src/fr-archive-libarchive.c | 551 ++++++++++++++++++++++++++++++++++++++++++-
src/fr-archive.c | 16 +-
src/gio-utils.c | 2 +
src/glib-utils.c | 21 ++
src/glib-utils.h | 1 +
5 files changed, 580 insertions(+), 11 deletions(-)
---
diff --git a/src/fr-archive-libarchive.c b/src/fr-archive-libarchive.c
index 02c06fa..c2e6a72 100644
--- a/src/fr-archive-libarchive.c
+++ b/src/fr-archive-libarchive.c
@@ -20,6 +20,9 @@
*/
#include <config.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <grp.h>
#include <glib.h>
#include <glib/gi18n.h>
#include <gio/gio.h>
@@ -32,6 +35,10 @@
#include "typedefs.h"
+#define BUFFER_SIZE (10 * 1024)
+#define FILE_ATTRIBUTES_NEEDED_BY_ARCHIVE_ENTRY ("standard::*,time::*,access::*,unix::*")
+
+
G_DEFINE_TYPE (FrArchiveLibarchive, fr_archive_libarchive, FR_TYPE_ARCHIVE)
@@ -80,7 +87,7 @@ fr_archive_libarchive_get_capabilities (FrArchive *archive,
const char *mime_type,
gboolean check_command)
{
- return FR_ARCHIVE_CAN_STORE_MANY_FILES | FR_ARCHIVE_CAN_READ;
+ return FR_ARCHIVE_CAN_STORE_MANY_FILES | FR_ARCHIVE_CAN_READ | FR_ARCHIVE_CAN_WRITE;
}
@@ -95,7 +102,6 @@ fr_archive_libarchive_get_packages (FrArchive *archive,
/* -- load -- */
-#define BUFFER_SIZE_FOR_READING (10 * 1024)
#define LOAD_DATA(x) ((LoadData *)(x))
@@ -258,7 +264,7 @@ fr_archive_libarchive_load (FrArchive *archive,
callback,
user_data,
fr_archive_load);
- load_data->buffer_size = BUFFER_SIZE_FOR_READING;
+ load_data->buffer_size = BUFFER_SIZE;
load_data->buffer = g_new (char, load_data->buffer_size);
g_simple_async_result_set_op_res_gpointer (load_data->result, load_data, NULL);
@@ -269,11 +275,484 @@ fr_archive_libarchive_load (FrArchive *archive,
}
+/* -- save data -- */
+
+
+#define SAVE_DATA(x) ((SaveData *)(x))
+
+
+typedef struct {
+ LoadData parent;
+ GFile *tmp_file;
+ GOutputStream *ostream;
+ GHashTable *usernames;
+ GHashTable *groupnames;
+} SaveData;
+
+
+static void
+save_data_init (SaveData *save_data)
+{
+ 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)
+{
+ 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 *name;
+
+ /* FIXME: use a better temp filename */
+ parent = g_file_get_parent (fr_archive_get_file (load_data->archive));
+ name = _g_filename_get_random (16);
+ save_data->tmp_file = g_file_get_child (parent, name);
+ save_data->ostream = (GOutputStream *) g_file_create (save_data->tmp_file, G_FILE_CREATE_NONE, load_data->cancellable, &load_data->error);
+
+ g_free (name);
+ 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);
+
+ 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)
+ g_output_stream_close (save_data->ostream, load_data->cancellable, &load_data->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 0;
+}
+
+
/* -- add -- */
+typedef struct {
+ SaveData parent;
+ GList *file_list;
+ GFile *base_dir;
+ char *dest_dir;
+ gboolean update;
+ gboolean recursive;
+ char *password;
+ gboolean encrypt_header;
+ FrCompression compression;
+ guint volume_size;
+ GHashTable *files_to_add;
+ int n_files_to_add;
+ void *buffer;
+ gsize buffer_size;
+} AddData;
+
+
+static void
+add_data_free (AddData *add_data)
+{
+ g_free (add_data->buffer);
+ g_hash_table_unref (add_data->files_to_add);
+ g_free (add_data->password);
+ g_free (add_data->dest_dir);
+ _g_object_unref (add_data->base_dir);
+ _g_string_list_free (add_data->file_list);
+ save_data_free (SAVE_DATA (add_data));
+}
+
+
+typedef struct {
+ GFile *file;
+ char *pathname;
+} FileToAdd;
+
+
+static FileToAdd *
+file_to_add_new (AddData *add_data,
+ const char *relative_name,
+ const char *full_name)
+{
+ FileToAdd *file_to_add;
+
+ file_to_add = g_new (FileToAdd, 1);
+ file_to_add->file = g_file_get_child (add_data->base_dir, relative_name);
+ file_to_add->pathname = g_strdup (full_name);
+
+ return file_to_add;
+}
+
+
+static void
+file_to_add_free (FileToAdd *file_to_add)
+{
+ g_object_unref (file_to_add->file);
+ g_free (file_to_add->pathname);
+ g_free (file_to_add);
+}
+
+
+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) {
+ g_print ("symlink: %s\n", g_file_info_get_attribute_byte_string (info, G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET));
+ 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 void
+_archive_write_set_format_from_filename (struct archive *a,
+ GFile *file)
+{
+ char *uri;
+ const char *ext;
+
+ uri = g_file_get_uri (file);
+ ext = _g_filename_get_extension (uri);
+
+ if (ext == NULL) {
+ /* defaults to an uncompressed tar */
+ ext = ".tar";
+ }
+
+ if ((strcmp (ext, ".tar.bz2") == 0) || (strcmp (ext, ".tbz2") == 0)) {
+ archive_write_add_filter_bzip2 (a);
+ archive_write_set_format_ustar (a);
+ }
+ else if ((strcmp (ext, ".tar.Z") == 0) || (strcmp (ext, ".taz") == 0)) {
+ archive_write_add_filter_compress (a);
+ archive_write_set_format_ustar (a);
+ }
+ else if ((strcmp (ext, ".tar.gz") == 0) || (strcmp (ext, ".tgz") == 0)) {
+ archive_write_add_filter_gzip (a);
+ archive_write_set_format_ustar (a);
+ }
+ else if ((strcmp (ext, ".tar.lz") == 0) || (strcmp (ext, ".tlz") == 0)) {
+ archive_write_add_filter_lzip (a);
+ archive_write_set_format_ustar (a);
+ }
+ else if ((strcmp (ext, ".tar.lzma") == 0) || (strcmp (ext, ".tzma") == 0)) {
+ archive_write_add_filter_lzma (a);
+ archive_write_set_format_ustar (a);
+ }
+ else if ((strcmp (ext, ".tar.xz") == 0) || (strcmp (ext, ".txz") == 0)) {
+ archive_write_add_filter_xz (a);
+ archive_write_set_format_ustar (a);
+ }
+ else {
+ /* defaults to an uncompressed tar */
+ archive_write_add_filter_none (a);
+ archive_write_set_format_ustar (a);
+ }
+
+ /* FIXME: add all the supported formats */
+
+ g_free (uri);
+}
+
+
+typedef enum {
+ WRITE_ACTION_ABORT,
+ WRITE_ACTION_SKIP_ENTRY,
+ WRITE_ACTION_WRITE_ENTRY
+} WriteAction;
+
+
+static WriteAction
+_archive_write_file (struct archive *b,
+ AddData *add_data,
+ FileToAdd *file_to_add,
+ struct archive_entry *r_entry,
+ GCancellable *cancellable)
+{
+ LoadData *load_data = LOAD_DATA (add_data);
+ GFileInfo *info;
+ struct archive_entry *w_entry;
+
+ /* write the file header */
+
+ info = g_file_query_info (file_to_add->file,
+ FILE_ATTRIBUTES_NEEDED_BY_ARCHIVE_ENTRY,
+ G_FILE_QUERY_INFO_NONE,
+ 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 (add_data))) {
+ archive_entry_free (w_entry);
+ g_object_unref (info);
+ return WRITE_ACTION_SKIP_ENTRY;
+ }
+
+ /* honor the update flag */
+ if (add_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, file_to_add->pathname);
+ 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 (file_to_add->file, cancellable, &load_data->error);
+ if (istream != NULL) {
+ gssize bytes_read;
+
+ while ((bytes_read = g_input_stream_read (istream, add_data->buffer, add_data->buffer_size, cancellable, &load_data->error)) > 0) {
+ archive_write_data (b, add_data->buffer, bytes_read);
+ fr_archive_progress_inc_completed_bytes (load_data->archive, bytes_read);
+ }
+
+ g_object_unref (istream);
+ }
+ }
+
+ add_data->n_files_to_add--;
+
+ archive_entry_free (w_entry);
+ g_object_unref (info);
+
+ return (load_data->error == NULL) ? WRITE_ACTION_SKIP_ENTRY : WRITE_ACTION_ABORT;
+}
+
+
static void
-fr_archive_libarchive_add_files (FrArchive *base,
+add_to_archive_thread (GSimpleAsyncResult *result,
+ GObject *object,
+ GCancellable *cancellable)
+{
+ AddData *add_data;
+ LoadData *load_data;
+ struct archive *a, *b;
+ struct archive_entry *r_entry;
+ int ra, rb;
+ GList *remaining_files;
+ GList *scan;
+
+ add_data = g_simple_async_result_get_op_res_gpointer (result);
+ load_data = LOAD_DATA (add_data);
+
+ fr_archive_progress_set_total_files (load_data->archive, add_data->n_files_to_add);
+
+ b = archive_write_new ();
+ _archive_write_set_format_from_filename (b, fr_archive_get_file (load_data->archive));
+ archive_write_open (b, add_data, save_data_open, save_data_write, save_data_close);
+
+ 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 ((load_data->error == NULL) && (ra = archive_read_next_header (a, &r_entry)) == ARCHIVE_OK) {
+ WriteAction action;
+ const char *pathname;
+ FileToAdd *file_to_add;
+ int64_t offset;
+
+ if (g_cancellable_is_cancelled (cancellable))
+ break;
+
+ fr_archive_progress_inc_completed_files (load_data->archive, 1);
+
+ action = WRITE_ACTION_WRITE_ENTRY;
+
+ pathname = archive_entry_pathname (r_entry);
+ file_to_add = g_hash_table_lookup (add_data->files_to_add, pathname);
+ if (file_to_add != NULL) {
+ action = _archive_write_file (b, add_data, file_to_add, r_entry, cancellable);
+ g_hash_table_remove (add_data->files_to_add, pathname);
+ }
+
+ if (action == WRITE_ACTION_WRITE_ENTRY) {
+ const void *buffer;
+ size_t buffer_size;
+
+ rb = archive_write_header (b, r_entry);
+ if (rb != ARCHIVE_OK)
+ 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_EOF)
+ load_data->error = g_error_new_literal (FR_ERROR, FR_ERROR_COMMAND_ERROR, archive_error_string (a));
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ /* 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);
+ ra = ARCHIVE_EOF;
+ }
+
+ remaining_files = g_hash_table_get_values (add_data->files_to_add);
+ for (scan = remaining_files; (load_data->error == NULL) && scan; scan = scan->next) {
+ FileToAdd *file_to_add = scan->data;
+
+ if (_archive_write_file (b, add_data, file_to_add, NULL, cancellable) == WRITE_ACTION_ABORT)
+ break;
+ }
+
+ if ((load_data->error == NULL) && (ra != ARCHIVE_EOF))
+ load_data->error = g_error_new_literal (FR_ERROR, FR_ERROR_COMMAND_ERROR, archive_error_string (a));
+ if ((load_data->error == NULL) && (rb != ARCHIVE_OK))
+ load_data->error = g_error_new_literal (FR_ERROR, FR_ERROR_COMMAND_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);
+ g_list_free (remaining_files);
+ add_data_free (add_data);
+}
+
+
+static void
+fr_archive_libarchive_add_files (FrArchive *archive,
GList *file_list,
const char *base_dir,
const char *dest_dir,
@@ -287,6 +766,54 @@ fr_archive_libarchive_add_files (FrArchive *base,
GAsyncReadyCallback callback,
gpointer user_data)
{
+ AddData *add_data;
+ LoadData *load_data;
+ GList *scan;
+
+ g_return_if_fail (base_dir != NULL);
+
+ add_data = g_new0 (AddData, 1);
+ save_data_init (SAVE_DATA (add_data));
+
+ load_data = LOAD_DATA (add_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_add_files);
+ load_data->buffer_size = BUFFER_SIZE;
+ load_data->buffer = g_new (char, load_data->buffer_size);
+
+ add_data->file_list = _g_string_list_dup (file_list);
+ add_data->base_dir = g_file_new_for_uri (base_dir);
+ add_data->dest_dir = g_strdup (dest_dir[0] == '/' ? dest_dir + 1 : dest_dir);
+ add_data->update = update;
+ add_data->recursive = recursive;
+ add_data->password = g_strdup (password);
+ add_data->encrypt_header = encrypt_header;
+ add_data->compression = compression;
+ add_data->volume_size = volume_size;
+ add_data->files_to_add = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify) file_to_add_free);
+ add_data->n_files_to_add = 0;
+ for (scan = add_data->file_list; scan; scan = scan->next) {
+ char *relative_pathname = scan->data;
+ char *full_pathname;
+
+ full_pathname = g_build_filename (add_data->dest_dir, relative_pathname, NULL);
+ g_hash_table_insert (add_data->files_to_add, full_pathname, file_to_add_new (add_data, relative_pathname, full_pathname));
+ add_data->n_files_to_add++;
+
+ g_free (full_pathname);
+ }
+ add_data->buffer_size = BUFFER_SIZE;
+ add_data->buffer = g_new (char, add_data->buffer_size);
+
+ g_simple_async_result_set_op_res_gpointer (load_data->result, add_data, NULL);
+ g_simple_async_result_run_in_thread (load_data->result,
+ add_to_archive_thread,
+ G_PRIORITY_DEFAULT,
+ cancellable);
}
@@ -385,7 +912,7 @@ extract_archive_thread (GSimpleAsyncResult *result,
}
fullpath = (*pathname == '/') ? g_strdup (pathname) : g_strconcat ("/", pathname, NULL);
- file = g_file_get_child (extract_data->destination, _g_path_get_base_name (fullpath, extract_data->base_dir, extract_data->junk_paths));
+ file = g_file_get_child (extract_data->destination, _g_path_get_basename (fullpath, extract_data->base_dir, extract_data->junk_paths));
/* honor the skip_older and overwrite options */
@@ -547,7 +1074,7 @@ fr_archive_libarchive_extract_files (FrArchive *archive,
callback,
user_data,
fr_archive_load);
- load_data->buffer_size = BUFFER_SIZE_FOR_READING;
+ 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);
@@ -680,5 +1207,17 @@ fr_archive_libarchive_class_init (FrArchiveLibarchiveClass *klass)
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->propExtractCanAvoidOverwrite = TRUE;
+ base->propExtractCanSkipOlder = TRUE;
+ base->propExtractCanJunkPaths = TRUE;
+ base->propCanExtractAll = TRUE;
+ base->propCanDeleteNonEmptyFolders = TRUE; /* FIXME: not implemented yet */
+ base->propCanExtractNonEmptyFolders = TRUE; /* FIXME: not implemented yet */
}
diff --git a/src/fr-archive.c b/src/fr-archive.c
index b1155c8..e097182 100644
--- a/src/fr-archive.c
+++ b/src/fr-archive.c
@@ -1004,7 +1004,7 @@ add_with_wildcard_data_free (AddWithWildcardData *aww_data)
static void
add_with_wildcard__step2 (GList *file_list,
- GList *dirs_list,
+ GList *dir_list,
GError *error,
gpointer data)
{
@@ -1022,6 +1022,11 @@ add_with_wildcard__step2 (GList *file_list,
g_simple_async_result_complete_in_idle (result);
}
else {
+ if (archive->propAddCanStoreFolders) {
+ file_list = g_list_concat (file_list, dir_list);
+ dir_list = NULL;
+ }
+
if (file_list == NULL)
g_simple_async_result_complete_in_idle (result);
else
@@ -1042,7 +1047,7 @@ add_with_wildcard__step2 (GList *file_list,
g_object_unref (result);
_g_string_list_free (file_list);
- _g_string_list_free (dirs_list);
+ _g_string_list_free (dir_list);
add_with_wildcard_data_free (aww_data);
}
@@ -1150,10 +1155,10 @@ add_directory__step2 (GList *file_list,
g_simple_async_result_complete_in_idle (result);
}
else {
- if (archive->propAddCanStoreFolders)
+ if (archive->propAddCanStoreFolders) {
file_list = g_list_concat (file_list, dir_list);
- else
- _g_string_list_free (dir_list);
+ dir_list = NULL;
+ }
if (file_list == NULL)
g_simple_async_result_complete_in_idle (result);
@@ -1174,6 +1179,7 @@ add_directory__step2 (GList *file_list,
}
_g_string_list_free (file_list);
+ _g_string_list_free (dir_list);
g_object_unref (result);
add_directory_data_free (ad_data);
}
diff --git a/src/gio-utils.c b/src/gio-utils.c
index d070f06..a07caa5 100644
--- a/src/gio-utils.c
+++ b/src/gio-utils.c
@@ -577,10 +577,12 @@ get_file_list_done (GError *error,
gfl->files = g_list_reverse (gfl->files);
gfl->dirs = g_list_reverse (gfl->dirs);
+ /* FIXME: delete the folders that contain only filtered out files
if (! filter_empty (gfl->include_filter) || (gfl->exclude_filter->pattern != NULL)) {
_g_string_list_free (gfl->dirs);
gfl->dirs = NULL;
}
+ */
h_dirs = g_hash_table_new (g_str_hash, g_str_equal);
diff --git a/src/glib-utils.c b/src/glib-utils.c
index de9cdf8..1904482 100644
--- a/src/glib-utils.c
+++ b/src/glib-utils.c
@@ -1080,6 +1080,27 @@ _g_filename_has_extension (const char *filename,
}
+char *
+_g_filename_get_random (int length)
+{
+ const char *letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+ const int n_letters = strlen (letters);
+ char *result, *c;
+ GRand *rand;
+ int i;
+
+ result = g_new (char, length + 1);
+
+ rand = g_rand_new ();
+ for (i = 0, c = result; i < length; i++, c++)
+ *c = letters[g_rand_int_range (rand, 0, n_letters)];
+ *c = '\0';
+ g_rand_free (rand);
+
+ return result;
+}
+
+
gboolean
_g_mime_type_matches (const char *mime_type,
const char *pattern)
diff --git a/src/glib-utils.h b/src/glib-utils.h
index 0904a3b..a2044b8 100644
--- a/src/glib-utils.h
+++ b/src/glib-utils.h
@@ -144,6 +144,7 @@ gboolean _g_filename_is_hidden (const char *name);
const char * _g_filename_get_extension (const char *filename);
gboolean _g_filename_has_extension (const char *filename,
const char *ext);
+char * _g_filename_get_random (int length);
gboolean _g_mime_type_matches (const char *type,
const char *pattern);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]