--- file-roller-2.15.90/src/fr-archive.c +++ file-roller-2.15.90/src/fr-archive.c @@ -1451,7 +1451,7 @@ 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); } --- file-roller-2.15.90/src/fr-command-ar.c +++ file-roller-2.15.90/src/fr-command-ar.c @@ -227,7 +227,7 @@ 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); } @@ -245,7 +245,7 @@ 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); } @@ -270,7 +270,7 @@ 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); } --- file-roller-2.15.90/src/fr-command-arj.c +++ file-roller-2.15.90/src/fr-command-arj.c @@ -219,7 +219,7 @@ 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_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_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); } --- file-roller-2.15.90/src/fr-command-lha.c +++ file-roller-2.15.90/src/fr-command-lha.c @@ -231,7 +231,7 @@ 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); } @@ -247,7 +247,7 @@ 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); } @@ -285,7 +285,7 @@ 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); } --- file-roller-2.15.90/src/fr-command-rar.c +++ file-roller-2.15.90/src/fr-command-rar.c @@ -258,7 +258,7 @@ 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); } @@ -279,7 +279,7 @@ 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); } @@ -324,7 +324,7 @@ 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); --- file-roller-2.15.90/src/fr-command-rpm.c +++ file-roller-2.15.90/src/fr-command-rpm.c @@ -157,7 +157,7 @@ fr_process_add_arg (comm->process, "| cpio --extract --force-local --unconditional --make-directories"); 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); --- file-roller-2.15.90/src/fr-command-tar.c +++ file-roller-2.15.90/src/fr-command-tar.c @@ -323,7 +323,7 @@ fr_process_add_arg (comm->process, c_tar->uncomp_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); } @@ -365,7 +365,7 @@ fr_process_add_arg (comm->process, c_tar->uncomp_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); } @@ -408,7 +408,7 @@ } 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); } --- file-roller-2.15.90/src/fr-command-unstuff.c +++ file-roller-2.15.90/src/fr-command-unstuff.c @@ -249,7 +249,7 @@ /* 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); --- file-roller-2.15.90/src/fr-command-zip.c +++ file-roller-2.15.90/src/fr-command-zip.c @@ -318,7 +318,7 @@ 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); } @@ -342,7 +342,7 @@ 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); } @@ -391,7 +391,7 @@ 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); } --- file-roller-2.15.90/src/fr-command-zoo.c +++ file-roller-2.15.90/src/fr-command-zoo.c @@ -259,7 +259,7 @@ 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_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_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); } --- file-roller-2.15.90/src/fr-process.c +++ file-roller-2.15.90/src/fr-process.c @@ -43,6 +43,11 @@ 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 @@ 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 @@ 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 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 @@ 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,7 +682,18 @@ command = g_string_new (""); for (scan = arg_list; scan; scan = scan->next) { - g_string_append (command, scan->data); + 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, ' '); } @@ -622,7 +712,7 @@ } #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, @@ -755,6 +845,14 @@ 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) --- file-roller-2.15.90/src/fr-process.h +++ file-roller-2.15.90/src/fr-process.h @@ -47,7 +47,9 @@ 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 @@ 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); --- file-roller-2.15.90/src/window.c +++ file-roller-2.15.90/src/window.c @@ -5914,7 +5914,7 @@ 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);