Index: file-roller-2.19.2/src/fr-archive.c =================================================================== --- file-roller-2.19.2.orig/src/fr-archive.c +++ file-roller-2.19.2/src/fr-archive.c @@ -2703,7 +2703,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.2/src/fr-command-ar.c =================================================================== --- file-roller-2.19.2.orig/src/fr-command-ar.c +++ file-roller-2.19.2/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.19.2/src/fr-command-arj.c =================================================================== --- file-roller-2.19.2.orig/src/fr-command-arj.c +++ file-roller-2.19.2/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.19.2/src/fr-command-lha.c =================================================================== --- file-roller-2.19.2.orig/src/fr-command-lha.c +++ file-roller-2.19.2/src/fr-command-lha.c @@ -242,7 +242,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); } @@ -258,7 +258,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); } @@ -296,7 +296,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.2/src/fr-command-rar.c =================================================================== --- file-roller-2.19.2.orig/src/fr-command-rar.c +++ file-roller-2.19.2/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.19.2/src/fr-command-rpm.c =================================================================== --- file-roller-2.19.2.orig/src/fr-command-rpm.c +++ file-roller-2.19.2/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.19.2/src/fr-command-tar.c =================================================================== --- file-roller-2.19.2.orig/src/fr-command-tar.c +++ file-roller-2.19.2/src/fr-command-tar.c @@ -327,7 +327,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); } @@ -371,7 +371,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); } @@ -418,7 +418,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.2/src/fr-command-unstuff.c =================================================================== --- file-roller-2.19.2.orig/src/fr-command-unstuff.c +++ file-roller-2.19.2/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.2/src/fr-command-zip.c =================================================================== --- file-roller-2.19.2.orig/src/fr-command-zip.c +++ file-roller-2.19.2/src/fr-command-zip.c @@ -317,7 +317,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); } @@ -341,7 +341,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); } @@ -390,7 +390,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.2/src/fr-command-zoo.c =================================================================== --- file-roller-2.19.2.orig/src/fr-command-zoo.c +++ file-roller-2.19.2/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.19.2/src/fr-process.c =================================================================== --- file-roller-2.19.2.orig/src/fr-process.c +++ file-roller-2.19.2/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.2/src/fr-process.h =================================================================== --- file-roller-2.19.2.orig/src/fr-process.h +++ file-roller-2.19.2/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.2/src/fr-window.c =================================================================== --- file-roller-2.19.2.orig/src/fr-window.c +++ file-roller-2.19.2/src/fr-window.c @@ -6448,7 +6448,7 @@ fr_window_open_files__extract_done_cb (F 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);