Skip to content

Commit ebde97f

Browse files
committed
wrappers: Use a response file on Windows, if the new command line seems too long
This should properly fix the issue that was reported at #296.
1 parent 089c625 commit ebde97f

File tree

1 file changed

+31
-5
lines changed

1 file changed

+31
-5
lines changed

wrappers/native-wrapper.h

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,27 @@ static inline const TCHAR *escape(const TCHAR *str) {
8989
return out;
9090
}
9191

92+
static inline TCHAR *concat(const TCHAR *prefix, const TCHAR *suffix);
93+
94+
static TCHAR *make_response_file(const TCHAR **argv) {
95+
if (!argv[1])
96+
return NULL;
97+
TCHAR *temp_path = malloc(MAX_PATH * sizeof(*temp_path));
98+
if (GetTempPath(MAX_PATH, temp_path) == 0)
99+
return NULL;
100+
TCHAR *rsp_file = malloc(MAX_PATH * sizeof(*rsp_file));
101+
if (GetTempFileName(temp_path, _T("ctw"), 0, rsp_file) == 0)
102+
return NULL;
103+
104+
FILE *f = _tfopen(rsp_file, _T("w, ccs=UNICODE"));
105+
for (int i = 1; argv[i]; i++)
106+
_ftprintf(f, _T(TS"\n"), argv[i]);
107+
fclose(f);
108+
argv[1] = escape(concat(_T("@"), rsp_file));
109+
argv[2] = NULL;
110+
return rsp_file;
111+
}
112+
92113
static inline int _tspawnvp_escape(int mode, const TCHAR *filename, const TCHAR * const *argv) {
93114
int num_args = 0;
94115
while (argv[num_args])
@@ -100,12 +121,17 @@ static inline int _tspawnvp_escape(int mode, const TCHAR *filename, const TCHAR
100121
total += 1 + _tcslen(escaped_argv[i]);
101122
}
102123
escaped_argv[num_args] = NULL;
103-
int ret = _tspawnvp(mode, filename, escaped_argv);
104-
if (ret == -1 && total >= 32767) {
105-
int err = errno;
106-
fprintf(stderr, "command line too long; %d characters\n", total);
107-
errno = err;
124+
const TCHAR *temp_file = NULL;
125+
if (total > 32000) {
126+
// If we are getting close to the limit, write the arguments to
127+
// a temporary response file.
128+
temp_file = make_response_file(escaped_argv);
129+
if (temp_file)
130+
total = _tcslen(escaped_argv[0]) + _tcslen(escaped_argv[1]) + 2;
108131
}
132+
int ret = _tspawnvp(mode, filename, escaped_argv);
133+
if (temp_file)
134+
DeleteFile(temp_file);
109135
return ret;
110136
}
111137
#else

0 commit comments

Comments
 (0)