about summary refs log tree commit diff
path: root/third_party/git/compat/mingw.c
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/git/compat/mingw.c')
-rw-r--r--third_party/git/compat/mingw.c409
1 files changed, 51 insertions, 358 deletions
diff --git a/third_party/git/compat/mingw.c b/third_party/git/compat/mingw.c
index d14065d60ec4..738f0a826a51 100644
--- a/third_party/git/compat/mingw.c
+++ b/third_party/git/compat/mingw.c
@@ -13,19 +13,6 @@
 
 static const int delay[] = { 0, 1, 10, 20, 40 };
 
-void open_in_gdb(void)
-{
-	static struct child_process cp = CHILD_PROCESS_INIT;
-	extern char *_pgmptr;
-
-	argv_array_pushl(&cp.args, "mintty", "gdb", NULL);
-	argv_array_pushf(&cp.args, "--pid=%d", getpid());
-	cp.clean_on_exit = 1;
-	if (start_command(&cp) < 0)
-		die_errno("Could not start gdb");
-	sleep(1);
-}
-
 int err_win_to_posix(DWORD winerr)
 {
 	int error = ENOSYS;
@@ -127,7 +114,6 @@ int err_win_to_posix(DWORD winerr)
 	case ERROR_SHARING_BUFFER_EXCEEDED: error = ENFILE; break;
 	case ERROR_SHARING_VIOLATION: error = EACCES; break;
 	case ERROR_STACK_OVERFLOW: error = ENOMEM; break;
-	case ERROR_SUCCESS: BUG("err_win_to_posix() called without an error!");
 	case ERROR_SWAPERROR: error = ENOENT; break;
 	case ERROR_TOO_MANY_MODULES: error = EMFILE; break;
 	case ERROR_TOO_MANY_OPEN_FILES: error = EMFILE; break;
@@ -226,7 +212,6 @@ enum hide_dotfiles_type {
 	HIDE_DOTFILES_DOTGITONLY
 };
 
-static int core_restrict_inherited_handles = -1;
 static enum hide_dotfiles_type hide_dotfiles = HIDE_DOTFILES_DOTGITONLY;
 static char *unset_environment_variables;
 
@@ -246,15 +231,6 @@ int mingw_core_config(const char *var, const char *value, void *cb)
 		return 0;
 	}
 
-	if (!strcmp(var, "core.restrictinheritedhandles")) {
-		if (value && !strcasecmp(value, "auto"))
-			core_restrict_inherited_handles = -1;
-		else
-			core_restrict_inherited_handles =
-				git_config_bool(var, value);
-		return 0;
-	}
-
 	return 0;
 }
 
@@ -387,8 +363,6 @@ static inline int needs_hiding(const char *path)
 			/* ignore trailing slashes */
 			if (*path)
 				basename = path;
-			else
-				break;
 		}
 
 	if (hide_dotfiles == HIDE_DOTFILES_TRUE)
