Index: file-roller-2.18.0/src/fr-archive.c =================================================================== --- file-roller-2.18.0.orig/src/fr-archive.c +++ file-roller-2.18.0/src/fr-archive.c @@ -1487,7 +1487,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.18.0/src/fr-command-ar.c =================================================================== --- file-roller-2.18.0.orig/src/fr-command-ar.c +++ file-roller-2.18.0/src/fr-command-ar.c @@ -225,7 +225,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); } @@ -243,7 +243,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); } @@ -268,7 +268,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.18.0/src/fr-command-arj.c =================================================================== --- file-roller-2.18.0.orig/src/fr-command-arj.c +++ file-roller-2.18.0/src/fr-command-arj.c @@ -217,7 +217,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); } @@ -239,7 +239,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); } @@ -290,7 +290,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.18.0/src/fr-command-lha.c =================================================================== --- file-roller-2.18.0.orig/src/fr-command-lha.c +++ file-roller-2.18.0/src/fr-command-lha.c @@ -234,7 +234,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); } @@ -250,7 +250,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); } @@ -288,7 +288,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.18.0/src/fr-command-rar.c =================================================================== --- file-roller-2.18.0.orig/src/fr-command-rar.c +++ file-roller-2.18.0/src/fr-command-rar.c @@ -263,7 +263,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); } @@ -284,7 +284,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); } @@ -329,7 +329,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.18.0/src/fr-command-rpm.c =================================================================== --- file-roller-2.18.0.orig/src/fr-command-rpm.c +++ file-roller-2.18.0/src/fr-command-rpm.c @@ -177,7 +177,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.18.0/src/fr-command-tar.c =================================================================== --- file-roller-2.18.0.orig/src/fr-command-tar.c +++ file-roller-2.18.0/src/fr-command-tar.c @@ -325,7 +325,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); } @@ -368,7 +368,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); } @@ -413,7 +413,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.18.0/src/fr-command-unstuff.c =================================================================== --- file-roller-2.18.0.orig/src/fr-command-unstuff.c +++ file-roller-2.18.0/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.18.0/src/fr-command-zip.c =================================================================== --- file-roller-2.18.0.orig/src/fr-command-zip.c +++ file-roller-2.18.0/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.18.0/src/fr-command-zoo.c =================================================================== --- file-roller-2.18.0.orig/src/fr-command-zoo.c +++ file-roller-2.18.0/src/fr-command-zoo.c @@ -257,7 +257,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); } @@ -275,7 +275,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); } @@ -304,7 +304,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.18.0/src/fr-process.c =================================================================== --- file-roller-2.18.0.orig/src/fr-process.c +++ file-roller-2.18.0/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 () 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; @@ -337,6 +362,25 @@ fr_process_add_arg (FRProcess *fr_proc, 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, int n_comm, int n_arg, @@ -575,10 +619,34 @@ static void child_setup (gpointer user_d } +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; @@ -592,6 +660,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); @@ -603,8 +682,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, ' '); } @@ -623,7 +713,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, @@ -756,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.18.0/src/fr-process.h =================================================================== --- file-roller-2.18.0.orig/src/fr-process.h +++ file-roller-2.18.0/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. */ @@ -144,6 +146,9 @@ void fr_process_set_arg_at int n_comm, int n_arg, const char *arg); +void fr_process_add_file_arg (FRProcess *fr_proc, + const char *arg); + void fr_process_set_begin_func (FRProcess *fr_proc, ProcFunc func, gpointer func_data); Index: file-roller-2.18.0/src/window.c =================================================================== --- file-roller-2.18.0.orig/src/window.c +++ file-roller-2.18.0/src/window.c @@ -6106,7 +6106,7 @@ window_open_files__extract_done_cb (FRAr fr_process_begin_command (proc, cdata->command); for (scan = cdata->file_list; scan; scan = scan->next) { char *filename = shell_escape (scan->data); - fr_process_add_arg (proc, filename); + fr_process_add_file_arg (proc, filename); g_free (filename); } fr_process_end_command (proc);