|
@@ -15,6 +15,8 @@ |
|
|
|
|
|
#include "script.h"
|
|
|
|
|
|
#include <algorithm>
|
|
|
#include <climits>
|
|
|
#include <memory>
|
|
|
#include <ranges>
|
|
|
#include <glib/gstdio.h>
|
|
@@ -64,6 +66,7 @@ |
|
|
#include <windows.h>
|
|
|
#define KILL_PROCESS(pid) TerminateProcess(pid, 0)
|
|
|
#else
|
|
|
#include <unistd.h>
|
|
|
#define KILL_PROCESS(pid) kill(pid, SIGTERM)
|
|
|
#endif
|
|
|
|
|
@@ -602,6 +605,29 @@ void Script::effect(Inkscape::Extension::Effect *mod, ExecutionEnv *executionEnv |
|
|
_change_extension(mod, executionEnv, document, params, mod->ignore_stderr);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* Conservative budget for the maximum command-line size
|
|
|
* Used to decide when to spill arguments to a file (see _change_extension).
|
|
|
*/
|
|
|
static size_t get_cmdline_budget()
|
|
|
{
|
|
|
#ifdef _WIN32
|
|
|
// Windows: Length limit is fixed at 32737
|
|
|
// Leave 4096 of overhead for executable and files
|
|
|
return 28701; // 32737-4096
|
|
|
#else
|
|
|
// Unix: Length limit is from sysconf
|
|
|
// Leave 32K of overhead for executable, files, and environment
|
|
|
// Also guard against sysconf failure (-1)
|
|
|
long const arg_max = sysconf(_SC_ARG_MAX);
|
|
|
size_t usable = 0;
|
|
|
if (arg_max > 32768) {
|
|
|
usable = static_cast<size_t>(arg_max) - 32768;
|
|
|
}
|
|
|
return std::max(size_t{_POSIX_ARG_MAX}, usable);
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* Internally, any modification of an existing document, used by effect and resize_page extensions.
|
|
|
*/
|
|
@@ -627,6 +653,28 @@ void Script::_change_extension(Inkscape::Extension::Extension *module, Execution |
|
|
Inkscape::Extension::FILE_SAVE_METHOD_TEMPORARY);
|
|
|
prefs->setBool("/options/svgoutput/disable_optimizations", false);
|
|
|
|
|
|
// Workaround for command-line length limits
|
|
|
// With thousands of arguments the accumulated command line overflows
|
|
|
// Spill into a temp file and replace with a single --arg-file=<path>.
|
|
|
auto tempfile_sel = Inkscape::IO::TempFilename("ink_sel_XXXXXX.txt");
|
|
|
size_t cmdline_size = 0;
|
|
|
for (auto const &p : params) {
|
|
|
cmdline_size += p.size() + 1;
|
|
|
}
|
|
|
if (cmdline_size > get_cmdline_budget()) {
|
|
|
try {
|
|
|
auto sel_channel = Glib::IOChannel::create_from_file(tempfile_sel.get_filename(), "w");
|
|
|
sel_channel->set_encoding("UTF-8");
|
|
|
for (auto const &p : params) {
|
|
|
sel_channel->write(p + "\n");
|
|
|
}
|
|
|
sel_channel->close();
|
|
|
params = {"--arg-file=" + tempfile_sel.get_filename()};
|
|
|
} catch (Glib::Error const &e) {
|
|
|
g_warning("Script::_change_extension(): failed to spill args: %s", e.what());
|
|
|
}
|
|
|
}
|
|
|
|
|
|
file_listener fileout;
|
|
|
int data_read = execute(command, params, tempfile_in.get_filename(), fileout, ignore_stderr, pipe_diffs);
|
|
|
if (data_read == 0) {
|
|
|