@@ -416,12 +390,6 @@ int mingw_mkdir(const char *path, int mode)
 {
 	int ret;
 	wchar_t wpath[MAX_PATH];
-
-	if (!is_valid_win32_path(path, 0)) {
-		errno = EINVAL;
-		return -1;
-	}
-
 	if (xutftowcs_path(wpath, path) < 0)
 		return -1;
 	ret = _wmkdir(wpath);
@@ -495,7 +463,7 @@ int mingw_open (const char *filename, int oflags, ...)
 	typedef int (*open_fn_t)(wchar_t const *wfilename, int oflags, ...);
 	va_list args;
 	unsigned mode;
-	int fd, create = (oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL);
+	int fd;
 	wchar_t wfilename[MAX_PATH];
 	open_fn_t open_fn;
 
@@ -503,21 +471,16 @@ int mingw_open (const char *filename, int oflags, ...)
 	mode = va_arg(args, int);
 	va_end(args);
 
-	if (!is_valid_win32_path(filename, !create)) {
-		errno = create ? EINVAL : ENOENT;
-		return -1;
-	}
+	if (filename && !strcmp(filename, "/dev/null"))
+		filename = "nul";
 
 	if ((oflags & O_APPEND) && !is_local_named_pipe_path(filename))
 		open_fn = mingw_open_append;
 	else
 		open_fn = _wopen;
 
-	if (filename && !strcmp(filename, "/dev/null"))
-		wcscpy(wfilename, L"nul");
-	else if (xutftowcs_path(wfilename, filename) < 0)
+	if (xutftowcs_path(wfilename, filename) < 0)
 		return -1;
-
 	fd = open_fn(wfilename, oflags, mode);
 
 	if (fd < 0 && (oflags & O_ACCMODE) != O_RDONLY && errno == EACCES) {
@@ -575,17 +538,10 @@ FILE *mingw_fopen (const char *filename, const char *otype)
 	FILE *file;
 	wchar_t wfilename[MAX_PATH], wotype[4];
 	if (filename && !strcmp(filename, "/dev/null"))
-		wcscpy(wfilename, L"nul");
-	else if (!is_valid_win32_path(filename, 1)) {
-		int create = otype && strchr(otype, 'w');
-		errno = create ? EINVAL : ENOENT;
-		return NULL;
-	} else if (xutftowcs_path(wfilename, filename) < 0)
-		return NULL;
-
-	if (xutftowcs(wotype, otype, ARRAY_SIZE(wotype)) < 0)
+		filename = "nul";
+	if (xutftowcs_path(wfilename, filename) < 0 ||
+		xutftowcs(wotype, otype, ARRAY_SIZE(wotype)) < 0)
 		return NULL;
-
 	if (hide && !access(filename, F_OK) && set_hidden_flag(wfilename, 0)) {
 		error("could not unhide %s", filename);
 		return NULL;
@@ -604,17 +560,10 @@ FILE *mingw_freopen (const char *filename, const char *otype, FILE *stream)
 	FILE *file;
 	wchar_t wfilename[MAX_PATH], wotype[4];
 	if (filename && !strcmp(filename, "/dev/null"))
-		wcscpy(wfilename, L"nul");
-	else if (!is_valid_win32_path(filename, 1)) {
-		int create = otype && strchr(otype, 'w');
-		errno = create ? EINVAL : ENOENT;
-		return NULL;
-	} else if (xutftowcs_path(wfilename, filename) < 0)
-		return NULL;
-
-	if (xutftowcs(wotype, otype, ARRAY_SIZE(wotype)) < 0)
+		filename = "nul";
+	if (xutftowcs_path(wfilename, filename) < 0 ||
+		xutftowcs(wotype, otype, ARRAY_SIZE(wotype)) < 0)
 		return NULL;
-
 	if (hide && !access(filename, F_OK) && set_hidden_flag(wfilename, 0)) {
 		error("could not unhide %s", filename);
 		return NULL;
@@ -1035,16 +984,16 @@ int pipe(int filedes[2])
 
 struct tm *gmtime_r(const time_t *timep, struct tm *result)
 {
-	if (gmtime_s(result, timep) == 0)
-		return result;
-	return NULL;
+	/* gmtime() in MSVCRT.DLL is thread-safe, but not reentrant */
+	memcpy(result, gmtime(timep), sizeof(struct tm));
+	return result;
 }
 
 struct tm *localtime_r(const time_t *timep, struct tm *result)
 {
-	if (localtime_s(result, timep) == 0)
-		return result;
-	return NULL;
+	/* localtime() in MSVCRT.DLL is thread-safe, but not reentrant */
+	memcpy(result, localtime(timep), sizeof(struct tm));
+	return result;
 }
 
 char *mingw_getcwd(char *pointer, int len)
@@ -1103,7 +1052,7 @@ static const char *quote_arg_msvc(const char *arg)
 				p++;
 				len++;
 			}
-			if (*p == '"' || !*p)
+			if (*p == '"')
 				n += count*2 + 1;
 			continue;
 		}
@@ -1125,19 +1074,16 @@ static const char *quote_arg_msvc(const char *arg)
 				count++;
 				*d++ = *arg++;
 			}
-			if (*arg == '"' || !*arg) {
+			if (*arg == '"') {
 				while (count-- > 0)
 					*d++ = '\\';
-				/* don't escape the surrounding end quote */
-				if (!*arg)
-					break;
 				*d++ = '\\';
 			}
 		}
 		*d++ = *arg++;
 	}
 	*d++ = '"';
