Program.inc revision 0b675d88309bdcbb387bbee907c4ef9d98e412a2
13c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//===- Win32/Program.cpp - Win32 Program Implementation ------- -*- C++ -*-===//
23c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//
33c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//                     The LLVM Compiler Infrastructure
43c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//
53c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// This file is distributed under the University of Illinois Open Source
63c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// License. See LICENSE.TXT for details.
73c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//
83c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//===----------------------------------------------------------------------===//
93c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//
103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// This file provides the Win32 specific implementation of the Program class.
113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//
123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//===----------------------------------------------------------------------===//
133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "Windows.h"
153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <cstdio>
163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <fcntl.h>
173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <io.h>
183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <malloc.h>
193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//===----------------------------------------------------------------------===//
213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//=== WARNING: Implementation here must contain only Win32 specific code
223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//===          and must not be UNIX code
233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//===----------------------------------------------------------------------===//
243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
253c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace {
263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  struct Win32ProcessInfo {
273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    HANDLE hProcess;
283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    DWORD  dwProcessId;
293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  };
303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
323c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace llvm {
333c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing namespace sys;
343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
353c827367444ee418f129b2c238299f49d3264554Jarkko PoyryProgram::Program() : Data_(0) {}
363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
373c827367444ee418f129b2c238299f49d3264554Jarkko PoyryProgram::~Program() {
383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (Data_) {
393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    Win32ProcessInfo* wpi = reinterpret_cast<Win32ProcessInfo*>(Data_);
403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    CloseHandle(wpi->hProcess);
413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    delete wpi;
423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    Data_ = 0;
433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  }
443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// This function just uses the PATH environment variable to find the program.
473c827367444ee418f129b2c238299f49d3264554Jarkko PoyryPath
483c827367444ee418f129b2c238299f49d3264554Jarkko PoyryProgram::FindProgramByName(const std::string& progName) {
493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  // Check some degenerate cases
513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (progName.length() == 0) // no program
523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    return Path();
533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  Path temp;
543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (!temp.set(progName)) // invalid name
553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    return Path();
563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  // Return paths with slashes verbatim.
573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (progName.find('\\') != std::string::npos ||
583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      progName.find('/') != std::string::npos)
593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    return temp;
603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  // At this point, the file name is valid and does not contain slashes.
623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  // Let Windows search for it.
633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  char buffer[MAX_PATH];
643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  char *dummy = NULL;
653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  DWORD len = SearchPath(NULL, progName.c_str(), ".exe", MAX_PATH,
663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry                         buffer, &dummy);
673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  // See if it wasn't found.
693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (len == 0)
703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    return Path();
713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  // See if we got the entire path.
733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (len < MAX_PATH)
743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    return Path(buffer);
753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  // Buffer was too small; grow and retry.
773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  while (true) {
783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    char *b = reinterpret_cast<char *>(_alloca(len+1));
793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    DWORD len2 = SearchPath(NULL, progName.c_str(), ".exe", len+1, b, &dummy);
803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    // It is unlikely the search failed, but it's always possible some file
823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    // was added or removed since the last search, so be paranoid...
833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    if (len2 == 0)
843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      return Path();
853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    else if (len2 <= len)
863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      return Path(b);
873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    len = len2;
893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  }
90c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry}
91c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
923c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic HANDLE RedirectIO(const Path *path, int fd, std::string* ErrMsg) {
93c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry  HANDLE h;
943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (path == 0) {
95c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry    DuplicateHandle(GetCurrentProcess(), (HANDLE)_get_osfhandle(fd),
96c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry                    GetCurrentProcess(), &h,
973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry                    0, TRUE, DUPLICATE_SAME_ACCESS);
98c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry    return h;
99c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry  }
100c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
101c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry  const char *fname;
1023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (path->isEmpty())
103c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry    fname = "NUL";
104c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry  else
105c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry    fname = path->c_str();
106c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
1073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  SECURITY_ATTRIBUTES sa;
108c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry  sa.nLength = sizeof(sa);
109c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry  sa.lpSecurityDescriptor = 0;
110c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry  sa.bInheritHandle = TRUE;
111c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry
112c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry  h = CreateFile(fname, fd ? GENERIC_WRITE : GENERIC_READ, FILE_SHARE_READ,
113c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry                 &sa, fd == 0 ? OPEN_EXISTING : CREATE_ALWAYS,
1143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry                 FILE_ATTRIBUTE_NORMAL, NULL);
1153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (h == INVALID_HANDLE_VALUE) {
116c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry    MakeErrMsg(ErrMsg, std::string(fname) + ": Can't open file for " +
117c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry        (fd ? "input: " : "output: "));
1183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  }
1193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  return h;
1213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
123c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry/// ArgNeedsQuotes - Check whether argument needs to be quoted when calling
124c423ce6164cdd88c8c3e47bec4ec34476743042aJarkko Pöyry/// CreateProcess.
1253c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic bool ArgNeedsQuotes(const char *Str) {
1263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  return Str[0] == '\0' || strpbrk(Str, "\t \"&\'()*<>\\`^|") != 0;
1273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/// CountPrecedingBackslashes - Returns the number of backslashes preceding Cur
1303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/// in the C string Start.
1313c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic unsigned int CountPrecedingBackslashes(const char *Start,
1323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry                                              const char *Cur) {
1333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  unsigned int Count = 0;
134  --Cur;
135  while (Cur >= Start && *Cur == '\\') {
136    ++Count;
137    --Cur;
138  }
139  return Count;
140}
141
142/// EscapePrecedingEscapes - Append a backslash to Dst for every backslash
143/// preceding Cur in the Start string.  Assumes Dst has enough space.
144static char *EscapePrecedingEscapes(char *Dst, const char *Start,
145                                    const char *Cur) {
146  unsigned PrecedingEscapes = CountPrecedingBackslashes(Start, Cur);
147  while (PrecedingEscapes > 0) {
148    *Dst++ = '\\';
149    --PrecedingEscapes;
150  }
151  return Dst;
152}
153
154/// ArgLenWithQuotes - Check whether argument needs to be quoted when calling
155/// CreateProcess and returns length of quoted arg with escaped quotes
156static unsigned int ArgLenWithQuotes(const char *Str) {
157  const char *Start = Str;
158  unsigned int len = ArgNeedsQuotes(Str) ? 2 : 0;
159
160  while (*Str != '\0') {
161    if (*Str == '\"') {
162      // We need to add a backslash, but ensure that it isn't escaped.
163      unsigned PrecedingEscapes = CountPrecedingBackslashes(Start, Str);
164      len += PrecedingEscapes + 1;
165    }
166    // Note that we *don't* need to escape runs of backslashes that don't
167    // precede a double quote!  See MSDN:
168    // http://msdn.microsoft.com/en-us/library/17w5ykft%28v=vs.85%29.aspx
169
170    ++len;
171    ++Str;
172  }
173
174  return len;
175}
176
177
178bool
179Program::Execute(const Path& path,
180                 const char** args,
181                 const char** envp,
182                 const Path** redirects,
183                 unsigned memoryLimit,
184                 std::string* ErrMsg) {
185  if (Data_) {
186    Win32ProcessInfo* wpi = reinterpret_cast<Win32ProcessInfo*>(Data_);
187    CloseHandle(wpi->hProcess);
188    delete wpi;
189    Data_ = 0;
190  }
191
192  if (!path.canExecute()) {
193    if (ErrMsg)
194      *ErrMsg = "program not executable";
195    return false;
196  }
197
198  // Windows wants a command line, not an array of args, to pass to the new
199  // process.  We have to concatenate them all, while quoting the args that
200  // have embedded spaces (or are empty).
201
202  // First, determine the length of the command line.
203  unsigned len = 0;
204  for (unsigned i = 0; args[i]; i++) {
205    len += ArgLenWithQuotes(args[i]) + 1;
206  }
207
208  // Now build the command line.
209  char *command = reinterpret_cast<char *>(_alloca(len+1));
210  char *p = command;
211
212  for (unsigned i = 0; args[i]; i++) {
213    const char *arg = args[i];
214    const char *start = arg;
215
216    bool needsQuoting = ArgNeedsQuotes(arg);
217    if (needsQuoting)
218      *p++ = '"';
219
220    while (*arg != '\0') {
221      if (*arg == '\"') {
222        // Escape all preceding escapes (if any), and then escape the quote.
223        p = EscapePrecedingEscapes(p, start, arg);
224        *p++ = '\\';
225      }
226
227      *p++ = *arg++;
228    }
229
230    if (needsQuoting) {
231      // Make sure our quote doesn't get escaped by a trailing backslash.
232      p = EscapePrecedingEscapes(p, start, arg);
233      *p++ = '"';
234    }
235    *p++ = ' ';
236  }
237
238  *p = 0;
239
240  // The pointer to the environment block for the new process.
241  char *envblock = 0;
242
243  if (envp) {
244    // An environment block consists of a null-terminated block of
245    // null-terminated strings. Convert the array of environment variables to
246    // an environment block by concatenating them.
247
248    // First, determine the length of the environment block.
249    len = 0;
250    for (unsigned i = 0; envp[i]; i++)
251      len += strlen(envp[i]) + 1;
252
253    // Now build the environment block.
254    envblock = reinterpret_cast<char *>(_alloca(len+1));
255    p = envblock;
256
257    for (unsigned i = 0; envp[i]; i++) {
258      const char *ev = envp[i];
259      size_t len = strlen(ev) + 1;
260      memcpy(p, ev, len);
261      p += len;
262    }
263
264    *p = 0;
265  }
266
267  // Create a child process.
268  STARTUPINFO si;
269  memset(&si, 0, sizeof(si));
270  si.cb = sizeof(si);
271  si.hStdInput = INVALID_HANDLE_VALUE;
272  si.hStdOutput = INVALID_HANDLE_VALUE;
273  si.hStdError = INVALID_HANDLE_VALUE;
274
275  if (redirects) {
276    si.dwFlags = STARTF_USESTDHANDLES;
277
278    si.hStdInput = RedirectIO(redirects[0], 0, ErrMsg);
279    if (si.hStdInput == INVALID_HANDLE_VALUE) {
280      MakeErrMsg(ErrMsg, "can't redirect stdin");
281      return false;
282    }
283    si.hStdOutput = RedirectIO(redirects[1], 1, ErrMsg);
284    if (si.hStdOutput == INVALID_HANDLE_VALUE) {
285      CloseHandle(si.hStdInput);
286      MakeErrMsg(ErrMsg, "can't redirect stdout");
287      return false;
288    }
289    if (redirects[1] && redirects[2] && *(redirects[1]) == *(redirects[2])) {
290      // If stdout and stderr should go to the same place, redirect stderr
291      // to the handle already open for stdout.
292      DuplicateHandle(GetCurrentProcess(), si.hStdOutput,
293                      GetCurrentProcess(), &si.hStdError,
294                      0, TRUE, DUPLICATE_SAME_ACCESS);
295    } else {
296      // Just redirect stderr
297      si.hStdError = RedirectIO(redirects[2], 2, ErrMsg);
298      if (si.hStdError == INVALID_HANDLE_VALUE) {
299        CloseHandle(si.hStdInput);
300        CloseHandle(si.hStdOutput);
301        MakeErrMsg(ErrMsg, "can't redirect stderr");
302        return false;
303      }
304    }
305  }
306
307  PROCESS_INFORMATION pi;
308  memset(&pi, 0, sizeof(pi));
309
310  fflush(stdout);
311  fflush(stderr);
312  BOOL rc = CreateProcess(path.c_str(), command, NULL, NULL, TRUE, 0,
313                          envblock, NULL, &si, &pi);
314  DWORD err = GetLastError();
315
316  // Regardless of whether the process got created or not, we are done with
317  // the handles we created for it to inherit.
318  CloseHandle(si.hStdInput);
319  CloseHandle(si.hStdOutput);
320  CloseHandle(si.hStdError);
321
322  // Now return an error if the process didn't get created.
323  if (!rc) {
324    SetLastError(err);
325    MakeErrMsg(ErrMsg, std::string("Couldn't execute program '") +
326               path.str() + "'");
327    return false;
328  }
329  Win32ProcessInfo* wpi = new Win32ProcessInfo;
330  wpi->hProcess = pi.hProcess;
331  wpi->dwProcessId = pi.dwProcessId;
332  Data_ = wpi;
333
334  // Make sure these get closed no matter what.
335  ScopedCommonHandle hThread(pi.hThread);
336
337  // Assign the process to a job if a memory limit is defined.
338  ScopedJobHandle hJob;
339  if (memoryLimit != 0) {
340    hJob = CreateJobObject(0, 0);
341    bool success = false;
342    if (hJob) {
343      JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli;
344      memset(&jeli, 0, sizeof(jeli));
345      jeli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_PROCESS_MEMORY;
346      jeli.ProcessMemoryLimit = uintptr_t(memoryLimit) * 1048576;
347      if (SetInformationJobObject(hJob, JobObjectExtendedLimitInformation,
348                                  &jeli, sizeof(jeli))) {
349        if (AssignProcessToJobObject(hJob, pi.hProcess))
350          success = true;
351      }
352    }
353    if (!success) {
354      SetLastError(GetLastError());
355      MakeErrMsg(ErrMsg, std::string("Unable to set memory limit"));
356      TerminateProcess(pi.hProcess, 1);
357      WaitForSingleObject(pi.hProcess, INFINITE);
358      return false;
359    }
360  }
361
362  return true;
363}
364
365int
366Program::Wait(const Path &path,
367              unsigned secondsToWait,
368              std::string* ErrMsg) {
369  if (Data_ == 0) {
370    MakeErrMsg(ErrMsg, "Process not started!");
371    return -1;
372  }
373
374  Win32ProcessInfo* wpi = reinterpret_cast<Win32ProcessInfo*>(Data_);
375  HANDLE hProcess = wpi->hProcess;
376
377  // Wait for the process to terminate.
378  DWORD millisecondsToWait = INFINITE;
379  if (secondsToWait > 0)
380    millisecondsToWait = secondsToWait * 1000;
381
382  if (WaitForSingleObject(hProcess, millisecondsToWait) == WAIT_TIMEOUT) {
383    if (!TerminateProcess(hProcess, 1)) {
384      MakeErrMsg(ErrMsg, "Failed to terminate timed-out program.");
385      // -2 indicates a crash or timeout as opposed to failure to execute.
386      return -2;
387    }
388    WaitForSingleObject(hProcess, INFINITE);
389  }
390
391  // Get its exit status.
392  DWORD status;
393  BOOL rc = GetExitCodeProcess(hProcess, &status);
394  DWORD err = GetLastError();
395
396  if (!rc) {
397    SetLastError(err);
398    MakeErrMsg(ErrMsg, "Failed getting status for program.");
399    // -2 indicates a crash or timeout as opposed to failure to execute.
400    return -2;
401  }
402
403  if (!status)
404    return 0;
405
406  // Pass 10(Warning) and 11(Error) to the callee as negative value.
407  if ((status & 0xBFFF0000U) == 0x80000000U)
408    return (int)status;
409
410  if (status & 0xFF)
411    return status & 0x7FFFFFFF;
412
413  return 1;
414}
415
416error_code Program::ChangeStdinToBinary(){
417  int result = _setmode( _fileno(stdin), _O_BINARY );
418  if (result == -1)
419    return error_code(errno, generic_category());
420  return make_error_code(errc::success);
421}
422
423error_code Program::ChangeStdoutToBinary(){
424  int result = _setmode( _fileno(stdout), _O_BINARY );
425  if (result == -1)
426    return error_code(errno, generic_category());
427  return make_error_code(errc::success);
428}
429
430error_code Program::ChangeStderrToBinary(){
431  int result = _setmode( _fileno(stderr), _O_BINARY );
432  if (result == -1)
433    return error_code(errno, generic_category());
434  return make_error_code(errc::success);
435}
436
437bool llvm::sys::argumentsFitWithinSystemLimits(ArrayRef<const char*> Args) {
438  // The documented max length of the command line passed to CreateProcess.
439  static const size_t MaxCommandStringLength = 32768;
440  size_t ArgLength = 0;
441  for (ArrayRef<const char*>::iterator I = Args.begin(), E = Args.end();
442       I != E; ++I) {
443    // Account for the trailing space for every arg but the last one and the
444    // trailing NULL of the last argument.
445    ArgLength += ArgLenWithQuotes(*I) + 1;
446    if (ArgLength > MaxCommandStringLength) {
447      return false;
448    }
449  }
450  return true;
451}
452
453}
454