Index: file-roller-2.19.4/src/fr-archive.c =================================================================== --- file-roller-2.19.4.orig/src/fr-archive.c +++ file-roller-2.19.4/src/fr-archive.c @@ -2705,7 +2705,7 @@ move_files_to_dir (FrArchive *archive, else sprintf (path, "%s/%s", source_dir, e_filename); - fr_process_add_arg (archive->process, path); + fr_process_add_file_arg (archive->process, path); g_free (e_filename); } Index: file-roller-2.19.4/src/fr-command-ar.c =================================================================== --- file-roller-2.19.4.orig/src/fr-command-ar.c +++ file-roller-2.19.4/src/fr-command-ar.c @@ -226,7 +226,7 @@ fr_command_ar_add (FrCommand *comm, fr_process_add_arg (comm->process, comm->e_filename); for (scan = file_list; scan; scan = scan->next) - fr_process_add_arg (comm->process, (gchar*) scan->data); + fr_process_add_file_arg (comm->process, (gchar*) scan->data); fr_process_end_command (comm->process); } @@ -244,7 +244,7 @@ fr_command_ar_delete (FrCommand *comm, fr_process_add_arg (comm->process, comm->e_filename); for (scan = file_list; scan; scan = scan->next) - fr_process_add_arg (comm->process, scan->data); + fr_process_add_file_arg (comm->process, scan->data); fr_process_end_command (comm->process); } @@ -269,7 +269,7 @@ fr_command_ar_extract (FrCommand *comm, fr_process_add_arg (comm->process, comm->e_filename); for (scan = file_list; scan; scan = scan->next) - fr_process_add_arg (comm->process, scan->data); + fr_process_add_file_arg (comm->process, scan->data); fr_process_end_command (comm->process); } Index: file-roller-2.19.4/src/fr-command-arj.c =================================================================== --- file-roller-2.19.4.orig/src/fr-command-arj.c +++ file-roller-2.19.4/src/fr-command-arj.c @@ -219,7 +219,7 @@ fr_command_arj_add (FrCommand *comm, fr_process_add_arg (comm->process, comm->e_filename); for (scan = file_list; scan; scan = scan->next) - fr_process_add_arg (comm->process, (gchar*) scan->data); + fr_process_add_file_arg (comm->process, (gchar*) scan->data); fr_process_end_command (comm->process); } @@ -241,7 +241,7 @@ fr_command_arj_delete (FrCommand *comm, fr_process_add_arg (comm->process, comm->e_filename); for (scan = file_list; scan; scan = scan->next) - fr_process_add_arg (comm->process, scan->data); + fr_process_add_file_arg (comm->process, scan->data); fr_process_end_command (comm->process); } @@ -292,7 +292,7 @@ fr_command_arj_extract (FrCommand *comm fr_process_add_arg (comm->process, comm->e_filename); for (scan = file_list; scan; scan = scan->next) - fr_process_add_arg (comm->process, scan->data); + fr_process_add_file_arg (comm->process, scan->data); fr_process_end_command (comm->process); } Index: file-roller-2.19.4/src/fr-command-lha.c =================================================================== --- file-roller-2.19.4.orig/src/fr-command-lha.c +++ file-roller-2.19.4/src/fr-command-lha.c @@ -244,7 +244,7 @@ fr_command_lha_add (FrCommand *comm, fr_process_add_arg (comm->process, "a"); fr_process_add_arg (comm->process, comm->e_filename); for (scan = file_list; scan; scan = scan->next) - fr_process_add_arg (comm->process, (gchar*) scan->data); + fr_process_add_file_arg (comm->process, (gchar*) scan->data); fr_process_end_command (comm->process); } @@ -260,7 +260,7 @@ fr_command_lha_delete (FrCommand *comm, fr_process_add_arg (comm->process, comm->e_filename); for (scan = file_list; scan; scan = scan->next) - fr_process_add_arg (comm->process, scan->data); + fr_process_add_file_arg (comm->process, scan->data); fr_process_end_command (comm->process); } @@ -298,7 +298,7 @@ fr_command_lha_extract (FrCommand *comm fr_process_add_arg (comm->process, comm->e_filename); for (scan = file_list; scan; scan = scan->next) - fr_process_add_arg (comm->process, scan->data); + fr_process_add_file_arg (comm->process, scan->data); fr_process_end_command (comm->process); } Index: file-roller-2.19.4/src/fr-command-rar.c =================================================================== --- file-roller-2.19.4.orig/src/fr-command-rar.c +++ file-roller-2.19.4/src/fr-command-rar.c @@ -265,7 +265,7 @@ fr_command_rar_add (FrCommand *comm, fr_process_add_arg (comm->process, comm->e_filename); for (scan = file_list; scan; scan = scan->next) - fr_process_add_arg (comm->process, (gchar*) scan->data); + fr_process_add_file_arg (comm->process, (gchar*) scan->data); fr_process_end_command (comm->process); } @@ -286,7 +286,7 @@ fr_command_rar_delete (FrCommand *comm, fr_process_add_arg (comm->process, comm->e_filename); for (scan = file_list; scan; scan = scan->next) - fr_process_add_arg (comm->process, scan->data); + fr_process_add_file_arg (comm->process, scan->data); fr_process_end_command (comm->process); } @@ -331,7 +331,7 @@ fr_command_rar_extract (FrCommand *comm fr_process_add_arg (comm->process, comm->e_filename); for (scan = file_list; scan; scan = scan->next) - fr_process_add_arg (comm->process, scan->data); + fr_process_add_file_arg (comm->process, scan->data); if (dest_dir != NULL) { char *e_dest_dir = fr_command_escape (comm, dest_dir); Index: file-roller-2.19.4/src/fr-command-rpm.c =================================================================== --- file-roller-2.19.4.orig/src/fr-command-rpm.c +++ file-roller-2.19.4/src/fr-command-rpm.c @@ -179,7 +179,7 @@ fr_command_rpm_extract (FrCommand *comm fr_process_add_arg (comm->process, "| cpio -idu"); for (scan = file_list; scan; scan = scan->next) { char *filename = (char*) scan->data; - fr_process_add_arg (comm->process, filename); + fr_process_add_file_arg (comm->process, filename); } fr_process_end_command (comm->process); fr_process_start (comm->process); Index: file-roller-2.19.4/src/fr-command-tar.c =================================================================== --- file-roller-2.19.4.orig/src/fr-command-tar.c +++ file-roller-2.19.4/src/fr-command-tar.c @@ -329,7 +329,7 @@ fr_command_tar_add (FrCommand *comm, fr_process_add_arg (comm->process, c_tar->uncomp_filename); fr_process_add_arg (comm->process, "--"); for (scan = file_list; scan; scan = scan->next) - fr_process_add_arg (comm->process, scan->data); + fr_process_add_file_arg (comm->process, scan->data); fr_process_end_command (comm->process); } @@ -373,7 +373,7 @@ fr_command_tar_delete (FrCommand *comm, fr_process_add_arg (comm->process, "--"); for (scan = file_list; scan; scan = scan->next) - fr_process_add_arg (comm->process, scan->data); + fr_process_add_file_arg (comm->process, scan->data); fr_process_end_command (comm->process); } @@ -420,7 +420,7 @@ fr_command_tar_extract (FrCommand *comm fr_process_add_arg (comm->process, "--"); for (scan = file_list; scan; scan = scan->next) - fr_process_add_arg (comm->process, scan->data); + fr_process_add_file_arg (comm->process, scan->data); fr_process_end_command (comm->process); } Index: file-roller-2.19.4/src/fr-command-unstuff.c =================================================================== --- file-roller-2.19.4.orig/src/fr-command-unstuff.c +++ file-roller-2.19.4/src/fr-command-unstuff.c @@ -249,7 +249,7 @@ fr_command_unstuff_extract (FrCommand * /* FIXME it is not possible to unpack only some files */ #if 0 for (scan = file_list; scan; scan = scan->next) - fr_process_add_arg (comm->process, scan->data); + fr_process_add_file_arg (comm->process, scan->data); #endif fr_process_end_command (comm->process); Index: file-roller-2.19.4/src/fr-command-zip.c =================================================================== --- file-roller-2.19.4.orig/src/fr-command-zip.c +++ file-roller-2.19.4/src/fr-command-zip.c @@ -319,7 +319,7 @@ fr_command_zip_add (FrCommand *comm, for (scan = file_list; scan; scan = scan->next) { char *temp = prepend_path_separator ((char*) scan->data); - fr_process_add_arg (comm->process, temp); + fr_process_add_file_arg (comm->process, temp); g_free (temp); } @@ -343,7 +343,7 @@ fr_command_zip_delete (FrCommand *comm, for (scan = file_list; scan; scan = scan->next) { char *temp = prepend_path_separator_zip_escape ((char*) scan->data); - fr_process_add_arg (comm->process, temp); + fr_process_add_file_arg (comm->process, temp); g_free (temp); } @@ -392,7 +392,7 @@ fr_command_zip_extract (FrCommand *comm for (scan = file_list; scan; scan = scan->next) { char *temp = prepend_path_separator_zip_escape ((char*) scan->data); - fr_process_add_arg (comm->process, temp); + fr_process_add_file_arg (comm->process, temp); g_free (temp); } Index: file-roller-2.19.4/src/fr-command-zoo.c =================================================================== --- file-roller-2.19.4.orig/src/fr-command-zoo.c +++ file-roller-2.19.4/src/fr-command-zoo.c @@ -259,7 +259,7 @@ fr_command_zoo_add (FrCommand *comm, fr_process_add_arg (comm->process, comm->e_filename); for (scan = file_list; scan; scan = scan->next) - fr_process_add_arg (comm->process, scan->data); + fr_process_add_file_arg (comm->process, scan->data); fr_process_end_command (comm->process); } @@ -277,7 +277,7 @@ fr_command_zoo_delete (FrCommand *comm, fr_process_add_arg (comm->process, comm->e_filename); for (scan = file_list; scan; scan = scan->next) - fr_process_add_arg (comm->process, scan->data); + fr_process_add_file_arg (comm->process, scan->data); fr_process_end_command (comm->process); } @@ -306,7 +306,7 @@ fr_command_zoo_extract (FrCommand *comm fr_process_set_working_dir (comm->process, dest_dir); for (scan = file_list; scan; scan = scan->next) - fr_process_add_arg (comm->process, scan->data); + fr_process_add_file_arg (comm->process, scan->data); fr_process_end_command (comm->process); } Index: file-roller-2.19.4/src/fr-process.c =================================================================== --- file-roller-2.19.4.orig/src/fr-process.c +++ file-roller-2.19.4/src/fr-process.c @@ -43,6 +43,11 @@ enum { LAST_SIGNAL }; +/* Shell limit minus a bit for fixed arguments */ +#define FILES_LIST_LENGTH_MAX 30000 + +static const gchar file_list_insertion_point [] = "{}"; + static GObjectClass *parent_class; static guint fr_process_signals[LAST_SIGNAL] = { 0 }; @@ -67,17 +72,37 @@ fr_command_info_new (void) static void +free_if_not_insertion_point (gpointer p) +{ + if (p != file_list_insertion_point) + g_free (p); +} + + +static void fr_command_info_free (FRCommandInfo * c_info) { if (c_info == NULL) return; if (c_info->args != NULL) { - g_list_foreach (c_info->args, (GFunc) g_free, NULL); + g_list_foreach (c_info->args, (GFunc) free_if_not_insertion_point, NULL); g_list_free (c_info->args); c_info->args = NULL; } + if (c_info->files != NULL) { + g_list_foreach (c_info->files, (GFunc) g_free, NULL); + g_list_free (c_info->files); + c_info->files = NULL; + } + + if (c_info->files_next != NULL) { + g_list_foreach (c_info->files_next, (GFunc) g_free, NULL); + g_list_free (c_info->files_next); + c_info->files_next = NULL; + } + if (c_info->dir != NULL) { g_free (c_info->dir); c_info->dir = NULL; @@ -338,6 +363,23 @@ fr_process_add_arg (FrProcess *fr_proc, c_info->args = g_list_prepend (c_info->args, g_strdup (arg)); } +void +fr_process_add_file_arg (FrProcess *fr_proc, + const char *arg) +{ + FRCommandInfo *c_info; + + g_return_if_fail (fr_proc != NULL); + + c_info = g_ptr_array_index (fr_proc->comm, fr_proc->current_comm); + c_info->files_next = g_list_prepend (c_info->files_next, g_strdup (arg)); + + /* Insertion point for file list */ + if (!c_info->args || !c_info->args->data || + c_info->args->data != file_list_insertion_point) { + c_info->args = g_list_prepend (c_info->args, (gpointer) file_list_insertion_point); + } +} void fr_process_set_arg_at (FrProcess *fr_proc, @@ -577,11 +619,33 @@ static void child_setup (gpointer user_d putenv ("LC_ALL=C"); } +static GList * +string_list_split_at_strlen (GList *strings, gint max_len) +{ + gint len = 0; + GList *l; + + for (l = strings; l; l = l->next) { + len += strlen (strings->data) + 1; + + if (len > max_len && l->prev) + break; + } + + if (l && l->prev) { + l->prev->next = NULL; + l->prev = NULL; + return l; + } + + return NULL; +} static void start_current_command (FrProcess *fr_proc) { FRCommandInfo *c_info; + gboolean ran_before = FALSE; GList *arg_list, *scan; GString *command; char *dir; @@ -595,6 +659,17 @@ start_current_command (FrProcess *fr_pro arg_list = c_info->args; dir = c_info->dir; + /* If command line would be too long, split up command */ + + if (c_info->files != NULL) { + g_list_foreach (c_info->files, (GFunc) g_free, NULL); + g_list_free (c_info->files); + ran_before = TRUE; + } + + c_info->files = c_info->files_next; + c_info->files_next = string_list_split_at_strlen (c_info->files, FILES_LIST_LENGTH_MAX); + if (dir != NULL) debug (DEBUG_INFO, "cd %s\n", dir); @@ -606,8 +681,19 @@ start_current_command (FrProcess *fr_pro command = g_string_new (""); for (scan = arg_list; scan; scan = scan->next) { - if (scan->data != NULL) - g_string_append (command, scan->data); + if (scan->data != NULL) { + if (scan->data == file_list_insertion_point) { + GList *subscan; + + for (subscan = c_info->files; subscan; subscan = subscan->next) { + g_string_append (command, subscan->data); + if (subscan->next != NULL) + g_string_append_c (command, ' '); + } + } else { + g_string_append (command, scan->data); + } + } if (scan->next != NULL) g_string_append_c (command, ' '); } @@ -626,7 +712,7 @@ start_current_command (FrProcess *fr_pro } #endif - if (c_info->begin_func != NULL) + if (c_info->begin_func != NULL && !ran_before) (*c_info->begin_func) (c_info->begin_data); if (! g_spawn_async_with_pipes (dir, @@ -760,6 +846,14 @@ check_child (gpointer data) fr_proc->output_fd = 0; fr_proc->error_fd = 0; + /* If we have more file names to process, re-run the command with + * the next batch */ + + if (fr_proc->error.type == FR_PROC_ERROR_NONE && c_info->files_next) { + start_current_command (fr_proc); + return FALSE; + } + /**/ if (c_info->end_func != NULL) Index: file-roller-2.19.4/src/fr-process.h =================================================================== --- file-roller-2.19.4.orig/src/fr-process.h +++ file-roller-2.19.4/src/fr-process.h @@ -47,7 +47,9 @@ typedef gboolean (*ContinueFunc) (gpoint typedef struct { - GList *args; /* command to execute */ + GList *args; /* command to execute; same for each invocation */ + GList *files; /* list of filenames to process */ + GList *files_next; /* next batch of filenames to process */ char *dir; /* working directory */ guint sticky : 1; /* whether the command must be executed even * if a previous command has failed. */ @@ -147,6 +149,8 @@ void fr_process_set_arg_at void fr_process_set_begin_func (FrProcess *fr_proc, ProcFunc func, gpointer func_data); +void fr_process_add_file_arg (FrProcess *fr_proc, + const char *arg); void fr_process_set_end_func (FrProcess *fr_proc, ProcFunc func, gpointer func_data); Index: file-roller-2.19.4/src/fr-window.c =================================================================== --- file-roller-2.19.4.orig/src/fr-window.c +++ file-roller-2.19.4/src/fr-window.c @@ -7043,7 +7043,7 @@ fr_window_open_files_with_command (FrWin fr_process_begin_command (cdata->process, command); for (scan = file_list; scan; scan = scan->next) { char *filename = shell_escape (scan->data); - fr_process_add_arg (cdata->process, filename); + fr_process_add_file_arg (cdata->process, filename); g_free (filename); } fr_process_end_command (cdata->process);