-	*d++ = '\0';
+	*d++ = 0;
 	return q;
 }
 
@@ -1150,14 +1096,13 @@ static const char *quote_arg_msys2(const char *arg)
 
 	for (p = arg; *p; p++) {
 		int ws = isspace(*p);
-		if (!ws && *p != '\\' && *p != '"' && *p != '{' && *p != '\'' &&
-		    *p != '?' && *p != '*' && *p != '~')
+		if (!ws && *p != '\\' && *p != '"' && *p != '{')
 			continue;
 		if (!buf.len)
 			strbuf_addch(&buf, '"');
 		if (p != p2)
 			strbuf_add(&buf, p2, p - p2);
-		if (*p == '\\' || *p == '"')
+		if (!ws && *p != '{')
 			strbuf_addch(&buf, '\\');
 		p2 = p;
 	}
@@ -1167,7 +1112,7 @@ static const char *quote_arg_msys2(const char *arg)
 	else if (!buf.len)
 		return arg;
 	else
-		strbuf_add(&buf, p2, p - p2);
+		strbuf_add(&buf, p2, p - p2),
 
 	strbuf_addch(&buf, '"');
 	return strbuf_detach(&buf, 0);
@@ -1216,21 +1161,14 @@ static char *lookup_prog(const char *dir, int dirlen, const char *cmd,
 			 int isexe, int exe_only)
 {
 	char path[MAX_PATH];
-	wchar_t wpath[MAX_PATH];
 	snprintf(path, sizeof(path), "%.*s\\%s.exe", dirlen, dir, cmd);
 
-	if (xutftowcs_path(wpath, path) < 0)
-		return NULL;
-
-	if (!isexe && _waccess(wpath, F_OK) == 0)
+	if (!isexe && access(path, F_OK) == 0)
 		return xstrdup(path);
-	wpath[wcslen(wpath)-4] = '\0';
-	if ((!exe_only || isexe) && _waccess(wpath, F_OK) == 0) {
-		if (!(GetFileAttributesW(wpath) & FILE_ATTRIBUTE_DIRECTORY)) {
-			path[strlen(path)-4] = '\0';
+	path[strlen(path)-4] = '\0';
+	if ((!exe_only || isexe) && access(path, F_OK) == 0)
+		if (!(GetFileAttributes(path) & FILE_ATTRIBUTE_DIRECTORY))
 			return xstrdup(path);
-		}
-	}
 	return NULL;
 }
 
@@ -1245,7 +1183,7 @@ static char *path_lookup(const char *cmd, int exe_only)
 	int len = strlen(cmd);
 	int isexe = len >= 4 && !strcasecmp(cmd+len-4, ".exe");
 
-	if (strpbrk(cmd, "/\\"))
+	if (strchr(cmd, '/') || strchr(cmd, '\\'))
 		return xstrdup(cmd);
 
 	path = mingw_getenv("PATH");
@@ -1291,6 +1229,11 @@ static int wenvcmp(const void *a, const void *b)
 	return _wcsnicmp(p, q, p_len);
 }
 
