1 #include "../git-compat-util.h"
2 #include "win32.h"
3 #include <conio.h>
4 #include <wchar.h>
5 #include "../strbuf.h"
6 #include "../run-command.h"
7 #include "../cache.h"
8 #include "win32/lazyload.h"
9 #include "../config.h"
10 #include "dir.h"
11 
12 #define HCAST(type, handle) ((type)(intptr_t)handle)
13 
14 static const int delay[] = { 0, 1, 10, 20, 40 };
15 
err_win_to_posix(DWORD winerr)16 int err_win_to_posix(DWORD winerr)
17 {
18 	int error = ENOSYS;
19 	switch(winerr) {
20 	case ERROR_ACCESS_DENIED: error = EACCES; break;
21 	case ERROR_ACCOUNT_DISABLED: error = EACCES; break;
22 	case ERROR_ACCOUNT_RESTRICTION: error = EACCES; break;
23 	case ERROR_ALREADY_ASSIGNED: error = EBUSY; break;
24 	case ERROR_ALREADY_EXISTS: error = EEXIST; break;
25 	case ERROR_ARITHMETIC_OVERFLOW: error = ERANGE; break;
26 	case ERROR_BAD_COMMAND: error = EIO; break;
27 	case ERROR_BAD_DEVICE: error = ENODEV; break;
28 	case ERROR_BAD_DRIVER_LEVEL: error = ENXIO; break;
29 	case ERROR_BAD_EXE_FORMAT: error = ENOEXEC; break;
30 	case ERROR_BAD_FORMAT: error = ENOEXEC; break;
31 	case ERROR_BAD_LENGTH: error = EINVAL; break;
32 	case ERROR_BAD_PATHNAME: error = ENOENT; break;
33 	case ERROR_BAD_PIPE: error = EPIPE; break;
34 	case ERROR_BAD_UNIT: error = ENODEV; break;
35 	case ERROR_BAD_USERNAME: error = EINVAL; break;
36 	case ERROR_BROKEN_PIPE: error = EPIPE; break;
37 	case ERROR_BUFFER_OVERFLOW: error = ENAMETOOLONG; break;
38 	case ERROR_BUSY: error = EBUSY; break;
39 	case ERROR_BUSY_DRIVE: error = EBUSY; break;
40 	case ERROR_CALL_NOT_IMPLEMENTED: error = ENOSYS; break;
41 	case ERROR_CANNOT_MAKE: error = EACCES; break;
42 	case ERROR_CANTOPEN: error = EIO; break;
43 	case ERROR_CANTREAD: error = EIO; break;
44 	case ERROR_CANTWRITE: error = EIO; break;
45 	case ERROR_CRC: error = EIO; break;
46 	case ERROR_CURRENT_DIRECTORY: error = EACCES; break;
47 	case ERROR_DEVICE_IN_USE: error = EBUSY; break;
48 	case ERROR_DEV_NOT_EXIST: error = ENODEV; break;
49 	case ERROR_DIRECTORY: error = EINVAL; break;
50 	case ERROR_DIR_NOT_EMPTY: error = ENOTEMPTY; break;
51 	case ERROR_DISK_CHANGE: error = EIO; break;
52 	case ERROR_DISK_FULL: error = ENOSPC; break;
53 	case ERROR_DRIVE_LOCKED: error = EBUSY; break;
54 	case ERROR_ENVVAR_NOT_FOUND: error = EINVAL; break;
55 	case ERROR_EXE_MARKED_INVALID: error = ENOEXEC; break;
56 	case ERROR_FILENAME_EXCED_RANGE: error = ENAMETOOLONG; break;
57 	case ERROR_FILE_EXISTS: error = EEXIST; break;
58 	case ERROR_FILE_INVALID: error = ENODEV; break;
59 	case ERROR_FILE_NOT_FOUND: error = ENOENT; break;
60 	case ERROR_GEN_FAILURE: error = EIO; break;
61 	case ERROR_HANDLE_DISK_FULL: error = ENOSPC; break;
62 	case ERROR_INSUFFICIENT_BUFFER: error = ENOMEM; break;
63 	case ERROR_INVALID_ACCESS: error = EACCES; break;
64 	case ERROR_INVALID_ADDRESS: error = EFAULT; break;
65 	case ERROR_INVALID_BLOCK: error = EFAULT; break;
66 	case ERROR_INVALID_DATA: error = EINVAL; break;
67 	case ERROR_INVALID_DRIVE: error = ENODEV; break;
68 	case ERROR_INVALID_EXE_SIGNATURE: error = ENOEXEC; break;
69 	case ERROR_INVALID_FLAGS: error = EINVAL; break;
70 	case ERROR_INVALID_FUNCTION: error = ENOSYS; break;
71 	case ERROR_INVALID_HANDLE: error = EBADF; break;
72 	case ERROR_INVALID_LOGON_HOURS: error = EACCES; break;
73 	case ERROR_INVALID_NAME: error = EINVAL; break;
74 	case ERROR_INVALID_OWNER: error = EINVAL; break;
75 	case ERROR_INVALID_PARAMETER: error = EINVAL; break;
76 	case ERROR_INVALID_PASSWORD: error = EPERM; break;
77 	case ERROR_INVALID_PRIMARY_GROUP: error = EINVAL; break;
78 	case ERROR_INVALID_SIGNAL_NUMBER: error = EINVAL; break;
79 	case ERROR_INVALID_TARGET_HANDLE: error = EIO; break;
80 	case ERROR_INVALID_WORKSTATION: error = EACCES; break;
81 	case ERROR_IO_DEVICE: error = EIO; break;
82 	case ERROR_IO_INCOMPLETE: error = EINTR; break;
83 	case ERROR_LOCKED: error = EBUSY; break;
84 	case ERROR_LOCK_VIOLATION: error = EACCES; break;
85 	case ERROR_LOGON_FAILURE: error = EACCES; break;
86 	case ERROR_MAPPED_ALIGNMENT: error = EINVAL; break;
87 	case ERROR_META_EXPANSION_TOO_LONG: error = E2BIG; break;
88 	case ERROR_MORE_DATA: error = EPIPE; break;
89 	case ERROR_NEGATIVE_SEEK: error = ESPIPE; break;
90 	case ERROR_NOACCESS: error = EFAULT; break;
91 	case ERROR_NONE_MAPPED: error = EINVAL; break;
92 	case ERROR_NOT_ENOUGH_MEMORY: error = ENOMEM; break;
93 	case ERROR_NOT_READY: error = EAGAIN; break;
94 	case ERROR_NOT_SAME_DEVICE: error = EXDEV; break;
95 	case ERROR_NO_DATA: error = EPIPE; break;
96 	case ERROR_NO_MORE_SEARCH_HANDLES: error = EIO; break;
97 	case ERROR_NO_PROC_SLOTS: error = EAGAIN; break;
98 	case ERROR_NO_SUCH_PRIVILEGE: error = EACCES; break;
99 	case ERROR_OPEN_FAILED: error = EIO; break;
100 	case ERROR_OPEN_FILES: error = EBUSY; break;
101 	case ERROR_OPERATION_ABORTED: error = EINTR; break;
102 	case ERROR_OUTOFMEMORY: error = ENOMEM; break;
103 	case ERROR_PASSWORD_EXPIRED: error = EACCES; break;
104 	case ERROR_PATH_BUSY: error = EBUSY; break;
105 	case ERROR_PATH_NOT_FOUND: error = ENOENT; break;
106 	case ERROR_PIPE_BUSY: error = EBUSY; break;
107 	case ERROR_PIPE_CONNECTED: error = EPIPE; break;
108 	case ERROR_PIPE_LISTENING: error = EPIPE; break;
109 	case ERROR_PIPE_NOT_CONNECTED: error = EPIPE; break;
110 	case ERROR_PRIVILEGE_NOT_HELD: error = EACCES; break;
111 	case ERROR_READ_FAULT: error = EIO; break;
112 	case ERROR_SEEK: error = EIO; break;
113 	case ERROR_SEEK_ON_DEVICE: error = ESPIPE; break;
114 	case ERROR_SHARING_BUFFER_EXCEEDED: error = ENFILE; break;
115 	case ERROR_SHARING_VIOLATION: error = EACCES; break;
116 	case ERROR_STACK_OVERFLOW: error = ENOMEM; break;
117 	case ERROR_SUCCESS: BUG("err_win_to_posix() called without an error!");
118 	case ERROR_SWAPERROR: error = ENOENT; break;
119 	case ERROR_TOO_MANY_MODULES: error = EMFILE; break;
120 	case ERROR_TOO_MANY_OPEN_FILES: error = EMFILE; break;
121 	case ERROR_UNRECOGNIZED_MEDIA: error = ENXIO; break;
122 	case ERROR_UNRECOGNIZED_VOLUME: error = ENODEV; break;
123 	case ERROR_WAIT_NO_CHILDREN: error = ECHILD; break;
124 	case ERROR_WRITE_FAULT: error = EIO; break;
125 	case ERROR_WRITE_PROTECT: error = EROFS; break;
126 	}
127 	return error;
128 }
129 
is_file_in_use_error(DWORD errcode)130 static inline int is_file_in_use_error(DWORD errcode)
131 {
132 	switch (errcode) {
133 	case ERROR_SHARING_VIOLATION:
134 	case ERROR_ACCESS_DENIED:
135 		return 1;
136 	}
137 
138 	return 0;
139 }
140 
read_yes_no_answer(void)141 static int read_yes_no_answer(void)
142 {
143 	char answer[1024];
144 
145 	if (fgets(answer, sizeof(answer), stdin)) {
146 		size_t answer_len = strlen(answer);
147 		int got_full_line = 0, c;
148 
149 		/* remove the newline */
150 		if (answer_len >= 2 && answer[answer_len-2] == '\r') {
151 			answer[answer_len-2] = '\0';
152 			got_full_line = 1;
153 		} else if (answer_len >= 1 && answer[answer_len-1] == '\n') {
154 			answer[answer_len-1] = '\0';
155 			got_full_line = 1;
156 		}
157 		/* flush the buffer in case we did not get the full line */
158 		if (!got_full_line)
159 			while ((c = getchar()) != EOF && c != '\n')
160 				;
161 	} else
162 		/* we could not read, return the
163 		 * default answer which is no */
164 		return 0;
165 
166 	if (tolower(answer[0]) == 'y' && !answer[1])
167 		return 1;
168 	if (!strncasecmp(answer, "yes", sizeof(answer)))
169 		return 1;
170 	if (tolower(answer[0]) == 'n' && !answer[1])
171 		return 0;
172 	if (!strncasecmp(answer, "no", sizeof(answer)))
173 		return 0;
174 
175 	/* did not find an answer we understand */
176 	return -1;
177 }
178 
ask_yes_no_if_possible(const char * format,...)179 static int ask_yes_no_if_possible(const char *format, ...)
180 {
181 	char question[4096];
182 	const char *retry_hook[] = { NULL, NULL, NULL };
183 	va_list args;
184 
185 	va_start(args, format);
186 	vsnprintf(question, sizeof(question), format, args);
187 	va_end(args);
188 
189 	if ((retry_hook[0] = mingw_getenv("GIT_ASK_YESNO"))) {
190 		retry_hook[1] = question;
191 		return !run_command_v_opt(retry_hook, 0);
192 	}
193 
194 	if (!isatty(_fileno(stdin)) || !isatty(_fileno(stderr)))
195 		return 0;
196 
197 	while (1) {
198 		int answer;
199 		fprintf(stderr, "%s (y/n) ", question);
200 
201 		if ((answer = read_yes_no_answer()) >= 0)
202 			return answer;
203 
204 		fprintf(stderr, "Sorry, I did not understand your answer. "
205 				"Please type 'y' or 'n'\n");
206 	}
207 }
208 
209 /* Windows only */
210 enum hide_dotfiles_type {
211 	HIDE_DOTFILES_FALSE = 0,
212 	HIDE_DOTFILES_TRUE,
213 	HIDE_DOTFILES_DOTGITONLY
214 };
215 
216 static int core_restrict_inherited_handles = -1;
217 static enum hide_dotfiles_type hide_dotfiles = HIDE_DOTFILES_DOTGITONLY;
218 static char *unset_environment_variables;
219 
mingw_core_config(const char * var,const char * value,void * cb)220 int mingw_core_config(const char *var, const char *value, void *cb)
221 {
222 	if (!strcmp(var, "core.hidedotfiles")) {
223 		if (value && !strcasecmp(value, "dotgitonly"))
224 			hide_dotfiles = HIDE_DOTFILES_DOTGITONLY;
225 		else
226 			hide_dotfiles = git_config_bool(var, value);
227 		return 0;
228 	}
229 
230 	if (!strcmp(var, "core.unsetenvvars")) {
231 		free(unset_environment_variables);
232 		unset_environment_variables = xstrdup(value);
233 		return 0;
234 	}
235 
236 	if (!strcmp(var, "core.restrictinheritedhandles")) {
237 		if (value && !strcasecmp(value, "auto"))
238 			core_restrict_inherited_handles = -1;
239 		else
240 			core_restrict_inherited_handles =
241 				git_config_bool(var, value);
242 		return 0;
243 	}
244 
245 	return 0;
246 }
247 
248 /* Normalizes NT paths as returned by some low-level APIs. */
normalize_ntpath(wchar_t * wbuf)249 static wchar_t *normalize_ntpath(wchar_t *wbuf)
250 {
251 	int i;
252 	/* fix absolute path prefixes */
253 	if (wbuf[0] == '\\') {
254 		/* strip NT namespace prefixes */
255 		if (!wcsncmp(wbuf, L"\\??\\", 4) ||
256 		    !wcsncmp(wbuf, L"\\\\?\\", 4))
257 			wbuf += 4;
258 		else if (!wcsnicmp(wbuf, L"\\DosDevices\\", 12))
259 			wbuf += 12;
260 		/* replace remaining '...UNC\' with '\\' */
261 		if (!wcsnicmp(wbuf, L"UNC\\", 4)) {
262 			wbuf += 2;
263 			*wbuf = '\\';
264 		}
265 	}
266 	/* convert backslashes to slashes */
267 	for (i = 0; wbuf[i]; i++)
268 		if (wbuf[i] == '\\')
269 			wbuf[i] = '/';
270 	return wbuf;
271 }
272 
mingw_unlink(const char * pathname)273 int mingw_unlink(const char *pathname)
274 {
275 	int ret, tries = 0;
276 	wchar_t wpathname[MAX_PATH];
277 	if (xutftowcs_path(wpathname, pathname) < 0)
278 		return -1;
279 
280 	/* read-only files cannot be removed */
281 	_wchmod(wpathname, 0666);
282 	while ((ret = _wunlink(wpathname)) == -1 && tries < ARRAY_SIZE(delay)) {
283 		if (!is_file_in_use_error(GetLastError()))
284 			break;
285 		/*
286 		 * We assume that some other process had the source or
287 		 * destination file open at the wrong moment and retry.
288 		 * In order to give the other process a higher chance to
289 		 * complete its operation, we give up our time slice now.
290 		 * If we have to retry again, we do sleep a bit.
291 		 */
292 		Sleep(delay[tries]);
293 		tries++;
294 	}
295 	while (ret == -1 && is_file_in_use_error(GetLastError()) &&
296 	       ask_yes_no_if_possible("Unlink of file '%s' failed. "
297 			"Should I try again?", pathname))
298 	       ret = _wunlink(wpathname);
299 	return ret;
300 }
301 
is_dir_empty(const wchar_t * wpath)302 static int is_dir_empty(const wchar_t *wpath)
303 {
304 	WIN32_FIND_DATAW findbuf;
305 	HANDLE handle;
306 	wchar_t wbuf[MAX_PATH + 2];
307 	wcscpy(wbuf, wpath);
308 	wcscat(wbuf, L"\\*");
309 	handle = FindFirstFileW(wbuf, &findbuf);
310 	if (handle == INVALID_HANDLE_VALUE)
311 		return GetLastError() == ERROR_NO_MORE_FILES;
312 
313 	while (!wcscmp(findbuf.cFileName, L".") ||
314 			!wcscmp(findbuf.cFileName, L".."))
315 		if (!FindNextFileW(handle, &findbuf)) {
316 			DWORD err = GetLastError();
317 			FindClose(handle);
318 			return err == ERROR_NO_MORE_FILES;
319 		}
320 	FindClose(handle);
321 	return 0;
322 }
323 
mingw_rmdir(const char * pathname)324 int mingw_rmdir(const char *pathname)
325 {
326 	int ret, tries = 0;
327 	wchar_t wpathname[MAX_PATH];
328 	if (xutftowcs_path(wpathname, pathname) < 0)
329 		return -1;
330 
331 	while ((ret = _wrmdir(wpathname)) == -1 && tries < ARRAY_SIZE(delay)) {
332 		if (!is_file_in_use_error(GetLastError()))
333 			errno = err_win_to_posix(GetLastError());
334 		if (errno != EACCES)
335 			break;
336 		if (!is_dir_empty(wpathname)) {
337 			errno = ENOTEMPTY;
338 			break;
339 		}
340 		/*
341 		 * We assume that some other process had the source or
342 		 * destination file open at the wrong moment and retry.
343 		 * In order to give the other process a higher chance to
344 		 * complete its operation, we give up our time slice now.
345 		 * If we have to retry again, we do sleep a bit.
346 		 */
347 		Sleep(delay[tries]);
348 		tries++;
349 	}
350 	while (ret == -1 && errno == EACCES && is_file_in_use_error(GetLastError()) &&
351 	       ask_yes_no_if_possible("Deletion of directory '%s' failed. "
352 			"Should I try again?", pathname))
353 	       ret = _wrmdir(wpathname);
354 	return ret;
355 }
356 
needs_hiding(const char * path)357 static inline int needs_hiding(const char *path)
358 {
359 	const char *basename;
360 
361 	if (hide_dotfiles == HIDE_DOTFILES_FALSE)
362 		return 0;
363 
364 	/* We cannot use basename(), as it would remove trailing slashes */
365 	win32_skip_dos_drive_prefix((char **)&path);
366 	if (!*path)
367 		return 0;
368 
369 	for (basename = path; *path; path++)
370 		if (is_dir_sep(*path)) {
371 			do {
372 				path++;
373 			} while (is_dir_sep(*path));
374 			/* ignore trailing slashes */
375 			if (*path)
376 				basename = path;
377 			else
378 				break;
379 		}
380 
381 	if (hide_dotfiles == HIDE_DOTFILES_TRUE)
382 		return *basename == '.';
383 
384 	assert(hide_dotfiles == HIDE_DOTFILES_DOTGITONLY);
385 	return !strncasecmp(".git", basename, 4) &&
386 		(!basename[4] || is_dir_sep(basename[4]));
387 }
388 
set_hidden_flag(const wchar_t * path,int set)389 static int set_hidden_flag(const wchar_t *path, int set)
390 {
391 	DWORD original = GetFileAttributesW(path), modified;
392 	if (set)
393 		modified = original | FILE_ATTRIBUTE_HIDDEN;
394 	else
395 		modified = original & ~FILE_ATTRIBUTE_HIDDEN;
396 	if (original == modified || SetFileAttributesW(path, modified))
397 		return 0;
398 	errno = err_win_to_posix(GetLastError());
399 	return -1;
400 }
401 
mingw_mkdir(const char * path,int mode)402 int mingw_mkdir(const char *path, int mode)
403 {
404 	int ret;
405 	wchar_t wpath[MAX_PATH];
406 
407 	if (!is_valid_win32_path(path, 0)) {
408 		errno = EINVAL;
409 		return -1;
410 	}
411 
412 	if (xutftowcs_path(wpath, path) < 0)
413 		return -1;
414 	ret = _wmkdir(wpath);
415 	if (!ret && needs_hiding(path))
416 		return set_hidden_flag(wpath, 1);
417 	return ret;
418 }
419 
420 /*
421  * Calling CreateFile() using FILE_APPEND_DATA and without FILE_WRITE_DATA
422  * is documented in [1] as opening a writable file handle in append mode.
423  * (It is believed that) this is atomic since it is maintained by the
424  * kernel unlike the O_APPEND flag which is racily maintained by the CRT.
425  *
426  * [1] https://docs.microsoft.com/en-us/windows/desktop/fileio/file-access-rights-constants
427  *
428  * This trick does not appear to work for named pipes.  Instead it creates
429  * a named pipe client handle that cannot be written to.  Callers should
430  * just use the regular _wopen() for them.  (And since client handle gets
431  * bound to a unique server handle, it isn't really an issue.)
432  */
mingw_open_append(wchar_t const * wfilename,int oflags,...)433 static int mingw_open_append(wchar_t const *wfilename, int oflags, ...)
434 {
435 	HANDLE handle;
436 	int fd;
437 	DWORD create = (oflags & O_CREAT) ? OPEN_ALWAYS : OPEN_EXISTING;
438 
439 	/* only these flags are supported */
440 	if ((oflags & ~O_CREAT) != (O_WRONLY | O_APPEND))
441 		return errno = ENOSYS, -1;
442 
443 	/*
444 	 * FILE_SHARE_WRITE is required to permit child processes
445 	 * to append to the file.
446 	 */
447 	handle = CreateFileW(wfilename, FILE_APPEND_DATA,
448 			FILE_SHARE_WRITE | FILE_SHARE_READ,
449 			NULL, create, FILE_ATTRIBUTE_NORMAL, NULL);
450 	if (handle == INVALID_HANDLE_VALUE)
451 		return errno = err_win_to_posix(GetLastError()), -1;
452 
453 	/*
454 	 * No O_APPEND here, because the CRT uses it only to reset the
455 	 * file pointer to EOF before each write(); but that is not
456 	 * necessary (and may lead to races) for a file created with
457 	 * FILE_APPEND_DATA.
458 	 */
459 	fd = _open_osfhandle((intptr_t)handle, O_BINARY);
460 	if (fd < 0)
461 		CloseHandle(handle);
462 	return fd;
463 }
464 
465 /*
466  * Does the pathname map to the local named pipe filesystem?
467  * That is, does it have a "//./pipe/" prefix?
468  */
is_local_named_pipe_path(const char * filename)469 static int is_local_named_pipe_path(const char *filename)
470 {
471 	return (is_dir_sep(filename[0]) &&
472 		is_dir_sep(filename[1]) &&
473 		filename[2] == '.'  &&
474 		is_dir_sep(filename[3]) &&
475 		!strncasecmp(filename+4, "pipe", 4) &&
476 		is_dir_sep(filename[8]) &&
477 		filename[9]);
478 }
479 
mingw_open(const char * filename,int oflags,...)480 int mingw_open (const char *filename, int oflags, ...)
481 {
482 	typedef int (*open_fn_t)(wchar_t const *wfilename, int oflags, ...);
483 	va_list args;
484 	unsigned mode;
485 	int fd, create = (oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL);
486 	wchar_t wfilename[MAX_PATH];
487 	open_fn_t open_fn;
488 
489 	va_start(args, oflags);
490 	mode = va_arg(args, int);
491 	va_end(args);
492 
493 	if (!is_valid_win32_path(filename, !create)) {
494 		errno = create ? EINVAL : ENOENT;
495 		return -1;
496 	}
497 
498 	if ((oflags & O_APPEND) && !is_local_named_pipe_path(filename))
499 		open_fn = mingw_open_append;
500 	else
501 		open_fn = _wopen;
502 
503 	if (filename && !strcmp(filename, "/dev/null"))
504 		wcscpy(wfilename, L"nul");
505 	else if (xutftowcs_path(wfilename, filename) < 0)
506 		return -1;
507 
508 	fd = open_fn(wfilename, oflags, mode);
509 
510 	if (fd < 0 && (oflags & O_ACCMODE) != O_RDONLY && errno == EACCES) {
511 		DWORD attrs = GetFileAttributesW(wfilename);
512 		if (attrs != INVALID_FILE_ATTRIBUTES && (attrs & FILE_ATTRIBUTE_DIRECTORY))
513 			errno = EISDIR;
514 	}
515 	if ((oflags & O_CREAT) && needs_hiding(filename)) {
516 		/*
517 		 * Internally, _wopen() uses the CreateFile() API which errors
518 		 * out with an ERROR_ACCESS_DENIED if CREATE_ALWAYS was
519 		 * specified and an already existing file's attributes do not
520 		 * match *exactly*. As there is no mode or flag we can set that
521 		 * would correspond to FILE_ATTRIBUTE_HIDDEN, let's just try
522 		 * again *without* the O_CREAT flag (that corresponds to the
523 		 * CREATE_ALWAYS flag of CreateFile()).
524 		 */
525 		if (fd < 0 && errno == EACCES)
526 			fd = open_fn(wfilename, oflags & ~O_CREAT, mode);
527 		if (fd >= 0 && set_hidden_flag(wfilename, 1))
528 			warning("could not mark '%s' as hidden.", filename);
529 	}
530 	return fd;
531 }
532 
ctrl_ignore(DWORD type)533 static BOOL WINAPI ctrl_ignore(DWORD type)
534 {
535 	return TRUE;
536 }
537 
538 #undef fgetc
mingw_fgetc(FILE * stream)539 int mingw_fgetc(FILE *stream)
540 {
541 	int ch;
542 	if (!isatty(_fileno(stream)))
543 		return fgetc(stream);
544 
545 	SetConsoleCtrlHandler(ctrl_ignore, TRUE);
546 	while (1) {
547 		ch = fgetc(stream);
548 		if (ch != EOF || GetLastError() != ERROR_OPERATION_ABORTED)
549 			break;
550 
551 		/* Ctrl+C was pressed, simulate SIGINT and retry */
552 		mingw_raise(SIGINT);
553 	}
554 	SetConsoleCtrlHandler(ctrl_ignore, FALSE);
555 	return ch;
556 }
557 
558 #undef fopen
mingw_fopen(const char * filename,const char * otype)559 FILE *mingw_fopen (const char *filename, const char *otype)
560 {
561 	int hide = needs_hiding(filename);
562 	FILE *file;
563 	wchar_t wfilename[MAX_PATH], wotype[4];
564 	if (filename && !strcmp(filename, "/dev/null"))
565 		wcscpy(wfilename, L"nul");
566 	else if (!is_valid_win32_path(filename, 1)) {
567 		int create = otype && strchr(otype, 'w');
568 		errno = create ? EINVAL : ENOENT;
569 		return NULL;
570 	} else if (xutftowcs_path(wfilename, filename) < 0)
571 		return NULL;
572 
573 	if (xutftowcs(wotype, otype, ARRAY_SIZE(wotype)) < 0)
574 		return NULL;
575 
576 	if (hide && !access(filename, F_OK) && set_hidden_flag(wfilename, 0)) {
577 		error("could not unhide %s", filename);
578 		return NULL;
579 	}
580 	file = _wfopen(wfilename, wotype);
581 	if (!file && GetLastError() == ERROR_INVALID_NAME)
582 		errno = ENOENT;
583 	if (file && hide && set_hidden_flag(wfilename, 1))
584 		warning("could not mark '%s' as hidden.", filename);
585 	return file;
586 }
587 
mingw_freopen(const char * filename,const char * otype,FILE * stream)588 FILE *mingw_freopen (const char *filename, const char *otype, FILE *stream)
589 {
590 	int hide = needs_hiding(filename);
591 	FILE *file;
592 	wchar_t wfilename[MAX_PATH], wotype[4];
593 	if (filename && !strcmp(filename, "/dev/null"))
594 		wcscpy(wfilename, L"nul");
595 	else if (!is_valid_win32_path(filename, 1)) {
596 		int create = otype && strchr(otype, 'w');
597 		errno = create ? EINVAL : ENOENT;
598 		return NULL;
599 	} else if (xutftowcs_path(wfilename, filename) < 0)
600 		return NULL;
601 
602 	if (xutftowcs(wotype, otype, ARRAY_SIZE(wotype)) < 0)
603 		return NULL;
604 
605 	if (hide && !access(filename, F_OK) && set_hidden_flag(wfilename, 0)) {
606 		error("could not unhide %s", filename);
607 		return NULL;
608 	}
609 	file = _wfreopen(wfilename, wotype, stream);
610 	if (file && hide && set_hidden_flag(wfilename, 1))
611 		warning("could not mark '%s' as hidden.", filename);
612 	return file;
613 }
614 
615 #undef fflush
mingw_fflush(FILE * stream)616 int mingw_fflush(FILE *stream)
617 {
618 	int ret = fflush(stream);
619 
620 	/*
621 	 * write() is used behind the scenes of stdio output functions.
622 	 * Since git code does not check for errors after each stdio write
623 	 * operation, it can happen that write() is called by a later
624 	 * stdio function even if an earlier write() call failed. In the
625 	 * case of a pipe whose readable end was closed, only the first
626 	 * call to write() reports EPIPE on Windows. Subsequent write()
627 	 * calls report EINVAL. It is impossible to notice whether this
628 	 * fflush invocation triggered such a case, therefore, we have to
629 	 * catch all EINVAL errors whole-sale.
630 	 */
631 	if (ret && errno == EINVAL)
632 		errno = EPIPE;
633 
634 	return ret;
635 }
636 
637 #undef write
mingw_write(int fd,const void * buf,size_t len)638 ssize_t mingw_write(int fd, const void *buf, size_t len)
639 {
640 	ssize_t result = write(fd, buf, len);
641 
642 	if (result < 0 && errno == EINVAL && buf) {
643 		/* check if fd is a pipe */
644 		HANDLE h = (HANDLE) _get_osfhandle(fd);
645 		if (GetFileType(h) == FILE_TYPE_PIPE)
646 			errno = EPIPE;
647 		else
648 			errno = EINVAL;
649 	}
650 
651 	return result;
652 }
653 
mingw_access(const char * filename,int mode)654 int mingw_access(const char *filename, int mode)
655 {
656 	wchar_t wfilename[MAX_PATH];
657 	if (xutftowcs_path(wfilename, filename) < 0)
658 		return -1;
659 	/* X_OK is not supported by the MSVCRT version */
660 	return _waccess(wfilename, mode & ~X_OK);
661 }
662 
mingw_chdir(const char * dirname)663 int mingw_chdir(const char *dirname)
664 {
665 	wchar_t wdirname[MAX_PATH];
666 	if (xutftowcs_path(wdirname, dirname) < 0)
667 		return -1;
668 	return _wchdir(wdirname);
669 }
670 
mingw_chmod(const char * filename,int mode)671 int mingw_chmod(const char *filename, int mode)
672 {
673 	wchar_t wfilename[MAX_PATH];
674 	if (xutftowcs_path(wfilename, filename) < 0)
675 		return -1;
676 	return _wchmod(wfilename, mode);
677 }
678 
679 /*
680  * The unit of FILETIME is 100-nanoseconds since January 1, 1601, UTC.
681  * Returns the 100-nanoseconds ("hekto nanoseconds") since the epoch.
682  */
filetime_to_hnsec(const FILETIME * ft)683 static inline long long filetime_to_hnsec(const FILETIME *ft)
684 {
685 	long long winTime = ((long long)ft->dwHighDateTime << 32) + ft->dwLowDateTime;
686 	/* Windows to Unix Epoch conversion */
687 	return winTime - 116444736000000000LL;
688 }
689 
filetime_to_timespec(const FILETIME * ft,struct timespec * ts)690 static inline void filetime_to_timespec(const FILETIME *ft, struct timespec *ts)
691 {
692 	long long hnsec = filetime_to_hnsec(ft);
693 	ts->tv_sec = (time_t)(hnsec / 10000000);
694 	ts->tv_nsec = (hnsec % 10000000) * 100;
695 }
696 
697 /**
698  * Verifies that safe_create_leading_directories() would succeed.
699  */
has_valid_directory_prefix(wchar_t * wfilename)700 static int has_valid_directory_prefix(wchar_t *wfilename)
701 {
702 	int n = wcslen(wfilename);
703 
704 	while (n > 0) {
705 		wchar_t c = wfilename[--n];
706 		DWORD attributes;
707 
708 		if (!is_dir_sep(c))
709 			continue;
710 
711 		wfilename[n] = L'\0';
712 		attributes = GetFileAttributesW(wfilename);
713 		wfilename[n] = c;
714 		if (attributes == FILE_ATTRIBUTE_DIRECTORY ||
715 				attributes == FILE_ATTRIBUTE_DEVICE)
716 			return 1;
717 		if (attributes == INVALID_FILE_ATTRIBUTES)
718 			switch (GetLastError()) {
719 			case ERROR_PATH_NOT_FOUND:
720 				continue;
721 			case ERROR_FILE_NOT_FOUND:
722 				/* This implies parent directory exists. */
723 				return 1;
724 			}
725 		return 0;
726 	}
727 	return 1;
728 }
729 
730 /* We keep the do_lstat code in a separate function to avoid recursion.
731  * When a path ends with a slash, the stat will fail with ENOENT. In
732  * this case, we strip the trailing slashes and stat again.
733  *
734  * If follow is true then act like stat() and report on the link
735  * target. Otherwise report on the link itself.
736  */
do_lstat(int follow,const char * file_name,struct stat * buf)737 static int do_lstat(int follow, const char *file_name, struct stat *buf)
738 {
739 	WIN32_FILE_ATTRIBUTE_DATA fdata;
740 	wchar_t wfilename[MAX_PATH];
741 	if (xutftowcs_path(wfilename, file_name) < 0)
742 		return -1;
743 
744 	if (GetFileAttributesExW(wfilename, GetFileExInfoStandard, &fdata)) {
745 		buf->st_ino = 0;
746 		buf->st_gid = 0;
747 		buf->st_uid = 0;
748 		buf->st_nlink = 1;
749 		buf->st_mode = file_attr_to_st_mode(fdata.dwFileAttributes);
750 		buf->st_size = fdata.nFileSizeLow |
751 			(((off_t)fdata.nFileSizeHigh)<<32);
752 		buf->st_dev = buf->st_rdev = 0; /* not used by Git */
753 		filetime_to_timespec(&(fdata.ftLastAccessTime), &(buf->st_atim));
754 		filetime_to_timespec(&(fdata.ftLastWriteTime), &(buf->st_mtim));
755 		filetime_to_timespec(&(fdata.ftCreationTime), &(buf->st_ctim));
756 		if (fdata.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
757 			WIN32_FIND_DATAW findbuf;
758 			HANDLE handle = FindFirstFileW(wfilename, &findbuf);
759 			if (handle != INVALID_HANDLE_VALUE) {
760 				if ((findbuf.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
761 						(findbuf.dwReserved0 == IO_REPARSE_TAG_SYMLINK)) {
762 					if (follow) {
763 						char buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
764 						buf->st_size = readlink(file_name, buffer, MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
765 					} else {
766 						buf->st_mode = S_IFLNK;
767 					}
768 					buf->st_mode |= S_IREAD;
769 					if (!(findbuf.dwFileAttributes & FILE_ATTRIBUTE_READONLY))
770 						buf->st_mode |= S_IWRITE;
771 				}
772 				FindClose(handle);
773 			}
774 		}
775 		return 0;
776 	}
777 	switch (GetLastError()) {
778 	case ERROR_ACCESS_DENIED:
779 	case ERROR_SHARING_VIOLATION:
780 	case ERROR_LOCK_VIOLATION:
781 	case ERROR_SHARING_BUFFER_EXCEEDED:
782 		errno = EACCES;
783 		break;
784 	case ERROR_BUFFER_OVERFLOW:
785 		errno = ENAMETOOLONG;
786 		break;
787 	case ERROR_NOT_ENOUGH_MEMORY:
788 		errno = ENOMEM;
789 		break;
790 	case ERROR_PATH_NOT_FOUND:
791 		if (!has_valid_directory_prefix(wfilename)) {
792 			errno = ENOTDIR;
793 			break;
794 		}
795 		/* fallthru */
796 	default:
797 		errno = ENOENT;
798 		break;
799 	}
800 	return -1;
801 }
802 
803 /* We provide our own lstat/fstat functions, since the provided
804  * lstat/fstat functions are so slow. These stat functions are
805  * tailored for Git's usage (read: fast), and are not meant to be
806  * complete. Note that Git stat()s are redirected to mingw_lstat()
807  * too, since Windows doesn't really handle symlinks that well.
808  */
do_stat_internal(int follow,const char * file_name,struct stat * buf)809 static int do_stat_internal(int follow, const char *file_name, struct stat *buf)
810 {
811 	int namelen;
812 	char alt_name[PATH_MAX];
813 
814 	if (!do_lstat(follow, file_name, buf))
815 		return 0;
816 
817 	/* if file_name ended in a '/', Windows returned ENOENT;
818 	 * try again without trailing slashes
819 	 */
820 	if (errno != ENOENT)
821 		return -1;
822 
823 	namelen = strlen(file_name);
824 	if (namelen && file_name[namelen-1] != '/')
825 		return -1;
826 	while (namelen && file_name[namelen-1] == '/')
827 		--namelen;
828 	if (!namelen || namelen >= PATH_MAX)
829 		return -1;
830 
831 	memcpy(alt_name, file_name, namelen);
832 	alt_name[namelen] = 0;
833 	return do_lstat(follow, alt_name, buf);
834 }
835 
get_file_info_by_handle(HANDLE hnd,struct stat * buf)836 static int get_file_info_by_handle(HANDLE hnd, struct stat *buf)
837 {
838 	BY_HANDLE_FILE_INFORMATION fdata;
839 
840 	if (!GetFileInformationByHandle(hnd, &fdata)) {
841 		errno = err_win_to_posix(GetLastError());
842 		return -1;
843 	}
844 
845 	buf->st_ino = 0;
846 	buf->st_gid = 0;
847 	buf->st_uid = 0;
848 	buf->st_nlink = 1;
849 	buf->st_mode = file_attr_to_st_mode(fdata.dwFileAttributes);
850 	buf->st_size = fdata.nFileSizeLow |
851 		(((off_t)fdata.nFileSizeHigh)<<32);
852 	buf->st_dev = buf->st_rdev = 0; /* not used by Git */
853 	filetime_to_timespec(&(fdata.ftLastAccessTime), &(buf->st_atim));
854 	filetime_to_timespec(&(fdata.ftLastWriteTime), &(buf->st_mtim));
855 	filetime_to_timespec(&(fdata.ftCreationTime), &(buf->st_ctim));
856 	return 0;
857 }
858 
mingw_lstat(const char * file_name,struct stat * buf)859 int mingw_lstat(const char *file_name, struct stat *buf)
860 {
861 	return do_stat_internal(0, file_name, buf);
862 }
mingw_stat(const char * file_name,struct stat * buf)863 int mingw_stat(const char *file_name, struct stat *buf)
864 {
865 	return do_stat_internal(1, file_name, buf);
866 }
867 
mingw_fstat(int fd,struct stat * buf)868 int mingw_fstat(int fd, struct stat *buf)
869 {
870 	HANDLE fh = (HANDLE)_get_osfhandle(fd);
871 	DWORD avail, type = GetFileType(fh) & ~FILE_TYPE_REMOTE;
872 
873 	switch (type) {
874 	case FILE_TYPE_DISK:
875 		return get_file_info_by_handle(fh, buf);
876 
877 	case FILE_TYPE_CHAR:
878 	case FILE_TYPE_PIPE:
879 		/* initialize stat fields */
880 		memset(buf, 0, sizeof(*buf));
881 		buf->st_nlink = 1;
882 
883 		if (type == FILE_TYPE_CHAR) {
884 			buf->st_mode = _S_IFCHR;
885 		} else {
886 			buf->st_mode = _S_IFIFO;
887 			if (PeekNamedPipe(fh, NULL, 0, NULL, &avail, NULL))
888 				buf->st_size = avail;
889 		}
890 		return 0;
891 
892 	default:
893 		errno = EBADF;
894 		return -1;
895 	}
896 }
897 
time_t_to_filetime(time_t t,FILETIME * ft)898 static inline void time_t_to_filetime(time_t t, FILETIME *ft)
899 {
900 	long long winTime = t * 10000000LL + 116444736000000000LL;
901 	ft->dwLowDateTime = winTime;
902 	ft->dwHighDateTime = winTime >> 32;
903 }
904 
mingw_utime(const char * file_name,const struct utimbuf * times)905 int mingw_utime (const char *file_name, const struct utimbuf *times)
906 {
907 	FILETIME mft, aft;
908 	int fh, rc;
909 	DWORD attrs;
910 	wchar_t wfilename[MAX_PATH];
911 	if (xutftowcs_path(wfilename, file_name) < 0)
912 		return -1;
913 
914 	/* must have write permission */
915 	attrs = GetFileAttributesW(wfilename);
916 	if (attrs != INVALID_FILE_ATTRIBUTES &&
917 	    (attrs & FILE_ATTRIBUTE_READONLY)) {
918 		/* ignore errors here; open() will report them */
919 		SetFileAttributesW(wfilename, attrs & ~FILE_ATTRIBUTE_READONLY);
920 	}
921 
922 	if ((fh = _wopen(wfilename, O_RDWR | O_BINARY)) < 0) {
923 		rc = -1;
924 		goto revert_attrs;
925 	}
926 
927 	if (times) {
928 		time_t_to_filetime(times->modtime, &mft);
929 		time_t_to_filetime(times->actime, &aft);
930 	} else {
931 		GetSystemTimeAsFileTime(&mft);
932 		aft = mft;
933 	}
934 	if (!SetFileTime((HANDLE)_get_osfhandle(fh), NULL, &aft, &mft)) {
935 		errno = EINVAL;
936 		rc = -1;
937 	} else
938 		rc = 0;
939 	close(fh);
940 
941 revert_attrs:
942 	if (attrs != INVALID_FILE_ATTRIBUTES &&
943 	    (attrs & FILE_ATTRIBUTE_READONLY)) {
944 		/* ignore errors again */
945 		SetFileAttributesW(wfilename, attrs);
946 	}
947 	return rc;
948 }
949 
950 #undef strftime
mingw_strftime(char * s,size_t max,const char * format,const struct tm * tm)951 size_t mingw_strftime(char *s, size_t max,
952 		      const char *format, const struct tm *tm)
953 {
954 	size_t ret = strftime(s, max, format, tm);
955 
956 	if (!ret && errno == EINVAL)
957 		die("invalid strftime format: '%s'", format);
958 	return ret;
959 }
960 
sleep(unsigned int seconds)961 unsigned int sleep (unsigned int seconds)
962 {
963 	Sleep(seconds*1000);
964 	return 0;
965 }
966 
mingw_mktemp(char * template)967 char *mingw_mktemp(char *template)
968 {
969 	wchar_t wtemplate[MAX_PATH];
970 	if (xutftowcs_path(wtemplate, template) < 0)
971 		return NULL;
972 	if (!_wmktemp(wtemplate))
973 		return NULL;
974 	if (xwcstoutf(template, wtemplate, strlen(template) + 1) < 0)
975 		return NULL;
976 	return template;
977 }
978 
mkstemp(char * template)979 int mkstemp(char *template)
980 {
981 	char *filename = mktemp(template);
982 	if (filename == NULL)
983 		return -1;
984 	return open(filename, O_RDWR | O_CREAT, 0600);
985 }
986 
gettimeofday(struct timeval * tv,void * tz)987 int gettimeofday(struct timeval *tv, void *tz)
988 {
989 	FILETIME ft;
990 	long long hnsec;
991 
992 	GetSystemTimeAsFileTime(&ft);
993 	hnsec = filetime_to_hnsec(&ft);
994 	tv->tv_sec = hnsec / 10000000;
995 	tv->tv_usec = (hnsec % 10000000) / 10;
996 	return 0;
997 }
998 
pipe(int filedes[2])999 int pipe(int filedes[2])
1000 {
1001 	HANDLE h[2];
1002 
1003 	/* this creates non-inheritable handles */
1004 	if (!CreatePipe(&h[0], &h[1], NULL, 8192)) {
1005 		errno = err_win_to_posix(GetLastError());
1006 		return -1;
1007 	}
1008 	filedes[0] = _open_osfhandle(HCAST(int, h[0]), O_NOINHERIT);
1009 	if (filedes[0] < 0) {
1010 		CloseHandle(h[0]);
1011 		CloseHandle(h[1]);
1012 		return -1;
1013 	}
1014 	filedes[1] = _open_osfhandle(HCAST(int, h[1]), O_NOINHERIT);
1015 	if (filedes[1] < 0) {
1016 		close(filedes[0]);
1017 		CloseHandle(h[1]);
1018 		return -1;
1019 	}
1020 	return 0;
1021 }
1022 
gmtime_r(const time_t * timep,struct tm * result)1023 struct tm *gmtime_r(const time_t *timep, struct tm *result)
1024 {
1025 	if (gmtime_s(result, timep) == 0)
1026 		return result;
1027 	return NULL;
1028 }
1029 
localtime_r(const time_t * timep,struct tm * result)1030 struct tm *localtime_r(const time_t *timep, struct tm *result)
1031 {
1032 	if (localtime_s(result, timep) == 0)
1033 		return result;
1034 	return NULL;
1035 }
1036 
mingw_getcwd(char * pointer,int len)1037 char *mingw_getcwd(char *pointer, int len)
1038 {
1039 	wchar_t cwd[MAX_PATH], wpointer[MAX_PATH];
1040 	DWORD ret = GetCurrentDirectoryW(ARRAY_SIZE(cwd), cwd);
1041 
1042 	if (!ret || ret >= ARRAY_SIZE(cwd)) {
1043 		errno = ret ? ENAMETOOLONG : err_win_to_posix(GetLastError());
1044 		return NULL;
1045 	}
1046 	ret = GetLongPathNameW(cwd, wpointer, ARRAY_SIZE(wpointer));
1047 	if (!ret && GetLastError() == ERROR_ACCESS_DENIED) {
1048 		HANDLE hnd = CreateFileW(cwd, 0,
1049 			FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
1050 			OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
1051 		if (hnd == INVALID_HANDLE_VALUE)
1052 			return NULL;
1053 		ret = GetFinalPathNameByHandleW(hnd, wpointer, ARRAY_SIZE(wpointer), 0);
1054 		CloseHandle(hnd);
1055 		if (!ret || ret >= ARRAY_SIZE(wpointer))
1056 			return NULL;
1057 		if (xwcstoutf(pointer, normalize_ntpath(wpointer), len) < 0)
1058 			return NULL;
1059 		return pointer;
1060 	}
1061 	if (!ret || ret >= ARRAY_SIZE(wpointer))
1062 		return NULL;
1063 	if (xwcstoutf(pointer, wpointer, len) < 0)
1064 		return NULL;
1065 	convert_slashes(pointer);
1066 	return pointer;
1067 }
1068 
1069 /*
1070  * See "Parsing C++ Command-Line Arguments" at Microsoft's Docs:
1071  * https://docs.microsoft.com/en-us/cpp/cpp/parsing-cpp-command-line-arguments
1072  */
quote_arg_msvc(const char * arg)1073 static const char *quote_arg_msvc(const char *arg)
1074 {
1075 	/* count chars to quote */
1076 	int len = 0, n = 0;
1077 	int force_quotes = 0;
1078 	char *q, *d;
1079 	const char *p = arg;
1080 	if (!*p) force_quotes = 1;
1081 	while (*p) {
1082 		if (isspace(*p) || *p == '*' || *p == '?' || *p == '{' || *p == '\'')
1083 			force_quotes = 1;
1084 		else if (*p == '"')
1085 			n++;
1086 		else if (*p == '\\') {
1087 			int count = 0;
1088 			while (*p == '\\') {
1089 				count++;
1090 				p++;
1091 				len++;
1092 			}
1093 			if (*p == '"' || !*p)
1094 				n += count*2 + 1;
1095 			continue;
1096 		}
1097 		len++;
1098 		p++;
1099 	}
1100 	if (!force_quotes && n == 0)
1101 		return arg;
1102 
1103 	/* insert \ where necessary */
1104 	d = q = xmalloc(st_add3(len, n, 3));
1105 	*d++ = '"';
1106 	while (*arg) {
1107 		if (*arg == '"')
1108 			*d++ = '\\';
1109 		else if (*arg == '\\') {
1110 			int count = 0;
1111 			while (*arg == '\\') {
1112 				count++;
1113 				*d++ = *arg++;
1114 			}
1115 			if (*arg == '"' || !*arg) {
1116 				while (count-- > 0)
1117 					*d++ = '\\';
1118 				/* don't escape the surrounding end quote */
1119 				if (!*arg)
1120 					break;
1121 				*d++ = '\\';
1122 			}
1123 		}
1124 		*d++ = *arg++;
1125 	}
1126 	*d++ = '"';
1127 	*d++ = '\0';
1128 	return q;
1129 }
1130 
1131 #include "quote.h"
1132 
quote_arg_msys2(const char * arg)1133 static const char *quote_arg_msys2(const char *arg)
1134 {
1135 	struct strbuf buf = STRBUF_INIT;
1136 	const char *p2 = arg, *p;
1137 
1138 	for (p = arg; *p; p++) {
1139 		int ws = isspace(*p);
1140 		if (!ws && *p != '\\' && *p != '"' && *p != '{' && *p != '\'' &&
1141 		    *p != '?' && *p != '*' && *p != '~')
1142 			continue;
1143 		if (!buf.len)
1144 			strbuf_addch(&buf, '"');
1145 		if (p != p2)
1146 			strbuf_add(&buf, p2, p - p2);
1147 		if (*p == '\\' || *p == '"')
1148 			strbuf_addch(&buf, '\\');
1149 		p2 = p;
1150 	}
1151 
1152 	if (p == arg)
1153 		strbuf_addch(&buf, '"');
1154 	else if (!buf.len)
1155 		return arg;
1156 	else
1157 		strbuf_add(&buf, p2, p - p2);
1158 
1159 	strbuf_addch(&buf, '"');
1160 	return strbuf_detach(&buf, 0);
1161 }
1162 
parse_interpreter(const char * cmd)1163 static const char *parse_interpreter(const char *cmd)
1164 {
1165 	static char buf[100];
1166 	char *p, *opt;
1167 	int n, fd;
1168 
1169 	/* don't even try a .exe */
1170 	n = strlen(cmd);
1171 	if (n >= 4 && !strcasecmp(cmd+n-4, ".exe"))
1172 		return NULL;
1173 
1174 	fd = open(cmd, O_RDONLY);
1175 	if (fd < 0)
1176 		return NULL;
1177 	n = read(fd, buf, sizeof(buf)-1);
1178 	close(fd);
1179 	if (n < 4)	/* at least '#!/x' and not error */
1180 		return NULL;
1181 
1182 	if (buf[0] != '#' || buf[1] != '!')
1183 		return NULL;
1184 	buf[n] = '\0';
1185 	p = buf + strcspn(buf, "\r\n");
1186 	if (!*p)
1187 		return NULL;
1188 
1189 	*p = '\0';
1190 	if (!(p = strrchr(buf+2, '/')) && !(p = strrchr(buf+2, '\\')))
1191 		return NULL;
1192 	/* strip options */
1193 	if ((opt = strchr(p+1, ' ')))
1194 		*opt = '\0';
1195 	return p+1;
1196 }
1197 
1198 /*
1199  * exe_only means that we only want to detect .exe files, but not scripts
1200  * (which do not have an extension)
1201  */
lookup_prog(const char * dir,int dirlen,const char * cmd,int isexe,int exe_only)1202 static char *lookup_prog(const char *dir, int dirlen, const char *cmd,
1203 			 int isexe, int exe_only)
1204 {
1205 	char path[MAX_PATH];
1206 	wchar_t wpath[MAX_PATH];
1207 	snprintf(path, sizeof(path), "%.*s\\%s.exe", dirlen, dir, cmd);
1208 
1209 	if (xutftowcs_path(wpath, path) < 0)
1210 		return NULL;
1211 
1212 	if (!isexe && _waccess(wpath, F_OK) == 0)
1213 		return xstrdup(path);
1214 	wpath[wcslen(wpath)-4] = '\0';
1215 	if ((!exe_only || isexe) && _waccess(wpath, F_OK) == 0) {
1216 		if (!(GetFileAttributesW(wpath) & FILE_ATTRIBUTE_DIRECTORY)) {
1217 			path[strlen(path)-4] = '\0';
1218 			return xstrdup(path);
1219 		}
1220 	}
1221 	return NULL;
1222 }
1223 
1224 /*
1225  * Determines the absolute path of cmd using the split path in path.
1226  * If cmd contains a slash or backslash, no lookup is performed.
1227  */
path_lookup(const char * cmd,int exe_only)1228 static char *path_lookup(const char *cmd, int exe_only)
1229 {
1230 	const char *path;
1231 	char *prog = NULL;
1232 	int len = strlen(cmd);
1233 	int isexe = len >= 4 && !strcasecmp(cmd+len-4, ".exe");
1234 
1235 	if (strchr(cmd, '/') || strchr(cmd, '\\'))
1236 		return xstrdup(cmd);
1237 
1238 	path = mingw_getenv("PATH");
1239 	if (!path)
1240 		return NULL;
1241 
1242 	while (!prog) {
1243 		const char *sep = strchrnul(path, ';');
1244 		int dirlen = sep - path;
1245 		if (dirlen)
1246 			prog = lookup_prog(path, dirlen, cmd, isexe, exe_only);
1247 		if (!*sep)
1248 			break;
1249 		path = sep + 1;
1250 	}
1251 
1252 	return prog;
1253 }
1254 
wcschrnul(const wchar_t * s,wchar_t c)1255 static const wchar_t *wcschrnul(const wchar_t *s, wchar_t c)
1256 {
1257 	while (*s && *s != c)
1258 		s++;
1259 	return s;
1260 }
1261 
1262 /* Compare only keys */
wenvcmp(const void * a,const void * b)1263 static int wenvcmp(const void *a, const void *b)
1264 {
1265 	wchar_t *p = *(wchar_t **)a, *q = *(wchar_t **)b;
1266 	size_t p_len, q_len;
1267 
1268 	/* Find the keys */
1269 	p_len = wcschrnul(p, L'=') - p;
1270 	q_len = wcschrnul(q, L'=') - q;
1271 
1272 	/* If the length differs, include the shorter key's NUL */
1273 	if (p_len < q_len)
1274 		p_len++;
1275 	else if (p_len > q_len)
1276 		p_len = q_len + 1;
1277 
1278 	return _wcsnicmp(p, q, p_len);
1279 }
1280 
1281 /*
1282  * Build an environment block combining the inherited environment
1283  * merged with the given list of settings.
1284  *
1285  * Values of the form "KEY=VALUE" in deltaenv override inherited values.
1286  * Values of the form "KEY" in deltaenv delete inherited values.
1287  *
1288  * Multiple entries in deltaenv for the same key are explicitly allowed.
1289  *
1290  * We return a contiguous block of UNICODE strings with a final trailing
1291  * zero word.
1292  */
make_environment_block(char ** deltaenv)1293 static wchar_t *make_environment_block(char **deltaenv)
1294 {
1295 	wchar_t *wenv = GetEnvironmentStringsW(), *wdeltaenv, *result, *p;
1296 	size_t wlen, s, delta_size, size;
1297 
1298 	wchar_t **array = NULL;
1299 	size_t alloc = 0, nr = 0, i;
1300 
1301 	size = 1; /* for extra NUL at the end */
1302 
1303 	/* If there is no deltaenv to apply, simply return a copy. */
1304 	if (!deltaenv || !*deltaenv) {
1305 		for (p = wenv; p && *p; ) {
1306 			size_t s = wcslen(p) + 1;
1307 			size += s;
1308 			p += s;
1309 		}
1310 
1311 		ALLOC_ARRAY(result, size);
1312 		COPY_ARRAY(result, wenv, size);
1313 		FreeEnvironmentStringsW(wenv);
1314 		return result;
1315 	}
1316 
1317 	/*
1318 	 * If there is a deltaenv, let's accumulate all keys into `array`,
1319 	 * sort them using the stable git_stable_qsort() and then copy,
1320 	 * skipping duplicate keys
1321 	 */
1322 	for (p = wenv; p && *p; ) {
1323 		ALLOC_GROW(array, nr + 1, alloc);
1324 		s = wcslen(p) + 1;
1325 		array[nr++] = p;
1326 		p += s;
1327 		size += s;
1328 	}
1329 
1330 	/* (over-)assess size needed for wchar version of deltaenv */
1331 	for (delta_size = 0, i = 0; deltaenv[i]; i++)
1332 		delta_size += strlen(deltaenv[i]) * 2 + 1;
1333 	ALLOC_ARRAY(wdeltaenv, delta_size);
1334 
1335 	/* convert the deltaenv, appending to array */
1336 	for (i = 0, p = wdeltaenv; deltaenv[i]; i++) {
1337 		ALLOC_GROW(array, nr + 1, alloc);
1338 		wlen = xutftowcs(p, deltaenv[i], wdeltaenv + delta_size - p);
1339 		array[nr++] = p;
1340 		p += wlen + 1;
1341 	}
1342 
1343 	git_stable_qsort(array, nr, sizeof(*array), wenvcmp);
1344 	ALLOC_ARRAY(result, size + delta_size);
1345 
1346 	for (p = result, i = 0; i < nr; i++) {
1347 		/* Skip any duplicate keys; last one wins */
1348 		while (i + 1 < nr && !wenvcmp(array + i, array + i + 1))
1349 		       i++;
1350 
1351 		/* Skip "to delete" entry */
1352 		if (!wcschr(array[i], L'='))
1353 			continue;
1354 
1355 		size = wcslen(array[i]) + 1;
1356 		COPY_ARRAY(p, array[i], size);
1357 		p += size;
1358 	}
1359 	*p = L'\0';
1360 
1361 	free(array);
1362 	free(wdeltaenv);
1363 	FreeEnvironmentStringsW(wenv);
1364 	return result;
1365 }
1366 
do_unset_environment_variables(void)1367 static void do_unset_environment_variables(void)
1368 {
1369 	static int done;
1370 	char *p = unset_environment_variables;
1371 
1372 	if (done || !p)
1373 		return;
1374 	done = 1;
1375 
1376 	for (;;) {
1377 		char *comma = strchr(p, ',');
1378 
1379 		if (comma)
1380 			*comma = '\0';
1381 		unsetenv(p);
1382 		if (!comma)
1383 			break;
1384 		p = comma + 1;
1385 	}
1386 }
1387 
1388 struct pinfo_t {
1389 	struct pinfo_t *next;
1390 	pid_t pid;
1391 	HANDLE proc;
1392 };
1393 static struct pinfo_t *pinfo = NULL;
1394 CRITICAL_SECTION pinfo_cs;
1395 
1396 /* Used to match and chomp off path components */
match_last_path_component(const char * path,size_t * len,const char * component)1397 static inline int match_last_path_component(const char *path, size_t *len,
1398 					    const char *component)
1399 {
1400 	size_t component_len = strlen(component);
1401 	if (*len < component_len + 1 ||
1402 	    !is_dir_sep(path[*len - component_len - 1]) ||
1403 	    fspathncmp(path + *len - component_len, component, component_len))
1404 		return 0;
1405 	*len -= component_len + 1;
1406 	/* chomp off repeated dir separators */
1407 	while (*len > 0 && is_dir_sep(path[*len - 1]))
1408 		(*len)--;
1409 	return 1;
1410 }
1411 
is_msys2_sh(const char * cmd)1412 static int is_msys2_sh(const char *cmd)
1413 {
1414 	if (!cmd)
1415 		return 0;
1416 
1417 	if (!strcmp(cmd, "sh")) {
1418 		static int ret = -1;
1419 		char *p;
1420 
1421 		if (ret >= 0)
1422 			return ret;
1423 
1424 		p = path_lookup(cmd, 0);
1425 		if (!p)
1426 			ret = 0;
1427 		else {
1428 			size_t len = strlen(p);
1429 
1430 			ret = match_last_path_component(p, &len, "sh.exe") &&
1431 				match_last_path_component(p, &len, "bin") &&
1432 				match_last_path_component(p, &len, "usr");
1433 			free(p);
1434 		}
1435 		return ret;
1436 	}
1437 
1438 	if (ends_with(cmd, "\\sh.exe")) {
1439 		static char *sh;
1440 
1441 		if (!sh)
1442 			sh = path_lookup("sh", 0);
1443 
1444 		return !fspathcmp(cmd, sh);
1445 	}
1446 
1447 	return 0;
1448 }
1449 
mingw_spawnve_fd(const char * cmd,const char ** argv,char ** deltaenv,const char * dir,int prepend_cmd,int fhin,int fhout,int fherr)1450 static pid_t mingw_spawnve_fd(const char *cmd, const char **argv, char **deltaenv,
1451 			      const char *dir,
1452 			      int prepend_cmd, int fhin, int fhout, int fherr)
1453 {
1454 	static int restrict_handle_inheritance = -1;
1455 	STARTUPINFOEXW si;
1456 	PROCESS_INFORMATION pi;
1457 	LPPROC_THREAD_ATTRIBUTE_LIST attr_list = NULL;
1458 	HANDLE stdhandles[3];
1459 	DWORD stdhandles_count = 0;
1460 	SIZE_T size;
1461 	struct strbuf args;
1462 	wchar_t wcmd[MAX_PATH], wdir[MAX_PATH], *wargs, *wenvblk = NULL;
1463 	unsigned flags = CREATE_UNICODE_ENVIRONMENT;
1464 	BOOL ret;
1465 	HANDLE cons;
1466 	const char *(*quote_arg)(const char *arg) =
1467 		is_msys2_sh(cmd ? cmd : *argv) ?
1468 		quote_arg_msys2 : quote_arg_msvc;
1469 
1470 	/* Make sure to override previous errors, if any */
1471 	errno = 0;
1472 
1473 	if (restrict_handle_inheritance < 0)
1474 		restrict_handle_inheritance = core_restrict_inherited_handles;
1475 	/*
1476 	 * The following code to restrict which handles are inherited seems
1477 	 * to work properly only on Windows 7 and later, so let's disable it
1478 	 * on Windows Vista and 2008.
1479 	 */
1480 	if (restrict_handle_inheritance < 0)
1481 		restrict_handle_inheritance = GetVersion() >> 16 >= 7601;
1482 
1483 	do_unset_environment_variables();
1484 
1485 	/* Determine whether or not we are associated to a console */
1486 	cons = CreateFileW(L"CONOUT$", GENERIC_WRITE,
1487 			FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
1488 			FILE_ATTRIBUTE_NORMAL, NULL);
1489 	if (cons == INVALID_HANDLE_VALUE) {
1490 		/* There is no console associated with this process.
1491 		 * Since the child is a console process, Windows
1492 		 * would normally create a console window. But
1493 		 * since we'll be redirecting std streams, we do
1494 		 * not need the console.
1495 		 * It is necessary to use DETACHED_PROCESS
1496 		 * instead of CREATE_NO_WINDOW to make ssh
1497 		 * recognize that it has no console.
1498 		 */
1499 		flags |= DETACHED_PROCESS;
1500 	} else {
1501 		/* There is already a console. If we specified
1502 		 * DETACHED_PROCESS here, too, Windows would
1503 		 * disassociate the child from the console.
1504 		 * The same is true for CREATE_NO_WINDOW.
1505 		 * Go figure!
1506 		 */
1507 		CloseHandle(cons);
1508 	}
1509 	memset(&si, 0, sizeof(si));
1510 	si.StartupInfo.cb = sizeof(si);
1511 	si.StartupInfo.hStdInput = winansi_get_osfhandle(fhin);
1512 	si.StartupInfo.hStdOutput = winansi_get_osfhandle(fhout);
1513 	si.StartupInfo.hStdError = winansi_get_osfhandle(fherr);
1514 
1515 	/* The list of handles cannot contain duplicates */
1516 	if (si.StartupInfo.hStdInput != INVALID_HANDLE_VALUE)
1517 		stdhandles[stdhandles_count++] = si.StartupInfo.hStdInput;
1518 	if (si.StartupInfo.hStdOutput != INVALID_HANDLE_VALUE &&
1519 	    si.StartupInfo.hStdOutput != si.StartupInfo.hStdInput)
1520 		stdhandles[stdhandles_count++] = si.StartupInfo.hStdOutput;
1521 	if (si.StartupInfo.hStdError != INVALID_HANDLE_VALUE &&
1522 	    si.StartupInfo.hStdError != si.StartupInfo.hStdInput &&
1523 	    si.StartupInfo.hStdError != si.StartupInfo.hStdOutput)
1524 		stdhandles[stdhandles_count++] = si.StartupInfo.hStdError;
1525 	if (stdhandles_count)
1526 		si.StartupInfo.dwFlags |= STARTF_USESTDHANDLES;
1527 
1528 	if (*argv && !strcmp(cmd, *argv))
1529 		wcmd[0] = L'\0';
1530 	else if (xutftowcs_path(wcmd, cmd) < 0)
1531 		return -1;
1532 	if (dir && xutftowcs_path(wdir, dir) < 0)
1533 		return -1;
1534 
1535 	/* concatenate argv, quoting args as we go */
1536 	strbuf_init(&args, 0);
1537 	if (prepend_cmd) {
1538 		char *quoted = (char *)quote_arg(cmd);
1539 		strbuf_addstr(&args, quoted);
1540 		if (quoted != cmd)
1541 			free(quoted);
1542 	}
1543 	for (; *argv; argv++) {
1544 		char *quoted = (char *)quote_arg(*argv);
1545 		if (*args.buf)
1546 			strbuf_addch(&args, ' ');
1547 		strbuf_addstr(&args, quoted);
1548 		if (quoted != *argv)
1549 			free(quoted);
1550 	}
1551 
1552 	ALLOC_ARRAY(wargs, st_add(st_mult(2, args.len), 1));
1553 	xutftowcs(wargs, args.buf, 2 * args.len + 1);
1554 	strbuf_release(&args);
1555 
1556 	wenvblk = make_environment_block(deltaenv);
1557 
1558 	memset(&pi, 0, sizeof(pi));
1559 	if (restrict_handle_inheritance && stdhandles_count &&
1560 	    (InitializeProcThreadAttributeList(NULL, 1, 0, &size) ||
1561 	     GetLastError() == ERROR_INSUFFICIENT_BUFFER) &&
1562 	    (attr_list = (LPPROC_THREAD_ATTRIBUTE_LIST)
1563 			(HeapAlloc(GetProcessHeap(), 0, size))) &&
1564 	    InitializeProcThreadAttributeList(attr_list, 1, 0, &size) &&
1565 	    UpdateProcThreadAttribute(attr_list, 0,
1566 				      PROC_THREAD_ATTRIBUTE_HANDLE_LIST,
1567 				      stdhandles,
1568 				      stdhandles_count * sizeof(HANDLE),
1569 				      NULL, NULL)) {
1570 		si.lpAttributeList = attr_list;
1571 		flags |= EXTENDED_STARTUPINFO_PRESENT;
1572 	}
1573 
1574 	ret = CreateProcessW(*wcmd ? wcmd : NULL, wargs, NULL, NULL,
1575 			     stdhandles_count ? TRUE : FALSE,
1576 			     flags, wenvblk, dir ? wdir : NULL,
1577 			     &si.StartupInfo, &pi);
1578 
1579 	/*
1580 	 * On Windows 2008 R2, it seems that specifying certain types of handles
1581 	 * (such as FILE_TYPE_CHAR or FILE_TYPE_PIPE) will always produce an
1582 	 * error. Rather than playing finicky and fragile games, let's just try
1583 	 * to detect this situation and simply try again without restricting any
1584 	 * handle inheritance. This is still better than failing to create
1585 	 * processes.
1586 	 */
1587 	if (!ret && restrict_handle_inheritance && stdhandles_count) {
1588 		DWORD err = GetLastError();
1589 		struct strbuf buf = STRBUF_INIT;
1590 
1591 		if (err != ERROR_NO_SYSTEM_RESOURCES &&
1592 		    /*
1593 		     * On Windows 7 and earlier, handles on pipes and character
1594 		     * devices are inherited automatically, and cannot be
1595 		     * specified in the thread handle list. Rather than trying
1596 		     * to catch each and every corner case (and running the
1597 		     * chance of *still* forgetting a few), let's just fall
1598 		     * back to creating the process without trying to limit the
1599 		     * handle inheritance.
1600 		     */
1601 		    !(err == ERROR_INVALID_PARAMETER &&
1602 		      GetVersion() >> 16 < 9200) &&
1603 		    !getenv("SUPPRESS_HANDLE_INHERITANCE_WARNING")) {
1604 			DWORD fl = 0;
1605 			int i;
1606 
1607 			setenv("SUPPRESS_HANDLE_INHERITANCE_WARNING", "1", 1);
1608 
1609 			for (i = 0; i < stdhandles_count; i++) {
1610 				HANDLE h = stdhandles[i];
1611 				strbuf_addf(&buf, "handle #%d: %p (type %lx, "
1612 					    "handle info (%d) %lx\n", i, h,
1613 					    GetFileType(h),
1614 					    GetHandleInformation(h, &fl),
1615 					    fl);
1616 			}
1617 			strbuf_addstr(&buf, "\nThis is a bug; please report it "
1618 				      "at\nhttps://github.com/git-for-windows/"
1619 				      "git/issues/new\n\n"
1620 				      "To suppress this warning, please set "
1621 				      "the environment variable\n\n"
1622 				      "\tSUPPRESS_HANDLE_INHERITANCE_WARNING=1"
1623 				      "\n");
1624 		}
1625 		restrict_handle_inheritance = 0;
1626 		flags &= ~EXTENDED_STARTUPINFO_PRESENT;
1627 		ret = CreateProcessW(*wcmd ? wcmd : NULL, wargs, NULL, NULL,
1628 				     TRUE, flags, wenvblk, dir ? wdir : NULL,
1629 				     &si.StartupInfo, &pi);
1630 		if (!ret)
1631 			errno = err_win_to_posix(GetLastError());
1632 		if (ret && buf.len) {
1633 			warning("failed to restrict file handles (%ld)\n\n%s",
1634 				err, buf.buf);
1635 		}
1636 		strbuf_release(&buf);
1637 	} else if (!ret)
1638 		errno = err_win_to_posix(GetLastError());
1639 
1640 	if (si.lpAttributeList)
1641 		DeleteProcThreadAttributeList(si.lpAttributeList);
1642 	if (attr_list)
1643 		HeapFree(GetProcessHeap(), 0, attr_list);
1644 
1645 	free(wenvblk);
1646 	free(wargs);
1647 
1648 	if (!ret)
1649 		return -1;
1650 
1651 	CloseHandle(pi.hThread);
1652 
1653 	/*
1654 	 * The process ID is the human-readable identifier of the process
1655 	 * that we want to present in log and error messages. The handle
1656 	 * is not useful for this purpose. But we cannot close it, either,
1657 	 * because it is not possible to turn a process ID into a process
1658 	 * handle after the process terminated.
1659 	 * Keep the handle in a list for waitpid.
1660 	 */
1661 	EnterCriticalSection(&pinfo_cs);
1662 	{
1663 		struct pinfo_t *info = xmalloc(sizeof(struct pinfo_t));
1664 		info->pid = pi.dwProcessId;
1665 		info->proc = pi.hProcess;
1666 		info->next = pinfo;
1667 		pinfo = info;
1668 	}
1669 	LeaveCriticalSection(&pinfo_cs);
1670 
1671 	return (pid_t)pi.dwProcessId;
1672 }
1673 
mingw_spawnv(const char * cmd,const char ** argv,int prepend_cmd)1674 static pid_t mingw_spawnv(const char *cmd, const char **argv, int prepend_cmd)
1675 {
1676 	return mingw_spawnve_fd(cmd, argv, NULL, NULL, prepend_cmd, 0, 1, 2);
1677 }
1678 
mingw_spawnvpe(const char * cmd,const char ** argv,char ** deltaenv,const char * dir,int fhin,int fhout,int fherr)1679 pid_t mingw_spawnvpe(const char *cmd, const char **argv, char **deltaenv,
1680 		     const char *dir,
1681 		     int fhin, int fhout, int fherr)
1682 {
1683 	pid_t pid;
1684 	char *prog = path_lookup(cmd, 0);
1685 
1686 	if (!prog) {
1687 		errno = ENOENT;
1688 		pid = -1;
1689 	}
1690 	else {
1691 		const char *interpr = parse_interpreter(prog);
1692 
1693 		if (interpr) {
1694 			const char *argv0 = argv[0];
1695 			char *iprog = path_lookup(interpr, 1);
1696 			argv[0] = prog;
1697 			if (!iprog) {
1698 				errno = ENOENT;
1699 				pid = -1;
1700 			}
1701 			else {
1702 				pid = mingw_spawnve_fd(iprog, argv, deltaenv, dir, 1,
1703 						       fhin, fhout, fherr);
1704 				free(iprog);
1705 			}
1706 			argv[0] = argv0;
1707 		}
1708 		else
1709 			pid = mingw_spawnve_fd(prog, argv, deltaenv, dir, 0,
1710 					       fhin, fhout, fherr);
1711 		free(prog);
1712 	}
1713 	return pid;
1714 }
1715 
try_shell_exec(const char * cmd,char * const * argv)1716 static int try_shell_exec(const char *cmd, char *const *argv)
1717 {
1718 	const char *interpr = parse_interpreter(cmd);
1719 	char *prog;
1720 	int pid = 0;
1721 
1722 	if (!interpr)
1723 		return 0;
1724 	prog = path_lookup(interpr, 1);
1725 	if (prog) {
1726 		int exec_id;
1727 		int argc = 0;
1728 #ifndef _MSC_VER
1729 		const
1730 #endif
1731 		char **argv2;
1732 		while (argv[argc]) argc++;
1733 		ALLOC_ARRAY(argv2, argc + 1);
1734 		argv2[0] = (char *)cmd;	/* full path to the script file */
1735 		COPY_ARRAY(&argv2[1], &argv[1], argc);
1736 		exec_id = trace2_exec(prog, argv2);
1737 		pid = mingw_spawnv(prog, argv2, 1);
1738 		if (pid >= 0) {
1739 			int status;
1740 			if (waitpid(pid, &status, 0) < 0)
1741 				status = 255;
1742 			trace2_exec_result(exec_id, status);
1743 			exit(status);
1744 		}
1745 		trace2_exec_result(exec_id, -1);
1746 		pid = 1;	/* indicate that we tried but failed */
1747 		free(prog);
1748 		free(argv2);
1749 	}
1750 	return pid;
1751 }
1752 
mingw_execv(const char * cmd,char * const * argv)1753 int mingw_execv(const char *cmd, char *const *argv)
1754 {
1755 	/* check if git_command is a shell script */
1756 	if (!try_shell_exec(cmd, argv)) {
1757 		int pid, status;
1758 		int exec_id;
1759 
1760 		exec_id = trace2_exec(cmd, (const char **)argv);
1761 		pid = mingw_spawnv(cmd, (const char **)argv, 0);
1762 		if (pid < 0) {
1763 			trace2_exec_result(exec_id, -1);
1764 			return -1;
1765 		}
1766 		if (waitpid(pid, &status, 0) < 0)
1767 			status = 255;
1768 		trace2_exec_result(exec_id, status);
1769 		exit(status);
1770 	}
1771 	return -1;
1772 }
1773 
mingw_execvp(const char * cmd,char * const * argv)1774 int mingw_execvp(const char *cmd, char *const *argv)
1775 {
1776 	char *prog = path_lookup(cmd, 0);
1777 
1778 	if (prog) {
1779 		mingw_execv(prog, argv);
1780 		free(prog);
1781 	} else
1782 		errno = ENOENT;
1783 
1784 	return -1;
1785 }
1786 
mingw_kill(pid_t pid,int sig)1787 int mingw_kill(pid_t pid, int sig)
1788 {
1789 	if (pid > 0 && sig == SIGTERM) {
1790 		HANDLE h = OpenProcess(PROCESS_TERMINATE, FALSE, pid);
1791 
1792 		if (TerminateProcess(h, -1)) {
1793 			CloseHandle(h);
1794 			return 0;
1795 		}
1796 
1797 		errno = err_win_to_posix(GetLastError());
1798 		CloseHandle(h);
1799 		return -1;
1800 	} else if (pid > 0 && sig == 0) {
1801 		HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
1802 		if (h) {
1803 			CloseHandle(h);
1804 			return 0;
1805 		}
1806 	}
1807 
1808 	errno = EINVAL;
1809 	return -1;
1810 }
1811 
1812 /*
1813  * UTF-8 versions of getenv(), putenv() and unsetenv().
1814  * Internally, they use the CRT's stock UNICODE routines
1815  * to avoid data loss.
1816  */
mingw_getenv(const char * name)1817 char *mingw_getenv(const char *name)
1818 {
1819 #define GETENV_MAX_RETAIN 64
1820 	static char *values[GETENV_MAX_RETAIN];
1821 	static int value_counter;
1822 	int len_key, len_value;
1823 	wchar_t *w_key;
1824 	char *value;
1825 	wchar_t w_value[32768];
1826 
1827 	if (!name || !*name)
1828 		return NULL;
1829 
1830 	len_key = strlen(name) + 1;
1831 	/* We cannot use xcalloc() here because that uses getenv() itself */
1832 	w_key = calloc(len_key, sizeof(wchar_t));
1833 	if (!w_key)
1834 		die("Out of memory, (tried to allocate %u wchar_t's)", len_key);
1835 	xutftowcs(w_key, name, len_key);
1836 	/* GetEnvironmentVariableW() only sets the last error upon failure */
1837 	SetLastError(ERROR_SUCCESS);
1838 	len_value = GetEnvironmentVariableW(w_key, w_value, ARRAY_SIZE(w_value));
1839 	if (!len_value && GetLastError() == ERROR_ENVVAR_NOT_FOUND) {
1840 		free(w_key);
1841 		return NULL;
1842 	}
1843 	free(w_key);
1844 
1845 	len_value = len_value * 3 + 1;
1846 	/* We cannot use xcalloc() here because that uses getenv() itself */
1847 	value = calloc(len_value, sizeof(char));
1848 	if (!value)
1849 		die("Out of memory, (tried to allocate %u bytes)", len_value);
1850 	xwcstoutf(value, w_value, len_value);
1851 
1852 	/*
1853 	 * We return `value` which is an allocated value and the caller is NOT
1854 	 * expecting to have to free it, so we keep a round-robin array,
1855 	 * invalidating the buffer after GETENV_MAX_RETAIN getenv() calls.
1856 	 */
1857 	free(values[value_counter]);
1858 	values[value_counter++] = value;
1859 	if (value_counter >= ARRAY_SIZE(values))
1860 		value_counter = 0;
1861 
1862 	return value;
1863 }
1864 
mingw_putenv(const char * namevalue)1865 int mingw_putenv(const char *namevalue)
1866 {
1867 	int size;
1868 	wchar_t *wide, *equal;
1869 	BOOL result;
1870 
1871 	if (!namevalue || !*namevalue)
1872 		return 0;
1873 
1874 	size = strlen(namevalue) * 2 + 1;
1875 	wide = calloc(size, sizeof(wchar_t));
1876 	if (!wide)
1877 		die("Out of memory, (tried to allocate %u wchar_t's)", size);
1878 	xutftowcs(wide, namevalue, size);
1879 	equal = wcschr(wide, L'=');
1880 	if (!equal)
1881 		result = SetEnvironmentVariableW(wide, NULL);
1882 	else {
1883 		*equal = L'\0';
1884 		result = SetEnvironmentVariableW(wide, equal + 1);
1885 	}
1886 	free(wide);
1887 
1888 	if (!result)
1889 		errno = err_win_to_posix(GetLastError());
1890 
1891 	return result ? 0 : -1;
1892 }
1893 
ensure_socket_initialization(void)1894 static void ensure_socket_initialization(void)
1895 {
1896 	WSADATA wsa;
1897 	static int initialized = 0;
1898 
1899 	if (initialized)
1900 		return;
1901 
1902 	if (WSAStartup(MAKEWORD(2,2), &wsa))
1903 		die("unable to initialize winsock subsystem, error %d",
1904 			WSAGetLastError());
1905 
1906 	atexit((void(*)(void)) WSACleanup);
1907 	initialized = 1;
1908 }
1909 
1910 #undef gethostname
mingw_gethostname(char * name,int namelen)1911 int mingw_gethostname(char *name, int namelen)
1912 {
1913     ensure_socket_initialization();
1914     return gethostname(name, namelen);
1915 }
1916 
1917 #undef gethostbyname
mingw_gethostbyname(const char * host)1918 struct hostent *mingw_gethostbyname(const char *host)
1919 {
1920 	ensure_socket_initialization();
1921 	return gethostbyname(host);
1922 }
1923 
1924 #undef getaddrinfo
mingw_getaddrinfo(const char * node,const char * service,const struct addrinfo * hints,struct addrinfo ** res)1925 int mingw_getaddrinfo(const char *node, const char *service,
1926 		      const struct addrinfo *hints, struct addrinfo **res)
1927 {
1928 	ensure_socket_initialization();
1929 	return getaddrinfo(node, service, hints, res);
1930 }
1931 
mingw_socket(int domain,int type,int protocol)1932 int mingw_socket(int domain, int type, int protocol)
1933 {
1934 	int sockfd;
1935 	SOCKET s;
1936 
1937 	ensure_socket_initialization();
1938 	s = WSASocket(domain, type, protocol, NULL, 0, 0);
1939 	if (s == INVALID_SOCKET) {
1940 		/*
1941 		 * WSAGetLastError() values are regular BSD error codes
1942 		 * biased by WSABASEERR.
1943 		 * However, strerror() does not know about networking
1944 		 * specific errors, which are values beginning at 38 or so.
1945 		 * Therefore, we choose to leave the biased error code
1946 		 * in errno so that _if_ someone looks up the code somewhere,
1947 		 * then it is at least the number that are usually listed.
1948 		 */
1949 		errno = WSAGetLastError();
1950 		return -1;
1951 	}
1952 	/* convert into a file descriptor */
1953 	if ((sockfd = _open_osfhandle(s, O_RDWR|O_BINARY)) < 0) {
1954 		closesocket(s);
1955 		return error("unable to make a socket file descriptor: %s",
1956 			strerror(errno));
1957 	}
1958 	return sockfd;
1959 }
1960 
1961 #undef connect
mingw_connect(int sockfd,struct sockaddr * sa,size_t sz)1962 int mingw_connect(int sockfd, struct sockaddr *sa, size_t sz)
1963 {
1964 	SOCKET s = (SOCKET)_get_osfhandle(sockfd);
1965 	return connect(s, sa, sz);
1966 }
1967 
1968 #undef bind
mingw_bind(int sockfd,struct sockaddr * sa,size_t sz)1969 int mingw_bind(int sockfd, struct sockaddr *sa, size_t sz)
1970 {
1971 	SOCKET s = (SOCKET)_get_osfhandle(sockfd);
1972 	return bind(s, sa, sz);
1973 }
1974 
1975 #undef setsockopt
mingw_setsockopt(int sockfd,int lvl,int optname,void * optval,int optlen)1976 int mingw_setsockopt(int sockfd, int lvl, int optname, void *optval, int optlen)
1977 {
1978 	SOCKET s = (SOCKET)_get_osfhandle(sockfd);
1979 	return setsockopt(s, lvl, optname, (const char*)optval, optlen);
1980 }
1981 
1982 #undef shutdown
mingw_shutdown(int sockfd,int how)1983 int mingw_shutdown(int sockfd, int how)
1984 {
1985 	SOCKET s = (SOCKET)_get_osfhandle(sockfd);
1986 	return shutdown(s, how);
1987 }
1988 
1989 #undef listen
mingw_listen(int sockfd,int backlog)1990 int mingw_listen(int sockfd, int backlog)
1991 {
1992 	SOCKET s = (SOCKET)_get_osfhandle(sockfd);
1993 	return listen(s, backlog);
1994 }
1995 
1996 #undef accept
mingw_accept(int sockfd1,struct sockaddr * sa,socklen_t * sz)1997 int mingw_accept(int sockfd1, struct sockaddr *sa, socklen_t *sz)
1998 {
1999 	int sockfd2;
2000 
2001 	SOCKET s1 = (SOCKET)_get_osfhandle(sockfd1);
2002 	SOCKET s2 = accept(s1, sa, sz);
2003 
2004 	/* convert into a file descriptor */
2005 	if ((sockfd2 = _open_osfhandle(s2, O_RDWR|O_BINARY)) < 0) {
2006 		int err = errno;
2007 		closesocket(s2);
2008 		return error("unable to make a socket file descriptor: %s",
2009 			strerror(err));
2010 	}
2011 	return sockfd2;
2012 }
2013 
2014 #undef rename
mingw_rename(const char * pold,const char * pnew)2015 int mingw_rename(const char *pold, const char *pnew)
2016 {
2017 	DWORD attrs, gle;
2018 	int tries = 0;
2019 	wchar_t wpold[MAX_PATH], wpnew[MAX_PATH];
2020 	if (xutftowcs_path(wpold, pold) < 0 || xutftowcs_path(wpnew, pnew) < 0)
2021 		return -1;
2022 
2023 	/*
2024 	 * Try native rename() first to get errno right.
2025 	 * It is based on MoveFile(), which cannot overwrite existing files.
2026 	 */
2027 	if (!_wrename(wpold, wpnew))
2028 		return 0;
2029 	if (errno != EEXIST)
2030 		return -1;
2031 repeat:
2032 	if (MoveFileExW(wpold, wpnew, MOVEFILE_REPLACE_EXISTING))
2033 		return 0;
2034 	/* TODO: translate more errors */
2035 	gle = GetLastError();
2036 	if (gle == ERROR_ACCESS_DENIED &&
2037 	    (attrs = GetFileAttributesW(wpnew)) != INVALID_FILE_ATTRIBUTES) {
2038 		if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
2039 			DWORD attrsold = GetFileAttributesW(wpold);
2040 			if (attrsold == INVALID_FILE_ATTRIBUTES ||
2041 			    !(attrsold & FILE_ATTRIBUTE_DIRECTORY))
2042 				errno = EISDIR;
2043 			else if (!_wrmdir(wpnew))
2044 				goto repeat;
2045 			return -1;
2046 		}
2047 		if ((attrs & FILE_ATTRIBUTE_READONLY) &&
2048 		    SetFileAttributesW(wpnew, attrs & ~FILE_ATTRIBUTE_READONLY)) {
2049 			if (MoveFileExW(wpold, wpnew, MOVEFILE_REPLACE_EXISTING))
2050 				return 0;
2051 			gle = GetLastError();
2052 			/* revert file attributes on failure */
2053 			SetFileAttributesW(wpnew, attrs);
2054 		}
2055 	}
2056 	if (tries < ARRAY_SIZE(delay) && gle == ERROR_ACCESS_DENIED) {
2057 		/*
2058 		 * We assume that some other process had the source or
2059 		 * destination file open at the wrong moment and retry.
2060 		 * In order to give the other process a higher chance to
2061 		 * complete its operation, we give up our time slice now.
2062 		 * If we have to retry again, we do sleep a bit.
2063 		 */
2064 		Sleep(delay[tries]);
2065 		tries++;
2066 		goto repeat;
2067 	}
2068 	if (gle == ERROR_ACCESS_DENIED &&
2069 	       ask_yes_no_if_possible("Rename from '%s' to '%s' failed. "
2070 		       "Should I try again?", pold, pnew))
2071 		goto repeat;
2072 
2073 	errno = EACCES;
2074 	return -1;
2075 }
2076 
2077 /*
2078  * Note that this doesn't return the actual pagesize, but
2079  * the allocation granularity. If future Windows specific git code
2080  * needs the real getpagesize function, we need to find another solution.
2081  */
mingw_getpagesize(void)2082 int mingw_getpagesize(void)
2083 {
2084 	SYSTEM_INFO si;
2085 	GetSystemInfo(&si);
2086 	return si.dwAllocationGranularity;
2087 }
2088 
2089 /* See https://msdn.microsoft.com/en-us/library/windows/desktop/ms724435.aspx */
2090 enum EXTENDED_NAME_FORMAT {
2091 	NameDisplay = 3,
2092 	NameUserPrincipal = 8
2093 };
2094 
get_extended_user_info(enum EXTENDED_NAME_FORMAT type)2095 static char *get_extended_user_info(enum EXTENDED_NAME_FORMAT type)
2096 {
2097 	DECLARE_PROC_ADDR(secur32.dll, BOOL, GetUserNameExW,
2098 		enum EXTENDED_NAME_FORMAT, LPCWSTR, PULONG);
2099 	static wchar_t wbuffer[1024];
2100 	DWORD len;
2101 
2102 	if (!INIT_PROC_ADDR(GetUserNameExW))
2103 		return NULL;
2104 
2105 	len = ARRAY_SIZE(wbuffer);
2106 	if (GetUserNameExW(type, wbuffer, &len)) {
2107 		char *converted = xmalloc((len *= 3));
2108 		if (xwcstoutf(converted, wbuffer, len) >= 0)
2109 			return converted;
2110 		free(converted);
2111 	}
2112 
2113 	return NULL;
2114 }
2115 
mingw_query_user_email(void)2116 char *mingw_query_user_email(void)
2117 {
2118 	return get_extended_user_info(NameUserPrincipal);
2119 }
2120 
getpwuid(int uid)2121 struct passwd *getpwuid(int uid)
2122 {
2123 	static unsigned initialized;
2124 	static char user_name[100];
2125 	static struct passwd *p;
2126 	wchar_t buf[100];
2127 	DWORD len;
2128 
2129 	if (initialized)
2130 		return p;
2131 
2132 	len = ARRAY_SIZE(buf);
2133 	if (!GetUserNameW(buf, &len)) {
2134 		initialized = 1;
2135 		return NULL;
2136 	}
2137 
2138 	if (xwcstoutf(user_name, buf, sizeof(user_name)) < 0) {
2139 		initialized = 1;
2140 		return NULL;
2141 	}
2142 
2143 	p = xmalloc(sizeof(*p));
2144 	p->pw_name = user_name;
2145 	p->pw_gecos = get_extended_user_info(NameDisplay);
2146 	if (!p->pw_gecos)
2147 		p->pw_gecos = "unknown";
2148 	p->pw_dir = NULL;
2149 
2150 	initialized = 1;
2151 	return p;
2152 }
2153 
2154 static HANDLE timer_event;
2155 static HANDLE timer_thread;
2156 static int timer_interval;
2157 static int one_shot;
2158 static sig_handler_t timer_fn = SIG_DFL, sigint_fn = SIG_DFL;
2159 
2160 /* The timer works like this:
2161  * The thread, ticktack(), is a trivial routine that most of the time
2162  * only waits to receive the signal to terminate. The main thread tells
2163  * the thread to terminate by setting the timer_event to the signalled
2164  * state.
2165  * But ticktack() interrupts the wait state after the timer's interval
2166  * length to call the signal handler.
2167  */
2168 
ticktack(void * dummy)2169 static unsigned __stdcall ticktack(void *dummy)
2170 {
2171 	while (WaitForSingleObject(timer_event, timer_interval) == WAIT_TIMEOUT) {
2172 		mingw_raise(SIGALRM);
2173 		if (one_shot)
2174 			break;
2175 	}
2176 	return 0;
2177 }
2178 
start_timer_thread(void)2179 static int start_timer_thread(void)
2180 {
2181 	timer_event = CreateEvent(NULL, FALSE, FALSE, NULL);
2182 	if (timer_event) {
2183 		timer_thread = (HANDLE) _beginthreadex(NULL, 0, ticktack, NULL, 0, NULL);
2184 		if (!timer_thread )
2185 			return errno = ENOMEM,
2186 				error("cannot start timer thread");
2187 	} else
2188 		return errno = ENOMEM,
2189 			error("cannot allocate resources for timer");
2190 	return 0;
2191 }
2192 
stop_timer_thread(void)2193 static void stop_timer_thread(void)
2194 {
2195 	if (timer_event)
2196 		SetEvent(timer_event);	/* tell thread to terminate */
2197 	if (timer_thread) {
2198 		int rc = WaitForSingleObject(timer_thread, 10000);
2199 		if (rc == WAIT_TIMEOUT)
2200 			error("timer thread did not terminate timely");
2201 		else if (rc != WAIT_OBJECT_0)
2202 			error("waiting for timer thread failed: %lu",
2203 			      GetLastError());
2204 		CloseHandle(timer_thread);
2205 	}
2206 	if (timer_event)
2207 		CloseHandle(timer_event);
2208 	timer_event = NULL;
2209 	timer_thread = NULL;
2210 }
2211 
is_timeval_eq(const struct timeval * i1,const struct timeval * i2)2212 static inline int is_timeval_eq(const struct timeval *i1, const struct timeval *i2)
2213 {
2214 	return i1->tv_sec == i2->tv_sec && i1->tv_usec == i2->tv_usec;
2215 }
2216 
setitimer(int type,struct itimerval * in,struct itimerval * out)2217 int setitimer(int type, struct itimerval *in, struct itimerval *out)
2218 {
2219 	static const struct timeval zero;
2220 	static int atexit_done;
2221 
2222 	if (out != NULL)
2223 		return errno = EINVAL,
2224 			error("setitimer param 3 != NULL not implemented");
2225 	if (!is_timeval_eq(&in->it_interval, &zero) &&
2226 	    !is_timeval_eq(&in->it_interval, &in->it_value))
2227 		return errno = EINVAL,
2228 			error("setitimer: it_interval must be zero or eq it_value");
2229 
2230 	if (timer_thread)
2231 		stop_timer_thread();
2232 
2233 	if (is_timeval_eq(&in->it_value, &zero) &&
2234 	    is_timeval_eq(&in->it_interval, &zero))
2235 		return 0;
2236 
2237 	timer_interval = in->it_value.tv_sec * 1000 + in->it_value.tv_usec / 1000;
2238 	one_shot = is_timeval_eq(&in->it_interval, &zero);
2239 	if (!atexit_done) {
2240 		atexit(stop_timer_thread);
2241 		atexit_done = 1;
2242 	}
2243 	return start_timer_thread();
2244 }
2245 
sigaction(int sig,struct sigaction * in,struct sigaction * out)2246 int sigaction(int sig, struct sigaction *in, struct sigaction *out)
2247 {
2248 	if (sig != SIGALRM)
2249 		return errno = EINVAL,
2250 			error("sigaction only implemented for SIGALRM");
2251 	if (out != NULL)
2252 		return errno = EINVAL,
2253 			error("sigaction: param 3 != NULL not implemented");
2254 
2255 	timer_fn = in->sa_handler;
2256 	return 0;
2257 }
2258 
2259 #undef signal
mingw_signal(int sig,sig_handler_t handler)2260 sig_handler_t mingw_signal(int sig, sig_handler_t handler)
2261 {
2262 	sig_handler_t old;
2263 
2264 	switch (sig) {
2265 	case SIGALRM:
2266 		old = timer_fn;
2267 		timer_fn = handler;
2268 		break;
2269 
2270 	case SIGINT:
2271 		old = sigint_fn;
2272 		sigint_fn = handler;
2273 		break;
2274 
2275 	default:
2276 		return signal(sig, handler);
2277 	}
2278 
2279 	return old;
2280 }
2281 
2282 #undef raise
mingw_raise(int sig)2283 int mingw_raise(int sig)
2284 {
2285 	switch (sig) {
2286 	case SIGALRM:
2287 		if (timer_fn == SIG_DFL) {
2288 			if (isatty(STDERR_FILENO))
2289 				fputs("Alarm clock\n", stderr);
2290 			exit(128 + SIGALRM);
2291 		} else if (timer_fn != SIG_IGN)
2292 			timer_fn(SIGALRM);
2293 		return 0;
2294 
2295 	case SIGINT:
2296 		if (sigint_fn == SIG_DFL)
2297 			exit(128 + SIGINT);
2298 		else if (sigint_fn != SIG_IGN)
2299 			sigint_fn(SIGINT);
2300 		return 0;
2301 
2302 #if defined(_MSC_VER)
2303 	case SIGILL:
2304 	case SIGFPE:
2305 	case SIGSEGV:
2306 	case SIGTERM:
2307 	case SIGBREAK:
2308 	case SIGABRT:
2309 	case SIGABRT_COMPAT:
2310 		/*
2311 		 * The <signal.h> header in the MS C Runtime defines 8 signals
2312 		 * as being supported on the platform. Anything else causes an
2313 		 * "Invalid signal or error" (which in DEBUG builds causes the
2314 		 * Abort/Retry/Ignore dialog). We by-pass the CRT for things we
2315 		 * already know will fail.
2316 		 */
2317 		return raise(sig);
2318 	default:
2319 		errno = EINVAL;
2320 		return -1;
2321 
2322 #else
2323 
2324 	default:
2325 		return raise(sig);
2326 
2327 #endif
2328 
2329 	}
2330 }
2331 
link(const char * oldpath,const char * newpath)2332 int link(const char *oldpath, const char *newpath)
2333 {
2334 	wchar_t woldpath[MAX_PATH], wnewpath[MAX_PATH];
2335 	if (xutftowcs_path(woldpath, oldpath) < 0 ||
2336 		xutftowcs_path(wnewpath, newpath) < 0)
2337 		return -1;
2338 
2339 	if (!CreateHardLinkW(wnewpath, woldpath, NULL)) {
2340 		errno = err_win_to_posix(GetLastError());
2341 		return -1;
2342 	}
2343 	return 0;
2344 }
2345 
waitpid(pid_t pid,int * status,int options)2346 pid_t waitpid(pid_t pid, int *status, int options)
2347 {
2348 	HANDLE h = OpenProcess(SYNCHRONIZE | PROCESS_QUERY_INFORMATION,
2349 	    FALSE, pid);
2350 	if (!h) {
2351 		errno = ECHILD;
2352 		return -1;
2353 	}
2354 
2355 	if (pid > 0 && options & WNOHANG) {
2356 		if (WAIT_OBJECT_0 != WaitForSingleObject(h, 0)) {
2357 			CloseHandle(h);
2358 			return 0;
2359 		}
2360 		options &= ~WNOHANG;
2361 	}
2362 
2363 	if (options == 0) {
2364 		struct pinfo_t **ppinfo;
2365 		if (WaitForSingleObject(h, INFINITE) != WAIT_OBJECT_0) {
2366 			CloseHandle(h);
2367 			return 0;
2368 		}
2369 
2370 		if (status)
2371 			GetExitCodeProcess(h, (LPDWORD)status);
2372 
2373 		EnterCriticalSection(&pinfo_cs);
2374 
2375 		ppinfo = &pinfo;
2376 		while (*ppinfo) {
2377 			struct pinfo_t *info = *ppinfo;
2378 			if (info->pid == pid) {
2379 				CloseHandle(info->proc);
2380 				*ppinfo = info->next;
2381 				free(info);
2382 				break;
2383 			}
2384 			ppinfo = &info->next;
2385 		}
2386 
2387 		LeaveCriticalSection(&pinfo_cs);
2388 
2389 		CloseHandle(h);
2390 		return pid;
2391 	}
2392 	CloseHandle(h);
2393 
2394 	errno = EINVAL;
2395 	return -1;
2396 }
2397 
xutftowcsn(wchar_t * wcs,const char * utfs,size_t wcslen,int utflen)2398 int xutftowcsn(wchar_t *wcs, const char *utfs, size_t wcslen, int utflen)
2399 {
2400 	int upos = 0, wpos = 0;
2401 	const unsigned char *utf = (const unsigned char*) utfs;
2402 	if (!utf || !wcs || wcslen < 1) {
2403 		errno = EINVAL;
2404 		return -1;
2405 	}
2406 	/* reserve space for \0 */
2407 	wcslen--;
2408 	if (utflen < 0)
2409 		utflen = INT_MAX;
2410 
2411 	while (upos < utflen) {
2412 		int c = utf[upos++] & 0xff;
2413 		if (utflen == INT_MAX && c == 0)
2414 			break;
2415 
2416 		if (wpos >= wcslen) {
2417 			wcs[wpos] = 0;
2418 			errno = ERANGE;
2419 			return -1;
2420 		}
2421 
2422 		if (c < 0x80) {
2423 			/* ASCII */
2424 			wcs[wpos++] = c;
2425 		} else if (c >= 0xc2 && c < 0xe0 && upos < utflen &&
2426 				(utf[upos] & 0xc0) == 0x80) {
2427 			/* 2-byte utf-8 */
2428 			c = ((c & 0x1f) << 6);
2429 			c |= (utf[upos++] & 0x3f);
2430 			wcs[wpos++] = c;
2431 		} else if (c >= 0xe0 && c < 0xf0 && upos + 1 < utflen &&
2432 				!(c == 0xe0 && utf[upos] < 0xa0) && /* over-long encoding */
2433 				(utf[upos] & 0xc0) == 0x80 &&
2434 				(utf[upos + 1] & 0xc0) == 0x80) {
2435 			/* 3-byte utf-8 */
2436 			c = ((c & 0x0f) << 12);
2437 			c |= ((utf[upos++] & 0x3f) << 6);
2438 			c |= (utf[upos++] & 0x3f);
2439 			wcs[wpos++] = c;
2440 		} else if (c >= 0xf0 && c < 0xf5 && upos + 2 < utflen &&
2441 				wpos + 1 < wcslen &&
2442 				!(c == 0xf0 && utf[upos] < 0x90) && /* over-long encoding */
2443 				!(c == 0xf4 && utf[upos] >= 0x90) && /* > \u10ffff */
2444 				(utf[upos] & 0xc0) == 0x80 &&
2445 				(utf[upos + 1] & 0xc0) == 0x80 &&
2446 				(utf[upos + 2] & 0xc0) == 0x80) {
2447 			/* 4-byte utf-8: convert to \ud8xx \udcxx surrogate pair */
2448 			c = ((c & 0x07) << 18);
2449 			c |= ((utf[upos++] & 0x3f) << 12);
2450 			c |= ((utf[upos++] & 0x3f) << 6);
2451 			c |= (utf[upos++] & 0x3f);
2452 			c -= 0x10000;
2453 			wcs[wpos++] = 0xd800 | (c >> 10);
2454 			wcs[wpos++] = 0xdc00 | (c & 0x3ff);
2455 		} else if (c >= 0xa0) {
2456 			/* invalid utf-8 byte, printable unicode char: convert 1:1 */
2457 			wcs[wpos++] = c;
2458 		} else {
2459 			/* invalid utf-8 byte, non-printable unicode: convert to hex */
2460 			static const char *hex = "0123456789abcdef";
2461 			wcs[wpos++] = hex[c >> 4];
2462 			if (wpos < wcslen)
2463 				wcs[wpos++] = hex[c & 0x0f];
2464 		}
2465 	}
2466 	wcs[wpos] = 0;
2467 	return wpos;
2468 }
2469 
xwcstoutf(char * utf,const wchar_t * wcs,size_t utflen)2470 int xwcstoutf(char *utf, const wchar_t *wcs, size_t utflen)
2471 {
2472 	if (!wcs || !utf || utflen < 1) {
2473 		errno = EINVAL;
2474 		return -1;
2475 	}
2476 	utflen = WideCharToMultiByte(CP_UTF8, 0, wcs, -1, utf, utflen, NULL, NULL);
2477 	if (utflen)
2478 		return utflen - 1;
2479 	errno = ERANGE;
2480 	return -1;
2481 }
2482 
setup_windows_environment(void)2483 static void setup_windows_environment(void)
2484 {
2485 	char *tmp = getenv("TMPDIR");
2486 
2487 	/* on Windows it is TMP and TEMP */
2488 	if (!tmp) {
2489 		if (!(tmp = getenv("TMP")))
2490 			tmp = getenv("TEMP");
2491 		if (tmp) {
2492 			setenv("TMPDIR", tmp, 1);
2493 			tmp = getenv("TMPDIR");
2494 		}
2495 	}
2496 
2497 	if (tmp) {
2498 		/*
2499 		 * Convert all dir separators to forward slashes,
2500 		 * to help shell commands called from the Git
2501 		 * executable (by not mistaking the dir separators
2502 		 * for escape characters).
2503 		 */
2504 		convert_slashes(tmp);
2505 	}
2506 
2507 	/* simulate TERM to enable auto-color (see color.c) */
2508 	if (!getenv("TERM"))
2509 		setenv("TERM", "cygwin", 1);
2510 
2511 	/* calculate HOME if not set */
2512 	if (!getenv("HOME")) {
2513 		/*
2514 		 * try $HOMEDRIVE$HOMEPATH - the home share may be a network
2515 		 * location, thus also check if the path exists (i.e. is not
2516 		 * disconnected)
2517 		 */
2518 		if ((tmp = getenv("HOMEDRIVE"))) {
2519 			struct strbuf buf = STRBUF_INIT;
2520 			strbuf_addstr(&buf, tmp);
2521 			if ((tmp = getenv("HOMEPATH"))) {
2522 				strbuf_addstr(&buf, tmp);
2523 				if (is_directory(buf.buf))
2524 					setenv("HOME", buf.buf, 1);
2525 				else
2526 					tmp = NULL; /* use $USERPROFILE */
2527 			}
2528 			strbuf_release(&buf);
2529 		}
2530 		/* use $USERPROFILE if the home share is not available */
2531 		if (!tmp && (tmp = getenv("USERPROFILE")))
2532 			setenv("HOME", tmp, 1);
2533 	}
2534 }
2535 
is_valid_win32_path(const char * path,int allow_literal_nul)2536 int is_valid_win32_path(const char *path, int allow_literal_nul)
2537 {
2538 	const char *p = path;
2539 	int preceding_space_or_period = 0, i = 0, periods = 0;
2540 
2541 	if (!protect_ntfs)
2542 		return 1;
2543 
2544 	skip_dos_drive_prefix((char **)&path);
2545 	goto segment_start;
2546 
2547 	for (;;) {
2548 		char c = *(path++);
2549 		switch (c) {
2550 		case '\0':
2551 		case '/': case '\\':
2552 			/* cannot end in ` ` or `.`, except for `.` and `..` */
2553 			if (preceding_space_or_period &&
2554 			    (i != periods || periods > 2))
2555 				return 0;
2556 			if (!c)
2557 				return 1;
2558 
2559 			i = periods = preceding_space_or_period = 0;
2560 
2561 segment_start:
2562 			switch (*path) {
2563 			case 'a': case 'A': /* AUX */
2564 				if (((c = path[++i]) != 'u' && c != 'U') ||
2565 				    ((c = path[++i]) != 'x' && c != 'X')) {
2566 not_a_reserved_name:
2567 					path += i;
2568 					continue;
2569 				}
2570 				break;
2571 			case 'c': case 'C': /* COM<N>, CON, CONIN$, CONOUT$ */
2572 				if ((c = path[++i]) != 'o' && c != 'O')
2573 					goto not_a_reserved_name;
2574 				c = path[++i];
2575 				if (c == 'm' || c == 'M') { /* COM<N> */
2576 					if (!isdigit(path[++i]))
2577 						goto not_a_reserved_name;
2578 				} else if (c == 'n' || c == 'N') { /* CON */
2579 					c = path[i + 1];
2580 					if ((c == 'i' || c == 'I') &&
2581 					    ((c = path[i + 2]) == 'n' ||
2582 					     c == 'N') &&
2583 					    path[i + 3] == '$')
2584 						i += 3; /* CONIN$ */
2585 					else if ((c == 'o' || c == 'O') &&
2586 						 ((c = path[i + 2]) == 'u' ||
2587 						  c == 'U') &&
2588 						 ((c = path[i + 3]) == 't' ||
2589 						  c == 'T') &&
2590 						 path[i + 4] == '$')
2591 						i += 4; /* CONOUT$ */
2592 				} else
2593 					goto not_a_reserved_name;
2594 				break;
2595 			case 'l': case 'L': /* LPT<N> */
2596 				if (((c = path[++i]) != 'p' && c != 'P') ||
2597 				    ((c = path[++i]) != 't' && c != 'T') ||
2598 				    !isdigit(path[++i]))
2599 					goto not_a_reserved_name;
2600 				break;
2601 			case 'n': case 'N': /* NUL */
2602 				if (((c = path[++i]) != 'u' && c != 'U') ||
2603 				    ((c = path[++i]) != 'l' && c != 'L') ||
2604 				    (allow_literal_nul &&
2605 				     !path[i + 1] && p == path))
2606 					goto not_a_reserved_name;
2607 				break;
2608 			case 'p': case 'P': /* PRN */
2609 				if (((c = path[++i]) != 'r' && c != 'R') ||
2610 				    ((c = path[++i]) != 'n' && c != 'N'))
2611 					goto not_a_reserved_name;
2612 				break;
2613 			default:
2614 				continue;
2615 			}
2616 
2617 			/*
2618 			 * So far, this looks like a reserved name. Let's see
2619 			 * whether it actually is one: trailing spaces, a file
2620 			 * extension, or an NTFS Alternate Data Stream do not
2621 			 * matter, the name is still reserved if any of those
2622 			 * follow immediately after the actual name.
2623 			 */
2624 			i++;
2625 			if (path[i] == ' ') {
2626 				preceding_space_or_period = 1;
2627 				while (path[++i] == ' ')
2628 					; /* skip all spaces */
2629 			}
2630 
2631 			c = path[i];
2632 			if (c && c != '.' && c != ':' && c != '/' && c != '\\')
2633 				goto not_a_reserved_name;
2634 
2635 			/* contains reserved name */
2636 			return 0;
2637 		case '.':
2638 			periods++;
2639 			/* fallthru */
2640 		case ' ':
2641 			preceding_space_or_period = 1;
2642 			i++;
2643 			continue;
2644 		case ':': /* DOS drive prefix was already skipped */
2645 		case '<': case '>': case '"': case '|': case '?': case '*':
2646 			/* illegal character */
2647 			return 0;
2648 		default:
2649 			if (c > '\0' && c < '\x20')
2650 				/* illegal character */
2651 				return 0;
2652 		}
2653 		preceding_space_or_period = 0;
2654 		i++;
2655 	}
2656 }
2657 
2658 #if !defined(_MSC_VER)
2659 /*
2660  * Disable MSVCRT command line wildcard expansion (__getmainargs called from
2661  * mingw startup code, see init.c in mingw runtime).
2662  */
2663 int _CRT_glob = 0;
2664 #endif
2665 
die_startup(void)2666 static NORETURN void die_startup(void)
2667 {
2668 	fputs("fatal: not enough memory for initialization", stderr);
2669 	exit(128);
2670 }
2671 
malloc_startup(size_t size)2672 static void *malloc_startup(size_t size)
2673 {
2674 	void *result = malloc(size);
2675 	if (!result)
2676 		die_startup();
2677 	return result;
2678 }
2679 
wcstoutfdup_startup(char * buffer,const wchar_t * wcs,size_t len)2680 static char *wcstoutfdup_startup(char *buffer, const wchar_t *wcs, size_t len)
2681 {
2682 	len = xwcstoutf(buffer, wcs, len) + 1;
2683 	return memcpy(malloc_startup(len), buffer, len);
2684 }
2685 
maybe_redirect_std_handle(const wchar_t * key,DWORD std_id,int fd,DWORD desired_access,DWORD flags)2686 static void maybe_redirect_std_handle(const wchar_t *key, DWORD std_id, int fd,
2687 				      DWORD desired_access, DWORD flags)
2688 {
2689 	DWORD create_flag = fd ? OPEN_ALWAYS : OPEN_EXISTING;
2690 	wchar_t buf[MAX_PATH];
2691 	DWORD max = ARRAY_SIZE(buf);
2692 	HANDLE handle;
2693 	DWORD ret = GetEnvironmentVariableW(key, buf, max);
2694 
2695 	if (!ret || ret >= max)
2696 		return;
2697 
2698 	/* make sure this does not leak into child processes */
2699 	SetEnvironmentVariableW(key, NULL);
2700 	if (!wcscmp(buf, L"off")) {
2701 		close(fd);
2702 		handle = GetStdHandle(std_id);
2703 		if (handle != INVALID_HANDLE_VALUE)
2704 			CloseHandle(handle);
2705 		return;
2706 	}
2707 	if (std_id == STD_ERROR_HANDLE && !wcscmp(buf, L"2>&1")) {
2708 		handle = GetStdHandle(STD_OUTPUT_HANDLE);
2709 		if (handle == INVALID_HANDLE_VALUE) {
2710 			close(fd);
2711 			handle = GetStdHandle(std_id);
2712 			if (handle != INVALID_HANDLE_VALUE)
2713 				CloseHandle(handle);
2714 		} else {
2715 			int new_fd = _open_osfhandle((intptr_t)handle, O_BINARY);
2716 			SetStdHandle(std_id, handle);
2717 			dup2(new_fd, fd);
2718 			/* do *not* close the new_fd: that would close stdout */
2719 		}
2720 		return;
2721 	}
2722 	handle = CreateFileW(buf, desired_access, 0, NULL, create_flag,
2723 			     flags, NULL);
2724 	if (handle != INVALID_HANDLE_VALUE) {
2725 		int new_fd = _open_osfhandle((intptr_t)handle, O_BINARY);
2726 		SetStdHandle(std_id, handle);
2727 		dup2(new_fd, fd);
2728 		close(new_fd);
2729 	}
2730 }
2731 
maybe_redirect_std_handles(void)2732 static void maybe_redirect_std_handles(void)
2733 {
2734 	maybe_redirect_std_handle(L"GIT_REDIRECT_STDIN", STD_INPUT_HANDLE, 0,
2735 				  GENERIC_READ, FILE_ATTRIBUTE_NORMAL);
2736 	maybe_redirect_std_handle(L"GIT_REDIRECT_STDOUT", STD_OUTPUT_HANDLE, 1,
2737 				  GENERIC_WRITE, FILE_ATTRIBUTE_NORMAL);
2738 	maybe_redirect_std_handle(L"GIT_REDIRECT_STDERR", STD_ERROR_HANDLE, 2,
2739 				  GENERIC_WRITE, FILE_FLAG_NO_BUFFERING);
2740 }
2741 
2742 #ifdef _MSC_VER
2743 #ifdef _DEBUG
2744 #include <crtdbg.h>
2745 #endif
2746 #endif
2747 
2748 /*
2749  * We implement wmain() and compile with -municode, which would
2750  * normally ignore main(), but we call the latter from the former
2751  * so that we can handle non-ASCII command-line parameters
2752  * appropriately.
2753  *
2754  * To be more compatible with the core git code, we convert
2755  * argv into UTF8 and pass them directly to main().
2756  */
wmain(int argc,const wchar_t ** wargv)2757 int wmain(int argc, const wchar_t **wargv)
2758 {
2759 	int i, maxlen, exit_status;
2760 	char *buffer, **save;
2761 	const char **argv;
2762 
2763 	trace2_initialize_clock();
2764 
2765 #ifdef _MSC_VER
2766 #ifdef _DEBUG
2767 	_CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG);
2768 #endif
2769 
2770 #ifdef USE_MSVC_CRTDBG
2771 	_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
2772 #endif
2773 #endif
2774 
2775 	maybe_redirect_std_handles();
2776 
2777 	/* determine size of argv and environ conversion buffer */
2778 	maxlen = wcslen(wargv[0]);
2779 	for (i = 1; i < argc; i++)
2780 		maxlen = max(maxlen, wcslen(wargv[i]));
2781 
2782 	/* allocate buffer (wchar_t encodes to max 3 UTF-8 bytes) */
2783 	maxlen = 3 * maxlen + 1;
2784 	buffer = malloc_startup(maxlen);
2785 
2786 	/*
2787 	 * Create a UTF-8 version of w_argv. Also create a "save" copy
2788 	 * to remember all the string pointers because parse_options()
2789 	 * will remove claimed items from the argv that we pass down.
2790 	 */
2791 	ALLOC_ARRAY(argv, argc + 1);
2792 	ALLOC_ARRAY(save, argc + 1);
2793 	for (i = 0; i < argc; i++)
2794 		argv[i] = save[i] = wcstoutfdup_startup(buffer, wargv[i], maxlen);
2795 	argv[i] = save[i] = NULL;
2796 	free(buffer);
2797 
2798 	/* fix Windows specific environment settings */
2799 	setup_windows_environment();
2800 
2801 	unset_environment_variables = xstrdup("PERL5LIB");
2802 
2803 	/* initialize critical section for waitpid pinfo_t list */
2804 	InitializeCriticalSection(&pinfo_cs);
2805 
2806 	/* set up default file mode and file modes for stdin/out/err */
2807 	_fmode = _O_BINARY;
2808 	_setmode(_fileno(stdin), _O_BINARY);
2809 	_setmode(_fileno(stdout), _O_BINARY);
2810 	_setmode(_fileno(stderr), _O_BINARY);
2811 
2812 	/* initialize Unicode console */
2813 	winansi_init();
2814 
2815 	/* invoke the real main() using our utf8 version of argv. */
2816 	exit_status = main(argc, argv);
2817 
2818 	for (i = 0; i < argc; i++)
2819 		free(save[i]);
2820 	free(save);
2821 	free(argv);
2822 
2823 	return exit_status;
2824 }
2825 
uname(struct utsname * buf)2826 int uname(struct utsname *buf)
2827 {
2828 	unsigned v = (unsigned)GetVersion();
2829 	memset(buf, 0, sizeof(*buf));
2830 	xsnprintf(buf->sysname, sizeof(buf->sysname), "Windows");
2831 	xsnprintf(buf->release, sizeof(buf->release),
2832 		 "%u.%u", v & 0xff, (v >> 8) & 0xff);
2833 	/* assuming NT variants only.. */
2834 	xsnprintf(buf->version, sizeof(buf->version),
2835 		  "%u", (v >> 16) & 0x7fff);
2836 	return 0;
2837 }
2838