Merge https://github.com/j6t/gitk
[git/gitster.git] / compat / mingw.c
blob63f36c893bfe96f223daa6c4c18d20fa3a347c2e
1 #define USE_THE_REPOSITORY_VARIABLE
3 #include "../git-compat-util.h"
4 #include "win32.h"
5 #include <aclapi.h>
6 #include <sddl.h>
7 #include <conio.h>
8 #include <wchar.h>
9 #include "../strbuf.h"
10 #include "../run-command.h"
11 #include "../abspath.h"
12 #include "../alloc.h"
13 #include "win32/lazyload.h"
14 #include "../config.h"
15 #include "../environment.h"
16 #include "../trace2.h"
17 #include "../symlinks.h"
18 #include "../wrapper.h"
19 #include "dir.h"
20 #include "gettext.h"
21 #define SECURITY_WIN32
22 #include <sspi.h>
24 #define HCAST(type, handle) ((type)(intptr_t)handle)
26 static const int delay[] = { 0, 1, 10, 20, 40 };
28 void open_in_gdb(void)
30 static struct child_process cp = CHILD_PROCESS_INIT;
32 strvec_pushl(&cp.args, "mintty", "gdb", NULL);
33 strvec_pushf(&cp.args, "--pid=%d", getpid());
34 cp.clean_on_exit = 1;
35 if (start_command(&cp) < 0)
36 die_errno("Could not start gdb");
37 sleep(1);
40 int err_win_to_posix(DWORD winerr)
42 int error = ENOSYS;
43 switch(winerr) {
44 case ERROR_ACCESS_DENIED: error = EACCES; break;
45 case ERROR_ACCOUNT_DISABLED: error = EACCES; break;
46 case ERROR_ACCOUNT_RESTRICTION: error = EACCES; break;
47 case ERROR_ALREADY_ASSIGNED: error = EBUSY; break;
48 case ERROR_ALREADY_EXISTS: error = EEXIST; break;
49 case ERROR_ARITHMETIC_OVERFLOW: error = ERANGE; break;
50 case ERROR_BAD_COMMAND: error = EIO; break;
51 case ERROR_BAD_DEVICE: error = ENODEV; break;
52 case ERROR_BAD_DRIVER_LEVEL: error = ENXIO; break;
53 case ERROR_BAD_EXE_FORMAT: error = ENOEXEC; break;
54 case ERROR_BAD_FORMAT: error = ENOEXEC; break;
55 case ERROR_BAD_LENGTH: error = EINVAL; break;
56 case ERROR_BAD_PATHNAME: error = ENOENT; break;
57 case ERROR_BAD_PIPE: error = EPIPE; break;
58 case ERROR_BAD_UNIT: error = ENODEV; break;
59 case ERROR_BAD_USERNAME: error = EINVAL; break;
60 case ERROR_BROKEN_PIPE: error = EPIPE; break;
61 case ERROR_BUFFER_OVERFLOW: error = ENAMETOOLONG; break;
62 case ERROR_BUSY: error = EBUSY; break;
63 case ERROR_BUSY_DRIVE: error = EBUSY; break;
64 case ERROR_CALL_NOT_IMPLEMENTED: error = ENOSYS; break;
65 case ERROR_CANNOT_MAKE: error = EACCES; break;
66 case ERROR_CANTOPEN: error = EIO; break;
67 case ERROR_CANTREAD: error = EIO; break;
68 case ERROR_CANTWRITE: error = EIO; break;
69 case ERROR_CRC: error = EIO; break;
70 case ERROR_CURRENT_DIRECTORY: error = EACCES; break;
71 case ERROR_DEVICE_IN_USE: error = EBUSY; break;
72 case ERROR_DEV_NOT_EXIST: error = ENODEV; break;
73 case ERROR_DIRECTORY: error = EINVAL; break;
74 case ERROR_DIR_NOT_EMPTY: error = ENOTEMPTY; break;
75 case ERROR_DISK_CHANGE: error = EIO; break;
76 case ERROR_DISK_FULL: error = ENOSPC; break;
77 case ERROR_DRIVE_LOCKED: error = EBUSY; break;
78 case ERROR_ENVVAR_NOT_FOUND: error = EINVAL; break;
79 case ERROR_EXE_MARKED_INVALID: error = ENOEXEC; break;
80 case ERROR_FILENAME_EXCED_RANGE: error = ENAMETOOLONG; break;
81 case ERROR_FILE_EXISTS: error = EEXIST; break;
82 case ERROR_FILE_INVALID: error = ENODEV; break;
83 case ERROR_FILE_NOT_FOUND: error = ENOENT; break;
84 case ERROR_GEN_FAILURE: error = EIO; break;
85 case ERROR_HANDLE_DISK_FULL: error = ENOSPC; break;
86 case ERROR_INSUFFICIENT_BUFFER: error = ENOMEM; break;
87 case ERROR_INVALID_ACCESS: error = EACCES; break;
88 case ERROR_INVALID_ADDRESS: error = EFAULT; break;
89 case ERROR_INVALID_BLOCK: error = EFAULT; break;
90 case ERROR_INVALID_DATA: error = EINVAL; break;
91 case ERROR_INVALID_DRIVE: error = ENODEV; break;
92 case ERROR_INVALID_EXE_SIGNATURE: error = ENOEXEC; break;
93 case ERROR_INVALID_FLAGS: error = EINVAL; break;
94 case ERROR_INVALID_FUNCTION: error = ENOSYS; break;
95 case ERROR_INVALID_HANDLE: error = EBADF; break;
96 case ERROR_INVALID_LOGON_HOURS: error = EACCES; break;
97 case ERROR_INVALID_NAME: error = EINVAL; break;
98 case ERROR_INVALID_OWNER: error = EINVAL; break;
99 case ERROR_INVALID_PARAMETER: error = EINVAL; break;
100 case ERROR_INVALID_PASSWORD: error = EPERM; break;
101 case ERROR_INVALID_PRIMARY_GROUP: error = EINVAL; break;
102 case ERROR_INVALID_SIGNAL_NUMBER: error = EINVAL; break;
103 case ERROR_INVALID_TARGET_HANDLE: error = EIO; break;
104 case ERROR_INVALID_WORKSTATION: error = EACCES; break;
105 case ERROR_IO_DEVICE: error = EIO; break;
106 case ERROR_IO_INCOMPLETE: error = EINTR; break;
107 case ERROR_LOCKED: error = EBUSY; break;
108 case ERROR_LOCK_VIOLATION: error = EACCES; break;
109 case ERROR_LOGON_FAILURE: error = EACCES; break;
110 case ERROR_MAPPED_ALIGNMENT: error = EINVAL; break;
111 case ERROR_META_EXPANSION_TOO_LONG: error = E2BIG; break;
112 case ERROR_MORE_DATA: error = EPIPE; break;
113 case ERROR_NEGATIVE_SEEK: error = ESPIPE; break;
114 case ERROR_NOACCESS: error = EFAULT; break;
115 case ERROR_NONE_MAPPED: error = EINVAL; break;
116 case ERROR_NOT_ENOUGH_MEMORY: error = ENOMEM; break;
117 case ERROR_NOT_READY: error = EAGAIN; break;
118 case ERROR_NOT_SAME_DEVICE: error = EXDEV; break;
119 case ERROR_NO_DATA: error = EPIPE; break;
120 case ERROR_NO_MORE_SEARCH_HANDLES: error = EIO; break;
121 case ERROR_NO_PROC_SLOTS: error = EAGAIN; break;
122 case ERROR_NO_SUCH_PRIVILEGE: error = EACCES; break;
123 case ERROR_OPEN_FAILED: error = EIO; break;
124 case ERROR_OPEN_FILES: error = EBUSY; break;
125 case ERROR_OPERATION_ABORTED: error = EINTR; break;
126 case ERROR_OUTOFMEMORY: error = ENOMEM; break;
127 case ERROR_PASSWORD_EXPIRED: error = EACCES; break;
128 case ERROR_PATH_BUSY: error = EBUSY; break;
129 case ERROR_PATH_NOT_FOUND: error = ENOENT; break;
130 case ERROR_PIPE_BUSY: error = EBUSY; break;
131 case ERROR_PIPE_CONNECTED: error = EPIPE; break;
132 case ERROR_PIPE_LISTENING: error = EPIPE; break;
133 case ERROR_PIPE_NOT_CONNECTED: error = EPIPE; break;
134 case ERROR_PRIVILEGE_NOT_HELD: error = EACCES; break;
135 case ERROR_READ_FAULT: error = EIO; break;
136 case ERROR_SEEK: error = EIO; break;
137 case ERROR_SEEK_ON_DEVICE: error = ESPIPE; break;
138 case ERROR_SHARING_BUFFER_EXCEEDED: error = ENFILE; break;
139 case ERROR_SHARING_VIOLATION: error = EACCES; break;
140 case ERROR_STACK_OVERFLOW: error = ENOMEM; break;
141 case ERROR_SUCCESS: BUG("err_win_to_posix() called without an error!");
142 case ERROR_SWAPERROR: error = ENOENT; break;
143 case ERROR_TOO_MANY_MODULES: error = EMFILE; break;
144 case ERROR_TOO_MANY_OPEN_FILES: error = EMFILE; break;
145 case ERROR_UNRECOGNIZED_MEDIA: error = ENXIO; break;
146 case ERROR_UNRECOGNIZED_VOLUME: error = ENODEV; break;
147 case ERROR_WAIT_NO_CHILDREN: error = ECHILD; break;
148 case ERROR_WRITE_FAULT: error = EIO; break;
149 case ERROR_WRITE_PROTECT: error = EROFS; break;
151 return error;
154 static inline int is_file_in_use_error(DWORD errcode)
156 switch (errcode) {
157 case ERROR_SHARING_VIOLATION:
158 case ERROR_ACCESS_DENIED:
159 return 1;
162 return 0;
165 static int read_yes_no_answer(void)
167 char answer[1024];
169 if (fgets(answer, sizeof(answer), stdin)) {
170 size_t answer_len = strlen(answer);
171 int got_full_line = 0, c;
173 /* remove the newline */
174 if (answer_len >= 2 && answer[answer_len-2] == '\r') {
175 answer[answer_len-2] = '\0';
176 got_full_line = 1;
177 } else if (answer_len >= 1 && answer[answer_len-1] == '\n') {
178 answer[answer_len-1] = '\0';
179 got_full_line = 1;
181 /* flush the buffer in case we did not get the full line */
182 if (!got_full_line)
183 while ((c = getchar()) != EOF && c != '\n')
185 } else
186 /* we could not read, return the
187 * default answer which is no */
188 return 0;
190 if (tolower(answer[0]) == 'y' && !answer[1])
191 return 1;
192 if (!strncasecmp(answer, "yes", sizeof(answer)))
193 return 1;
194 if (tolower(answer[0]) == 'n' && !answer[1])
195 return 0;
196 if (!strncasecmp(answer, "no", sizeof(answer)))
197 return 0;
199 /* did not find an answer we understand */
200 return -1;
203 static int ask_yes_no_if_possible(const char *format, ...)
205 char question[4096];
206 const char *retry_hook;
207 va_list args;
209 va_start(args, format);
210 vsnprintf(question, sizeof(question), format, args);
211 va_end(args);
213 retry_hook = mingw_getenv("GIT_ASK_YESNO");
214 if (retry_hook) {
215 struct child_process cmd = CHILD_PROCESS_INIT;
217 strvec_pushl(&cmd.args, retry_hook, question, NULL);
218 return !run_command(&cmd);
221 if (!isatty(_fileno(stdin)) || !isatty(_fileno(stderr)))
222 return 0;
224 while (1) {
225 int answer;
226 fprintf(stderr, "%s (y/n) ", question);
228 if ((answer = read_yes_no_answer()) >= 0)
229 return answer;
231 fprintf(stderr, "Sorry, I did not understand your answer. "
232 "Please type 'y' or 'n'\n");
236 /* Windows only */
237 enum hide_dotfiles_type {
238 HIDE_DOTFILES_FALSE = 0,
239 HIDE_DOTFILES_TRUE,
240 HIDE_DOTFILES_DOTGITONLY
243 static int core_restrict_inherited_handles = -1;
244 static enum hide_dotfiles_type hide_dotfiles = HIDE_DOTFILES_DOTGITONLY;
245 static char *unset_environment_variables;
247 int mingw_core_config(const char *var, const char *value,
248 const struct config_context *ctx UNUSED,
249 void *cb UNUSED)
251 if (!strcmp(var, "core.hidedotfiles")) {
252 if (value && !strcasecmp(value, "dotgitonly"))
253 hide_dotfiles = HIDE_DOTFILES_DOTGITONLY;
254 else
255 hide_dotfiles = git_config_bool(var, value);
256 return 0;
259 if (!strcmp(var, "core.unsetenvvars")) {
260 if (!value)
261 return config_error_nonbool(var);
262 free(unset_environment_variables);
263 unset_environment_variables = xstrdup(value);
264 return 0;
267 if (!strcmp(var, "core.restrictinheritedhandles")) {
268 if (value && !strcasecmp(value, "auto"))
269 core_restrict_inherited_handles = -1;
270 else
271 core_restrict_inherited_handles =
272 git_config_bool(var, value);
273 return 0;
276 return 0;
279 /* Normalizes NT paths as returned by some low-level APIs. */
280 static wchar_t *normalize_ntpath(wchar_t *wbuf)
282 int i;
283 /* fix absolute path prefixes */
284 if (wbuf[0] == '\\') {
285 /* strip NT namespace prefixes */
286 if (!wcsncmp(wbuf, L"\\??\\", 4) ||
287 !wcsncmp(wbuf, L"\\\\?\\", 4))
288 wbuf += 4;
289 else if (!wcsnicmp(wbuf, L"\\DosDevices\\", 12))
290 wbuf += 12;
291 /* replace remaining '...UNC\' with '\\' */
292 if (!wcsnicmp(wbuf, L"UNC\\", 4)) {
293 wbuf += 2;
294 *wbuf = '\\';
297 /* convert backslashes to slashes */
298 for (i = 0; wbuf[i]; i++)
299 if (wbuf[i] == '\\')
300 wbuf[i] = '/';
301 return wbuf;
304 int mingw_unlink(const char *pathname)
306 int ret, tries = 0;
307 wchar_t wpathname[MAX_PATH];
308 if (xutftowcs_path(wpathname, pathname) < 0)
309 return -1;
311 if (DeleteFileW(wpathname))
312 return 0;
314 /* read-only files cannot be removed */
315 _wchmod(wpathname, 0666);
316 while ((ret = _wunlink(wpathname)) == -1 && tries < ARRAY_SIZE(delay)) {
317 if (!is_file_in_use_error(GetLastError()))
318 break;
320 * We assume that some other process had the source or
321 * destination file open at the wrong moment and retry.
322 * In order to give the other process a higher chance to
323 * complete its operation, we give up our time slice now.
324 * If we have to retry again, we do sleep a bit.
326 Sleep(delay[tries]);
327 tries++;
329 while (ret == -1 && is_file_in_use_error(GetLastError()) &&
330 ask_yes_no_if_possible("Unlink of file '%s' failed. "
331 "Should I try again?", pathname))
332 ret = _wunlink(wpathname);
333 return ret;
336 static int is_dir_empty(const wchar_t *wpath)
338 WIN32_FIND_DATAW findbuf;
339 HANDLE handle;
340 wchar_t wbuf[MAX_PATH + 2];
341 wcscpy(wbuf, wpath);
342 wcscat(wbuf, L"\\*");
343 handle = FindFirstFileW(wbuf, &findbuf);
344 if (handle == INVALID_HANDLE_VALUE)
345 return GetLastError() == ERROR_NO_MORE_FILES;
347 while (!wcscmp(findbuf.cFileName, L".") ||
348 !wcscmp(findbuf.cFileName, L".."))
349 if (!FindNextFileW(handle, &findbuf)) {
350 DWORD err = GetLastError();
351 FindClose(handle);
352 return err == ERROR_NO_MORE_FILES;
354 FindClose(handle);
355 return 0;
358 int mingw_rmdir(const char *pathname)
360 int ret, tries = 0;
361 wchar_t wpathname[MAX_PATH];
362 struct stat st;
365 * Contrary to Linux' `rmdir()`, Windows' _wrmdir() and _rmdir()
366 * (and `RemoveDirectoryW()`) will attempt to remove the target of a
367 * symbolic link (if it points to a directory).
369 * This behavior breaks the assumption of e.g. `remove_path()` which
370 * upon successful deletion of a file will attempt to remove its parent
371 * directories recursively until failure (which usually happens when
372 * the directory is not empty).
374 * Therefore, before calling `_wrmdir()`, we first check if the path is
375 * a symbolic link. If it is, we exit and return the same error as
376 * Linux' `rmdir()` would, i.e. `ENOTDIR`.
378 if (!mingw_lstat(pathname, &st) && S_ISLNK(st.st_mode)) {
379 errno = ENOTDIR;
380 return -1;
383 if (xutftowcs_path(wpathname, pathname) < 0)
384 return -1;
386 while ((ret = _wrmdir(wpathname)) == -1 && tries < ARRAY_SIZE(delay)) {
387 if (!is_file_in_use_error(GetLastError()))
388 errno = err_win_to_posix(GetLastError());
389 if (errno != EACCES)
390 break;
391 if (!is_dir_empty(wpathname)) {
392 errno = ENOTEMPTY;
393 break;
396 * We assume that some other process had the source or
397 * destination file open at the wrong moment and retry.
398 * In order to give the other process a higher chance to
399 * complete its operation, we give up our time slice now.
400 * If we have to retry again, we do sleep a bit.
402 Sleep(delay[tries]);
403 tries++;
405 while (ret == -1 && errno == EACCES && is_file_in_use_error(GetLastError()) &&
406 ask_yes_no_if_possible("Deletion of directory '%s' failed. "
407 "Should I try again?", pathname))
408 ret = _wrmdir(wpathname);
409 if (!ret)
410 invalidate_lstat_cache();
411 return ret;
414 static inline int needs_hiding(const char *path)
416 const char *basename;
418 if (hide_dotfiles == HIDE_DOTFILES_FALSE)
419 return 0;
421 /* We cannot use basename(), as it would remove trailing slashes */
422 win32_skip_dos_drive_prefix((char **)&path);
423 if (!*path)
424 return 0;
426 for (basename = path; *path; path++)
427 if (is_dir_sep(*path)) {
428 do {
429 path++;
430 } while (is_dir_sep(*path));
431 /* ignore trailing slashes */
432 if (*path)
433 basename = path;
434 else
435 break;
438 if (hide_dotfiles == HIDE_DOTFILES_TRUE)
439 return *basename == '.';
441 assert(hide_dotfiles == HIDE_DOTFILES_DOTGITONLY);
442 return !strncasecmp(".git", basename, 4) &&
443 (!basename[4] || is_dir_sep(basename[4]));
446 static int set_hidden_flag(const wchar_t *path, int set)
448 DWORD original = GetFileAttributesW(path), modified;
449 if (set)
450 modified = original | FILE_ATTRIBUTE_HIDDEN;
451 else
452 modified = original & ~FILE_ATTRIBUTE_HIDDEN;
453 if (original == modified || SetFileAttributesW(path, modified))
454 return 0;
455 errno = err_win_to_posix(GetLastError());
456 return -1;
459 int mingw_mkdir(const char *path, int mode UNUSED)
461 int ret;
462 wchar_t wpath[MAX_PATH];
464 if (!is_valid_win32_path(path, 0)) {
465 errno = EINVAL;
466 return -1;
469 if (xutftowcs_path(wpath, path) < 0)
470 return -1;
471 ret = _wmkdir(wpath);
472 if (!ret && needs_hiding(path))
473 return set_hidden_flag(wpath, 1);
474 return ret;
478 * Calling CreateFile() using FILE_APPEND_DATA and without FILE_WRITE_DATA
479 * is documented in [1] as opening a writable file handle in append mode.
480 * (It is believed that) this is atomic since it is maintained by the
481 * kernel unlike the O_APPEND flag which is racily maintained by the CRT.
483 * [1] https://docs.microsoft.com/en-us/windows/desktop/fileio/file-access-rights-constants
485 * This trick does not appear to work for named pipes. Instead it creates
486 * a named pipe client handle that cannot be written to. Callers should
487 * just use the regular _wopen() for them. (And since client handle gets
488 * bound to a unique server handle, it isn't really an issue.)
490 static int mingw_open_append(wchar_t const *wfilename, int oflags, ...)
492 HANDLE handle;
493 int fd;
494 DWORD create = (oflags & O_CREAT) ? OPEN_ALWAYS : OPEN_EXISTING;
496 /* only these flags are supported */
497 if ((oflags & ~O_CREAT) != (O_WRONLY | O_APPEND))
498 return errno = ENOSYS, -1;
501 * FILE_SHARE_WRITE is required to permit child processes
502 * to append to the file.
504 handle = CreateFileW(wfilename, FILE_APPEND_DATA,
505 FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE,
506 NULL, create, FILE_ATTRIBUTE_NORMAL, NULL);
507 if (handle == INVALID_HANDLE_VALUE) {
508 DWORD err = GetLastError();
511 * Some network storage solutions (e.g. Isilon) might return
512 * ERROR_INVALID_PARAMETER instead of expected error
513 * ERROR_PATH_NOT_FOUND, which results in an unknown error. If
514 * so, let's turn the error to ERROR_PATH_NOT_FOUND instead.
516 if (err == ERROR_INVALID_PARAMETER)
517 err = ERROR_PATH_NOT_FOUND;
519 errno = err_win_to_posix(err);
520 return -1;
524 * No O_APPEND here, because the CRT uses it only to reset the
525 * file pointer to EOF before each write(); but that is not
526 * necessary (and may lead to races) for a file created with
527 * FILE_APPEND_DATA.
529 fd = _open_osfhandle((intptr_t)handle, O_BINARY);
530 if (fd < 0)
531 CloseHandle(handle);
532 return fd;
536 * Ideally, we'd use `_wopen()` to implement this functionality so that we
537 * don't have to reimplement it, but unfortunately we do not have tight control
538 * over the share mode there. And while `_wsopen()` and friends exist that give
539 * us _some_ control over the share mode, this family of functions doesn't give
540 * us the ability to enable FILE_SHARE_DELETE, either. But this is a strict
541 * requirement for us though so that we can unlink or rename over files that
542 * are held open by another process.
544 * We are thus forced to implement our own emulation of `open()`. To make our
545 * life simpler we only implement basic support for this, namely opening
546 * existing files for reading and/or writing. This means that newly created
547 * files won't have their sharing mode set up correctly, but for now I couldn't
548 * find any case where this matters. We may have to revisit that in the future
549 * though based on our needs.
551 static int mingw_open_existing(const wchar_t *filename, int oflags, ...)
553 SECURITY_ATTRIBUTES security_attributes = {
554 .nLength = sizeof(security_attributes),
555 .bInheritHandle = !(oflags & O_NOINHERIT),
557 HANDLE handle;
558 DWORD access;
559 int fd;
561 /* We only support basic flags. */
562 if (oflags & ~(O_ACCMODE | O_NOINHERIT)) {
563 errno = ENOSYS;
564 return -1;
567 switch (oflags & O_ACCMODE) {
568 case O_RDWR:
569 access = GENERIC_READ | GENERIC_WRITE;
570 break;
571 case O_WRONLY:
572 access = GENERIC_WRITE;
573 break;
574 default:
575 access = GENERIC_READ;
576 break;
579 handle = CreateFileW(filename, access,
580 FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE,
581 &security_attributes, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
582 if (handle == INVALID_HANDLE_VALUE) {
583 DWORD err = GetLastError();
585 /* See `mingw_open_append()` for why we have this conversion. */
586 if (err == ERROR_INVALID_PARAMETER)
587 err = ERROR_PATH_NOT_FOUND;
589 errno = err_win_to_posix(err);
590 return -1;
593 fd = _open_osfhandle((intptr_t)handle, oflags | O_BINARY);
594 if (fd < 0)
595 CloseHandle(handle);
596 return fd;
600 * Does the pathname map to the local named pipe filesystem?
601 * That is, does it have a "//./pipe/" prefix?
603 static int is_local_named_pipe_path(const char *filename)
605 return (is_dir_sep(filename[0]) &&
606 is_dir_sep(filename[1]) &&
607 filename[2] == '.' &&
608 is_dir_sep(filename[3]) &&
609 !strncasecmp(filename+4, "pipe", 4) &&
610 is_dir_sep(filename[8]) &&
611 filename[9]);
614 int mingw_open (const char *filename, int oflags, ...)
616 typedef int (*open_fn_t)(wchar_t const *wfilename, int oflags, ...);
617 va_list args;
618 unsigned mode;
619 int fd, create = (oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL);
620 wchar_t wfilename[MAX_PATH];
621 open_fn_t open_fn;
623 va_start(args, oflags);
624 mode = va_arg(args, int);
625 va_end(args);
627 if (!is_valid_win32_path(filename, !create)) {
628 errno = create ? EINVAL : ENOENT;
629 return -1;
632 if ((oflags & O_APPEND) && !is_local_named_pipe_path(filename))
633 open_fn = mingw_open_append;
634 else if (!(oflags & ~(O_ACCMODE | O_NOINHERIT)))
635 open_fn = mingw_open_existing;
636 else
637 open_fn = _wopen;
639 if (filename && !strcmp(filename, "/dev/null"))
640 wcscpy(wfilename, L"nul");
641 else if (xutftowcs_path(wfilename, filename) < 0)
642 return -1;
644 fd = open_fn(wfilename, oflags, mode);
646 if (fd < 0 && (oflags & O_ACCMODE) != O_RDONLY && errno == EACCES) {
647 DWORD attrs = GetFileAttributesW(wfilename);
648 if (attrs != INVALID_FILE_ATTRIBUTES && (attrs & FILE_ATTRIBUTE_DIRECTORY))
649 errno = EISDIR;
651 if ((oflags & O_CREAT) && needs_hiding(filename)) {
653 * Internally, _wopen() uses the CreateFile() API which errors
654 * out with an ERROR_ACCESS_DENIED if CREATE_ALWAYS was
655 * specified and an already existing file's attributes do not
656 * match *exactly*. As there is no mode or flag we can set that
657 * would correspond to FILE_ATTRIBUTE_HIDDEN, let's just try
658 * again *without* the O_CREAT flag (that corresponds to the
659 * CREATE_ALWAYS flag of CreateFile()).
661 if (fd < 0 && errno == EACCES)
662 fd = open_fn(wfilename, oflags & ~O_CREAT, mode);
663 if (fd >= 0 && set_hidden_flag(wfilename, 1))
664 warning("could not mark '%s' as hidden.", filename);
666 return fd;
669 static BOOL WINAPI ctrl_ignore(DWORD type UNUSED)
671 return TRUE;
674 #undef fgetc
675 int mingw_fgetc(FILE *stream)
677 int ch;
678 if (!isatty(_fileno(stream)))
679 return fgetc(stream);
681 SetConsoleCtrlHandler(ctrl_ignore, TRUE);
682 while (1) {
683 ch = fgetc(stream);
684 if (ch != EOF || GetLastError() != ERROR_OPERATION_ABORTED)
685 break;
687 /* Ctrl+C was pressed, simulate SIGINT and retry */
688 mingw_raise(SIGINT);
690 SetConsoleCtrlHandler(ctrl_ignore, FALSE);
691 return ch;
694 #undef fopen
695 FILE *mingw_fopen (const char *filename, const char *otype)
697 int hide = needs_hiding(filename);
698 FILE *file;
699 wchar_t wfilename[MAX_PATH], wotype[4];
700 if (filename && !strcmp(filename, "/dev/null"))
701 wcscpy(wfilename, L"nul");
702 else if (!is_valid_win32_path(filename, 1)) {
703 int create = otype && strchr(otype, 'w');
704 errno = create ? EINVAL : ENOENT;
705 return NULL;
706 } else if (xutftowcs_path(wfilename, filename) < 0)
707 return NULL;
709 if (xutftowcs(wotype, otype, ARRAY_SIZE(wotype)) < 0)
710 return NULL;
712 if (hide && !access(filename, F_OK) && set_hidden_flag(wfilename, 0)) {
713 error("could not unhide %s", filename);
714 return NULL;
716 file = _wfopen(wfilename, wotype);
717 if (!file && GetLastError() == ERROR_INVALID_NAME)
718 errno = ENOENT;
719 if (file && hide && set_hidden_flag(wfilename, 1))
720 warning("could not mark '%s' as hidden.", filename);
721 return file;
724 FILE *mingw_freopen (const char *filename, const char *otype, FILE *stream)
726 int hide = needs_hiding(filename);
727 FILE *file;
728 wchar_t wfilename[MAX_PATH], wotype[4];
729 if (filename && !strcmp(filename, "/dev/null"))
730 wcscpy(wfilename, L"nul");
731 else if (!is_valid_win32_path(filename, 1)) {
732 int create = otype && strchr(otype, 'w');
733 errno = create ? EINVAL : ENOENT;
734 return NULL;
735 } else if (xutftowcs_path(wfilename, filename) < 0)
736 return NULL;
738 if (xutftowcs(wotype, otype, ARRAY_SIZE(wotype)) < 0)
739 return NULL;
741 if (hide && !access(filename, F_OK) && set_hidden_flag(wfilename, 0)) {
742 error("could not unhide %s", filename);
743 return NULL;
745 file = _wfreopen(wfilename, wotype, stream);
746 if (file && hide && set_hidden_flag(wfilename, 1))
747 warning("could not mark '%s' as hidden.", filename);
748 return file;
751 #undef fflush
752 int mingw_fflush(FILE *stream)
754 int ret = fflush(stream);
757 * write() is used behind the scenes of stdio output functions.
758 * Since git code does not check for errors after each stdio write
759 * operation, it can happen that write() is called by a later
760 * stdio function even if an earlier write() call failed. In the
761 * case of a pipe whose readable end was closed, only the first
762 * call to write() reports EPIPE on Windows. Subsequent write()
763 * calls report EINVAL. It is impossible to notice whether this
764 * fflush invocation triggered such a case, therefore, we have to
765 * catch all EINVAL errors whole-sale.
767 if (ret && errno == EINVAL)
768 errno = EPIPE;
770 return ret;
773 #undef write
774 ssize_t mingw_write(int fd, const void *buf, size_t len)
776 ssize_t result = write(fd, buf, len);
778 if (result < 0 && (errno == EINVAL || errno == ENOSPC) && buf) {
779 int orig = errno;
781 /* check if fd is a pipe */
782 HANDLE h = (HANDLE) _get_osfhandle(fd);
783 if (GetFileType(h) != FILE_TYPE_PIPE)
784 errno = orig;
785 else if (orig == EINVAL)
786 errno = EPIPE;
787 else {
788 DWORD buf_size;
790 if (!GetNamedPipeInfo(h, NULL, NULL, &buf_size, NULL))
791 buf_size = 4096;
792 if (len > buf_size)
793 return write(fd, buf, buf_size);
794 errno = orig;
798 return result;
801 int mingw_access(const char *filename, int mode)
803 wchar_t wfilename[MAX_PATH];
804 if (!strcmp("nul", filename) || !strcmp("/dev/null", filename))
805 return 0;
806 if (xutftowcs_path(wfilename, filename) < 0)
807 return -1;
808 /* X_OK is not supported by the MSVCRT version */
809 return _waccess(wfilename, mode & ~X_OK);
812 int mingw_chdir(const char *dirname)
814 wchar_t wdirname[MAX_PATH];
815 if (xutftowcs_path(wdirname, dirname) < 0)
816 return -1;
817 return _wchdir(wdirname);
820 int mingw_chmod(const char *filename, int mode)
822 wchar_t wfilename[MAX_PATH];
823 if (xutftowcs_path(wfilename, filename) < 0)
824 return -1;
825 return _wchmod(wfilename, mode);
829 * The unit of FILETIME is 100-nanoseconds since January 1, 1601, UTC.
830 * Returns the 100-nanoseconds ("hekto nanoseconds") since the epoch.
832 static inline long long filetime_to_hnsec(const FILETIME *ft)
834 long long winTime = ((long long)ft->dwHighDateTime << 32) + ft->dwLowDateTime;
835 /* Windows to Unix Epoch conversion */
836 return winTime - 116444736000000000LL;
839 static inline void filetime_to_timespec(const FILETIME *ft, struct timespec *ts)
841 long long hnsec = filetime_to_hnsec(ft);
842 ts->tv_sec = (time_t)(hnsec / 10000000);
843 ts->tv_nsec = (hnsec % 10000000) * 100;
847 * Verifies that safe_create_leading_directories() would succeed.
849 static int has_valid_directory_prefix(wchar_t *wfilename)
851 size_t n = wcslen(wfilename);
853 while (n > 0) {
854 wchar_t c = wfilename[--n];
855 DWORD attributes;
857 if (!is_dir_sep(c))
858 continue;
860 wfilename[n] = L'\0';
861 attributes = GetFileAttributesW(wfilename);
862 wfilename[n] = c;
863 if (attributes &
864 (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_DEVICE))
865 return 1;
866 if (attributes == INVALID_FILE_ATTRIBUTES)
867 switch (GetLastError()) {
868 case ERROR_PATH_NOT_FOUND:
869 continue;
870 case ERROR_FILE_NOT_FOUND:
871 /* This implies parent directory exists. */
872 return 1;
874 return 0;
876 return 1;
879 /* We keep the do_lstat code in a separate function to avoid recursion.
880 * When a path ends with a slash, the stat will fail with ENOENT. In
881 * this case, we strip the trailing slashes and stat again.
883 * If follow is true then act like stat() and report on the link
884 * target. Otherwise report on the link itself.
886 static int do_lstat(int follow, const char *file_name, struct stat *buf)
888 WIN32_FILE_ATTRIBUTE_DATA fdata;
889 wchar_t wfilename[MAX_PATH];
890 if (xutftowcs_path(wfilename, file_name) < 0)
891 return -1;
893 if (GetFileAttributesExW(wfilename, GetFileExInfoStandard, &fdata)) {
894 buf->st_ino = 0;
895 buf->st_gid = 0;
896 buf->st_uid = 0;
897 buf->st_nlink = 1;
898 buf->st_mode = file_attr_to_st_mode(fdata.dwFileAttributes);
899 buf->st_size = fdata.nFileSizeLow |
900 (((off_t)fdata.nFileSizeHigh)<<32);
901 buf->st_dev = buf->st_rdev = 0; /* not used by Git */
902 filetime_to_timespec(&(fdata.ftLastAccessTime), &(buf->st_atim));
903 filetime_to_timespec(&(fdata.ftLastWriteTime), &(buf->st_mtim));
904 filetime_to_timespec(&(fdata.ftCreationTime), &(buf->st_ctim));
905 if (fdata.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
906 WIN32_FIND_DATAW findbuf;
907 HANDLE handle = FindFirstFileW(wfilename, &findbuf);
908 if (handle != INVALID_HANDLE_VALUE) {
909 if ((findbuf.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
910 (findbuf.dwReserved0 == IO_REPARSE_TAG_SYMLINK)) {
911 if (follow) {
912 char buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
913 buf->st_size = readlink(file_name, buffer, MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
914 } else {
915 buf->st_mode = S_IFLNK;
917 buf->st_mode |= S_IREAD;
918 if (!(findbuf.dwFileAttributes & FILE_ATTRIBUTE_READONLY))
919 buf->st_mode |= S_IWRITE;
921 FindClose(handle);
924 return 0;
926 switch (GetLastError()) {
927 case ERROR_ACCESS_DENIED:
928 case ERROR_SHARING_VIOLATION:
929 case ERROR_LOCK_VIOLATION:
930 case ERROR_SHARING_BUFFER_EXCEEDED:
931 errno = EACCES;
932 break;
933 case ERROR_BUFFER_OVERFLOW:
934 errno = ENAMETOOLONG;
935 break;
936 case ERROR_NOT_ENOUGH_MEMORY:
937 errno = ENOMEM;
938 break;
939 case ERROR_PATH_NOT_FOUND:
940 if (!has_valid_directory_prefix(wfilename)) {
941 errno = ENOTDIR;
942 break;
944 /* fallthru */
945 default:
946 errno = ENOENT;
947 break;
949 return -1;
952 /* We provide our own lstat/fstat functions, since the provided
953 * lstat/fstat functions are so slow. These stat functions are
954 * tailored for Git's usage (read: fast), and are not meant to be
955 * complete. Note that Git stat()s are redirected to mingw_lstat()
956 * too, since Windows doesn't really handle symlinks that well.
958 static int do_stat_internal(int follow, const char *file_name, struct stat *buf)
960 size_t namelen;
961 char alt_name[PATH_MAX];
963 if (!do_lstat(follow, file_name, buf))
964 return 0;
966 /* if file_name ended in a '/', Windows returned ENOENT;
967 * try again without trailing slashes
969 if (errno != ENOENT)
970 return -1;
972 namelen = strlen(file_name);
973 if (namelen && file_name[namelen-1] != '/')
974 return -1;
975 while (namelen && file_name[namelen-1] == '/')
976 --namelen;
977 if (!namelen || namelen >= PATH_MAX)
978 return -1;
980 memcpy(alt_name, file_name, namelen);
981 alt_name[namelen] = 0;
982 return do_lstat(follow, alt_name, buf);
985 static int get_file_info_by_handle(HANDLE hnd, struct stat *buf)
987 BY_HANDLE_FILE_INFORMATION fdata;
989 if (!GetFileInformationByHandle(hnd, &fdata)) {
990 errno = err_win_to_posix(GetLastError());
991 return -1;
994 buf->st_ino = 0;
995 buf->st_gid = 0;
996 buf->st_uid = 0;
997 buf->st_nlink = 1;
998 buf->st_mode = file_attr_to_st_mode(fdata.dwFileAttributes);
999 buf->st_size = fdata.nFileSizeLow |
1000 (((off_t)fdata.nFileSizeHigh)<<32);
1001 buf->st_dev = buf->st_rdev = 0; /* not used by Git */
1002 filetime_to_timespec(&(fdata.ftLastAccessTime), &(buf->st_atim));
1003 filetime_to_timespec(&(fdata.ftLastWriteTime), &(buf->st_mtim));
1004 filetime_to_timespec(&(fdata.ftCreationTime), &(buf->st_ctim));
1005 return 0;
1008 int mingw_lstat(const char *file_name, struct stat *buf)
1010 return do_stat_internal(0, file_name, buf);
1012 int mingw_stat(const char *file_name, struct stat *buf)
1014 return do_stat_internal(1, file_name, buf);
1017 int mingw_fstat(int fd, struct stat *buf)
1019 HANDLE fh = (HANDLE)_get_osfhandle(fd);
1020 DWORD avail, type = GetFileType(fh) & ~FILE_TYPE_REMOTE;
1022 switch (type) {
1023 case FILE_TYPE_DISK:
1024 return get_file_info_by_handle(fh, buf);
1026 case FILE_TYPE_CHAR:
1027 case FILE_TYPE_PIPE:
1028 /* initialize stat fields */
1029 memset(buf, 0, sizeof(*buf));
1030 buf->st_nlink = 1;
1032 if (type == FILE_TYPE_CHAR) {
1033 buf->st_mode = _S_IFCHR;
1034 } else {
1035 buf->st_mode = _S_IFIFO;
1036 if (PeekNamedPipe(fh, NULL, 0, NULL, &avail, NULL))
1037 buf->st_size = avail;
1039 return 0;
1041 default:
1042 errno = EBADF;
1043 return -1;
1047 static inline void time_t_to_filetime(time_t t, FILETIME *ft)
1049 long long winTime = t * 10000000LL + 116444736000000000LL;
1050 ft->dwLowDateTime = winTime;
1051 ft->dwHighDateTime = winTime >> 32;
1054 int mingw_utime (const char *file_name, const struct utimbuf *times)
1056 FILETIME mft, aft;
1057 int rc;
1058 DWORD attrs;
1059 wchar_t wfilename[MAX_PATH];
1060 HANDLE osfilehandle;
1062 if (xutftowcs_path(wfilename, file_name) < 0)
1063 return -1;
1065 /* must have write permission */
1066 attrs = GetFileAttributesW(wfilename);
1067 if (attrs != INVALID_FILE_ATTRIBUTES &&
1068 (attrs & FILE_ATTRIBUTE_READONLY)) {
1069 /* ignore errors here; open() will report them */
1070 SetFileAttributesW(wfilename, attrs & ~FILE_ATTRIBUTE_READONLY);
1073 osfilehandle = CreateFileW(wfilename,
1074 FILE_WRITE_ATTRIBUTES,
1075 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
1076 NULL,
1077 OPEN_EXISTING,
1078 (attrs != INVALID_FILE_ATTRIBUTES &&
1079 (attrs & FILE_ATTRIBUTE_DIRECTORY)) ?
1080 FILE_FLAG_BACKUP_SEMANTICS : 0,
1081 NULL);
1082 if (osfilehandle == INVALID_HANDLE_VALUE) {
1083 errno = err_win_to_posix(GetLastError());
1084 rc = -1;
1085 goto revert_attrs;
1088 if (times) {
1089 time_t_to_filetime(times->modtime, &mft);
1090 time_t_to_filetime(times->actime, &aft);
1091 } else {
1092 GetSystemTimeAsFileTime(&mft);
1093 aft = mft;
1096 if (!SetFileTime(osfilehandle, NULL, &aft, &mft)) {
1097 errno = EINVAL;
1098 rc = -1;
1099 } else
1100 rc = 0;
1102 if (osfilehandle != INVALID_HANDLE_VALUE)
1103 CloseHandle(osfilehandle);
1105 revert_attrs:
1106 if (attrs != INVALID_FILE_ATTRIBUTES &&
1107 (attrs & FILE_ATTRIBUTE_READONLY)) {
1108 /* ignore errors again */
1109 SetFileAttributesW(wfilename, attrs);
1111 return rc;
1114 #undef strftime
1115 size_t mingw_strftime(char *s, size_t max,
1116 const char *format, const struct tm *tm)
1118 /* a pointer to the original strftime in case we can't find the UCRT version */
1119 static size_t (*fallback)(char *, size_t, const char *, const struct tm *) = strftime;
1120 size_t ret;
1121 DECLARE_PROC_ADDR(ucrtbase.dll, size_t, __cdecl, strftime, char *, size_t,
1122 const char *, const struct tm *);
1124 if (INIT_PROC_ADDR(strftime))
1125 ret = strftime(s, max, format, tm);
1126 else
1127 ret = fallback(s, max, format, tm);
1129 if (!ret && errno == EINVAL)
1130 die("invalid strftime format: '%s'", format);
1131 return ret;
1134 unsigned int sleep (unsigned int seconds)
1136 Sleep(seconds*1000);
1137 return 0;
1140 char *mingw_mktemp(char *template)
1142 wchar_t wtemplate[MAX_PATH];
1143 if (xutftowcs_path(wtemplate, template) < 0)
1144 return NULL;
1145 if (!_wmktemp(wtemplate))
1146 return NULL;
1147 if (xwcstoutf(template, wtemplate, strlen(template) + 1) < 0)
1148 return NULL;
1149 return template;
1152 int mkstemp(char *template)
1154 return git_mkstemp_mode(template, 0600);
1157 int gettimeofday(struct timeval *tv, void *tz UNUSED)
1159 FILETIME ft;
1160 long long hnsec;
1162 GetSystemTimeAsFileTime(&ft);
1163 hnsec = filetime_to_hnsec(&ft);
1164 tv->tv_sec = hnsec / 10000000;
1165 tv->tv_usec = (hnsec % 10000000) / 10;
1166 return 0;
1169 int pipe(int filedes[2])
1171 HANDLE h[2];
1173 /* this creates non-inheritable handles */
1174 if (!CreatePipe(&h[0], &h[1], NULL, 8192)) {
1175 errno = err_win_to_posix(GetLastError());
1176 return -1;
1178 filedes[0] = _open_osfhandle(HCAST(int, h[0]), O_NOINHERIT);
1179 if (filedes[0] < 0) {
1180 CloseHandle(h[0]);
1181 CloseHandle(h[1]);
1182 return -1;
1184 filedes[1] = _open_osfhandle(HCAST(int, h[1]), O_NOINHERIT);
1185 if (filedes[1] < 0) {
1186 close(filedes[0]);
1187 CloseHandle(h[1]);
1188 return -1;
1190 return 0;
1193 #ifndef __MINGW64__
1194 struct tm *gmtime_r(const time_t *timep, struct tm *result)
1196 if (gmtime_s(result, timep) == 0)
1197 return result;
1198 return NULL;
1201 struct tm *localtime_r(const time_t *timep, struct tm *result)
1203 if (localtime_s(result, timep) == 0)
1204 return result;
1205 return NULL;
1207 #endif
1209 char *mingw_getcwd(char *pointer, int len)
1211 wchar_t cwd[MAX_PATH], wpointer[MAX_PATH];
1212 DWORD ret = GetCurrentDirectoryW(ARRAY_SIZE(cwd), cwd);
1214 if (!ret || ret >= ARRAY_SIZE(cwd)) {
1215 errno = ret ? ENAMETOOLONG : err_win_to_posix(GetLastError());
1216 return NULL;
1218 ret = GetLongPathNameW(cwd, wpointer, ARRAY_SIZE(wpointer));
1219 if (!ret && GetLastError() == ERROR_ACCESS_DENIED) {
1220 HANDLE hnd = CreateFileW(cwd, 0,
1221 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
1222 OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
1223 if (hnd == INVALID_HANDLE_VALUE)
1224 return NULL;
1225 ret = GetFinalPathNameByHandleW(hnd, wpointer, ARRAY_SIZE(wpointer), 0);
1226 CloseHandle(hnd);
1227 if (!ret || ret >= ARRAY_SIZE(wpointer))
1228 return NULL;
1229 if (xwcstoutf(pointer, normalize_ntpath(wpointer), len) < 0)
1230 return NULL;
1231 return pointer;
1233 if (!ret || ret >= ARRAY_SIZE(wpointer))
1234 return NULL;
1235 if (GetFileAttributesW(wpointer) == INVALID_FILE_ATTRIBUTES) {
1236 errno = ENOENT;
1237 return NULL;
1239 if (xwcstoutf(pointer, wpointer, len) < 0)
1240 return NULL;
1241 convert_slashes(pointer);
1242 return pointer;
1246 * See "Parsing C++ Command-Line Arguments" at Microsoft's Docs:
1247 * https://docs.microsoft.com/en-us/cpp/cpp/parsing-cpp-command-line-arguments
1249 static const char *quote_arg_msvc(const char *arg)
1251 /* count chars to quote */
1252 int len = 0, n = 0;
1253 int force_quotes = 0;
1254 char *q, *d;
1255 const char *p = arg;
1256 if (!*p) force_quotes = 1;
1257 while (*p) {
1258 if (isspace(*p) || *p == '*' || *p == '?' || *p == '{' || *p == '\'')
1259 force_quotes = 1;
1260 else if (*p == '"')
1261 n++;
1262 else if (*p == '\\') {
1263 int count = 0;
1264 while (*p == '\\') {
1265 count++;
1266 p++;
1267 len++;
1269 if (*p == '"' || !*p)
1270 n += count*2 + 1;
1271 continue;
1273 len++;
1274 p++;
1276 if (!force_quotes && n == 0)
1277 return arg;
1279 /* insert \ where necessary */
1280 d = q = xmalloc(st_add3(len, n, 3));
1281 *d++ = '"';
1282 while (*arg) {
1283 if (*arg == '"')
1284 *d++ = '\\';
1285 else if (*arg == '\\') {
1286 int count = 0;
1287 while (*arg == '\\') {
1288 count++;
1289 *d++ = *arg++;
1291 if (*arg == '"' || !*arg) {
1292 while (count-- > 0)
1293 *d++ = '\\';
1294 /* don't escape the surrounding end quote */
1295 if (!*arg)
1296 break;
1297 *d++ = '\\';
1300 *d++ = *arg++;
1302 *d++ = '"';
1303 *d++ = '\0';
1304 return q;
1307 #include "quote.h"
1309 static const char *quote_arg_msys2(const char *arg)
1311 struct strbuf buf = STRBUF_INIT;
1312 const char *p2 = arg, *p;
1314 for (p = arg; *p; p++) {
1315 int ws = isspace(*p);
1316 if (!ws && *p != '\\' && *p != '"' && *p != '{' && *p != '\'' &&
1317 *p != '?' && *p != '*' && *p != '~')
1318 continue;
1319 if (!buf.len)
1320 strbuf_addch(&buf, '"');
1321 if (p != p2)
1322 strbuf_add(&buf, p2, p - p2);
1323 if (*p == '\\' || *p == '"')
1324 strbuf_addch(&buf, '\\');
1325 p2 = p;
1328 if (p == arg)
1329 strbuf_addch(&buf, '"');
1330 else if (!buf.len)
1331 return arg;
1332 else
1333 strbuf_add(&buf, p2, p - p2);
1335 strbuf_addch(&buf, '"');
1336 return strbuf_detach(&buf, 0);
1339 static const char *parse_interpreter(const char *cmd)
1341 static char buf[100];
1342 char *p, *opt;
1343 ssize_t n; /* read() can return negative values */
1344 int fd;
1346 /* don't even try a .exe */
1347 n = strlen(cmd);
1348 if (n >= 4 && !strcasecmp(cmd+n-4, ".exe"))
1349 return NULL;
1351 fd = open(cmd, O_RDONLY);
1352 if (fd < 0)
1353 return NULL;
1354 n = read(fd, buf, sizeof(buf)-1);
1355 close(fd);
1356 if (n < 4) /* at least '#!/x' and not error */
1357 return NULL;
1359 if (buf[0] != '#' || buf[1] != '!')
1360 return NULL;
1361 buf[n] = '\0';
1362 p = buf + strcspn(buf, "\r\n");
1363 if (!*p)
1364 return NULL;
1366 *p = '\0';
1367 if (!(p = strrchr(buf+2, '/')) && !(p = strrchr(buf+2, '\\')))
1368 return NULL;
1369 /* strip options */
1370 if ((opt = strchr(p+1, ' ')))
1371 *opt = '\0';
1372 return p+1;
1376 * exe_only means that we only want to detect .exe files, but not scripts
1377 * (which do not have an extension)
1379 static char *lookup_prog(const char *dir, int dirlen, const char *cmd,
1380 int isexe, int exe_only)
1382 char path[MAX_PATH];
1383 wchar_t wpath[MAX_PATH];
1384 snprintf(path, sizeof(path), "%.*s\\%s.exe", dirlen, dir, cmd);
1386 if (xutftowcs_path(wpath, path) < 0)
1387 return NULL;
1389 if (!isexe && _waccess(wpath, F_OK) == 0)
1390 return xstrdup(path);
1391 wpath[wcslen(wpath)-4] = '\0';
1392 if ((!exe_only || isexe) && _waccess(wpath, F_OK) == 0) {
1393 if (!(GetFileAttributesW(wpath) & FILE_ATTRIBUTE_DIRECTORY)) {
1394 path[strlen(path)-4] = '\0';
1395 return xstrdup(path);
1398 return NULL;
1402 * Determines the absolute path of cmd using the split path in path.
1403 * If cmd contains a slash or backslash, no lookup is performed.
1405 static char *path_lookup(const char *cmd, int exe_only)
1407 const char *path;
1408 char *prog = NULL;
1409 size_t len = strlen(cmd);
1410 int isexe = len >= 4 && !strcasecmp(cmd+len-4, ".exe");
1412 if (strpbrk(cmd, "/\\"))
1413 return xstrdup(cmd);
1415 path = mingw_getenv("PATH");
1416 if (!path)
1417 return NULL;
1419 while (!prog) {
1420 const char *sep = strchrnul(path, ';');
1421 int dirlen = sep - path;
1422 if (dirlen)
1423 prog = lookup_prog(path, dirlen, cmd, isexe, exe_only);
1424 if (!*sep)
1425 break;
1426 path = sep + 1;
1429 return prog;
1432 char *mingw_locate_in_PATH(const char *cmd)
1434 return path_lookup(cmd, 0);
1437 static const wchar_t *wcschrnul(const wchar_t *s, wchar_t c)
1439 while (*s && *s != c)
1440 s++;
1441 return s;
1444 /* Compare only keys */
1445 static int wenvcmp(const void *a, const void *b)
1447 wchar_t *p = *(wchar_t **)a, *q = *(wchar_t **)b;
1448 size_t p_len, q_len;
1450 /* Find the keys */
1451 p_len = wcschrnul(p, L'=') - p;
1452 q_len = wcschrnul(q, L'=') - q;
1454 /* If the length differs, include the shorter key's NUL */
1455 if (p_len < q_len)
1456 p_len++;
1457 else if (p_len > q_len)
1458 p_len = q_len + 1;
1460 return _wcsnicmp(p, q, p_len);
1464 * Build an environment block combining the inherited environment
1465 * merged with the given list of settings.
1467 * Values of the form "KEY=VALUE" in deltaenv override inherited values.
1468 * Values of the form "KEY" in deltaenv delete inherited values.
1470 * Multiple entries in deltaenv for the same key are explicitly allowed.
1472 * We return a contiguous block of UNICODE strings with a final trailing
1473 * zero word.
1475 static wchar_t *make_environment_block(char **deltaenv)
1477 wchar_t *wenv = GetEnvironmentStringsW(), *wdeltaenv, *result, *p;
1478 size_t wlen, s, delta_size, size;
1480 wchar_t **array = NULL;
1481 size_t alloc = 0, nr = 0, i;
1483 size = 1; /* for extra NUL at the end */
1485 /* If there is no deltaenv to apply, simply return a copy. */
1486 if (!deltaenv || !*deltaenv) {
1487 for (p = wenv; p && *p; ) {
1488 size_t s = wcslen(p) + 1;
1489 size += s;
1490 p += s;
1493 DUP_ARRAY(result, wenv, size);
1494 FreeEnvironmentStringsW(wenv);
1495 return result;
1499 * If there is a deltaenv, let's accumulate all keys into `array`,
1500 * sort them using the stable git_stable_qsort() and then copy,
1501 * skipping duplicate keys
1503 for (p = wenv; p && *p; ) {
1504 ALLOC_GROW(array, nr + 1, alloc);
1505 s = wcslen(p) + 1;
1506 array[nr++] = p;
1507 p += s;
1508 size += s;
1511 /* (over-)assess size needed for wchar version of deltaenv */
1512 for (delta_size = 0, i = 0; deltaenv[i]; i++)
1513 delta_size += strlen(deltaenv[i]) * 2 + 1;
1514 ALLOC_ARRAY(wdeltaenv, delta_size);
1516 /* convert the deltaenv, appending to array */
1517 for (i = 0, p = wdeltaenv; deltaenv[i]; i++) {
1518 ALLOC_GROW(array, nr + 1, alloc);
1519 wlen = xutftowcs(p, deltaenv[i], wdeltaenv + delta_size - p);
1520 array[nr++] = p;
1521 p += wlen + 1;
1524 git_stable_qsort(array, nr, sizeof(*array), wenvcmp);
1525 ALLOC_ARRAY(result, size + delta_size);
1527 for (p = result, i = 0; i < nr; i++) {
1528 /* Skip any duplicate keys; last one wins */
1529 while (i + 1 < nr && !wenvcmp(array + i, array + i + 1))
1530 i++;
1532 /* Skip "to delete" entry */
1533 if (!wcschr(array[i], L'='))
1534 continue;
1536 size = wcslen(array[i]) + 1;
1537 COPY_ARRAY(p, array[i], size);
1538 p += size;
1540 *p = L'\0';
1542 free(array);
1543 free(wdeltaenv);
1544 FreeEnvironmentStringsW(wenv);
1545 return result;
1548 static void do_unset_environment_variables(void)
1550 static int done;
1551 char *p = unset_environment_variables;
1553 if (done || !p)
1554 return;
1555 done = 1;
1557 for (;;) {
1558 char *comma = strchr(p, ',');
1560 if (comma)
1561 *comma = '\0';
1562 unsetenv(p);
1563 if (!comma)
1564 break;
1565 p = comma + 1;
1569 struct pinfo_t {
1570 struct pinfo_t *next;
1571 pid_t pid;
1572 HANDLE proc;
1574 static struct pinfo_t *pinfo = NULL;
1575 CRITICAL_SECTION pinfo_cs;
1577 /* Used to match and chomp off path components */
1578 static inline int match_last_path_component(const char *path, size_t *len,
1579 const char *component)
1581 size_t component_len = strlen(component);
1582 if (*len < component_len + 1 ||
1583 !is_dir_sep(path[*len - component_len - 1]) ||
1584 fspathncmp(path + *len - component_len, component, component_len))
1585 return 0;
1586 *len -= component_len + 1;
1587 /* chomp off repeated dir separators */
1588 while (*len > 0 && is_dir_sep(path[*len - 1]))
1589 (*len)--;
1590 return 1;
1593 static int is_msys2_sh(const char *cmd)
1595 if (!cmd)
1596 return 0;
1598 if (!strcmp(cmd, "sh")) {
1599 static int ret = -1;
1600 char *p;
1602 if (ret >= 0)
1603 return ret;
1605 p = path_lookup(cmd, 0);
1606 if (!p)
1607 ret = 0;
1608 else {
1609 size_t len = strlen(p);
1611 ret = match_last_path_component(p, &len, "sh.exe") &&
1612 match_last_path_component(p, &len, "bin") &&
1613 match_last_path_component(p, &len, "usr");
1614 free(p);
1616 return ret;
1619 if (ends_with(cmd, "\\sh.exe") || ends_with(cmd, "/sh.exe")) {
1620 static char *sh;
1622 if (!sh)
1623 sh = path_lookup("sh", 0);
1625 return !fspathcmp(cmd, sh);
1628 return 0;
1631 static pid_t mingw_spawnve_fd(const char *cmd, const char **argv, char **deltaenv,
1632 const char *dir,
1633 int prepend_cmd, int fhin, int fhout, int fherr)
1635 static int restrict_handle_inheritance = -1;
1636 STARTUPINFOEXW si;
1637 PROCESS_INFORMATION pi;
1638 LPPROC_THREAD_ATTRIBUTE_LIST attr_list = NULL;
1639 HANDLE stdhandles[3];
1640 DWORD stdhandles_count = 0;
1641 SIZE_T size;
1642 struct strbuf args;
1643 wchar_t wcmd[MAX_PATH], wdir[MAX_PATH], *wargs, *wenvblk = NULL;
1644 unsigned flags = CREATE_UNICODE_ENVIRONMENT;
1645 BOOL ret;
1646 HANDLE cons;
1647 const char *(*quote_arg)(const char *arg) =
1648 is_msys2_sh(cmd ? cmd : *argv) ?
1649 quote_arg_msys2 : quote_arg_msvc;
1650 const char *strace_env;
1652 /* Make sure to override previous errors, if any */
1653 errno = 0;
1655 if (restrict_handle_inheritance < 0)
1656 restrict_handle_inheritance = core_restrict_inherited_handles;
1658 * The following code to restrict which handles are inherited seems
1659 * to work properly only on Windows 7 and later, so let's disable it
1660 * on Windows Vista and 2008.
1662 if (restrict_handle_inheritance < 0)
1663 restrict_handle_inheritance = GetVersion() >> 16 >= 7601;
1665 do_unset_environment_variables();
1667 /* Determine whether or not we are associated to a console */
1668 cons = CreateFileW(L"CONOUT$", GENERIC_WRITE,
1669 FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
1670 FILE_ATTRIBUTE_NORMAL, NULL);
1671 if (cons == INVALID_HANDLE_VALUE) {
1672 /* There is no console associated with this process.
1673 * Since the child is a console process, Windows
1674 * would normally create a console window. But
1675 * since we'll be redirecting std streams, we do
1676 * not need the console.
1677 * It is necessary to use DETACHED_PROCESS
1678 * instead of CREATE_NO_WINDOW to make ssh
1679 * recognize that it has no console.
1681 flags |= DETACHED_PROCESS;
1682 } else {
1683 /* There is already a console. If we specified
1684 * DETACHED_PROCESS here, too, Windows would
1685 * disassociate the child from the console.
1686 * The same is true for CREATE_NO_WINDOW.
1687 * Go figure!
1689 CloseHandle(cons);
1691 memset(&si, 0, sizeof(si));
1692 si.StartupInfo.cb = sizeof(si);
1693 si.StartupInfo.hStdInput = winansi_get_osfhandle(fhin);
1694 si.StartupInfo.hStdOutput = winansi_get_osfhandle(fhout);
1695 si.StartupInfo.hStdError = winansi_get_osfhandle(fherr);
1697 /* The list of handles cannot contain duplicates */
1698 if (si.StartupInfo.hStdInput != INVALID_HANDLE_VALUE)
1699 stdhandles[stdhandles_count++] = si.StartupInfo.hStdInput;
1700 if (si.StartupInfo.hStdOutput != INVALID_HANDLE_VALUE &&
1701 si.StartupInfo.hStdOutput != si.StartupInfo.hStdInput)
1702 stdhandles[stdhandles_count++] = si.StartupInfo.hStdOutput;
1703 if (si.StartupInfo.hStdError != INVALID_HANDLE_VALUE &&
1704 si.StartupInfo.hStdError != si.StartupInfo.hStdInput &&
1705 si.StartupInfo.hStdError != si.StartupInfo.hStdOutput)
1706 stdhandles[stdhandles_count++] = si.StartupInfo.hStdError;
1707 if (stdhandles_count)
1708 si.StartupInfo.dwFlags |= STARTF_USESTDHANDLES;
1710 if (*argv && !strcmp(cmd, *argv))
1711 wcmd[0] = L'\0';
1712 else if (xutftowcs_path(wcmd, cmd) < 0)
1713 return -1;
1714 if (dir && xutftowcs_path(wdir, dir) < 0)
1715 return -1;
1717 /* concatenate argv, quoting args as we go */
1718 strbuf_init(&args, 0);
1719 if (prepend_cmd) {
1720 char *quoted = (char *)quote_arg(cmd);
1721 strbuf_addstr(&args, quoted);
1722 if (quoted != cmd)
1723 free(quoted);
1725 for (; *argv; argv++) {
1726 char *quoted = (char *)quote_arg(*argv);
1727 if (*args.buf)
1728 strbuf_addch(&args, ' ');
1729 strbuf_addstr(&args, quoted);
1730 if (quoted != *argv)
1731 free(quoted);
1734 strace_env = getenv("GIT_STRACE_COMMANDS");
1735 if (strace_env) {
1736 char *p = path_lookup("strace.exe", 1);
1737 if (!p)
1738 return error("strace not found!");
1739 if (xutftowcs_path(wcmd, p) < 0) {
1740 free(p);
1741 return -1;
1743 free(p);
1744 if (!strcmp("1", strace_env) ||
1745 !strcasecmp("yes", strace_env) ||
1746 !strcasecmp("true", strace_env))
1747 strbuf_insert(&args, 0, "strace ", 7);
1748 else {
1749 const char *quoted = quote_arg(strace_env);
1750 struct strbuf buf = STRBUF_INIT;
1751 strbuf_addf(&buf, "strace -o %s ", quoted);
1752 if (quoted != strace_env)
1753 free((char *)quoted);
1754 strbuf_insert(&args, 0, buf.buf, buf.len);
1755 strbuf_release(&buf);
1759 ALLOC_ARRAY(wargs, st_add(st_mult(2, args.len), 1));
1760 xutftowcs(wargs, args.buf, 2 * args.len + 1);
1761 strbuf_release(&args);
1763 wenvblk = make_environment_block(deltaenv);
1765 memset(&pi, 0, sizeof(pi));
1766 if (restrict_handle_inheritance && stdhandles_count &&
1767 (InitializeProcThreadAttributeList(NULL, 1, 0, &size) ||
1768 GetLastError() == ERROR_INSUFFICIENT_BUFFER) &&
1769 (attr_list = (LPPROC_THREAD_ATTRIBUTE_LIST)
1770 (HeapAlloc(GetProcessHeap(), 0, size))) &&
1771 InitializeProcThreadAttributeList(attr_list, 1, 0, &size) &&
1772 UpdateProcThreadAttribute(attr_list, 0,
1773 PROC_THREAD_ATTRIBUTE_HANDLE_LIST,
1774 stdhandles,
1775 stdhandles_count * sizeof(HANDLE),
1776 NULL, NULL)) {
1777 si.lpAttributeList = attr_list;
1778 flags |= EXTENDED_STARTUPINFO_PRESENT;
1781 ret = CreateProcessW(*wcmd ? wcmd : NULL, wargs, NULL, NULL,
1782 stdhandles_count ? TRUE : FALSE,
1783 flags, wenvblk, dir ? wdir : NULL,
1784 &si.StartupInfo, &pi);
1787 * On Windows 2008 R2, it seems that specifying certain types of handles
1788 * (such as FILE_TYPE_CHAR or FILE_TYPE_PIPE) will always produce an
1789 * error. Rather than playing finicky and fragile games, let's just try
1790 * to detect this situation and simply try again without restricting any
1791 * handle inheritance. This is still better than failing to create
1792 * processes.
1794 if (!ret && restrict_handle_inheritance && stdhandles_count) {
1795 DWORD err = GetLastError();
1796 struct strbuf buf = STRBUF_INIT;
1798 if (err != ERROR_NO_SYSTEM_RESOURCES &&
1800 * On Windows 7 and earlier, handles on pipes and character
1801 * devices are inherited automatically, and cannot be
1802 * specified in the thread handle list. Rather than trying
1803 * to catch each and every corner case (and running the
1804 * chance of *still* forgetting a few), let's just fall
1805 * back to creating the process without trying to limit the
1806 * handle inheritance.
1808 !(err == ERROR_INVALID_PARAMETER &&
1809 GetVersion() >> 16 < 9200) &&
1810 !getenv("SUPPRESS_HANDLE_INHERITANCE_WARNING")) {
1811 DWORD fl = 0;
1812 int i;
1814 setenv("SUPPRESS_HANDLE_INHERITANCE_WARNING", "1", 1);
1816 for (i = 0; i < stdhandles_count; i++) {
1817 HANDLE h = stdhandles[i];
1818 strbuf_addf(&buf, "handle #%d: %p (type %lx, "
1819 "handle info (%d) %lx\n", i, h,
1820 GetFileType(h),
1821 GetHandleInformation(h, &fl),
1822 fl);
1824 strbuf_addstr(&buf, "\nThis is a bug; please report it "
1825 "at\nhttps://github.com/git-for-windows/"
1826 "git/issues/new\n\n"
1827 "To suppress this warning, please set "
1828 "the environment variable\n\n"
1829 "\tSUPPRESS_HANDLE_INHERITANCE_WARNING=1"
1830 "\n");
1832 restrict_handle_inheritance = 0;
1833 flags &= ~EXTENDED_STARTUPINFO_PRESENT;
1834 ret = CreateProcessW(*wcmd ? wcmd : NULL, wargs, NULL, NULL,
1835 TRUE, flags, wenvblk, dir ? wdir : NULL,
1836 &si.StartupInfo, &pi);
1837 if (!ret)
1838 errno = err_win_to_posix(GetLastError());
1839 if (ret && buf.len) {
1840 warning("failed to restrict file handles (%ld)\n\n%s",
1841 err, buf.buf);
1843 strbuf_release(&buf);
1844 } else if (!ret)
1845 errno = err_win_to_posix(GetLastError());
1847 if (si.lpAttributeList)
1848 DeleteProcThreadAttributeList(si.lpAttributeList);
1849 if (attr_list)
1850 HeapFree(GetProcessHeap(), 0, attr_list);
1852 free(wenvblk);
1853 free(wargs);
1855 if (!ret)
1856 return -1;
1858 CloseHandle(pi.hThread);
1861 * The process ID is the human-readable identifier of the process
1862 * that we want to present in log and error messages. The handle
1863 * is not useful for this purpose. But we cannot close it, either,
1864 * because it is not possible to turn a process ID into a process
1865 * handle after the process terminated.
1866 * Keep the handle in a list for waitpid.
1868 EnterCriticalSection(&pinfo_cs);
1870 struct pinfo_t *info = xmalloc(sizeof(struct pinfo_t));
1871 info->pid = pi.dwProcessId;
1872 info->proc = pi.hProcess;
1873 info->next = pinfo;
1874 pinfo = info;
1876 LeaveCriticalSection(&pinfo_cs);
1878 return (pid_t)pi.dwProcessId;
1881 static pid_t mingw_spawnv(const char *cmd, const char **argv, int prepend_cmd)
1883 return mingw_spawnve_fd(cmd, argv, NULL, NULL, prepend_cmd, 0, 1, 2);
1886 pid_t mingw_spawnvpe(const char *cmd, const char **argv, char **deltaenv,
1887 const char *dir,
1888 int fhin, int fhout, int fherr)
1890 pid_t pid;
1891 char *prog = path_lookup(cmd, 0);
1893 if (!prog) {
1894 errno = ENOENT;
1895 pid = -1;
1897 else {
1898 const char *interpr = parse_interpreter(prog);
1900 if (interpr) {
1901 const char *argv0 = argv[0];
1902 char *iprog = path_lookup(interpr, 1);
1903 argv[0] = prog;
1904 if (!iprog) {
1905 errno = ENOENT;
1906 pid = -1;
1908 else {
1909 pid = mingw_spawnve_fd(iprog, argv, deltaenv, dir, 1,
1910 fhin, fhout, fherr);
1911 free(iprog);
1913 argv[0] = argv0;
1915 else
1916 pid = mingw_spawnve_fd(prog, argv, deltaenv, dir, 0,
1917 fhin, fhout, fherr);
1918 free(prog);
1920 return pid;
1923 static int try_shell_exec(const char *cmd, char *const *argv)
1925 const char *interpr = parse_interpreter(cmd);
1926 char *prog;
1927 int pid = 0;
1929 if (!interpr)
1930 return 0;
1931 prog = path_lookup(interpr, 1);
1932 if (prog) {
1933 int exec_id;
1934 int argc = 0;
1935 char **argv2;
1936 while (argv[argc]) argc++;
1937 ALLOC_ARRAY(argv2, argc + 1);
1938 argv2[0] = (char *)cmd; /* full path to the script file */
1939 COPY_ARRAY(&argv2[1], &argv[1], argc);
1940 exec_id = trace2_exec(prog, (const char **)argv2);
1941 pid = mingw_spawnv(prog, (const char **)argv2, 1);
1942 if (pid >= 0) {
1943 int status;
1944 if (waitpid(pid, &status, 0) < 0)
1945 status = 255;
1946 trace2_exec_result(exec_id, status);
1947 exit(status);
1949 trace2_exec_result(exec_id, -1);
1950 pid = 1; /* indicate that we tried but failed */
1951 free(prog);
1952 free(argv2);
1954 return pid;
1957 int mingw_execv(const char *cmd, char *const *argv)
1959 /* check if git_command is a shell script */
1960 if (!try_shell_exec(cmd, argv)) {
1961 int pid, status;
1962 int exec_id;
1964 exec_id = trace2_exec(cmd, (const char **)argv);
1965 pid = mingw_spawnv(cmd, (const char **)argv, 0);
1966 if (pid < 0) {
1967 trace2_exec_result(exec_id, -1);
1968 return -1;
1970 if (waitpid(pid, &status, 0) < 0)
1971 status = 255;
1972 trace2_exec_result(exec_id, status);
1973 exit(status);
1975 return -1;
1978 int mingw_execvp(const char *cmd, char *const *argv)
1980 char *prog = path_lookup(cmd, 0);
1982 if (prog) {
1983 mingw_execv(prog, argv);
1984 free(prog);
1985 } else
1986 errno = ENOENT;
1988 return -1;
1991 int mingw_kill(pid_t pid, int sig)
1993 if (pid > 0 && sig == SIGTERM) {
1994 HANDLE h = OpenProcess(PROCESS_TERMINATE, FALSE, pid);
1996 if (TerminateProcess(h, -1)) {
1997 CloseHandle(h);
1998 return 0;
2001 errno = err_win_to_posix(GetLastError());
2002 CloseHandle(h);
2003 return -1;
2004 } else if (pid > 0 && sig == 0) {
2005 HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
2006 if (h) {
2007 CloseHandle(h);
2008 return 0;
2012 errno = EINVAL;
2013 return -1;
2017 * UTF-8 versions of getenv(), putenv() and unsetenv().
2018 * Internally, they use the CRT's stock UNICODE routines
2019 * to avoid data loss.
2021 char *mingw_getenv(const char *name)
2023 #define GETENV_MAX_RETAIN 64
2024 static char *values[GETENV_MAX_RETAIN];
2025 static int value_counter;
2026 size_t len_key, len_value;
2027 wchar_t *w_key;
2028 char *value;
2029 wchar_t w_value[32768];
2031 if (!name || !*name)
2032 return NULL;
2034 len_key = strlen(name) + 1;
2035 /* We cannot use xcalloc() here because that uses getenv() itself */
2036 w_key = calloc(len_key, sizeof(wchar_t));
2037 if (!w_key)
2038 die("Out of memory, (tried to allocate %"PRIuMAX" wchar_t's)",
2039 (uintmax_t)len_key);
2040 xutftowcs(w_key, name, len_key);
2041 /* GetEnvironmentVariableW() only sets the last error upon failure */
2042 SetLastError(ERROR_SUCCESS);
2043 len_value = GetEnvironmentVariableW(w_key, w_value, ARRAY_SIZE(w_value));
2044 if (!len_value && GetLastError() == ERROR_ENVVAR_NOT_FOUND) {
2045 free(w_key);
2046 return NULL;
2048 free(w_key);
2050 len_value = len_value * 3 + 1;
2051 /* We cannot use xcalloc() here because that uses getenv() itself */
2052 value = calloc(len_value, sizeof(char));
2053 if (!value)
2054 die("Out of memory, (tried to allocate %"PRIuMAX" bytes)",
2055 (uintmax_t)len_value);
2056 xwcstoutf(value, w_value, len_value);
2059 * We return `value` which is an allocated value and the caller is NOT
2060 * expecting to have to free it, so we keep a round-robin array,
2061 * invalidating the buffer after GETENV_MAX_RETAIN getenv() calls.
2063 free(values[value_counter]);
2064 values[value_counter++] = value;
2065 if (value_counter >= ARRAY_SIZE(values))
2066 value_counter = 0;
2068 return value;
2071 int mingw_putenv(const char *namevalue)
2073 size_t size;
2074 wchar_t *wide, *equal;
2075 BOOL result;
2077 if (!namevalue || !*namevalue)
2078 return 0;
2080 size = strlen(namevalue) * 2 + 1;
2081 wide = calloc(size, sizeof(wchar_t));
2082 if (!wide)
2083 die("Out of memory, (tried to allocate %" PRIuMAX " wchar_t's)",
2084 (uintmax_t)size);
2085 xutftowcs(wide, namevalue, size);
2086 equal = wcschr(wide, L'=');
2087 if (!equal)
2088 result = SetEnvironmentVariableW(wide, NULL);
2089 else {
2090 *equal = L'\0';
2091 result = SetEnvironmentVariableW(wide, equal + 1);
2093 free(wide);
2095 if (!result)
2096 errno = err_win_to_posix(GetLastError());
2098 return result ? 0 : -1;
2101 static void ensure_socket_initialization(void)
2103 WSADATA wsa;
2104 static int initialized = 0;
2106 if (initialized)
2107 return;
2109 if (WSAStartup(MAKEWORD(2,2), &wsa))
2110 die("unable to initialize winsock subsystem, error %d",
2111 WSAGetLastError());
2113 atexit((void(*)(void)) WSACleanup);
2114 initialized = 1;
2117 #undef gethostname
2118 int mingw_gethostname(char *name, int namelen)
2120 ensure_socket_initialization();
2121 return gethostname(name, namelen);
2124 #undef gethostbyname
2125 struct hostent *mingw_gethostbyname(const char *host)
2127 ensure_socket_initialization();
2128 return gethostbyname(host);
2131 #undef getaddrinfo
2132 int mingw_getaddrinfo(const char *node, const char *service,
2133 const struct addrinfo *hints, struct addrinfo **res)
2135 ensure_socket_initialization();
2136 return getaddrinfo(node, service, hints, res);
2139 int mingw_socket(int domain, int type, int protocol)
2141 int sockfd;
2142 SOCKET s;
2144 ensure_socket_initialization();
2145 s = WSASocket(domain, type, protocol, NULL, 0, 0);
2146 if (s == INVALID_SOCKET) {
2148 * WSAGetLastError() values are regular BSD error codes
2149 * biased by WSABASEERR.
2150 * However, strerror() does not know about networking
2151 * specific errors, which are values beginning at 38 or so.
2152 * Therefore, we choose to leave the biased error code
2153 * in errno so that _if_ someone looks up the code somewhere,
2154 * then it is at least the number that are usually listed.
2156 errno = WSAGetLastError();
2157 return -1;
2159 /* convert into a file descriptor */
2160 if ((sockfd = _open_osfhandle(s, O_RDWR|O_BINARY)) < 0) {
2161 closesocket(s);
2162 return error("unable to make a socket file descriptor: %s",
2163 strerror(errno));
2165 return sockfd;
2168 #undef connect
2169 int mingw_connect(int sockfd, struct sockaddr *sa, size_t sz)
2171 SOCKET s = (SOCKET)_get_osfhandle(sockfd);
2172 return connect(s, sa, sz);
2175 #undef bind
2176 int mingw_bind(int sockfd, struct sockaddr *sa, size_t sz)
2178 SOCKET s = (SOCKET)_get_osfhandle(sockfd);
2179 return bind(s, sa, sz);
2182 #undef setsockopt
2183 int mingw_setsockopt(int sockfd, int lvl, int optname, void *optval, int optlen)
2185 SOCKET s = (SOCKET)_get_osfhandle(sockfd);
2186 return setsockopt(s, lvl, optname, (const char*)optval, optlen);
2189 #undef shutdown
2190 int mingw_shutdown(int sockfd, int how)
2192 SOCKET s = (SOCKET)_get_osfhandle(sockfd);
2193 return shutdown(s, how);
2196 #undef listen
2197 int mingw_listen(int sockfd, int backlog)
2199 SOCKET s = (SOCKET)_get_osfhandle(sockfd);
2200 return listen(s, backlog);
2203 #undef accept
2204 int mingw_accept(int sockfd1, struct sockaddr *sa, socklen_t *sz)
2206 int sockfd2;
2208 SOCKET s1 = (SOCKET)_get_osfhandle(sockfd1);
2209 SOCKET s2 = accept(s1, sa, sz);
2211 /* convert into a file descriptor */
2212 if ((sockfd2 = _open_osfhandle(s2, O_RDWR|O_BINARY)) < 0) {
2213 int err = errno;
2214 closesocket(s2);
2215 return error("unable to make a socket file descriptor: %s",
2216 strerror(err));
2218 return sockfd2;
2221 #undef rename
2222 int mingw_rename(const char *pold, const char *pnew)
2224 static int supports_file_rename_info_ex = 1;
2225 DWORD attrs, gle;
2226 int tries = 0;
2227 wchar_t wpold[MAX_PATH], wpnew[MAX_PATH];
2228 int wpnew_len;
2230 if (xutftowcs_path(wpold, pold) < 0)
2231 return -1;
2232 wpnew_len = xutftowcs_path(wpnew, pnew);
2233 if (wpnew_len < 0)
2234 return -1;
2237 * Try native rename() first to get errno right.
2238 * It is based on MoveFile(), which cannot overwrite existing files.
2240 if (!_wrename(wpold, wpnew))
2241 return 0;
2242 if (errno != EEXIST)
2243 return -1;
2245 repeat:
2246 if (supports_file_rename_info_ex) {
2248 * Our minimum required Windows version is still set to Windows
2249 * Vista. We thus have to declare required infrastructure for
2250 * FileRenameInfoEx ourselves until we bump _WIN32_WINNT to
2251 * 0x0A00. Furthermore, we have to handle cases where the
2252 * FileRenameInfoEx call isn't supported yet.
2254 #define FILE_RENAME_FLAG_REPLACE_IF_EXISTS 0x00000001
2255 #define FILE_RENAME_FLAG_POSIX_SEMANTICS 0x00000002
2256 FILE_INFO_BY_HANDLE_CLASS FileRenameInfoEx = 22;
2257 struct {
2259 * This is usually an unnamed union, but that is not
2260 * part of ISO C99. We thus inline the field, as we
2261 * really only care for the Flags field anyway.
2263 DWORD Flags;
2264 HANDLE RootDirectory;
2265 DWORD FileNameLength;
2267 * The actual structure is defined with a single-character
2268 * flex array so that the structure has to be allocated on
2269 * the heap. As we declare this structure ourselves though
2270 * we can avoid the allocation and define FileName to have
2271 * MAX_PATH bytes.
2273 WCHAR FileName[MAX_PATH];
2274 } rename_info = { 0 };
2275 HANDLE old_handle = INVALID_HANDLE_VALUE;
2276 BOOL success;
2278 old_handle = CreateFileW(wpold, DELETE,
2279 FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE,
2280 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
2281 if (old_handle == INVALID_HANDLE_VALUE) {
2282 errno = err_win_to_posix(GetLastError());
2283 return -1;
2286 rename_info.Flags = FILE_RENAME_FLAG_REPLACE_IF_EXISTS |
2287 FILE_RENAME_FLAG_POSIX_SEMANTICS;
2288 rename_info.FileNameLength = wpnew_len * sizeof(WCHAR);
2289 memcpy(rename_info.FileName, wpnew, wpnew_len * sizeof(WCHAR));
2291 success = SetFileInformationByHandle(old_handle, FileRenameInfoEx,
2292 &rename_info, sizeof(rename_info));
2293 gle = GetLastError();
2294 CloseHandle(old_handle);
2295 if (success)
2296 return 0;
2299 * When we see ERROR_INVALID_PARAMETER we can assume that the
2300 * current system doesn't support FileRenameInfoEx. Keep us
2301 * from using it in future calls and retry.
2303 if (gle == ERROR_INVALID_PARAMETER) {
2304 supports_file_rename_info_ex = 0;
2305 goto repeat;
2309 * In theory, we shouldn't get ERROR_ACCESS_DENIED because we
2310 * always open files with FILE_SHARE_DELETE But in practice we
2311 * cannot assume that Git is the only one accessing files, and
2312 * other applications may not set FILE_SHARE_DELETE. So we have
2313 * to retry.
2315 } else {
2316 if (MoveFileExW(wpold, wpnew, MOVEFILE_REPLACE_EXISTING))
2317 return 0;
2318 gle = GetLastError();
2321 /* TODO: translate more errors */
2322 if (gle == ERROR_ACCESS_DENIED &&
2323 (attrs = GetFileAttributesW(wpnew)) != INVALID_FILE_ATTRIBUTES) {
2324 if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
2325 DWORD attrsold = GetFileAttributesW(wpold);
2326 if (attrsold == INVALID_FILE_ATTRIBUTES ||
2327 !(attrsold & FILE_ATTRIBUTE_DIRECTORY))
2328 errno = EISDIR;
2329 else if (!_wrmdir(wpnew))
2330 goto repeat;
2331 return -1;
2333 if ((attrs & FILE_ATTRIBUTE_READONLY) &&
2334 SetFileAttributesW(wpnew, attrs & ~FILE_ATTRIBUTE_READONLY)) {
2335 if (MoveFileExW(wpold, wpnew, MOVEFILE_REPLACE_EXISTING))
2336 return 0;
2337 gle = GetLastError();
2338 /* revert file attributes on failure */
2339 SetFileAttributesW(wpnew, attrs);
2342 if (tries < ARRAY_SIZE(delay) && gle == ERROR_ACCESS_DENIED) {
2344 * We assume that some other process had the source or
2345 * destination file open at the wrong moment and retry.
2346 * In order to give the other process a higher chance to
2347 * complete its operation, we give up our time slice now.
2348 * If we have to retry again, we do sleep a bit.
2350 Sleep(delay[tries]);
2351 tries++;
2352 goto repeat;
2354 if (gle == ERROR_ACCESS_DENIED &&
2355 ask_yes_no_if_possible("Rename from '%s' to '%s' failed. "
2356 "Should I try again?", pold, pnew))
2357 goto repeat;
2359 errno = EACCES;
2360 return -1;
2364 * Note that this doesn't return the actual pagesize, but
2365 * the allocation granularity. If future Windows specific git code
2366 * needs the real getpagesize function, we need to find another solution.
2368 int mingw_getpagesize(void)
2370 SYSTEM_INFO si;
2371 GetSystemInfo(&si);
2372 return si.dwAllocationGranularity;
2375 /* See https://msdn.microsoft.com/en-us/library/windows/desktop/ms724435.aspx */
2376 enum EXTENDED_NAME_FORMAT {
2377 NameDisplay = 3,
2378 NameUserPrincipal = 8
2381 static char *get_extended_user_info(enum EXTENDED_NAME_FORMAT type)
2383 DECLARE_PROC_ADDR(secur32.dll, BOOL, SEC_ENTRY, GetUserNameExW,
2384 enum EXTENDED_NAME_FORMAT, LPCWSTR, PULONG);
2385 static wchar_t wbuffer[1024];
2386 DWORD len;
2388 if (!INIT_PROC_ADDR(GetUserNameExW))
2389 return NULL;
2391 len = ARRAY_SIZE(wbuffer);
2392 if (GetUserNameExW(type, wbuffer, &len)) {
2393 char *converted = xmalloc((len *= 3));
2394 if (xwcstoutf(converted, wbuffer, len) >= 0)
2395 return converted;
2396 free(converted);
2399 return NULL;
2402 char *mingw_query_user_email(void)
2404 return get_extended_user_info(NameUserPrincipal);
2407 struct passwd *getpwuid(int uid UNUSED)
2409 static unsigned initialized;
2410 static char user_name[100];
2411 static struct passwd *p;
2412 wchar_t buf[100];
2413 DWORD len;
2415 if (initialized)
2416 return p;
2418 len = ARRAY_SIZE(buf);
2419 if (!GetUserNameW(buf, &len)) {
2420 initialized = 1;
2421 return NULL;
2424 if (xwcstoutf(user_name, buf, sizeof(user_name)) < 0) {
2425 initialized = 1;
2426 return NULL;
2429 p = xmalloc(sizeof(*p));
2430 p->pw_name = user_name;
2431 p->pw_gecos = get_extended_user_info(NameDisplay);
2432 if (!p->pw_gecos)
2434 * Data returned by getpwuid(3P) is treated as internal and
2435 * must never be written to or freed.
2437 p->pw_gecos = (char *) "unknown";
2438 p->pw_dir = NULL;
2440 initialized = 1;
2441 return p;
2444 static HANDLE timer_event;
2445 static HANDLE timer_thread;
2446 static int timer_interval;
2447 static int one_shot;
2448 static sig_handler_t timer_fn = SIG_DFL, sigint_fn = SIG_DFL;
2450 /* The timer works like this:
2451 * The thread, ticktack(), is a trivial routine that most of the time
2452 * only waits to receive the signal to terminate. The main thread tells
2453 * the thread to terminate by setting the timer_event to the signalled
2454 * state.
2455 * But ticktack() interrupts the wait state after the timer's interval
2456 * length to call the signal handler.
2459 static unsigned __stdcall ticktack(void *dummy UNUSED)
2461 while (WaitForSingleObject(timer_event, timer_interval) == WAIT_TIMEOUT) {
2462 mingw_raise(SIGALRM);
2463 if (one_shot)
2464 break;
2466 return 0;
2469 static int start_timer_thread(void)
2471 timer_event = CreateEvent(NULL, FALSE, FALSE, NULL);
2472 if (timer_event) {
2473 timer_thread = (HANDLE) _beginthreadex(NULL, 0, ticktack, NULL, 0, NULL);
2474 if (!timer_thread )
2475 return errno = ENOMEM,
2476 error("cannot start timer thread");
2477 } else
2478 return errno = ENOMEM,
2479 error("cannot allocate resources for timer");
2480 return 0;
2483 static void stop_timer_thread(void)
2485 if (timer_event)
2486 SetEvent(timer_event); /* tell thread to terminate */
2487 if (timer_thread) {
2488 int rc = WaitForSingleObject(timer_thread, 10000);
2489 if (rc == WAIT_TIMEOUT)
2490 error("timer thread did not terminate timely");
2491 else if (rc != WAIT_OBJECT_0)
2492 error("waiting for timer thread failed: %lu",
2493 GetLastError());
2494 CloseHandle(timer_thread);
2496 if (timer_event)
2497 CloseHandle(timer_event);
2498 timer_event = NULL;
2499 timer_thread = NULL;
2502 static inline int is_timeval_eq(const struct timeval *i1, const struct timeval *i2)
2504 return i1->tv_sec == i2->tv_sec && i1->tv_usec == i2->tv_usec;
2507 int setitimer(int type UNUSED, struct itimerval *in, struct itimerval *out)
2509 static const struct timeval zero;
2510 static int atexit_done;
2512 if (out)
2513 return errno = EINVAL,
2514 error("setitimer param 3 != NULL not implemented");
2515 if (!is_timeval_eq(&in->it_interval, &zero) &&
2516 !is_timeval_eq(&in->it_interval, &in->it_value))
2517 return errno = EINVAL,
2518 error("setitimer: it_interval must be zero or eq it_value");
2520 if (timer_thread)
2521 stop_timer_thread();
2523 if (is_timeval_eq(&in->it_value, &zero) &&
2524 is_timeval_eq(&in->it_interval, &zero))
2525 return 0;
2527 timer_interval = in->it_value.tv_sec * 1000 + in->it_value.tv_usec / 1000;
2528 one_shot = is_timeval_eq(&in->it_interval, &zero);
2529 if (!atexit_done) {
2530 atexit(stop_timer_thread);
2531 atexit_done = 1;
2533 return start_timer_thread();
2536 int sigaction(int sig, struct sigaction *in, struct sigaction *out)
2538 if (sig != SIGALRM)
2539 return errno = EINVAL,
2540 error("sigaction only implemented for SIGALRM");
2541 if (out)
2542 return errno = EINVAL,
2543 error("sigaction: param 3 != NULL not implemented");
2545 timer_fn = in->sa_handler;
2546 return 0;
2549 #undef signal
2550 sig_handler_t mingw_signal(int sig, sig_handler_t handler)
2552 sig_handler_t old;
2554 switch (sig) {
2555 case SIGALRM:
2556 old = timer_fn;
2557 timer_fn = handler;
2558 break;
2560 case SIGINT:
2561 old = sigint_fn;
2562 sigint_fn = handler;
2563 break;
2565 default:
2566 return signal(sig, handler);
2569 return old;
2572 #undef raise
2573 int mingw_raise(int sig)
2575 switch (sig) {
2576 case SIGALRM:
2577 if (timer_fn == SIG_DFL) {
2578 if (isatty(STDERR_FILENO))
2579 fputs("Alarm clock\n", stderr);
2580 exit(128 + SIGALRM);
2581 } else if (timer_fn != SIG_IGN)
2582 timer_fn(SIGALRM);
2583 return 0;
2585 case SIGINT:
2586 if (sigint_fn == SIG_DFL)
2587 exit(128 + SIGINT);
2588 else if (sigint_fn != SIG_IGN)
2589 sigint_fn(SIGINT);
2590 return 0;
2592 #if defined(_MSC_VER)
2593 case SIGILL:
2594 case SIGFPE:
2595 case SIGSEGV:
2596 case SIGTERM:
2597 case SIGBREAK:
2598 case SIGABRT:
2599 case SIGABRT_COMPAT:
2601 * The <signal.h> header in the MS C Runtime defines 8 signals
2602 * as being supported on the platform. Anything else causes an
2603 * "Invalid signal or error" (which in DEBUG builds causes the
2604 * Abort/Retry/Ignore dialog). We by-pass the CRT for things we
2605 * already know will fail.
2607 return raise(sig);
2608 default:
2609 errno = EINVAL;
2610 return -1;
2612 #else
2614 default:
2615 return raise(sig);
2617 #endif
2622 int link(const char *oldpath, const char *newpath)
2624 wchar_t woldpath[MAX_PATH], wnewpath[MAX_PATH];
2625 if (xutftowcs_path(woldpath, oldpath) < 0 ||
2626 xutftowcs_path(wnewpath, newpath) < 0)
2627 return -1;
2629 if (!CreateHardLinkW(wnewpath, woldpath, NULL)) {
2630 errno = err_win_to_posix(GetLastError());
2631 return -1;
2633 return 0;
2636 pid_t waitpid(pid_t pid, int *status, int options)
2638 HANDLE h = OpenProcess(SYNCHRONIZE | PROCESS_QUERY_INFORMATION,
2639 FALSE, pid);
2640 if (!h) {
2641 errno = ECHILD;
2642 return -1;
2645 if (pid > 0 && options & WNOHANG) {
2646 if (WAIT_OBJECT_0 != WaitForSingleObject(h, 0)) {
2647 CloseHandle(h);
2648 return 0;
2650 options &= ~WNOHANG;
2653 if (options == 0) {
2654 struct pinfo_t **ppinfo;
2655 if (WaitForSingleObject(h, INFINITE) != WAIT_OBJECT_0) {
2656 CloseHandle(h);
2657 return 0;
2660 if (status)
2661 GetExitCodeProcess(h, (LPDWORD)status);
2663 EnterCriticalSection(&pinfo_cs);
2665 ppinfo = &pinfo;
2666 while (*ppinfo) {
2667 struct pinfo_t *info = *ppinfo;
2668 if (info->pid == pid) {
2669 CloseHandle(info->proc);
2670 *ppinfo = info->next;
2671 free(info);
2672 break;
2674 ppinfo = &info->next;
2677 LeaveCriticalSection(&pinfo_cs);
2679 CloseHandle(h);
2680 return pid;
2682 CloseHandle(h);
2684 errno = EINVAL;
2685 return -1;
2688 int xutftowcsn(wchar_t *wcs, const char *utfs, size_t wcslen, int utflen)
2690 int upos = 0, wpos = 0;
2691 const unsigned char *utf = (const unsigned char*) utfs;
2692 if (!utf || !wcs || wcslen < 1) {
2693 errno = EINVAL;
2694 return -1;
2696 /* reserve space for \0 */
2697 wcslen--;
2698 if (utflen < 0)
2699 utflen = INT_MAX;
2701 while (upos < utflen) {
2702 int c = utf[upos++] & 0xff;
2703 if (utflen == INT_MAX && c == 0)
2704 break;
2706 if (wpos >= wcslen) {
2707 wcs[wpos] = 0;
2708 errno = ERANGE;
2709 return -1;
2712 if (c < 0x80) {
2713 /* ASCII */
2714 wcs[wpos++] = c;
2715 } else if (c >= 0xc2 && c < 0xe0 && upos < utflen &&
2716 (utf[upos] & 0xc0) == 0x80) {
2717 /* 2-byte utf-8 */
2718 c = ((c & 0x1f) << 6);
2719 c |= (utf[upos++] & 0x3f);
2720 wcs[wpos++] = c;
2721 } else if (c >= 0xe0 && c < 0xf0 && upos + 1 < utflen &&
2722 !(c == 0xe0 && utf[upos] < 0xa0) && /* over-long encoding */
2723 (utf[upos] & 0xc0) == 0x80 &&
2724 (utf[upos + 1] & 0xc0) == 0x80) {
2725 /* 3-byte utf-8 */
2726 c = ((c & 0x0f) << 12);
2727 c |= ((utf[upos++] & 0x3f) << 6);
2728 c |= (utf[upos++] & 0x3f);
2729 wcs[wpos++] = c;
2730 } else if (c >= 0xf0 && c < 0xf5 && upos + 2 < utflen &&
2731 wpos + 1 < wcslen &&
2732 !(c == 0xf0 && utf[upos] < 0x90) && /* over-long encoding */
2733 !(c == 0xf4 && utf[upos] >= 0x90) && /* > \u10ffff */
2734 (utf[upos] & 0xc0) == 0x80 &&
2735 (utf[upos + 1] & 0xc0) == 0x80 &&
2736 (utf[upos + 2] & 0xc0) == 0x80) {
2737 /* 4-byte utf-8: convert to \ud8xx \udcxx surrogate pair */
2738 c = ((c & 0x07) << 18);
2739 c |= ((utf[upos++] & 0x3f) << 12);
2740 c |= ((utf[upos++] & 0x3f) << 6);
2741 c |= (utf[upos++] & 0x3f);
2742 c -= 0x10000;
2743 wcs[wpos++] = 0xd800 | (c >> 10);
2744 wcs[wpos++] = 0xdc00 | (c & 0x3ff);
2745 } else if (c >= 0xa0) {
2746 /* invalid utf-8 byte, printable unicode char: convert 1:1 */
2747 wcs[wpos++] = c;
2748 } else {
2749 /* invalid utf-8 byte, non-printable unicode: convert to hex */
2750 static const char *hex = "0123456789abcdef";
2751 wcs[wpos++] = hex[c >> 4];
2752 if (wpos < wcslen)
2753 wcs[wpos++] = hex[c & 0x0f];
2756 wcs[wpos] = 0;
2757 return wpos;
2760 int xwcstoutf(char *utf, const wchar_t *wcs, size_t utflen)
2762 if (!wcs || !utf || utflen < 1) {
2763 errno = EINVAL;
2764 return -1;
2766 utflen = WideCharToMultiByte(CP_UTF8, 0, wcs, -1, utf, utflen, NULL, NULL);
2767 if (utflen)
2768 return utflen - 1;
2769 errno = ERANGE;
2770 return -1;
2773 static void setup_windows_environment(void)
2775 char *tmp = getenv("TMPDIR");
2777 /* on Windows it is TMP and TEMP */
2778 if (!tmp) {
2779 if (!(tmp = getenv("TMP")))
2780 tmp = getenv("TEMP");
2781 if (tmp) {
2782 setenv("TMPDIR", tmp, 1);
2783 tmp = getenv("TMPDIR");
2787 if (tmp) {
2789 * Convert all dir separators to forward slashes,
2790 * to help shell commands called from the Git
2791 * executable (by not mistaking the dir separators
2792 * for escape characters).
2794 convert_slashes(tmp);
2797 /* simulate TERM to enable auto-color (see color.c) */
2798 if (!getenv("TERM"))
2799 setenv("TERM", "cygwin", 1);
2801 /* calculate HOME if not set */
2802 if (!getenv("HOME")) {
2804 * try $HOMEDRIVE$HOMEPATH - the home share may be a network
2805 * location, thus also check if the path exists (i.e. is not
2806 * disconnected)
2808 if ((tmp = getenv("HOMEDRIVE"))) {
2809 struct strbuf buf = STRBUF_INIT;
2810 strbuf_addstr(&buf, tmp);
2811 if ((tmp = getenv("HOMEPATH"))) {
2812 strbuf_addstr(&buf, tmp);
2813 if (is_directory(buf.buf))
2814 setenv("HOME", buf.buf, 1);
2815 else
2816 tmp = NULL; /* use $USERPROFILE */
2818 strbuf_release(&buf);
2820 /* use $USERPROFILE if the home share is not available */
2821 if (!tmp && (tmp = getenv("USERPROFILE")))
2822 setenv("HOME", tmp, 1);
2826 static PSID get_current_user_sid(void)
2828 HANDLE token;
2829 DWORD len = 0;
2830 PSID result = NULL;
2832 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token))
2833 return NULL;
2835 if (!GetTokenInformation(token, TokenUser, NULL, 0, &len)) {
2836 TOKEN_USER *info = xmalloc((size_t)len);
2837 if (GetTokenInformation(token, TokenUser, info, len, &len)) {
2838 len = GetLengthSid(info->User.Sid);
2839 result = xmalloc(len);
2840 if (!CopySid(len, result, info->User.Sid)) {
2841 error(_("failed to copy SID (%ld)"),
2842 GetLastError());
2843 FREE_AND_NULL(result);
2846 FREE_AND_NULL(info);
2848 CloseHandle(token);
2850 return result;
2853 static BOOL user_sid_to_user_name(PSID sid, LPSTR *str)
2855 SID_NAME_USE pe_use;
2856 DWORD len_user = 0, len_domain = 0;
2857 BOOL translate_sid_to_user;
2860 * returns only FALSE, because the string pointers are NULL
2862 LookupAccountSidA(NULL, sid, NULL, &len_user, NULL, &len_domain,
2863 &pe_use);
2865 * Alloc needed space of the strings
2867 ALLOC_ARRAY((*str), (size_t)len_domain + (size_t)len_user);
2868 translate_sid_to_user = LookupAccountSidA(NULL, sid,
2869 (*str) + len_domain, &len_user, *str, &len_domain, &pe_use);
2870 if (!translate_sid_to_user)
2871 FREE_AND_NULL(*str);
2872 else
2873 (*str)[len_domain] = '/';
2874 return translate_sid_to_user;
2877 static int acls_supported(const char *path)
2879 size_t offset = offset_1st_component(path);
2880 WCHAR wroot[MAX_PATH];
2881 DWORD file_system_flags;
2883 if (offset &&
2884 xutftowcsn(wroot, path, MAX_PATH, offset) > 0 &&
2885 GetVolumeInformationW(wroot, NULL, 0, NULL, NULL,
2886 &file_system_flags, NULL, 0))
2887 return !!(file_system_flags & FILE_PERSISTENT_ACLS);
2889 return 0;
2892 int is_path_owned_by_current_sid(const char *path, struct strbuf *report)
2894 WCHAR wpath[MAX_PATH];
2895 PSID sid = NULL;
2896 PSECURITY_DESCRIPTOR descriptor = NULL;
2897 DWORD err;
2899 static wchar_t home[MAX_PATH];
2901 int result = 0;
2903 if (xutftowcs_path(wpath, path) < 0)
2904 return 0;
2907 * On Windows, the home directory is owned by the administrator, but for
2908 * all practical purposes, it belongs to the user. Do pretend that it is
2909 * owned by the user.
2911 if (!*home) {
2912 DWORD size = ARRAY_SIZE(home);
2913 DWORD len = GetEnvironmentVariableW(L"HOME", home, size);
2914 if (!len || len > size)
2915 wcscpy(home, L"::N/A::");
2917 if (!wcsicmp(wpath, home))
2918 return 1;
2920 /* Get the owner SID */
2921 err = GetNamedSecurityInfoW(wpath, SE_FILE_OBJECT,
2922 OWNER_SECURITY_INFORMATION |
2923 DACL_SECURITY_INFORMATION,
2924 &sid, NULL, NULL, NULL, &descriptor);
2926 if (err != ERROR_SUCCESS)
2927 error(_("failed to get owner for '%s' (%ld)"), path, err);
2928 else if (sid && IsValidSid(sid)) {
2929 /* Now, verify that the SID matches the current user's */
2930 static PSID current_user_sid;
2931 BOOL is_member;
2933 if (!current_user_sid)
2934 current_user_sid = get_current_user_sid();
2936 if (current_user_sid &&
2937 IsValidSid(current_user_sid) &&
2938 EqualSid(sid, current_user_sid))
2939 result = 1;
2940 else if (IsWellKnownSid(sid, WinBuiltinAdministratorsSid) &&
2941 CheckTokenMembership(NULL, sid, &is_member) &&
2942 is_member)
2944 * If owned by the Administrators group, and the
2945 * current user is an administrator, we consider that
2946 * okay, too.
2948 result = 1;
2949 else if (report &&
2950 IsWellKnownSid(sid, WinWorldSid) &&
2951 !acls_supported(path)) {
2953 * On FAT32 volumes, ownership is not actually recorded.
2955 strbuf_addf(report, "'%s' is on a file system that does "
2956 "not record ownership\n", path);
2957 } else if (report) {
2958 PCSTR str1, str2, str3, str4;
2959 LPSTR to_free1 = NULL, to_free3 = NULL,
2960 to_local_free2 = NULL, to_local_free4 = NULL;
2962 if (user_sid_to_user_name(sid, &to_free1))
2963 str1 = to_free1;
2964 else
2965 str1 = "(inconvertible)";
2966 if (ConvertSidToStringSidA(sid, &to_local_free2))
2967 str2 = to_local_free2;
2968 else
2969 str2 = "(inconvertible)";
2971 if (!current_user_sid) {
2972 str3 = "(none)";
2973 str4 = "(none)";
2975 else if (!IsValidSid(current_user_sid)) {
2976 str3 = "(invalid)";
2977 str4 = "(invalid)";
2978 } else {
2979 if (user_sid_to_user_name(current_user_sid,
2980 &to_free3))
2981 str3 = to_free3;
2982 else
2983 str3 = "(inconvertible)";
2984 if (ConvertSidToStringSidA(current_user_sid,
2985 &to_local_free4))
2986 str4 = to_local_free4;
2987 else
2988 str4 = "(inconvertible)";
2990 strbuf_addf(report,
2991 "'%s' is owned by:\n"
2992 "\t%s (%s)\nbut the current user is:\n"
2993 "\t%s (%s)\n",
2994 path, str1, str2, str3, str4);
2995 free(to_free1);
2996 LocalFree(to_local_free2);
2997 free(to_free3);
2998 LocalFree(to_local_free4);
3003 * We can release the security descriptor struct only now because `sid`
3004 * actually points into this struct.
3006 if (descriptor)
3007 LocalFree(descriptor);
3009 return result;
3012 int is_valid_win32_path(const char *path, int allow_literal_nul)
3014 const char *p = path;
3015 int preceding_space_or_period = 0, i = 0, periods = 0;
3017 if (!protect_ntfs)
3018 return 1;
3020 skip_dos_drive_prefix((char **)&path);
3021 goto segment_start;
3023 for (;;) {
3024 char c = *(path++);
3025 switch (c) {
3026 case '\0':
3027 case '/': case '\\':
3028 /* cannot end in ` ` or `.`, except for `.` and `..` */
3029 if (preceding_space_or_period &&
3030 (i != periods || periods > 2))
3031 return 0;
3032 if (!c)
3033 return 1;
3035 i = periods = preceding_space_or_period = 0;
3037 segment_start:
3038 switch (*path) {
3039 case 'a': case 'A': /* AUX */
3040 if (((c = path[++i]) != 'u' && c != 'U') ||
3041 ((c = path[++i]) != 'x' && c != 'X')) {
3042 not_a_reserved_name:
3043 path += i;
3044 continue;
3046 break;
3047 case 'c': case 'C':
3048 /* COM1 ... COM9, CON, CONIN$, CONOUT$ */
3049 if ((c = path[++i]) != 'o' && c != 'O')
3050 goto not_a_reserved_name;
3051 c = path[++i];
3052 if (c == 'm' || c == 'M') { /* COM1 ... COM9 */
3053 c = path[++i];
3054 if (c < '1' || c > '9')
3055 goto not_a_reserved_name;
3056 } else if (c == 'n' || c == 'N') { /* CON */
3057 c = path[i + 1];
3058 if ((c == 'i' || c == 'I') &&
3059 ((c = path[i + 2]) == 'n' ||
3060 c == 'N') &&
3061 path[i + 3] == '$')
3062 i += 3; /* CONIN$ */
3063 else if ((c == 'o' || c == 'O') &&
3064 ((c = path[i + 2]) == 'u' ||
3065 c == 'U') &&
3066 ((c = path[i + 3]) == 't' ||
3067 c == 'T') &&
3068 path[i + 4] == '$')
3069 i += 4; /* CONOUT$ */
3070 } else
3071 goto not_a_reserved_name;
3072 break;
3073 case 'l': case 'L': /* LPT<N> */
3074 if (((c = path[++i]) != 'p' && c != 'P') ||
3075 ((c = path[++i]) != 't' && c != 'T') ||
3076 !isdigit(path[++i]))
3077 goto not_a_reserved_name;
3078 break;
3079 case 'n': case 'N': /* NUL */
3080 if (((c = path[++i]) != 'u' && c != 'U') ||
3081 ((c = path[++i]) != 'l' && c != 'L') ||
3082 (allow_literal_nul &&
3083 !path[i + 1] && p == path))
3084 goto not_a_reserved_name;
3085 break;
3086 case 'p': case 'P': /* PRN */
3087 if (((c = path[++i]) != 'r' && c != 'R') ||
3088 ((c = path[++i]) != 'n' && c != 'N'))
3089 goto not_a_reserved_name;
3090 break;
3091 default:
3092 continue;
3096 * So far, this looks like a reserved name. Let's see
3097 * whether it actually is one: trailing spaces, a file
3098 * extension, or an NTFS Alternate Data Stream do not
3099 * matter, the name is still reserved if any of those
3100 * follow immediately after the actual name.
3102 i++;
3103 if (path[i] == ' ') {
3104 preceding_space_or_period = 1;
3105 while (path[++i] == ' ')
3106 ; /* skip all spaces */
3109 c = path[i];
3110 if (c && c != '.' && c != ':' && !is_xplatform_dir_sep(c))
3111 goto not_a_reserved_name;
3113 /* contains reserved name */
3114 return 0;
3115 case '.':
3116 periods++;
3117 /* fallthru */
3118 case ' ':
3119 preceding_space_or_period = 1;
3120 i++;
3121 continue;
3122 case ':': /* DOS drive prefix was already skipped */
3123 case '<': case '>': case '"': case '|': case '?': case '*':
3124 /* illegal character */
3125 return 0;
3126 default:
3127 if (c > '\0' && c < '\x20')
3128 /* illegal character */
3129 return 0;
3131 preceding_space_or_period = 0;
3132 i++;
3136 #if !defined(_MSC_VER)
3138 * Disable MSVCRT command line wildcard expansion (__getmainargs called from
3139 * mingw startup code, see init.c in mingw runtime).
3141 int _CRT_glob = 0;
3142 #endif
3144 static NORETURN void die_startup(void)
3146 fputs("fatal: not enough memory for initialization", stderr);
3147 exit(128);
3150 static void *malloc_startup(size_t size)
3152 void *result = malloc(size);
3153 if (!result)
3154 die_startup();
3155 return result;
3158 static char *wcstoutfdup_startup(char *buffer, const wchar_t *wcs, size_t len)
3160 len = xwcstoutf(buffer, wcs, len) + 1;
3161 return memcpy(malloc_startup(len), buffer, len);
3164 static void maybe_redirect_std_handle(const wchar_t *key, DWORD std_id, int fd,
3165 DWORD desired_access, DWORD flags)
3167 DWORD create_flag = fd ? OPEN_ALWAYS : OPEN_EXISTING;
3168 wchar_t buf[MAX_PATH];
3169 DWORD max = ARRAY_SIZE(buf);
3170 HANDLE handle;
3171 DWORD ret = GetEnvironmentVariableW(key, buf, max);
3173 if (!ret || ret >= max)
3174 return;
3176 /* make sure this does not leak into child processes */
3177 SetEnvironmentVariableW(key, NULL);
3178 if (!wcscmp(buf, L"off")) {
3179 close(fd);
3180 handle = GetStdHandle(std_id);
3181 if (handle != INVALID_HANDLE_VALUE)
3182 CloseHandle(handle);
3183 return;
3185 if (std_id == STD_ERROR_HANDLE && !wcscmp(buf, L"2>&1")) {
3186 handle = GetStdHandle(STD_OUTPUT_HANDLE);
3187 if (handle == INVALID_HANDLE_VALUE) {
3188 close(fd);
3189 handle = GetStdHandle(std_id);
3190 if (handle != INVALID_HANDLE_VALUE)
3191 CloseHandle(handle);
3192 } else {
3193 int new_fd = _open_osfhandle((intptr_t)handle, O_BINARY);
3194 SetStdHandle(std_id, handle);
3195 dup2(new_fd, fd);
3196 /* do *not* close the new_fd: that would close stdout */
3198 return;
3200 handle = CreateFileW(buf, desired_access, 0, NULL, create_flag,
3201 flags, NULL);
3202 if (handle != INVALID_HANDLE_VALUE) {
3203 int new_fd = _open_osfhandle((intptr_t)handle, O_BINARY);
3204 SetStdHandle(std_id, handle);
3205 dup2(new_fd, fd);
3206 close(new_fd);
3210 static void maybe_redirect_std_handles(void)
3212 maybe_redirect_std_handle(L"GIT_REDIRECT_STDIN", STD_INPUT_HANDLE, 0,
3213 GENERIC_READ, FILE_ATTRIBUTE_NORMAL);
3214 maybe_redirect_std_handle(L"GIT_REDIRECT_STDOUT", STD_OUTPUT_HANDLE, 1,
3215 GENERIC_WRITE, FILE_ATTRIBUTE_NORMAL);
3216 maybe_redirect_std_handle(L"GIT_REDIRECT_STDERR", STD_ERROR_HANDLE, 2,
3217 GENERIC_WRITE, FILE_FLAG_NO_BUFFERING);
3220 #ifdef _MSC_VER
3221 #ifdef _DEBUG
3222 #include <crtdbg.h>
3223 #endif
3224 #endif
3227 * We implement wmain() and compile with -municode, which would
3228 * normally ignore main(), but we call the latter from the former
3229 * so that we can handle non-ASCII command-line parameters
3230 * appropriately.
3232 * To be more compatible with the core git code, we convert
3233 * argv into UTF8 and pass them directly to main().
3235 int wmain(int argc, const wchar_t **wargv)
3237 int i, exit_status;
3238 size_t maxlen;
3239 char *buffer, **save;
3240 const char **argv;
3242 trace2_initialize_clock();
3244 #ifdef _MSC_VER
3245 #ifdef _DEBUG
3246 _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG);
3247 #endif
3249 #ifdef USE_MSVC_CRTDBG
3250 _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
3251 #endif
3252 #endif
3254 maybe_redirect_std_handles();
3256 /* determine size of argv and environ conversion buffer */
3257 maxlen = wcslen(wargv[0]);
3258 for (i = 1; i < argc; i++)
3259 maxlen = max(maxlen, wcslen(wargv[i]));
3261 /* allocate buffer (wchar_t encodes to max 3 UTF-8 bytes) */
3262 maxlen = 3 * maxlen + 1;
3263 buffer = malloc_startup(maxlen);
3266 * Create a UTF-8 version of w_argv. Also create a "save" copy
3267 * to remember all the string pointers because parse_options()
3268 * will remove claimed items from the argv that we pass down.
3270 ALLOC_ARRAY(argv, argc + 1);
3271 ALLOC_ARRAY(save, argc + 1);
3272 for (i = 0; i < argc; i++)
3273 argv[i] = save[i] = wcstoutfdup_startup(buffer, wargv[i], maxlen);
3274 argv[i] = save[i] = NULL;
3275 free(buffer);
3277 /* fix Windows specific environment settings */
3278 setup_windows_environment();
3280 unset_environment_variables = xstrdup("PERL5LIB");
3282 /* initialize critical section for waitpid pinfo_t list */
3283 InitializeCriticalSection(&pinfo_cs);
3285 /* set up default file mode and file modes for stdin/out/err */
3286 _fmode = _O_BINARY;
3287 _setmode(_fileno(stdin), _O_BINARY);
3288 _setmode(_fileno(stdout), _O_BINARY);
3289 _setmode(_fileno(stderr), _O_BINARY);
3291 /* initialize Unicode console */
3292 winansi_init();
3294 /* invoke the real main() using our utf8 version of argv. */
3295 exit_status = main(argc, argv);
3297 for (i = 0; i < argc; i++)
3298 free(save[i]);
3299 free(save);
3300 free(argv);
3302 return exit_status;
3305 int uname(struct utsname *buf)
3307 unsigned v = (unsigned)GetVersion();
3308 memset(buf, 0, sizeof(*buf));
3309 xsnprintf(buf->sysname, sizeof(buf->sysname), "Windows");
3310 xsnprintf(buf->release, sizeof(buf->release),
3311 "%u.%u", v & 0xff, (v >> 8) & 0xff);
3312 /* assuming NT variants only.. */
3313 xsnprintf(buf->version, sizeof(buf->version),
3314 "%u", (v >> 16) & 0x7fff);
3315 return 0;
3318 #ifndef NO_UNIX_SOCKETS
3319 int mingw_have_unix_sockets(void)
3321 SC_HANDLE scm, srvc;
3322 SERVICE_STATUS_PROCESS status;
3323 DWORD bytes;
3324 int ret = 0;
3325 scm = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
3326 if (scm) {
3327 srvc = OpenServiceA(scm, "afunix", SERVICE_QUERY_STATUS);
3328 if (srvc) {
3329 if(QueryServiceStatusEx(srvc, SC_STATUS_PROCESS_INFO, (LPBYTE)&status, sizeof(SERVICE_STATUS_PROCESS), &bytes))
3330 ret = status.dwCurrentState == SERVICE_RUNNING;
3331 CloseServiceHandle(srvc);
3333 CloseServiceHandle(scm);
3335 return ret;
3337 #endif