+/* We need a stable sort to convert the environment between UTF-16 <-> UTF-8 */
+#ifndef INTERNAL_QSORT
+#include "qsort.c"
+#endif
+
 /*
  * Build an environment block combining the inherited environment
  * merged with the given list of settings.
@@ -1322,15 +1265,15 @@ static wchar_t *make_environment_block(char **deltaenv)
 		}
 
 		ALLOC_ARRAY(result, size);
-		COPY_ARRAY(result, wenv, size);
+		memcpy(result, wenv, size * sizeof(*wenv));
 		FreeEnvironmentStringsW(wenv);
 		return result;
 	}
 
 	/*
 	 * If there is a deltaenv, let's accumulate all keys into `array`,
-	 * sort them using the stable git_stable_qsort() and then copy,
-	 * skipping duplicate keys
+	 * sort them using the stable git_qsort() and then copy, skipping
+	 * duplicate keys
 	 */
 	for (p = wenv; p && *p; ) {
 		ALLOC_GROW(array, nr + 1, alloc);
@@ -1353,7 +1296,7 @@ static wchar_t *make_environment_block(char **deltaenv)
 		p += wlen + 1;
 	}
 
-	git_stable_qsort(array, nr, sizeof(*array), wenvcmp);
+	git_qsort(array, nr, sizeof(*array), wenvcmp);
 	ALLOC_ARRAY(result, size + delta_size);
 
 	for (p = result, i = 0; i < nr; i++) {
@@ -1366,7 +1309,7 @@ static wchar_t *make_environment_block(char **deltaenv)
 			continue;
 
 		size = wcslen(array[i]) + 1;
-		COPY_ARRAY(p, array[i], size);
+		memcpy(p, array[i], size * sizeof(*p));
 		p += size;
 	}
 	*p = L'\0';
@@ -1424,10 +1367,7 @@ static inline int match_last_path_component(const char *path, size_t *len,
 
 static int is_msys2_sh(const char *cmd)
 {
-	if (!cmd)
-		return 0;
-
-	if (!strcmp(cmd, "sh")) {
+	if (cmd && !strcmp(cmd, "sh")) {
 		static int ret = -1;
 		char *p;
 
@@ -1447,16 +1387,6 @@ static int is_msys2_sh(const char *cmd)
 		}
 		return ret;
 	}
-
-	if (ends_with(cmd, "\\sh.exe")) {
-		static char *sh;
-
-		if (!sh)
-			sh = path_lookup("sh", 0);
-
-		return !fspathcmp(cmd, sh);
-	}
-
 	return 0;
 }
 
@@ -1464,34 +1394,15 @@ static pid_t mingw_spawnve_fd(const char *cmd, const char **argv, char **deltaen
 			      const char *dir,
 			      int prepend_cmd, int fhin, int fhout, int fherr)
 {
-	static int restrict_handle_inheritance = -1;
-	STARTUPINFOEXW si;
+	STARTUPINFOW si;
 	PROCESS_INFORMATION pi;
-	LPPROC_THREAD_ATTRIBUTE_LIST attr_list = NULL;
-	HANDLE stdhandles[3];
-	DWORD stdhandles_count = 0;
-	SIZE_T size;
 	struct strbuf args;
 	wchar_t wcmd[MAX_PATH], wdir[MAX_PATH], *wargs, *wenvblk = NULL;
 	unsigned flags = CREATE_UNICODE_ENVIRONMENT;
 	BOOL ret;
 	HANDLE cons;
 	const char *(*quote_arg)(const char *arg) =
-		is_msys2_sh(cmd ? cmd : *argv) ?
-		quote_arg_msys2 : quote_arg_msvc;
-
-	/* Make sure to override previous errors, if any */
-	errno = 0;
-
-	if (restrict_handle_inheritance < 0)
-		restrict_handle_inheritance = core_restrict_inherited_handles;
-	/*
-	 * The following code to restrict which handles are inherited seems
-	 * to work properly only on Windows 7 and later, so let's disable it
-	 * on Windows Vista and 2008.
-	 */
-	if (restrict_handle_inheritance < 0)
-		restrict_handle_inheritance = GetVersion() >> 16 >= 7601;
+		is_msys2_sh(*argv) ? quote_arg_msys2 : quote_arg_msvc;
 
 	do_unset_environment_variables();
 
@@ -1520,23 +1431,11 @@ static pid_t mingw_spawnve_fd(const char *cmd, const char **argv, char **deltaen
 		CloseHandle(cons);
 	}
 	memset(&si, 0, sizeof(si));
-	si.StartupInfo.cb = sizeof(si);
-	si.StartupInfo.hStdInput = winansi_get_osfhandle(fhin);
-	si.StartupInfo.hStdOutput = winansi_get_osfhandle(fhout);
-	si.StartupInfo.hStdError = winansi_get_osfhandle(fherr);
-
-	/* The list of handles cannot contain duplicates */
-	if (si.StartupInfo.hStdInput != INVALID_HANDLE_VALUE)
-		stdhandles[stdhandles_count++] = si.StartupInfo.hStdInput;
-	if (si.StartupInfo.hStdOutput != INVALID_HANDLE_VALUE &&
-	    si.StartupInfo.hStdOutput != si.StartupInfo.hStdInput)
-		stdhandles[stdhandles_count++] = si.StartupInfo.hStdOutput;
-	if (si.StartupInfo.hStdError != INVALID_HANDLE_VALUE &&
-	    si.StartupInfo.hStdError != si.StartupInfo.hStdInput &&
-	    si.StartupInfo.hStdError != si.StartupInfo.hStdOutput)
-		stdhandles[stdhandles_count++] = si.StartupInfo.hStdError;
-	if (stdhandles_count)
-		si.StartupInfo.dwFlags |= STARTF_USESTDHANDLES;
+	si.cb = sizeof(si);
+	si.dwFlags = STARTF_USESTDHANDLES;
+	si.hStdInput = winansi_get_osfhandle(fhin);
+	si.hStdOutput = winansi_get_osfhandle(fhout);
+	si.hStdError = winansi_get_osfhandle(fherr);
 
 	if (*argv && !strcmp(cmd, *argv))
 		wcmd[0] = L'\0';
@@ -1569,98 +1468,16 @@ static pid_t mingw_spawnve_fd(const char *cmd, const char **argv, char **deltaen
 	wenvblk = make_environment_block(deltaenv);
 
 	memset(&pi, 0, sizeof(pi));
-	if (restrict_handle_inheritance && stdhandles_count &&
-	    (InitializeProcThreadAttributeList(NULL, 1, 0, &size) ||
-	     GetLastError() == ERROR_INSUFFICIENT_BUFFER) &&
-	    (attr_list = (LPPROC_THREAD_ATTRIBUTE_LIST)
-			(HeapAlloc(GetProcessHeap(), 0, size))) &&
-	    InitializeProcThreadAttributeList(attr_list, 1, 0, &size) &&
-	    UpdateProcThreadAttribute(attr_list, 0,
-				      PROC_THREAD_ATTRIBUTE_HANDLE_LIST,
-				      stdhandles,
-				      stdhandles_count * sizeof(HANDLE),
-				      NULL, NULL)) {
-		si.lpAttributeList = attr_list;
-		flags |= EXTENDED_STARTUPINFO_PRESENT;
-	}
-
-	ret = CreateProcessW(*wcmd ? wcmd : NULL, wargs, NULL, NULL,
-			     stdhandles_count ? TRUE : FALSE,
-			     flags, wenvblk, dir ? wdir : NULL,
-			     &si.StartupInfo, &pi);
-
-	/*
-	 * On Windows 2008 R2, it seems that specifying certain types of handles
-	 * (such as FILE_TYPE_CHAR or FILE_TYPE_PIPE) will always produce an
-	 * error. Rather than playing finicky and fragile games, let's just try
-	 * to detect this situation and simply try again without restricting any
-	 * handle inheritance. This is still better than failing to create
-	 * processes.
-	 */
-	if (!ret && restrict_handle_inheritance && stdhandles_count) {
-		DWORD err = GetLastError();
-		struct strbuf buf = STRBUF_INIT;
-
-		if (err != ERROR_NO_SYSTEM_RESOURCES &&
-		    /*
-		     * On Windows 7 and earlier, handles on pipes and character
-		     * devices are inherited automatically, and cannot be
-		     * specified in the thread handle list. Rather than trying
-		     * to catch each and every corner case (and running the
-		     * chance of *still* forgetting a few), let's just fall
-		     * back to creating the process without trying to limit the
-		     * handle inheritance.
-		     */
-		    !(err == ERROR_INVALID_PARAMETER &&
-		      GetVersion() >> 16 < 9200) &&
-		    !getenv("SUPPRESS_HANDLE_INHERITANCE_WARNING")) {
-			DWORD fl = 0;
-			int i;
-
-			setenv("SUPPRESS_HANDLE_INHERITANCE_WARNING", "1", 1);
-
-			for (i = 0; i < stdhandles_count; i++) {
-				HANDLE h = stdhandles[i];
-				strbuf_addf(&buf, "handle #%d: %p (type %lx, "
-					    "handle info (%d) %lx\n", i, h,
-					    GetFileType(h),
-					    GetHandleInformation(h, &fl),
-					    fl);
-			}
-			strbuf_addstr(&buf, "\nThis is a bug; please report it "
-				      "at\nhttps://github.com/git-for-windows/"
-				      "git/issues/new\n\n"
-				      "To suppress this warning, please set "
-				      "the environment variable\n\n"
-				      "\tSUPPRESS_HANDLE_INHERITANCE_WARNING=1"
-				      "\n");
-		}
-		restrict_handle_inheritance = 0;
-		flags &= ~EXTENDED_STARTUPINFO_PRESENT;
-		ret = CreateProcessW(*wcmd ? wcmd : NULL, wargs, NULL, NULL,
-				     TRUE, flags, wenvblk, dir ? wdir : NULL,
-				     &si.StartupInfo, &pi);
-		if (!ret)
-			errno = err_win_to_posix(GetLastError());
-		if (ret && buf.len) {
-			warning("failed to restrict file handles (%ld)\n\n%s",
-				err, buf.buf);
-		}
-		strbuf_release(&buf);
-	} else if (!ret)
-		errno = err_win_to_posix(GetLastError());
-
-	if (si.lpAttributeList)
-		DeleteProcThreadAttributeList(si.lpAttributeList);
-	if (attr_list)
-		HeapFree(GetProcessHeap(), 0, attr_list);
+	ret = CreateProcessW(*wcmd ? wcmd : NULL, wargs, NULL, NULL, TRUE,
+		flags, wenvblk, dir ? wdir : NULL, &si, &pi);
 
 	free(wenvblk);
 	free(wargs);
 
-	if (!ret)
+	if (!ret) {
+		errno = ENOENT;
 		return -1;
-
+	}
 	CloseHandle(pi.hThread);
 
 	/*
@@ -1745,7 +1562,7 @@ static int try_shell_exec(const char *cmd, char *const *argv)
 		while (argv[argc]) argc++;
 		ALLOC_ARRAY(argv2, argc + 1);
 		argv2[0] = (char *)cmd;	/* full path to the script file */
-		COPY_ARRAY(&argv2[1], &argv[1], argc);
+		memcpy(&argv2[1], &argv[1], sizeof(*argv) * argc);
 		exec_id = trace2_exec(prog, argv2);
 		pid = mingw_spawnv(prog, argv2, 1);
 		if (pid >= 0) {
@@ -1846,8 +1663,6 @@ char *mingw_getenv(const char *name)
 	if (!w_key)
 		die("Out of memory, (tried to allocate %u wchar_t's)", len_key);
 	xutftowcs(w_key, name, len_key);
-	/* GetEnvironmentVariableW() only sets the last error upon failure */
-	SetLastError(ERROR_SUCCESS);
 	len_value = GetEnvironmentVariableW(w_key, w_value, ARRAY_SIZE(w_value));
 	if (!len_value && GetLastError() == ERROR_ENVVAR_NOT_FOUND) {
 		free(w_key);
@@ -2546,128 +2361,6 @@ static void setup_windows_environment(void)
 	}
 }
 
-int is_valid_win32_path(const char *path, int allow_literal_nul)
-{
-	const char *p = path;
-	int preceding_space_or_period = 0, i = 0, periods = 0;
-
-	if (!protect_ntfs)
-		return 1;
-
-	skip_dos_drive_prefix((char **)&path);
-	goto segment_start;
-
-	for (;;) {
-		char c = *(path++);
-		switch (c) {
-		case '\0':
-		case '/': case '\\':
-			/* cannot end in ` ` or `.`, except for `.` and `..` */
-			if (preceding_space_or_period &&
-			    (i != periods || periods > 2))
-				return 0;
-			if (!c)
-				return 1;
-
-			i = periods = preceding_space_or_period = 0;
-
-segment_start:
-			switch (*path) {
-			case 'a': case 'A': /* AUX */
-				if (((c = path[++i]) != 'u' && c != 'U') ||
-				    ((c = path[++i]) != 'x' && c != 'X')) {
-not_a_reserved_name:
-					path += i;
-					continue;
-				}
-				break;
-			case 'c': case 'C': /* COM<N>, CON, CONIN$, CONOUT$ */
-				if ((c = path[++i]) != 'o' && c != 'O')
-					goto not_a_reserved_name;
-				c = path[++i];
-				if (c == 'm' || c == 'M') { /* COM<N> */
-					if (!isdigit(path[++i]))
-						goto not_a_reserved_name;
-				} else if (c == 'n' || c == 'N') { /* CON */
-					c = path[i + 1];
-					if ((c == 'i' || c == 'I') &&
-					    ((c = path[i + 2]) == 'n' ||
-					     c == 'N') &&
-					    path[i + 3] == '$')
-						i += 3; /* CONIN$ */
-					else if ((c == 'o' || c == 'O') &&
-						 ((c = path[i + 2]) == 'u' ||
-						  c == 'U') &&
-						 ((c = path[i + 3]) == 't' ||
-						  c == 'T') &&
-						 path[i + 4] == '$')
-						i += 4; /* CONOUT$ */
-				} else
-					goto not_a_reserved_name;
-				break;
-			case 'l': case 'L': /* LPT<N> */
-				if (((c = path[++i]) != 'p' && c != 'P') ||
-				    ((c = path[++i]) != 't' && c != 'T') ||
-				    !isdigit(path[++i]))
-					goto not_a_reserved_name;
-				break;
-			case 'n': case 'N': /* NUL */
-				if (((c = path[++i]) != 'u' && c != 'U') ||
-				    ((c = path[++i]) != 'l' && c != 'L') ||
-				    (allow_literal_nul &&
-				     !path[i + 1] && p == path))
-					goto not_a_reserved_name;
-				break;
-			case 'p': case 'P': /* PRN */
-				if (((c = path[++i]) != 'r' && c != 'R') ||
-				    ((c = path[++i]) != 'n' && c != 'N'))
-					goto not_a_reserved_name;
-				break;
-			default:
-				continue;
-			}
-
-			/*
-			 * So far, this looks like a reserved name. Let's see
-			 * whether it actually is one: trailing spaces, a file
-			 * extension, or an NTFS Alternate Data Stream do not
-			 * matter, the name is still reserved if any of those
-			 * follow immediately after the actual name.
-			 */
-			i++;
-			if (path[i] == ' ') {
-				preceding_space_or_period = 1;
-				while (path[++i] == ' ')
-					; /* skip all spaces */
-			}
-
-			c = path[i];
-			if (c && c != '.' && c != ':' && c != '/' && c != '\\')
-				goto not_a_reserved_name;
-
-			/* contains reserved name */
-			return 0;
-		case '.':
-			periods++;
-			/* fallthru */
-		case ' ':
-			preceding_space_or_period = 1;
-			i++;
-			continue;
-		case ':': /* DOS drive prefix was already skipped */
-		case '<': case '>': case '"': case '|': case '?': case '*':
-			/* illegal character */
-			return 0;
-		default:
-			if (c > '\0' && c < '\x20')
-				/* illegal character */
-				return 0;
-		}
-		preceding_space_or_period = 0;
-		i++;
-	}
-}
-
 #if !defined(_MSC_VER)
 /*
  * Disable MSVCRT command line wildcard expansion (__getmainargs called from