Raw
1 #define USE_THE_REPOSITORY_VARIABLE
2 #define DISABLE_SIGN_COMPARE_WARNINGS
3
4 #include "git-compat-util.h"
5 #include "abspath.h"
6 #include "alloc.h"
7 #include "config.h"
8 #include "dir.h"
9 #include "environment.h"
10 #include "gettext.h"
11 #include "run-command.h"
12 #include "strbuf.h"
13 #include "symlinks.h"
14 #include "trace2.h"
15 #include "win32.h"
16 #include "win32/exit-process.h"
17 #include "win32/lazyload.h"
18 #include "wrapper.h"
19 #include <aclapi.h>
20 #include <conio.h>
21 #include <sddl.h>
22 #define SECURITY_WIN32
23 #include <sspi.h>
24 #include <wchar.h>
25 #include <winioctl.h>
26 #include <winternl.h>
27
28 #define STATUS_DELETE_PENDING ((NTSTATUS) 0xC0000056)
29
30 #define HCAST(type, handle) ((type)(intptr_t)handle)
31
32 void open_in_gdb(void)
33 {
34 static struct child_process cp = CHILD_PROCESS_INIT;
35
36 strvec_pushl(&cp.args, "mintty", "gdb", NULL);
37 strvec_pushf(&cp.args, "--pid=%d", getpid());
38 cp.clean_on_exit = 1;
39 if (start_command(&cp) < 0)
40 die_errno("Could not start gdb");
41 sleep(1);
42 }
43
44 int err_win_to_posix(DWORD winerr)
45 {
46 int error = ENOSYS;
47 switch(winerr) {
48 case ERROR_ACCESS_DENIED: error = EACCES; break;
49 case ERROR_ACCOUNT_DISABLED: error = EACCES; break;
50 case ERROR_ACCOUNT_RESTRICTION: error = EACCES; break;
51 case ERROR_ALREADY_ASSIGNED: error = EBUSY; break;
52 case ERROR_ALREADY_EXISTS: error = EEXIST; break;
53 case ERROR_ARITHMETIC_OVERFLOW: error = ERANGE; break;
54 case ERROR_BAD_COMMAND: error = EIO; break;
55 case ERROR_BAD_DEVICE: error = ENODEV; break;
56 case ERROR_BAD_DRIVER_LEVEL: error = ENXIO; break;
57 case ERROR_BAD_EXE_FORMAT: error = ENOEXEC; break;
58 case ERROR_BAD_FORMAT: error = ENOEXEC; break;
59 case ERROR_BAD_LENGTH: error = EINVAL; break;
60 case ERROR_BAD_PATHNAME: error = ENOENT; break;
61 case ERROR_BAD_PIPE: error = EPIPE; break;
62 case ERROR_BAD_UNIT: error = ENODEV; break;
63 case ERROR_BAD_USERNAME: error = EINVAL; break;
64 case ERROR_BROKEN_PIPE: error = EPIPE; break;
65 case ERROR_BUFFER_OVERFLOW: error = ENAMETOOLONG; break;
66 case ERROR_BUSY: error = EBUSY; break;
67 case ERROR_BUSY_DRIVE: error = EBUSY; break;
68 case ERROR_CALL_NOT_IMPLEMENTED: error = ENOSYS; break;
69 case ERROR_CANNOT_MAKE: error = EACCES; break;
70 case ERROR_CANTOPEN: error = EIO; break;
71 case ERROR_CANTREAD: error = EIO; break;
72 case ERROR_CANTWRITE: error = EIO; break;
73 case ERROR_CRC: error = EIO; break;
74 case ERROR_CURRENT_DIRECTORY: error = EACCES; break;
75 case ERROR_DEVICE_IN_USE: error = EBUSY; break;
76 case ERROR_DEV_NOT_EXIST: error = ENODEV; break;
77 case ERROR_DIRECTORY: error = EINVAL; break;
78 case ERROR_DIR_NOT_EMPTY: error = ENOTEMPTY; break;
79 case ERROR_DISK_CHANGE: error = EIO; break;
80 case ERROR_DISK_FULL: error = ENOSPC; break;
81 case ERROR_DRIVE_LOCKED: error = EBUSY; break;
82 case ERROR_ENVVAR_NOT_FOUND: error = EINVAL; break;
83 case ERROR_EXE_MARKED_INVALID: error = ENOEXEC; break;
84 case ERROR_FILENAME_EXCED_RANGE: error = ENAMETOOLONG; break;
85 case ERROR_FILE_EXISTS: error = EEXIST; break;
86 case ERROR_FILE_INVALID: error = ENODEV; break;
87 case ERROR_FILE_NOT_FOUND: error = ENOENT; break;
88 case ERROR_GEN_FAILURE: error = EIO; break;
89 case ERROR_HANDLE_DISK_FULL: error = ENOSPC; break;
90 case ERROR_INSUFFICIENT_BUFFER: error = ENOMEM; break;
91 case ERROR_INVALID_ACCESS: error = EACCES; break;
92 case ERROR_INVALID_ADDRESS: error = EFAULT; break;
93 case ERROR_INVALID_BLOCK: error = EFAULT; break;
94 case ERROR_INVALID_DATA: error = EINVAL; break;
95 case ERROR_INVALID_DRIVE: error = ENODEV; break;
96 case ERROR_INVALID_EXE_SIGNATURE: error = ENOEXEC; break;
97 case ERROR_INVALID_FLAGS: error = EINVAL; break;
98 case ERROR_INVALID_FUNCTION: error = ENOSYS; break;
99 case ERROR_INVALID_HANDLE: error = EBADF; break;
100 case ERROR_INVALID_LOGON_HOURS: error = EACCES; break;
101 case ERROR_INVALID_NAME: error = EINVAL; break;
102 case ERROR_INVALID_OWNER: error = EINVAL; break;
103 case ERROR_INVALID_PARAMETER: error = EINVAL; break;
104 case ERROR_INVALID_PASSWORD: error = EPERM; break;
105 case ERROR_INVALID_PRIMARY_GROUP: error = EINVAL; break;
106 case ERROR_INVALID_REPARSE_DATA: error = EINVAL; break;
107 case ERROR_INVALID_SIGNAL_NUMBER: error = EINVAL; break;
108 case ERROR_INVALID_TARGET_HANDLE: error = EIO; break;
109 case ERROR_INVALID_WORKSTATION: error = EACCES; break;
110 case ERROR_IO_DEVICE: error = EIO; break;
111 case ERROR_IO_INCOMPLETE: error = EINTR; break;
112 case ERROR_LOCKED: error = EBUSY; break;
113 case ERROR_LOCK_VIOLATION: error = EACCES; break;
114 case ERROR_LOGON_FAILURE: error = EACCES; break;
115 case ERROR_MAPPED_ALIGNMENT: error = EINVAL; break;
116 case ERROR_META_EXPANSION_TOO_LONG: error = E2BIG; break;
117 case ERROR_MORE_DATA: error = EPIPE; break;
118 case ERROR_NEGATIVE_SEEK: error = ESPIPE; break;
119 case ERROR_NOACCESS: error = EFAULT; break;
120 case ERROR_NONE_MAPPED: error = EINVAL; break;
121 case ERROR_NOT_A_REPARSE_POINT: error = EINVAL; break;
122 case ERROR_NOT_ENOUGH_MEMORY: error = ENOMEM; break;
123 case ERROR_NOT_READY: error = EAGAIN; break;
124 case ERROR_NOT_SAME_DEVICE: error = EXDEV; break;
125 case ERROR_NO_DATA: error = EPIPE; break;
126 case ERROR_NO_MORE_SEARCH_HANDLES: error = EIO; break;
127 case ERROR_NO_PROC_SLOTS: error = EAGAIN; break;
128 case ERROR_NO_SUCH_PRIVILEGE: error = EACCES; break;
129 case ERROR_OPEN_FAILED: error = EIO; break;
130 case ERROR_OPEN_FILES: error = EBUSY; break;
131 case ERROR_OPERATION_ABORTED: error = EINTR; break;
132 case ERROR_OUTOFMEMORY: error = ENOMEM; break;
133 case ERROR_PASSWORD_EXPIRED: error = EACCES; break;
134 case ERROR_PATH_BUSY: error = EBUSY; break;
135 case ERROR_PATH_NOT_FOUND: error = ENOENT; break;
136 case ERROR_PIPE_BUSY: error = EBUSY; break;
137 case ERROR_PIPE_CONNECTED: error = EPIPE; break;
138 case ERROR_PIPE_LISTENING: error = EPIPE; break;
139 case ERROR_PIPE_NOT_CONNECTED: error = EPIPE; break;
140 case ERROR_PRIVILEGE_NOT_HELD: error = EACCES; break;
141 case ERROR_READ_FAULT: error = EIO; break;
142 case ERROR_REPARSE_ATTRIBUTE_CONFLICT: error = EINVAL; break;
143 case ERROR_REPARSE_TAG_INVALID: error = EINVAL; break;
144 case ERROR_REPARSE_TAG_MISMATCH: error = EINVAL; break;
145 case ERROR_SEEK: error = EIO; break;
146 case ERROR_SEEK_ON_DEVICE: error = ESPIPE; break;
147 case ERROR_SHARING_BUFFER_EXCEEDED: error = ENFILE; break;
148 case ERROR_SHARING_VIOLATION: error = EACCES; break;
149 case ERROR_STACK_OVERFLOW: error = ENOMEM; break;
150 case ERROR_SUCCESS: BUG("err_win_to_posix() called without an error!");
151 case ERROR_SWAPERROR: error = ENOENT; break;
152 case ERROR_TOO_MANY_MODULES: error = EMFILE; break;
153 case ERROR_TOO_MANY_OPEN_FILES: error = EMFILE; break;
154 case ERROR_UNRECOGNIZED_MEDIA: error = ENXIO; break;
155 case ERROR_UNRECOGNIZED_VOLUME: error = ENODEV; break;
156 case ERROR_WAIT_NO_CHILDREN: error = ECHILD; break;
157 case ERROR_WRITE_FAULT: error = EIO; break;
158 case ERROR_WRITE_PROTECT: error = EROFS; break;
159 }
160 return error;
161 }
162
163 static inline int is_file_in_use_error(DWORD errcode)
164 {
165 switch (errcode) {
166 case ERROR_SHARING_VIOLATION:
167 case ERROR_ACCESS_DENIED:
168 return 1;
169 }
170
171 return 0;
172 }
173
174 static int read_yes_no_answer(void)
175 {
176 char answer[1024];
177
178 if (fgets(answer, sizeof(answer), stdin)) {
179 size_t answer_len = strlen(answer);
180 int got_full_line = 0, c;
181
182 /* remove the newline */
183 if (answer_len >= 2 && answer[answer_len-2] == '\r') {
184 answer[answer_len-2] = '\0';
185 got_full_line = 1;
186 } else if (answer_len >= 1 && answer[answer_len-1] == '\n') {
187 answer[answer_len-1] = '\0';
188 got_full_line = 1;
189 }
190 /* flush the buffer in case we did not get the full line */
191 if (!got_full_line)
192 while ((c = getchar()) != EOF && c != '\n')
193 ;
194 } else
195 /* we could not read, return the
196 * default answer which is no */
197 return 0;
198
199 if (tolower(answer[0]) == 'y' && !answer[1])
200 return 1;
201 if (!strncasecmp(answer, "yes", sizeof(answer)))
202 return 1;
203 if (tolower(answer[0]) == 'n' && !answer[1])
204 return 0;
205 if (!strncasecmp(answer, "no", sizeof(answer)))
206 return 0;
207
208 /* did not find an answer we understand */
209 return -1;
210 }
211
212 static int ask_yes_no_if_possible(const char *format, va_list args)
213 {
214 char question[4096];
215 const char *retry_hook;
216
217 vsnprintf(question, sizeof(question), format, args);
218
219 retry_hook = mingw_getenv("GIT_ASK_YESNO");
220 if (retry_hook) {
221 struct child_process cmd = CHILD_PROCESS_INIT;
222
223 strvec_pushl(&cmd.args, retry_hook, question, NULL);
224 return !run_command(&cmd);
225 }
226
227 if (!isatty(_fileno(stdin)) || !isatty(_fileno(stderr)))
228 return 0;
229
230 while (1) {
231 int answer;
232 fprintf(stderr, "%s (y/n) ", question);
233
234 if ((answer = read_yes_no_answer()) >= 0)
235 return answer;
236
237 fprintf(stderr, "Sorry, I did not understand your answer. "
238 "Please type 'y' or 'n'\n");
239 }
240 }
241
242 static int retry_ask_yes_no(int *tries, const char *format, ...)
243 {
244 static const int delay[] = { 0, 1, 10, 20, 40 };
245 va_list args;
246 int result, saved_errno = errno;
247
248 if ((*tries) < ARRAY_SIZE(delay)) {
249 /*
250 * We assume that some other process had the file open at the wrong
251 * moment and retry. In order to give the other process a higher
252 * chance to complete its operation, we give up our time slice now.
253 * If we have to retry again, we do sleep a bit.
254 */
255 Sleep(delay[*tries]);
256 (*tries)++;
257 return 1;
258 }
259
260 va_start(args, format);
261 result = ask_yes_no_if_possible(format, args);
262 va_end(args);
263 errno = saved_errno;
264 return result;
265 }
266
267 /* Windows only */
268 enum hide_dotfiles_type {
269 HIDE_DOTFILES_FALSE = 0,
270 HIDE_DOTFILES_TRUE,
271 HIDE_DOTFILES_DOTGITONLY
272 };
273
274 static enum hide_dotfiles_type hide_dotfiles = HIDE_DOTFILES_DOTGITONLY;
275 static char *unset_environment_variables;
276
277 int mingw_core_config(const char *var, const char *value,
278 const struct config_context *ctx UNUSED,
279 void *cb UNUSED)
280 {
281 if (!strcmp(var, "core.hidedotfiles")) {
282 if (value && !strcasecmp(value, "dotgitonly"))
283 hide_dotfiles = HIDE_DOTFILES_DOTGITONLY;
284 else
285 hide_dotfiles = git_config_bool(var, value);
286 return 0;
287 }
288
289 if (!strcmp(var, "core.unsetenvvars")) {
290 if (!value)
291 return config_error_nonbool(var);
292 free(unset_environment_variables);
293 unset_environment_variables = xstrdup(value);
294 return 0;
295 }
296
297 return 0;
298 }
299
300 static inline int is_wdir_sep(wchar_t wchar)
301 {
302 return wchar == L'/' || wchar == L'\\';
303 }
304
305 static const wchar_t *make_relative_to(const wchar_t *path,
306 const wchar_t *relative_to, wchar_t *out,
307 size_t size)
308 {
309 size_t i = wcslen(relative_to), len;
310
311 /* Is `path` already absolute? */
312 if (is_wdir_sep(path[0]) ||
313 (iswalpha(path[0]) && path[1] == L':' && is_wdir_sep(path[2])))
314 return path;
315
316 while (i > 0 && !is_wdir_sep(relative_to[i - 1]))
317 i--;
318
319 /* Is `relative_to` in the current directory? */
320 if (!i)
321 return path;
322
323 len = wcslen(path);
324 if (i + len + 1 > size) {
325 error("Could not make '%ls' relative to '%ls' (too large)",
326 path, relative_to);
327 return NULL;
328 }
329
330 memcpy(out, relative_to, i * sizeof(wchar_t));
331 wcscpy(out + i, path);
332 return out;
333 }
334
335 static DWORD symlink_file_flags = 0, symlink_directory_flags = 1;
336
337 enum phantom_symlink_result {
338 PHANTOM_SYMLINK_RETRY,
339 PHANTOM_SYMLINK_DONE,
340 PHANTOM_SYMLINK_DIRECTORY
341 };
342
343 /*
344 * Changes a file symlink to a directory symlink if the target exists and is a
345 * directory.
346 */
347 static enum phantom_symlink_result
348 process_phantom_symlink(const wchar_t *wtarget, const wchar_t *wlink)
349 {
350 HANDLE hnd;
351 BY_HANDLE_FILE_INFORMATION fdata;
352 wchar_t relative[MAX_PATH];
353 const wchar_t *rel;
354
355 /* check that wlink is still a file symlink */
356 if ((GetFileAttributesW(wlink)
357 & (FILE_ATTRIBUTE_REPARSE_POINT | FILE_ATTRIBUTE_DIRECTORY))
358 != FILE_ATTRIBUTE_REPARSE_POINT)
359 return PHANTOM_SYMLINK_DONE;
360
361 /* make it relative, if necessary */
362 rel = make_relative_to(wtarget, wlink, relative, ARRAY_SIZE(relative));
363 if (!rel)
364 return PHANTOM_SYMLINK_DONE;
365
366 /* let Windows resolve the link by opening it */
367 hnd = CreateFileW(rel, 0,
368 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
369 OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
370 if (hnd == INVALID_HANDLE_VALUE) {
371 errno = err_win_to_posix(GetLastError());
372 return PHANTOM_SYMLINK_RETRY;
373 }
374
375 if (!GetFileInformationByHandle(hnd, &fdata)) {
376 errno = err_win_to_posix(GetLastError());
377 CloseHandle(hnd);
378 return PHANTOM_SYMLINK_RETRY;
379 }
380 CloseHandle(hnd);
381
382 /* if target exists and is a file, we're done */
383 if (!(fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
384 return PHANTOM_SYMLINK_DONE;
385
386 /* otherwise recreate the symlink with directory flag */
387 if (DeleteFileW(wlink) &&
388 CreateSymbolicLinkW(wlink, wtarget, symlink_directory_flags))
389 return PHANTOM_SYMLINK_DIRECTORY;
390
391 errno = err_win_to_posix(GetLastError());
392 return PHANTOM_SYMLINK_RETRY;
393 }
394
395 /* keep track of newly created symlinks to non-existing targets */
396 struct phantom_symlink_info {
397 struct phantom_symlink_info *next;
398 wchar_t *wlink;
399 wchar_t *wtarget;
400 };
401
402 static struct phantom_symlink_info *phantom_symlinks = NULL;
403 static CRITICAL_SECTION phantom_symlinks_cs;
404
405 static void process_phantom_symlinks(void)
406 {
407 struct phantom_symlink_info *current, **psi;
408 EnterCriticalSection(&phantom_symlinks_cs);
409 /* process phantom symlinks list */
410 psi = &phantom_symlinks;
411 while ((current = *psi)) {
412 enum phantom_symlink_result result = process_phantom_symlink(
413 current->wtarget, current->wlink);
414 if (result == PHANTOM_SYMLINK_RETRY) {
415 psi = &current->next;
416 } else {
417 /* symlink was processed, remove from list */
418 *psi = current->next;
419 free(current);
420 /* if symlink was a directory, start over */
421 if (result == PHANTOM_SYMLINK_DIRECTORY)
422 psi = &phantom_symlinks;
423 }
424 }
425 LeaveCriticalSection(&phantom_symlinks_cs);
426 }
427
428 /* Normalizes NT paths as returned by some low-level APIs. */
429 static wchar_t *normalize_ntpath(wchar_t *wbuf)
430 {
431 int i;
432 /* fix absolute path prefixes */
433 if (wbuf[0] == '\\') {
434 /* strip NT namespace prefixes */
435 if (!wcsncmp(wbuf, L"\\??\\", 4) ||
436 !wcsncmp(wbuf, L"\\\\?\\", 4))
437 wbuf += 4;
438 else if (!wcsnicmp(wbuf, L"\\DosDevices\\", 12))
439 wbuf += 12;
440 /* replace remaining '...UNC\' with '\\' */
441 if (!wcsnicmp(wbuf, L"UNC\\", 4)) {
442 wbuf += 2;
443 *wbuf = '\\';
444 }
445 }
446 /* convert backslashes to slashes */
447 for (i = 0; wbuf[i]; i++)
448 if (wbuf[i] == '\\')
449 wbuf[i] = '/';
450 return wbuf;
451 }
452
453 /*
454 * Use SetFileInformationByHandle(FileDispositionInfo) to force legacy
455 * (non-POSIX) delete semantics. On Windows 11, DeleteFileW() uses POSIX
456 * delete semantics internally, allowing deletion even with active
457 * MapViewOfFile views. This helper simulates Windows 10 behavior where
458 * deletion fails if a file mapping exists.
459 *
460 * Returns nonzero on success (like DeleteFileW), 0 on failure.
461 */
462 static int legacy_delete_file(const wchar_t *wpathname)
463 {
464 FILE_DISPOSITION_INFO fdi = { TRUE };
465 DWORD gle;
466 HANDLE h = CreateFileW(wpathname, DELETE,
467 FILE_SHARE_READ | FILE_SHARE_WRITE |
468 FILE_SHARE_DELETE,
469 NULL, OPEN_EXISTING,
470 FILE_FLAG_OPEN_REPARSE_POINT, NULL);
471 if (h == INVALID_HANDLE_VALUE)
472 return 0;
473
474 if (SetFileInformationByHandle(h, FileDispositionInfo,
475 &fdi, sizeof(fdi))) {
476 CloseHandle(h);
477 return 1;
478 }
479 gle = GetLastError();
480 CloseHandle(h);
481 SetLastError(gle);
482 return 0;
483 }
484
485 static int try_delete_file(const wchar_t *wpathname, int use_legacy)
486 {
487 if (use_legacy)
488 return legacy_delete_file(wpathname);
489 return DeleteFileW(wpathname);
490 }
491
492 int mingw_unlink(const char *pathname, int handle_in_use_error)
493 {
494 static int use_legacy_delete = -1;
495 int tries = 0;
496 wchar_t wpathname[MAX_PATH];
497 if (xutftowcs_path(wpathname, pathname) < 0)
498 return -1;
499
500 if (use_legacy_delete < 0)
501 use_legacy_delete = git_env_bool("GIT_TEST_LEGACY_DELETE", 0);
502
503 if (try_delete_file(wpathname, use_legacy_delete))
504 return 0;
505
506 do {
507 /* read-only files cannot be removed */
508 _wchmod(wpathname, 0666);
509 if (try_delete_file(wpathname, use_legacy_delete))
510 return 0;
511 if (!is_file_in_use_error(GetLastError()))
512 break;
513 /*
514 * _wunlink() / DeleteFileW() for directory symlinks fails with
515 * ERROR_ACCESS_DENIED (EACCES), so try _wrmdir() as well. This is the
516 * same error we get if a file is in use (already checked above).
517 */
518 if (!_wrmdir(wpathname))
519 return 0;
520
521 if (!handle_in_use_error)
522 return -1;
523 } while (retry_ask_yes_no(&tries, "Unlink of file '%s' failed. "
524 "Should I try again?", pathname));
525 return -1;
526 }
527
528 static int is_dir_empty(const wchar_t *wpath)
529 {
530 WIN32_FIND_DATAW findbuf;
531 HANDLE handle;
532 wchar_t wbuf[MAX_PATH + 2];
533 wcscpy(wbuf, wpath);
534 wcscat(wbuf, L"\\*");
535 handle = FindFirstFileW(wbuf, &findbuf);
536 if (handle == INVALID_HANDLE_VALUE)
537 return GetLastError() == ERROR_NO_MORE_FILES;
538
539 while (!wcscmp(findbuf.cFileName, L".") ||
540 !wcscmp(findbuf.cFileName, L".."))
541 if (!FindNextFileW(handle, &findbuf)) {
542 DWORD err = GetLastError();
543 FindClose(handle);
544 return err == ERROR_NO_MORE_FILES;
545 }
546 FindClose(handle);
547 return 0;
548 }
549
550 int mingw_rmdir(const char *pathname)
551 {
552 int tries = 0;
553 wchar_t wpathname[MAX_PATH];
554 struct stat st;
555
556 /*
557 * Contrary to Linux' `rmdir()`, Windows' _wrmdir() and _rmdir()
558 * (and `RemoveDirectoryW()`) will attempt to remove the target of a
559 * symbolic link (if it points to a directory).
560 *
561 * This behavior breaks the assumption of e.g. `remove_path()` which
562 * upon successful deletion of a file will attempt to remove its parent
563 * directories recursively until failure (which usually happens when
564 * the directory is not empty).
565 *
566 * Therefore, before calling `_wrmdir()`, we first check if the path is
567 * a symbolic link. If it is, we exit and return the same error as
568 * Linux' `rmdir()` would, i.e. `ENOTDIR`.
569 */
570 if (!mingw_lstat(pathname, &st) && S_ISLNK(st.st_mode)) {
571 errno = ENOTDIR;
572 return -1;
573 }
574
575 if (xutftowcs_path(wpathname, pathname) < 0)
576 return -1;
577
578 do {
579 if (!_wrmdir(wpathname)) {
580 invalidate_lstat_cache();
581 return 0;
582 }
583 if (!is_file_in_use_error(GetLastError()))
584 errno = err_win_to_posix(GetLastError());
585 if (errno != EACCES)
586 break;
587 if (!is_dir_empty(wpathname)) {
588 errno = ENOTEMPTY;
589 break;
590 }
591 } while (retry_ask_yes_no(&tries, "Deletion of directory '%s' failed. "
592 "Should I try again?", pathname));
593 return -1;
594 }
595
596 static inline int needs_hiding(const char *path)
597 {
598 const char *basename;
599
600 if (hide_dotfiles == HIDE_DOTFILES_FALSE)
601 return 0;
602
603 /* We cannot use basename(), as it would remove trailing slashes */
604 win32_skip_dos_drive_prefix((char **)&path);
605 if (!*path)
606 return 0;
607
608 for (basename = path; *path; path++)
609 if (is_dir_sep(*path)) {
610 do {
611 path++;
612 } while (is_dir_sep(*path));
613 /* ignore trailing slashes */
614 if (*path)
615 basename = path;
616 else
617 break;
618 }
619
620 if (hide_dotfiles == HIDE_DOTFILES_TRUE)
621 return *basename == '.';
622
623 assert(hide_dotfiles == HIDE_DOTFILES_DOTGITONLY);
624 return !strncasecmp(".git", basename, 4) &&
625 (!basename[4] || is_dir_sep(basename[4]));
626 }
627
628 static int set_hidden_flag(const wchar_t *path, int set)
629 {
630 DWORD original = GetFileAttributesW(path), modified;
631 if (set)
632 modified = original | FILE_ATTRIBUTE_HIDDEN;
633 else
634 modified = original & ~FILE_ATTRIBUTE_HIDDEN;
635 if (original == modified || SetFileAttributesW(path, modified))
636 return 0;
637 errno = err_win_to_posix(GetLastError());
638 return -1;
639 }
640
641 int mingw_mkdir(const char *path, int mode UNUSED)
642 {
643 int ret;
644 wchar_t wpath[MAX_PATH];
645
646 if (!is_valid_win32_path(path, 0)) {
647 errno = EINVAL;
648 return -1;
649 }
650
651 if (xutftowcs_path(wpath, path) < 0)
652 return -1;
653 ret = _wmkdir(wpath);
654 if (!ret)
655 process_phantom_symlinks();
656 if (!ret && needs_hiding(path))
657 return set_hidden_flag(wpath, 1);
658 return ret;
659 }
660
661 /*
662 * Calling CreateFile() using FILE_APPEND_DATA and without FILE_WRITE_DATA
663 * is documented in [1] as opening a writable file handle in append mode.
664 * (It is believed that) this is atomic since it is maintained by the
665 * kernel unlike the O_APPEND flag which is racily maintained by the CRT.
666 *
667 * [1] https://docs.microsoft.com/en-us/windows/desktop/fileio/file-access-rights-constants
668 *
669 * This trick does not appear to work for named pipes. Instead it creates
670 * a named pipe client handle that cannot be written to. Callers should
671 * just use the regular _wopen() for them. (And since client handle gets
672 * bound to a unique server handle, it isn't really an issue.)
673 */
674 static int mingw_open_append(wchar_t const *wfilename, int oflags, ...)
675 {
676 HANDLE handle;
677 int fd;
678 DWORD create = (oflags & O_CREAT) ? OPEN_ALWAYS : OPEN_EXISTING;
679
680 /* only these flags are supported */
681 if ((oflags & ~O_CREAT) != (O_WRONLY | O_APPEND)) {
682 errno = ENOSYS;
683 return -1;
684 }
685
686 /*
687 * FILE_SHARE_WRITE is required to permit child processes
688 * to append to the file.
689 */
690 handle = CreateFileW(wfilename, FILE_APPEND_DATA,
691 FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE,
692 NULL, create, FILE_ATTRIBUTE_NORMAL, NULL);
693 if (handle == INVALID_HANDLE_VALUE) {
694 DWORD err = GetLastError();
695
696 /*
697 * Some network storage solutions (e.g. Isilon) might return
698 * ERROR_INVALID_PARAMETER instead of expected error
699 * ERROR_PATH_NOT_FOUND, which results in an unknown error. If
700 * so, let's turn the error to ERROR_PATH_NOT_FOUND instead.
701 */
702 if (err == ERROR_INVALID_PARAMETER)
703 err = ERROR_PATH_NOT_FOUND;
704
705 errno = err_win_to_posix(err);
706 return -1;
707 }
708
709 /*
710 * No O_APPEND here, because the CRT uses it only to reset the
711 * file pointer to EOF before each write(); but that is not
712 * necessary (and may lead to races) for a file created with
713 * FILE_APPEND_DATA.
714 */
715 fd = _open_osfhandle((intptr_t)handle, O_BINARY);
716 if (fd < 0)
717 CloseHandle(handle);
718 return fd;
719 }
720
721 /*
722 * Ideally, we'd use `_wopen()` to implement this functionality so that we
723 * don't have to reimplement it, but unfortunately we do not have tight control
724 * over the share mode there. And while `_wsopen()` and friends exist that give
725 * us _some_ control over the share mode, this family of functions doesn't give
726 * us the ability to enable FILE_SHARE_DELETE, either. But this is a strict
727 * requirement for us though so that we can unlink or rename over files that
728 * are held open by another process.
729 *
730 * We are thus forced to implement our own emulation of `open()`. To make our
731 * life simpler we only implement basic support for this, namely opening
732 * existing files for reading and/or writing. This means that newly created
733 * files won't have their sharing mode set up correctly, but for now I couldn't
734 * find any case where this matters. We may have to revisit that in the future
735 * though based on our needs.
736 */
737 static int mingw_open_existing(const wchar_t *filename, int oflags, ...)
738 {
739 SECURITY_ATTRIBUTES security_attributes = {
740 .nLength = sizeof(security_attributes),
741 .bInheritHandle = !(oflags & O_NOINHERIT),
742 };
743 HANDLE handle;
744 DWORD access;
745 int fd;
746
747 /* We only support basic flags. */
748 if (oflags & ~(O_ACCMODE | O_NOINHERIT)) {
749 errno = ENOSYS;
750 return -1;
751 }
752
753 switch (oflags & O_ACCMODE) {
754 case O_RDWR:
755 access = GENERIC_READ | GENERIC_WRITE;
756 break;
757 case O_WRONLY:
758 access = GENERIC_WRITE;
759 break;
760 default:
761 access = GENERIC_READ;
762 break;
763 }
764
765 handle = CreateFileW(filename, access,
766 FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE,
767 &security_attributes, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
768 if (handle == INVALID_HANDLE_VALUE) {
769 DWORD err = GetLastError();
770 if (err == ERROR_ACCESS_DENIED) {
771 DWORD attrs = GetFileAttributesW(filename);
772 if (attrs != INVALID_FILE_ATTRIBUTES && (attrs & FILE_ATTRIBUTE_DIRECTORY))
773 handle = CreateFileW(filename, access,
774 FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE,
775 &security_attributes, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL| FILE_FLAG_BACKUP_SEMANTICS, NULL);
776 }
777
778 if (handle == INVALID_HANDLE_VALUE) {
779 err = GetLastError();
780
781 /* See `mingw_open_append()` for why we have this conversion. */
782 if (err == ERROR_INVALID_PARAMETER)
783 err = ERROR_PATH_NOT_FOUND;
784
785 errno = err_win_to_posix(err);
786 return -1;
787 }
788 }
789
790 fd = _open_osfhandle((intptr_t)handle, oflags | O_BINARY);
791 if (fd < 0)
792 CloseHandle(handle);
793 return fd;
794 }
795
796 /*
797 * Does the pathname map to the local named pipe filesystem?
798 * That is, does it have a "//./pipe/" prefix?
799 */
800 static int is_local_named_pipe_path(const char *filename)
801 {
802 return (is_dir_sep(filename[0]) &&
803 is_dir_sep(filename[1]) &&
804 filename[2] == '.' &&
805 is_dir_sep(filename[3]) &&
806 !strncasecmp(filename+4, "pipe", 4) &&
807 is_dir_sep(filename[8]) &&
808 filename[9]);
809 }
810
811 int mingw_open (const char *filename, int oflags, ...)
812 {
813 typedef int (*open_fn_t)(wchar_t const *wfilename, int oflags, ...);
814 va_list args;
815 unsigned mode;
816 int fd, create = (oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL);
817 wchar_t wfilename[MAX_PATH];
818 open_fn_t open_fn;
819 WIN32_FILE_ATTRIBUTE_DATA fdata;
820
821 DECLARE_PROC_ADDR(ntdll.dll, NTSTATUS, NTAPI, RtlGetLastNtStatus, void);
822
823 va_start(args, oflags);
824 mode = va_arg(args, int);
825 va_end(args);
826
827 if (!is_valid_win32_path(filename, !create)) {
828 errno = create ? EINVAL : ENOENT;
829 return -1;
830 }
831
832 if ((oflags & O_APPEND) && !is_local_named_pipe_path(filename))
833 open_fn = mingw_open_append;
834 else if (!(oflags & ~(O_ACCMODE | O_NOINHERIT)))
835 open_fn = mingw_open_existing;
836 else
837 open_fn = _wopen;
838
839 if (filename && !strcmp(filename, "/dev/null"))
840 wcscpy(wfilename, L"nul");
841 else if (xutftowcs_path(wfilename, filename) < 0)
842 return -1;
843
844 /*
845 * When `symlink` exists and is a symbolic link pointing to a
846 * non-existing file, `_wopen(symlink, O_CREAT | O_EXCL)` would
847 * create that file. Not what we want: Linux would say `EEXIST`
848 * in that instance, which is therefore what Git expects.
849 */
850 if (create &&
851 GetFileAttributesExW(wfilename, GetFileExInfoStandard, &fdata) &&
852 (fdata.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) {
853 errno = EEXIST;
854 return -1;
855 }
856
857 fd = open_fn(wfilename, oflags, mode);
858
859 /*
860 * Internally, `_wopen()` uses the `CreateFile()` API with CREATE_NEW,
861 * which may error out with ERROR_ACCESS_DENIED and an NtStatus of
862 * STATUS_DELETE_PENDING when the file is scheduled for deletion via
863 * `DeleteFileW()`. The file essentially exists, so we map errno to
864 * EEXIST instead of EACCESS so that callers don't have to special-case
865 * this.
866 *
867 * This fixes issues for example with the lockfile interface when one
868 * process has a lock that it is about to commit or release while
869 * another process wants to acquire it.
870 */
871 if (fd < 0 && create && GetLastError() == ERROR_ACCESS_DENIED &&
872 INIT_PROC_ADDR(RtlGetLastNtStatus) && RtlGetLastNtStatus() == STATUS_DELETE_PENDING)
873 errno = EEXIST;
874 if (fd < 0 && (oflags & O_ACCMODE) != O_RDONLY && errno == EACCES) {
875 DWORD attrs = GetFileAttributesW(wfilename);
876 if (attrs != INVALID_FILE_ATTRIBUTES && (attrs & FILE_ATTRIBUTE_DIRECTORY))
877 errno = EISDIR;
878 }
879 if ((oflags & O_CREAT) && needs_hiding(filename)) {
880 /*
881 * Internally, _wopen() uses the CreateFile() API which errors
882 * out with an ERROR_ACCESS_DENIED if CREATE_ALWAYS was
883 * specified and an already existing file's attributes do not
884 * match *exactly*. As there is no mode or flag we can set that
885 * would correspond to FILE_ATTRIBUTE_HIDDEN, let's just try
886 * again *without* the O_CREAT flag (that corresponds to the
887 * CREATE_ALWAYS flag of CreateFile()).
888 */
889 if (fd < 0 && errno == EACCES)
890 fd = open_fn(wfilename, oflags & ~O_CREAT, mode);
891 if (fd >= 0 && set_hidden_flag(wfilename, 1))
892 warning("could not mark '%s' as hidden.", filename);
893 }
894 return fd;
895 }
896
897 static BOOL WINAPI ctrl_ignore(DWORD type UNUSED)
898 {
899 return TRUE;
900 }
901
902 #undef fgetc
903 int mingw_fgetc(FILE *stream)
904 {
905 int ch;
906 if (!isatty(_fileno(stream)))
907 return fgetc(stream);
908
909 SetConsoleCtrlHandler(ctrl_ignore, TRUE);
910 while (1) {
911 ch = fgetc(stream);
912 if (ch != EOF || GetLastError() != ERROR_OPERATION_ABORTED)
913 break;
914
915 /* Ctrl+C was pressed, simulate SIGINT and retry */
916 mingw_raise(SIGINT);
917 }
918 SetConsoleCtrlHandler(ctrl_ignore, FALSE);
919 return ch;
920 }
921
922 #undef fopen
923 FILE *mingw_fopen (const char *filename, const char *otype)
924 {
925 int hide = needs_hiding(filename);
926 FILE *file;
927 wchar_t wfilename[MAX_PATH], wotype[4];
928 if (filename && !strcmp(filename, "/dev/null"))
929 wcscpy(wfilename, L"nul");
930 else if (!is_valid_win32_path(filename, 1)) {
931 int create = otype && strchr(otype, 'w');
932 errno = create ? EINVAL : ENOENT;
933 return NULL;
934 } else if (xutftowcs_path(wfilename, filename) < 0)
935 return NULL;
936
937 if (xutftowcs(wotype, otype, ARRAY_SIZE(wotype)) < 0)
938 return NULL;
939
940 if (hide && !access(filename, F_OK) && set_hidden_flag(wfilename, 0)) {
941 error("could not unhide %s", filename);
942 return NULL;
943 }
944 file = _wfopen(wfilename, wotype);
945 if (!file && GetLastError() == ERROR_INVALID_NAME)
946 errno = ENOENT;
947 if (file && hide && set_hidden_flag(wfilename, 1))
948 warning("could not mark '%s' as hidden.", filename);
949 return file;
950 }
951
952 FILE *mingw_freopen (const char *filename, const char *otype, FILE *stream)
953 {
954 int hide = needs_hiding(filename);
955 FILE *file;
956 wchar_t wfilename[MAX_PATH], wotype[4];
957 if (filename && !strcmp(filename, "/dev/null"))
958 wcscpy(wfilename, L"nul");
959 else if (!is_valid_win32_path(filename, 1)) {
960 int create = otype && strchr(otype, 'w');
961 errno = create ? EINVAL : ENOENT;
962 return NULL;
963 } else if (xutftowcs_path(wfilename, filename) < 0)
964 return NULL;
965
966 if (xutftowcs(wotype, otype, ARRAY_SIZE(wotype)) < 0)
967 return NULL;
968
969 if (hide && !access(filename, F_OK) && set_hidden_flag(wfilename, 0)) {
970 error("could not unhide %s", filename);
971 return NULL;
972 }
973 file = _wfreopen(wfilename, wotype, stream);
974 if (file && hide && set_hidden_flag(wfilename, 1))
975 warning("could not mark '%s' as hidden.", filename);
976 return file;
977 }
978
979 #undef fflush
980 int mingw_fflush(FILE *stream)
981 {
982 int ret = fflush(stream);
983
984 /*
985 * write() is used behind the scenes of stdio output functions.
986 * Since git code does not check for errors after each stdio write
987 * operation, it can happen that write() is called by a later
988 * stdio function even if an earlier write() call failed. In the
989 * case of a pipe whose readable end was closed, only the first
990 * call to write() reports EPIPE on Windows. Subsequent write()
991 * calls report EINVAL. It is impossible to notice whether this
992 * fflush invocation triggered such a case, therefore, we have to
993 * catch all EINVAL errors whole-sale.
994 */
995 if (ret && errno == EINVAL)
996 errno = EPIPE;
997
998 return ret;
999 }
1000
1001 #undef write
1002 ssize_t mingw_write(int fd, const void *buf, size_t len)
1003 {
1004 ssize_t result = write(fd, buf, len);
1005
1006 if (result < 0 && (errno == EINVAL || errno == ENOSPC) && buf) {
1007 int orig = errno;
1008
1009 /* check if fd is a pipe */
1010 HANDLE h = (HANDLE) _get_osfhandle(fd);
1011 if (GetFileType(h) != FILE_TYPE_PIPE)
1012 errno = orig;
1013 else if (orig == EINVAL)
1014 errno = EPIPE;
1015 else {
1016 DWORD buf_size;
1017
1018 if (!GetNamedPipeInfo(h, NULL, NULL, &buf_size, NULL))
1019 buf_size = 4096;
1020 if (len > buf_size)
1021 return write(fd, buf, buf_size);
1022 errno = orig;
1023 }
1024 }
1025
1026 return result;
1027 }
1028
1029 int mingw_access(const char *filename, int mode)
1030 {
1031 wchar_t wfilename[MAX_PATH];
1032 if (!strcmp("nul", filename) || !strcmp("/dev/null", filename))
1033 return 0;
1034 if (xutftowcs_path(wfilename, filename) < 0)
1035 return -1;
1036 /* X_OK is not supported by the MSVCRT version */
1037 return _waccess(wfilename, mode & ~X_OK);
1038 }
1039
1040 int mingw_chdir(const char *dirname)
1041 {
1042 wchar_t wdirname[MAX_PATH];
1043
1044 if (xutftowcs_path(wdirname, dirname) < 0)
1045 return -1;
1046
1047 if (has_symlinks) {
1048 HANDLE hnd = CreateFileW(wdirname, 0,
1049 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
1050 OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
1051 if (hnd == INVALID_HANDLE_VALUE) {
1052 errno = err_win_to_posix(GetLastError());
1053 return -1;
1054 }
1055 if (!GetFinalPathNameByHandleW(hnd, wdirname, ARRAY_SIZE(wdirname), 0)) {
1056 errno = err_win_to_posix(GetLastError());
1057 CloseHandle(hnd);
1058 return -1;
1059 }
1060 CloseHandle(hnd);
1061 }
1062
1063 return _wchdir(normalize_ntpath(wdirname));
1064 }
1065
1066 int mingw_chmod(const char *filename, int mode)
1067 {
1068 wchar_t wfilename[MAX_PATH];
1069 if (xutftowcs_path(wfilename, filename) < 0)
1070 return -1;
1071 return _wchmod(wfilename, mode);
1072 }
1073
1074 /*
1075 * The unit of FILETIME is 100-nanoseconds since January 1, 1601, UTC.
1076 * Returns the 100-nanoseconds ("hekto nanoseconds") since the epoch.
1077 */
1078 static inline long long filetime_to_hnsec(const FILETIME *ft)
1079 {
1080 long long winTime = ((long long)ft->dwHighDateTime << 32) + ft->dwLowDateTime;
1081 /* Windows to Unix Epoch conversion */
1082 return winTime - 116444736000000000LL;
1083 }
1084
1085 static inline void filetime_to_timespec(const FILETIME *ft, struct timespec *ts)
1086 {
1087 long long hnsec = filetime_to_hnsec(ft);
1088 ts->tv_sec = (time_t)(hnsec / 10000000);
1089 ts->tv_nsec = (hnsec % 10000000) * 100;
1090 }
1091
1092 /**
1093 * Verifies that safe_create_leading_directories() would succeed.
1094 */
1095 static int has_valid_directory_prefix(wchar_t *wfilename)
1096 {
1097 size_t n = wcslen(wfilename);
1098
1099 while (n > 0) {
1100 wchar_t c = wfilename[--n];
1101 DWORD attributes;
1102
1103 if (!is_dir_sep(c))
1104 continue;
1105
1106 wfilename[n] = L'\0';
1107 attributes = GetFileAttributesW(wfilename);
1108 wfilename[n] = c;
1109 if (attributes &
1110 (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_DEVICE))
1111 return 1;
1112 if (attributes == INVALID_FILE_ATTRIBUTES)
1113 switch (GetLastError()) {
1114 case ERROR_PATH_NOT_FOUND:
1115 continue;
1116 case ERROR_FILE_NOT_FOUND:
1117 /* This implies parent directory exists. */
1118 return 1;
1119 }
1120 return 0;
1121 }
1122 return 1;
1123 }
1124
1125 #ifndef _WINNT_H
1126 /*
1127 * The REPARSE_DATA_BUFFER structure is defined in the Windows DDK (in
1128 * ntifs.h) and in MSYS1's winnt.h (which defines _WINNT_H). So define
1129 * it ourselves if we are on MSYS2 (whose winnt.h defines _WINNT_).
1130 */
1131 typedef struct _REPARSE_DATA_BUFFER {
1132 DWORD ReparseTag;
1133 WORD ReparseDataLength;
1134 WORD Reserved;
1135 #ifndef _MSC_VER
1136 _ANONYMOUS_UNION
1137 #endif
1138 union {
1139 struct {
1140 WORD SubstituteNameOffset;
1141 WORD SubstituteNameLength;
1142 WORD PrintNameOffset;
1143 WORD PrintNameLength;
1144 ULONG Flags;
1145 WCHAR PathBuffer[1];
1146 } SymbolicLinkReparseBuffer;
1147 struct {
1148 WORD SubstituteNameOffset;
1149 WORD SubstituteNameLength;
1150 WORD PrintNameOffset;
1151 WORD PrintNameLength;
1152 WCHAR PathBuffer[1];
1153 } MountPointReparseBuffer;
1154 struct {
1155 BYTE DataBuffer[1];
1156 } GenericReparseBuffer;
1157 } DUMMYUNIONNAME;
1158 } REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
1159 #endif
1160
1161 static int read_reparse_point(const WCHAR *wpath, BOOL fail_on_unknown_tag,
1162 char *tmpbuf, int *plen, DWORD *ptag)
1163 {
1164 HANDLE handle;
1165 WCHAR *wbuf;
1166 REPARSE_DATA_BUFFER *b = alloca(MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
1167 DWORD dummy;
1168
1169 /* read reparse point data */
1170 handle = CreateFileW(wpath, 0,
1171 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
1172 OPEN_EXISTING,
1173 FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL);
1174 if (handle == INVALID_HANDLE_VALUE) {
1175 errno = err_win_to_posix(GetLastError());
1176 return -1;
1177 }
1178 if (!DeviceIoControl(handle, FSCTL_GET_REPARSE_POINT, NULL, 0, b,
1179 MAXIMUM_REPARSE_DATA_BUFFER_SIZE, &dummy, NULL)) {
1180 errno = err_win_to_posix(GetLastError());
1181 CloseHandle(handle);
1182 return -1;
1183 }
1184 CloseHandle(handle);
1185
1186 /* get target path for symlinks or mount points (aka 'junctions') */
1187 switch ((*ptag = b->ReparseTag)) {
1188 case IO_REPARSE_TAG_SYMLINK:
1189 wbuf = (WCHAR*) (((char*) b->SymbolicLinkReparseBuffer.PathBuffer)
1190 + b->SymbolicLinkReparseBuffer.SubstituteNameOffset);
1191 *(WCHAR*) (((char*) wbuf)
1192 + b->SymbolicLinkReparseBuffer.SubstituteNameLength) = 0;
1193 break;
1194 case IO_REPARSE_TAG_MOUNT_POINT:
1195 wbuf = (WCHAR*) (((char*) b->MountPointReparseBuffer.PathBuffer)
1196 + b->MountPointReparseBuffer.SubstituteNameOffset);
1197 *(WCHAR*) (((char*) wbuf)
1198 + b->MountPointReparseBuffer.SubstituteNameLength) = 0;
1199 break;
1200 default:
1201 if (fail_on_unknown_tag) {
1202 errno = EINVAL;
1203 return -1;
1204 } else {
1205 *plen = MAX_PATH;
1206 return 0;
1207 }
1208 }
1209
1210 if ((*plen =
1211 xwcstoutf(tmpbuf, normalize_ntpath(wbuf), MAX_PATH)) < 0)
1212 return -1;
1213 return 0;
1214 }
1215
1216 int mingw_lstat(const char *file_name, struct stat *buf)
1217 {
1218 WIN32_FILE_ATTRIBUTE_DATA fdata;
1219 DWORD reparse_tag = 0;
1220 int link_len = 0;
1221 wchar_t wfilename[MAX_PATH];
1222 int wlen = xutftowcs_path(wfilename, file_name);
1223 if (wlen < 0)
1224 return -1;
1225
1226 /* strip trailing '/', or GetFileAttributes will fail */
1227 while (wlen && is_dir_sep(wfilename[wlen - 1]))
1228 wfilename[--wlen] = 0;
1229 if (!wlen) {
1230 errno = ENOENT;
1231 return -1;
1232 }
1233
1234 if (GetFileAttributesExW(wfilename, GetFileExInfoStandard, &fdata)) {
1235 /* for reparse points, get the link tag and length */
1236 if (fdata.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
1237 char tmpbuf[MAX_PATH];
1238
1239 if (read_reparse_point(wfilename, FALSE, tmpbuf,
1240 &link_len, &reparse_tag) < 0)
1241 return -1;
1242 }
1243 buf->st_ino = 0;
1244 buf->st_gid = 0;
1245 buf->st_uid = 0;
1246 buf->st_nlink = 1;
1247 buf->st_mode = file_attr_to_st_mode(fdata.dwFileAttributes,
1248 reparse_tag);
1249 buf->st_size = S_ISLNK(buf->st_mode) ? link_len :
1250 fdata.nFileSizeLow | (((off_t) fdata.nFileSizeHigh) << 32);
1251 buf->st_dev = buf->st_rdev = 0; /* not used by Git */
1252 filetime_to_timespec(&(fdata.ftLastAccessTime), &(buf->st_atim));
1253 filetime_to_timespec(&(fdata.ftLastWriteTime), &(buf->st_mtim));
1254 filetime_to_timespec(&(fdata.ftCreationTime), &(buf->st_ctim));
1255 return 0;
1256 }
1257
1258 switch (GetLastError()) {
1259 case ERROR_ACCESS_DENIED:
1260 case ERROR_SHARING_VIOLATION:
1261 case ERROR_LOCK_VIOLATION:
1262 case ERROR_SHARING_BUFFER_EXCEEDED:
1263 errno = EACCES;
1264 break;
1265 case ERROR_BUFFER_OVERFLOW:
1266 errno = ENAMETOOLONG;
1267 break;
1268 case ERROR_NOT_ENOUGH_MEMORY:
1269 errno = ENOMEM;
1270 break;
1271 case ERROR_PATH_NOT_FOUND:
1272 if (!has_valid_directory_prefix(wfilename)) {
1273 errno = ENOTDIR;
1274 break;
1275 }
1276 /* fallthru */
1277 default:
1278 errno = ENOENT;
1279 break;
1280 }
1281 return -1;
1282 }
1283
1284 static int get_file_info_by_handle(HANDLE hnd, struct stat *buf)
1285 {
1286 BY_HANDLE_FILE_INFORMATION fdata;
1287
1288 if (!GetFileInformationByHandle(hnd, &fdata)) {
1289 errno = err_win_to_posix(GetLastError());
1290 return -1;
1291 }
1292
1293 buf->st_ino = 0;
1294 buf->st_gid = 0;
1295 buf->st_uid = 0;
1296 buf->st_nlink = 1;
1297 buf->st_mode = file_attr_to_st_mode(fdata.dwFileAttributes, 0);
1298 buf->st_size = fdata.nFileSizeLow |
1299 (((off_t)fdata.nFileSizeHigh)<<32);
1300 buf->st_dev = buf->st_rdev = 0; /* not used by Git */
1301 filetime_to_timespec(&(fdata.ftLastAccessTime), &(buf->st_atim));
1302 filetime_to_timespec(&(fdata.ftLastWriteTime), &(buf->st_mtim));
1303 filetime_to_timespec(&(fdata.ftCreationTime), &(buf->st_ctim));
1304 return 0;
1305 }
1306
1307 int mingw_stat(const char *file_name, struct stat *buf)
1308 {
1309 wchar_t wfile_name[MAX_PATH];
1310 HANDLE hnd;
1311 int result;
1312
1313 /* open the file and let Windows resolve the links */
1314 if (xutftowcs_path(wfile_name, file_name) < 0)
1315 return -1;
1316 hnd = CreateFileW(wfile_name, 0,
1317 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
1318 OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
1319 if (hnd == INVALID_HANDLE_VALUE) {
1320 DWORD err = GetLastError();
1321
1322 if (err == ERROR_ACCESS_DENIED &&
1323 !mingw_lstat(file_name, buf) &&
1324 !S_ISLNK(buf->st_mode))
1325 /*
1326 * POSIX semantics state to still try to fill
1327 * information, even if permission is denied to create
1328 * a file handle.
1329 */
1330 return 0;
1331
1332 errno = err_win_to_posix(err);
1333 return -1;
1334 }
1335 result = get_file_info_by_handle(hnd, buf);
1336 CloseHandle(hnd);
1337 return result;
1338 }
1339
1340 int mingw_fstat(int fd, struct stat *buf)
1341 {
1342 HANDLE fh = (HANDLE)_get_osfhandle(fd);
1343 DWORD avail, type = GetFileType(fh) & ~FILE_TYPE_REMOTE;
1344
1345 switch (type) {
1346 case FILE_TYPE_DISK:
1347 return get_file_info_by_handle(fh, buf);
1348
1349 case FILE_TYPE_CHAR:
1350 case FILE_TYPE_PIPE:
1351 /* initialize stat fields */
1352 memset(buf, 0, sizeof(*buf));
1353 buf->st_nlink = 1;
1354
1355 if (type == FILE_TYPE_CHAR) {
1356 buf->st_mode = _S_IFCHR;
1357 } else {
1358 buf->st_mode = _S_IFIFO;
1359 if (PeekNamedPipe(fh, NULL, 0, NULL, &avail, NULL))
1360 buf->st_size = avail;
1361 }
1362 return 0;
1363
1364 default:
1365 errno = EBADF;
1366 return -1;
1367 }
1368 }
1369
1370 static inline void time_t_to_filetime(time_t t, FILETIME *ft)
1371 {
1372 long long winTime = t * 10000000LL + 116444736000000000LL;
1373 ft->dwLowDateTime = winTime;
1374 ft->dwHighDateTime = winTime >> 32;
1375 }
1376
1377 int mingw_utime (const char *file_name, const struct utimbuf *times)
1378 {
1379 FILETIME mft, aft;
1380 int rc;
1381 DWORD attrs;
1382 wchar_t wfilename[MAX_PATH];
1383 HANDLE osfilehandle;
1384
1385 if (xutftowcs_path(wfilename, file_name) < 0)
1386 return -1;
1387
1388 /* must have write permission */
1389 attrs = GetFileAttributesW(wfilename);
1390 if (attrs != INVALID_FILE_ATTRIBUTES &&
1391 (attrs & FILE_ATTRIBUTE_READONLY)) {
1392 /* ignore errors here; open() will report them */
1393 SetFileAttributesW(wfilename, attrs & ~FILE_ATTRIBUTE_READONLY);
1394 }
1395
1396 osfilehandle = CreateFileW(wfilename,
1397 FILE_WRITE_ATTRIBUTES,
1398 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
1399 NULL,
1400 OPEN_EXISTING,
1401 (attrs != INVALID_FILE_ATTRIBUTES &&
1402 (attrs & FILE_ATTRIBUTE_DIRECTORY)) ?
1403 FILE_FLAG_BACKUP_SEMANTICS : 0,
1404 NULL);
1405 if (osfilehandle == INVALID_HANDLE_VALUE) {
1406 errno = err_win_to_posix(GetLastError());
1407 rc = -1;
1408 goto revert_attrs;
1409 }
1410
1411 if (times) {
1412 time_t_to_filetime(times->modtime, &mft);
1413 time_t_to_filetime(times->actime, &aft);
1414 } else {
1415 GetSystemTimeAsFileTime(&mft);
1416 aft = mft;
1417 }
1418
1419 if (!SetFileTime(osfilehandle, NULL, &aft, &mft)) {
1420 errno = EINVAL;
1421 rc = -1;
1422 } else
1423 rc = 0;
1424
1425 if (osfilehandle != INVALID_HANDLE_VALUE)
1426 CloseHandle(osfilehandle);
1427
1428 revert_attrs:
1429 if (attrs != INVALID_FILE_ATTRIBUTES &&
1430 (attrs & FILE_ATTRIBUTE_READONLY)) {
1431 /* ignore errors again */
1432 SetFileAttributesW(wfilename, attrs);
1433 }
1434 return rc;
1435 }
1436
1437 #undef strftime
1438 size_t mingw_strftime(char *s, size_t max,
1439 const char *format, const struct tm *tm)
1440 {
1441 #ifdef _UCRT
1442 size_t ret = strftime(s, max, format, tm);
1443 #else
1444 /* a pointer to the original strftime in case we can't find the UCRT version */
1445 static size_t (*fallback)(char *, size_t, const char *, const struct tm *) = strftime;
1446 size_t ret;
1447 DECLARE_PROC_ADDR(ucrtbase.dll, size_t, __cdecl, strftime, char *, size_t,
1448 const char *, const struct tm *);
1449
1450 if (INIT_PROC_ADDR(strftime))
1451 ret = strftime(s, max, format, tm);
1452 else
1453 ret = fallback(s, max, format, tm);
1454 #endif
1455
1456 if (!ret && errno == EINVAL)
1457 die("invalid strftime format: '%s'", format);
1458 return ret;
1459 }
1460
1461 unsigned int sleep (unsigned int seconds)
1462 {
1463 Sleep(seconds*1000);
1464 return 0;
1465 }
1466
1467 int mkstemp(char *template)
1468 {
1469 return git_mkstemp_mode(template, 0600);
1470 }
1471
1472 int gettimeofday(struct timeval *tv, void *tz UNUSED)
1473 {
1474 FILETIME ft;
1475 long long hnsec;
1476
1477 GetSystemTimeAsFileTime(&ft);
1478 hnsec = filetime_to_hnsec(&ft);
1479 tv->tv_sec = hnsec / 10000000;
1480 tv->tv_usec = (hnsec % 10000000) / 10;
1481 return 0;
1482 }
1483
1484 int pipe(int filedes[2])
1485 {
1486 HANDLE h[2];
1487
1488 /* this creates non-inheritable handles */
1489 if (!CreatePipe(&h[0], &h[1], NULL, 8192)) {
1490 errno = err_win_to_posix(GetLastError());
1491 return -1;
1492 }
1493 filedes[0] = _open_osfhandle(HCAST(int, h[0]), O_NOINHERIT);
1494 if (filedes[0] < 0) {
1495 CloseHandle(h[0]);
1496 CloseHandle(h[1]);
1497 return -1;
1498 }
1499 filedes[1] = _open_osfhandle(HCAST(int, h[1]), O_NOINHERIT);
1500 if (filedes[1] < 0) {
1501 close(filedes[0]);
1502 CloseHandle(h[1]);
1503 return -1;
1504 }
1505 return 0;
1506 }
1507
1508 #ifndef __MINGW64__
1509 struct tm *gmtime_r(const time_t *timep, struct tm *result)
1510 {
1511 if (gmtime_s(result, timep) == 0)
1512 return result;
1513 return NULL;
1514 }
1515
1516 struct tm *localtime_r(const time_t *timep, struct tm *result)
1517 {
1518 if (localtime_s(result, timep) == 0)
1519 return result;
1520 return NULL;
1521 }
1522 #endif
1523
1524 char *mingw_getcwd(char *pointer, int len)
1525 {
1526 wchar_t cwd[MAX_PATH], wpointer[MAX_PATH];
1527 DWORD ret = GetCurrentDirectoryW(ARRAY_SIZE(cwd), cwd);
1528 HANDLE hnd;
1529
1530 if (!ret || ret >= ARRAY_SIZE(cwd)) {
1531 errno = ret ? ENAMETOOLONG : err_win_to_posix(GetLastError());
1532 return NULL;
1533 }
1534 hnd = CreateFileW(cwd, 0,
1535 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
1536 OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
1537 if (hnd != INVALID_HANDLE_VALUE) {
1538 ret = GetFinalPathNameByHandleW(hnd, wpointer, ARRAY_SIZE(wpointer), 0);
1539 CloseHandle(hnd);
1540 if (!ret || ret >= ARRAY_SIZE(wpointer))
1541 return NULL;
1542 if (xwcstoutf(pointer, normalize_ntpath(wpointer), len) < 0)
1543 return NULL;
1544 return pointer;
1545 }
1546 if (GetFileAttributesW(cwd) == INVALID_FILE_ATTRIBUTES) {
1547 errno = ENOENT;
1548 return NULL;
1549 }
1550 if (xwcstoutf(pointer, cwd, len) < 0)
1551 return NULL;
1552 convert_slashes(pointer);
1553 return pointer;
1554 }
1555
1556 /*
1557 * See "Parsing C++ Command-Line Arguments" at Microsoft's Docs:
1558 * https://docs.microsoft.com/en-us/cpp/cpp/parsing-cpp-command-line-arguments
1559 */
1560 static const char *quote_arg_msvc(const char *arg)
1561 {
1562 /* count chars to quote */
1563 int len = 0, n = 0;
1564 int force_quotes = 0;
1565 char *q, *d;
1566 const char *p = arg;
1567 if (!*p) force_quotes = 1;
1568 while (*p) {
1569 if (isspace(*p) || *p == '*' || *p == '?' || *p == '{' || *p == '\'')
1570 force_quotes = 1;
1571 else if (*p == '"')
1572 n++;
1573 else if (*p == '\\') {
1574 int count = 0;
1575 while (*p == '\\') {
1576 count++;
1577 p++;
1578 len++;
1579 }
1580 if (*p == '"' || !*p)
1581 n += count*2 + 1;
1582 continue;
1583 }
1584 len++;
1585 p++;
1586 }
1587 if (!force_quotes && n == 0)
1588 return arg;
1589
1590 /* insert \ where necessary */
1591 d = q = xmalloc(st_add3(len, n, 3));
1592 *d++ = '"';
1593 while (*arg) {
1594 if (*arg == '"')
1595 *d++ = '\\';
1596 else if (*arg == '\\') {
1597 int count = 0;
1598 while (*arg == '\\') {
1599 count++;
1600 *d++ = *arg++;
1601 }
1602 if (*arg == '"' || !*arg) {
1603 while (count-- > 0)
1604 *d++ = '\\';
1605 /* don't escape the surrounding end quote */
1606 if (!*arg)
1607 break;
1608 *d++ = '\\';
1609 }
1610 }
1611 *d++ = *arg++;
1612 }
1613 *d++ = '"';
1614 *d++ = '\0';
1615 return q;
1616 }
1617
1618 #include "quote.h"
1619
1620 static const char *quote_arg_msys2(const char *arg)
1621 {
1622 struct strbuf buf = STRBUF_INIT;
1623 const char *p2 = arg, *p;
1624
1625 for (p = arg; *p; p++) {
1626 int ws = isspace(*p);
1627 if (!ws && *p != '\\' && *p != '"' && *p != '{' && *p != '\'' &&
1628 *p != '?' && *p != '*' && *p != '~')
1629 continue;
1630 if (!buf.len)
1631 strbuf_addch(&buf, '"');
1632 if (p != p2)
1633 strbuf_add(&buf, p2, p - p2);
1634 if (*p == '\\' || *p == '"')
1635 strbuf_addch(&buf, '\\');
1636 p2 = p;
1637 }
1638
1639 if (p == arg)
1640 strbuf_addch(&buf, '"');
1641 else if (!buf.len)
1642 return arg;
1643 else
1644 strbuf_add(&buf, p2, p - p2);
1645
1646 strbuf_addch(&buf, '"');
1647 return strbuf_detach(&buf, 0);
1648 }
1649
1650 static const char *parse_interpreter(const char *cmd)
1651 {
1652 static char buf[100];
1653 char *p, *opt;
1654 ssize_t n; /* read() can return negative values */
1655 int fd;
1656
1657 /* don't even try a .exe */
1658 n = strlen(cmd);
1659 if (n >= 4 && !strcasecmp(cmd+n-4, ".exe"))
1660 return NULL;
1661
1662 fd = open(cmd, O_RDONLY);
1663 if (fd < 0)
1664 return NULL;
1665 n = read(fd, buf, sizeof(buf)-1);
1666 close(fd);
1667 if (n < 4) /* at least '#!/x' and not error */
1668 return NULL;
1669
1670 if (buf[0] != '#' || buf[1] != '!')
1671 return NULL;
1672 buf[n] = '\0';
1673 p = buf + strcspn(buf, "\r\n");
1674 if (!*p)
1675 return NULL;
1676
1677 *p = '\0';
1678 if (!(p = strrchr(buf+2, '/')) && !(p = strrchr(buf+2, '\\')))
1679 return NULL;
1680 /* strip options */
1681 if ((opt = strchr(p+1, ' ')))
1682 *opt = '\0';
1683 return p+1;
1684 }
1685
1686 /*
1687 * exe_only means that we only want to detect .exe files, but not scripts
1688 * (which do not have an extension)
1689 */
1690 static char *lookup_prog(const char *dir, int dirlen, const char *cmd,
1691 int isexe, int exe_only)
1692 {
1693 char path[MAX_PATH];
1694 wchar_t wpath[MAX_PATH];
1695 snprintf(path, sizeof(path), "%.*s\\%s.exe", dirlen, dir, cmd);
1696
1697 if (xutftowcs_path(wpath, path) < 0)
1698 return NULL;
1699
1700 if (!isexe && _waccess(wpath, F_OK) == 0)
1701 return xstrdup(path);
1702 wpath[wcslen(wpath)-4] = '\0';
1703 if ((!exe_only || isexe) && _waccess(wpath, F_OK) == 0) {
1704 if (!(GetFileAttributesW(wpath) & FILE_ATTRIBUTE_DIRECTORY)) {
1705 path[strlen(path)-4] = '\0';
1706 return xstrdup(path);
1707 }
1708 }
1709 return NULL;
1710 }
1711
1712 /*
1713 * Determines the absolute path of cmd using the split path in path.
1714 * If cmd contains a slash or backslash, no lookup is performed.
1715 */
1716 static char *path_lookup(const char *cmd, int exe_only)
1717 {
1718 const char *path;
1719 char *prog = NULL;
1720 size_t len = strlen(cmd);
1721 int isexe = len >= 4 && !strcasecmp(cmd+len-4, ".exe");
1722
1723 if (strpbrk(cmd, "/\\"))
1724 return xstrdup(cmd);
1725
1726 path = mingw_getenv("PATH");
1727 if (!path)
1728 return NULL;
1729
1730 while (!prog) {
1731 const char *sep = strchrnul(path, ';');
1732 int dirlen = sep - path;
1733 if (dirlen)
1734 prog = lookup_prog(path, dirlen, cmd, isexe, exe_only);
1735 if (!*sep)
1736 break;
1737 path = sep + 1;
1738 }
1739
1740 return prog;
1741 }
1742
1743 char *mingw_locate_in_PATH(const char *cmd)
1744 {
1745 return path_lookup(cmd, 0);
1746 }
1747
1748 static const wchar_t *wcschrnul(const wchar_t *s, wchar_t c)
1749 {
1750 while (*s && *s != c)
1751 s++;
1752 return s;
1753 }
1754
1755 /* Compare only keys */
1756 static int wenvcmp(const void *a, const void *b)
1757 {
1758 wchar_t *p = *(wchar_t **)a, *q = *(wchar_t **)b;
1759 size_t p_len, q_len;
1760
1761 /* Find the keys */
1762 p_len = wcschrnul(p, L'=') - p;
1763 q_len = wcschrnul(q, L'=') - q;
1764
1765 /* If the length differs, include the shorter key's NUL */
1766 if (p_len < q_len)
1767 p_len++;
1768 else if (p_len > q_len)
1769 p_len = q_len + 1;
1770
1771 return _wcsnicmp(p, q, p_len);
1772 }
1773
1774 /*
1775 * Build an environment block combining the inherited environment
1776 * merged with the given list of settings.
1777 *
1778 * Values of the form "KEY=VALUE" in deltaenv override inherited values.
1779 * Values of the form "KEY" in deltaenv delete inherited values.
1780 *
1781 * Multiple entries in deltaenv for the same key are explicitly allowed.
1782 *
1783 * We return a contiguous block of UNICODE strings with a final trailing
1784 * zero word.
1785 */
1786 static wchar_t *make_environment_block(char **deltaenv)
1787 {
1788 wchar_t *wenv = GetEnvironmentStringsW(), *wdeltaenv, *result, *p;
1789 size_t wlen, s, delta_size, size;
1790
1791 wchar_t **array = NULL;
1792 size_t alloc = 0, nr = 0, i;
1793
1794 size = 1; /* for extra NUL at the end */
1795
1796 /* If there is no deltaenv to apply, simply return a copy. */
1797 if (!deltaenv || !*deltaenv) {
1798 for (p = wenv; p && *p; ) {
1799 size_t s = wcslen(p) + 1;
1800 size += s;
1801 p += s;
1802 }
1803
1804 DUP_ARRAY(result, wenv, size);
1805 FreeEnvironmentStringsW(wenv);
1806 return result;
1807 }
1808
1809 /*
1810 * If there is a deltaenv, let's accumulate all keys into `array`,
1811 * sort them using the stable git_stable_qsort() and then copy,
1812 * skipping duplicate keys
1813 */
1814 for (p = wenv; p && *p; ) {
1815 ALLOC_GROW(array, nr + 1, alloc);
1816 s = wcslen(p) + 1;
1817 array[nr++] = p;
1818 p += s;
1819 size += s;
1820 }
1821
1822 /* (over-)assess size needed for wchar version of deltaenv */
1823 for (delta_size = 0, i = 0; deltaenv[i]; i++)
1824 delta_size += strlen(deltaenv[i]) * 2 + 1;
1825 ALLOC_ARRAY(wdeltaenv, delta_size);
1826
1827 /* convert the deltaenv, appending to array */
1828 for (i = 0, p = wdeltaenv; deltaenv[i]; i++) {
1829 ALLOC_GROW(array, nr + 1, alloc);
1830 wlen = xutftowcs(p, deltaenv[i], wdeltaenv + delta_size - p);
1831 array[nr++] = p;
1832 p += wlen + 1;
1833 }
1834
1835 git_stable_qsort(array, nr, sizeof(*array), wenvcmp);
1836 ALLOC_ARRAY(result, size + delta_size);
1837
1838 for (p = result, i = 0; i < nr; i++) {
1839 /* Skip any duplicate keys; last one wins */
1840 while (i + 1 < nr && !wenvcmp(array + i, array + i + 1))
1841 i++;
1842
1843 /* Skip "to delete" entry */
1844 if (!wcschr(array[i], L'='))
1845 continue;
1846
1847 size = wcslen(array[i]) + 1;
1848 COPY_ARRAY(p, array[i], size);
1849 p += size;
1850 }
1851 *p = L'\0';
1852
1853 free(array);
1854 free(wdeltaenv);
1855 FreeEnvironmentStringsW(wenv);
1856 return result;
1857 }
1858
1859 static void do_unset_environment_variables(void)
1860 {
1861 static int done;
1862 char *p = unset_environment_variables;
1863
1864 if (done || !p)
1865 return;
1866 done = 1;
1867
1868 for (;;) {
1869 char *comma = strchr(p, ',');
1870
1871 if (comma)
1872 *comma = '\0';
1873 unsetenv(p);
1874 if (!comma)
1875 break;
1876 p = comma + 1;
1877 }
1878 }
1879
1880 struct pinfo_t {
1881 struct pinfo_t *next;
1882 pid_t pid;
1883 HANDLE proc;
1884 };
1885 static struct pinfo_t *pinfo = NULL;
1886 CRITICAL_SECTION pinfo_cs;
1887
1888 /* Used to match and chomp off path components */
1889 static inline int match_last_path_component(const char *path, size_t *len,
1890 const char *component)
1891 {
1892 size_t component_len = strlen(component);
1893 if (*len < component_len + 1 ||
1894 !is_dir_sep(path[*len - component_len - 1]) ||
1895 fspathncmp(path + *len - component_len, component, component_len))
1896 return 0;
1897 *len -= component_len + 1;
1898 /* chomp off repeated dir separators */
1899 while (*len > 0 && is_dir_sep(path[*len - 1]))
1900 (*len)--;
1901 return 1;
1902 }
1903
1904 static int is_msys2_sh(const char *cmd)
1905 {
1906 if (!cmd)
1907 return 0;
1908
1909 if (!strcmp(cmd, "sh")) {
1910 static int ret = -1;
1911 char *p;
1912
1913 if (ret >= 0)
1914 return ret;
1915
1916 p = path_lookup(cmd, 0);
1917 if (!p)
1918 ret = 0;
1919 else {
1920 size_t len = strlen(p);
1921
1922 ret = match_last_path_component(p, &len, "sh.exe") &&
1923 match_last_path_component(p, &len, "bin") &&
1924 match_last_path_component(p, &len, "usr");
1925 free(p);
1926 }
1927 return ret;
1928 }
1929
1930 if (ends_with(cmd, "\\sh.exe") || ends_with(cmd, "/sh.exe")) {
1931 static char *sh;
1932
1933 if (!sh)
1934 sh = path_lookup("sh", 0);
1935
1936 return !fspathcmp(cmd, sh);
1937 }
1938
1939 return 0;
1940 }
1941
1942 static pid_t mingw_spawnve_fd(const char *cmd, const char **argv, char **deltaenv,
1943 const char *dir,
1944 int prepend_cmd, int fhin, int fhout, int fherr)
1945 {
1946 STARTUPINFOEXW si;
1947 PROCESS_INFORMATION pi;
1948 LPPROC_THREAD_ATTRIBUTE_LIST attr_list = NULL;
1949 HANDLE stdhandles[3];
1950 DWORD stdhandles_count = 0;
1951 SIZE_T size;
1952 struct strbuf args;
1953 wchar_t wcmd[MAX_PATH], wdir[MAX_PATH], *wargs, *wenvblk = NULL;
1954 unsigned flags = CREATE_UNICODE_ENVIRONMENT;
1955 BOOL ret;
1956 HANDLE cons;
1957 const char *(*quote_arg)(const char *arg) =
1958 is_msys2_sh(cmd ? cmd : *argv) ?
1959 quote_arg_msys2 : quote_arg_msvc;
1960 const char *strace_env;
1961
1962 /* Make sure to override previous errors, if any */
1963 errno = 0;
1964
1965 do_unset_environment_variables();
1966
1967 /* Determine whether or not we are associated to a console */
1968 cons = CreateFileW(L"CONOUT$", GENERIC_WRITE,
1969 FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
1970 FILE_ATTRIBUTE_NORMAL, NULL);
1971 if (cons == INVALID_HANDLE_VALUE) {
1972 /* There is no console associated with this process.
1973 * Since the child is a console process, Windows
1974 * would normally create a console window. But
1975 * since we'll be redirecting std streams, we do
1976 * not need the console.
1977 * It is necessary to use DETACHED_PROCESS
1978 * instead of CREATE_NO_WINDOW to make ssh
1979 * recognize that it has no console.
1980 */
1981 flags |= DETACHED_PROCESS;
1982 } else {
1983 /* There is already a console. If we specified
1984 * DETACHED_PROCESS here, too, Windows would
1985 * disassociate the child from the console.
1986 * The same is true for CREATE_NO_WINDOW.
1987 * Go figure!
1988 */
1989 CloseHandle(cons);
1990 }
1991 memset(&si, 0, sizeof(si));
1992 si.StartupInfo.cb = sizeof(si);
1993 si.StartupInfo.hStdInput = winansi_get_osfhandle(fhin);
1994 si.StartupInfo.hStdOutput = winansi_get_osfhandle(fhout);
1995 si.StartupInfo.hStdError = winansi_get_osfhandle(fherr);
1996
1997 /* The list of handles cannot contain duplicates */
1998 if (si.StartupInfo.hStdInput != INVALID_HANDLE_VALUE)
1999 stdhandles[stdhandles_count++] = si.StartupInfo.hStdInput;
2000 if (si.StartupInfo.hStdOutput != INVALID_HANDLE_VALUE &&
2001 si.StartupInfo.hStdOutput != si.StartupInfo.hStdInput)
2002 stdhandles[stdhandles_count++] = si.StartupInfo.hStdOutput;
2003 if (si.StartupInfo.hStdError != INVALID_HANDLE_VALUE &&
2004 si.StartupInfo.hStdError != si.StartupInfo.hStdInput &&
2005 si.StartupInfo.hStdError != si.StartupInfo.hStdOutput)
2006 stdhandles[stdhandles_count++] = si.StartupInfo.hStdError;
2007 if (stdhandles_count)
2008 si.StartupInfo.dwFlags |= STARTF_USESTDHANDLES;
2009
2010 if (*argv && !strcmp(cmd, *argv))
2011 wcmd[0] = L'\0';
2012 else if (xutftowcs_path(wcmd, cmd) < 0)
2013 return -1;
2014 if (dir && xutftowcs_path(wdir, dir) < 0)
2015 return -1;
2016
2017 /* concatenate argv, quoting args as we go */
2018 strbuf_init(&args, 0);
2019 if (prepend_cmd) {
2020 char *quoted = (char *)quote_arg(cmd);
2021 strbuf_addstr(&args, quoted);
2022 if (quoted != cmd)
2023 free(quoted);
2024 }
2025 for (; *argv; argv++) {
2026 char *quoted = (char *)quote_arg(*argv);
2027 if (*args.buf)
2028 strbuf_addch(&args, ' ');
2029 strbuf_addstr(&args, quoted);
2030 if (quoted != *argv)
2031 free(quoted);
2032 }
2033
2034 strace_env = getenv("GIT_STRACE_COMMANDS");
2035 if (strace_env) {
2036 char *p = path_lookup("strace.exe", 1);
2037 if (!p)
2038 return error("strace not found!");
2039 if (xutftowcs_path(wcmd, p) < 0) {
2040 free(p);
2041 return -1;
2042 }
2043 free(p);
2044 if (!strcmp("1", strace_env) ||
2045 !strcasecmp("yes", strace_env) ||
2046 !strcasecmp("true", strace_env))
2047 strbuf_insert(&args, 0, "strace ", 7);
2048 else {
2049 const char *quoted = quote_arg(strace_env);
2050 struct strbuf buf = STRBUF_INIT;
2051 strbuf_addf(&buf, "strace -o %s ", quoted);
2052 if (quoted != strace_env)
2053 free((char *)quoted);
2054 strbuf_insert(&args, 0, buf.buf, buf.len);
2055 strbuf_release(&buf);
2056 }
2057 }
2058
2059 ALLOC_ARRAY(wargs, st_add(st_mult(2, args.len), 1));
2060 xutftowcs(wargs, args.buf, 2 * args.len + 1);
2061 strbuf_release(&args);
2062
2063 wenvblk = make_environment_block(deltaenv);
2064
2065 memset(&pi, 0, sizeof(pi));
2066 if (stdhandles_count &&
2067 (InitializeProcThreadAttributeList(NULL, 1, 0, &size) ||
2068 GetLastError() == ERROR_INSUFFICIENT_BUFFER) &&
2069 (attr_list = (LPPROC_THREAD_ATTRIBUTE_LIST)
2070 (HeapAlloc(GetProcessHeap(), 0, size))) &&
2071 InitializeProcThreadAttributeList(attr_list, 1, 0, &size) &&
2072 UpdateProcThreadAttribute(attr_list, 0,
2073 PROC_THREAD_ATTRIBUTE_HANDLE_LIST,
2074 stdhandles,
2075 stdhandles_count * sizeof(HANDLE),
2076 NULL, NULL)) {
2077 si.lpAttributeList = attr_list;
2078 flags |= EXTENDED_STARTUPINFO_PRESENT;
2079 }
2080
2081 ret = CreateProcessW(*wcmd ? wcmd : NULL, wargs, NULL, NULL,
2082 stdhandles_count ? TRUE : FALSE,
2083 flags, wenvblk, dir ? wdir : NULL,
2084 &si.StartupInfo, &pi);
2085
2086 /*
2087 * On the off-chance that something with the file handle restriction
2088 * went wrong, silently fall back to trying without it.
2089 */
2090 if (!ret && stdhandles_count) {
2091 DWORD err = GetLastError();
2092 struct strbuf buf = STRBUF_INIT;
2093
2094 flags &= ~EXTENDED_STARTUPINFO_PRESENT;
2095 ret = CreateProcessW(*wcmd ? wcmd : NULL, wargs, NULL, NULL,
2096 TRUE, flags, wenvblk, dir ? wdir : NULL,
2097 &si.StartupInfo, &pi);
2098 if (!ret)
2099 errno = err_win_to_posix(GetLastError());
2100 if (ret && buf.len) {
2101 warning("failed to restrict file handles (%ld)\n\n%s",
2102 err, buf.buf);
2103 }
2104 strbuf_release(&buf);
2105 } else if (!ret)
2106 errno = err_win_to_posix(GetLastError());
2107
2108 if (si.lpAttributeList)
2109 DeleteProcThreadAttributeList(si.lpAttributeList);
2110 if (attr_list)
2111 HeapFree(GetProcessHeap(), 0, attr_list);
2112
2113 free(wenvblk);
2114 free(wargs);
2115
2116 if (!ret)
2117 return -1;
2118
2119 CloseHandle(pi.hThread);
2120
2121 /*
2122 * The process ID is the human-readable identifier of the process
2123 * that we want to present in log and error messages. The handle
2124 * is not useful for this purpose. But we cannot close it, either,
2125 * because it is not possible to turn a process ID into a process
2126 * handle after the process terminated.
2127 * Keep the handle in a list for waitpid.
2128 */
2129 EnterCriticalSection(&pinfo_cs);
2130 {
2131 struct pinfo_t *info = xmalloc(sizeof(struct pinfo_t));
2132 info->pid = pi.dwProcessId;
2133 info->proc = pi.hProcess;
2134 info->next = pinfo;
2135 pinfo = info;
2136 }
2137 LeaveCriticalSection(&pinfo_cs);
2138
2139 return (pid_t)pi.dwProcessId;
2140 }
2141
2142 static pid_t mingw_spawnv(const char *cmd, const char **argv, int prepend_cmd)
2143 {
2144 return mingw_spawnve_fd(cmd, argv, NULL, NULL, prepend_cmd, 0, 1, 2);
2145 }
2146
2147 pid_t mingw_spawnvpe(const char *cmd, const char **argv, char **deltaenv,
2148 const char *dir,
2149 int fhin, int fhout, int fherr)
2150 {
2151 pid_t pid;
2152 char *prog = path_lookup(cmd, 0);
2153
2154 if (!prog) {
2155 errno = ENOENT;
2156 pid = -1;
2157 }
2158 else {
2159 const char *interpr = parse_interpreter(prog);
2160
2161 if (interpr) {
2162 const char *argv0 = argv[0];
2163 char *iprog = path_lookup(interpr, 1);
2164 argv[0] = prog;
2165 if (!iprog) {
2166 errno = ENOENT;
2167 pid = -1;
2168 }
2169 else {
2170 pid = mingw_spawnve_fd(iprog, argv, deltaenv, dir, 1,
2171 fhin, fhout, fherr);
2172 free(iprog);
2173 }
2174 argv[0] = argv0;
2175 }
2176 else
2177 pid = mingw_spawnve_fd(prog, argv, deltaenv, dir, 0,
2178 fhin, fhout, fherr);
2179 free(prog);
2180 }
2181 return pid;
2182 }
2183
2184 static int try_shell_exec(const char *cmd, char *const *argv)
2185 {
2186 const char *interpr = parse_interpreter(cmd);
2187 char *prog;
2188 int pid = 0;
2189
2190 if (!interpr)
2191 return 0;
2192 prog = path_lookup(interpr, 1);
2193 if (prog) {
2194 int exec_id;
2195 int argc = 0;
2196 char **argv2;
2197 while (argv[argc]) argc++;
2198 ALLOC_ARRAY(argv2, argc + 1);
2199 argv2[0] = (char *)cmd; /* full path to the script file */
2200 COPY_ARRAY(&argv2[1], &argv[1], argc);
2201 exec_id = trace2_exec(prog, (const char **)argv2);
2202 pid = mingw_spawnv(prog, (const char **)argv2, 1);
2203 if (pid >= 0) {
2204 int status;
2205 if (waitpid(pid, &status, 0) < 0)
2206 status = 255;
2207 trace2_exec_result(exec_id, status);
2208 exit(status);
2209 }
2210 trace2_exec_result(exec_id, -1);
2211 pid = 1; /* indicate that we tried but failed */
2212 free(prog);
2213 free(argv2);
2214 }
2215 return pid;
2216 }
2217
2218 int mingw_execv(const char *cmd, char *const *argv)
2219 {
2220 /* check if git_command is a shell script */
2221 if (!try_shell_exec(cmd, argv)) {
2222 int pid, status;
2223 int exec_id;
2224
2225 exec_id = trace2_exec(cmd, (const char **)argv);
2226 pid = mingw_spawnv(cmd, (const char **)argv, 0);
2227 if (pid < 0) {
2228 trace2_exec_result(exec_id, -1);
2229 return -1;
2230 }
2231 if (waitpid(pid, &status, 0) < 0)
2232 status = 255;
2233 trace2_exec_result(exec_id, status);
2234 exit(status);
2235 }
2236 return -1;
2237 }
2238
2239 int mingw_execvp(const char *cmd, char *const *argv)
2240 {
2241 char *prog = path_lookup(cmd, 0);
2242
2243 if (prog) {
2244 mingw_execv(prog, argv);
2245 free(prog);
2246 } else
2247 errno = ENOENT;
2248
2249 return -1;
2250 }
2251
2252 int mingw_kill(pid_t pid, int sig)
2253 {
2254 if (pid > 0 && sig == SIGTERM) {
2255 HANDLE h = OpenProcess(PROCESS_CREATE_THREAD |
2256 PROCESS_QUERY_INFORMATION |
2257 PROCESS_VM_OPERATION | PROCESS_VM_WRITE |
2258 PROCESS_VM_READ | PROCESS_TERMINATE,
2259 FALSE, pid);
2260 int ret;
2261
2262 if (h)
2263 ret = exit_process(h, 128 + sig);
2264 else {
2265 h = OpenProcess(PROCESS_TERMINATE, FALSE, pid);
2266 if (!h) {
2267 errno = err_win_to_posix(GetLastError());
2268 return -1;
2269 }
2270 ret = terminate_process_tree(h, 128 + sig);
2271 }
2272 if (ret) {
2273 errno = err_win_to_posix(GetLastError());
2274 CloseHandle(h);
2275 }
2276 return ret;
2277 } else if (pid > 0 && sig == 0) {
2278 HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
2279 if (h) {
2280 CloseHandle(h);
2281 return 0;
2282 }
2283 /*
2284 * OpenProcess returns ERROR_INVALID_PARAMETER for
2285 * non-existent PIDs. Map this to ESRCH for POSIX
2286 * compatibility with kill(pid, 0).
2287 */
2288 if (GetLastError() == ERROR_INVALID_PARAMETER)
2289 errno = ESRCH;
2290 else
2291 errno = err_win_to_posix(GetLastError());
2292 return -1;
2293 }
2294
2295 errno = EINVAL;
2296 return -1;
2297 }
2298
2299 /*
2300 * UTF-8 versions of getenv(), putenv() and unsetenv().
2301 * Internally, they use the CRT's stock UNICODE routines
2302 * to avoid data loss.
2303 */
2304 char *mingw_getenv(const char *name)
2305 {
2306 #define GETENV_MAX_RETAIN 64
2307 static char *values[GETENV_MAX_RETAIN];
2308 static int value_counter;
2309 size_t len_key, len_value;
2310 wchar_t *w_key;
2311 char *value;
2312 wchar_t w_value[32768];
2313
2314 if (!name || !*name)
2315 return NULL;
2316
2317 len_key = strlen(name) + 1;
2318 /* We cannot use xcalloc() here because that uses getenv() itself */
2319 w_key = calloc(len_key, sizeof(wchar_t));
2320 if (!w_key)
2321 die("Out of memory, (tried to allocate %"PRIuMAX" wchar_t's)",
2322 (uintmax_t)len_key);
2323 xutftowcs(w_key, name, len_key);
2324 /* GetEnvironmentVariableW() only sets the last error upon failure */
2325 SetLastError(ERROR_SUCCESS);
2326 len_value = GetEnvironmentVariableW(w_key, w_value, ARRAY_SIZE(w_value));
2327 if (!len_value && GetLastError() == ERROR_ENVVAR_NOT_FOUND) {
2328 free(w_key);
2329 return NULL;
2330 }
2331 free(w_key);
2332
2333 len_value = len_value * 3 + 1;
2334 /* We cannot use xcalloc() here because that uses getenv() itself */
2335 value = calloc(len_value, sizeof(char));
2336 if (!value)
2337 die("Out of memory, (tried to allocate %"PRIuMAX" bytes)",
2338 (uintmax_t)len_value);
2339 xwcstoutf(value, w_value, len_value);
2340
2341 /*
2342 * We return `value` which is an allocated value and the caller is NOT
2343 * expecting to have to free it, so we keep a round-robin array,
2344 * invalidating the buffer after GETENV_MAX_RETAIN getenv() calls.
2345 */
2346 free(values[value_counter]);
2347 values[value_counter++] = value;
2348 if (value_counter >= ARRAY_SIZE(values))
2349 value_counter = 0;
2350
2351 return value;
2352 }
2353
2354 int mingw_putenv(const char *namevalue)
2355 {
2356 size_t size;
2357 wchar_t *wide, *equal;
2358 BOOL result;
2359
2360 if (!namevalue || !*namevalue)
2361 return 0;
2362
2363 size = strlen(namevalue) * 2 + 1;
2364 wide = calloc(size, sizeof(wchar_t));
2365 if (!wide)
2366 die("Out of memory, (tried to allocate %" PRIuMAX " wchar_t's)",
2367 (uintmax_t)size);
2368 xutftowcs(wide, namevalue, size);
2369 equal = wcschr(wide, L'=');
2370 if (!equal)
2371 result = SetEnvironmentVariableW(wide, NULL);
2372 else {
2373 *equal = L'\0';
2374 result = SetEnvironmentVariableW(wide, equal + 1);
2375 }
2376 free(wide);
2377
2378 if (!result)
2379 errno = err_win_to_posix(GetLastError());
2380
2381 return result ? 0 : -1;
2382 }
2383
2384 static void ensure_socket_initialization(void)
2385 {
2386 WSADATA wsa;
2387 static int initialized = 0;
2388
2389 if (initialized)
2390 return;
2391
2392 if (WSAStartup(MAKEWORD(2,2), &wsa))
2393 die("unable to initialize winsock subsystem, error %d",
2394 WSAGetLastError());
2395
2396 atexit((void(*)(void)) WSACleanup);
2397 initialized = 1;
2398 }
2399
2400 #undef gethostname
2401 int mingw_gethostname(char *name, int namelen)
2402 {
2403 ensure_socket_initialization();
2404 return gethostname(name, namelen);
2405 }
2406
2407 #undef gethostbyname
2408 struct hostent *mingw_gethostbyname(const char *host)
2409 {
2410 ensure_socket_initialization();
2411 return gethostbyname(host);
2412 }
2413
2414 #undef getaddrinfo
2415 int mingw_getaddrinfo(const char *node, const char *service,
2416 const struct addrinfo *hints, struct addrinfo **res)
2417 {
2418 ensure_socket_initialization();
2419 return getaddrinfo(node, service, hints, res);
2420 }
2421
2422 int mingw_socket(int domain, int type, int protocol)
2423 {
2424 int sockfd;
2425 SOCKET s;
2426
2427 ensure_socket_initialization();
2428 s = WSASocket(domain, type, protocol, NULL, 0, 0);
2429 if (s == INVALID_SOCKET) {
2430 /*
2431 * WSAGetLastError() values are regular BSD error codes
2432 * biased by WSABASEERR.
2433 * However, strerror() does not know about networking
2434 * specific errors, which are values beginning at 38 or so.
2435 * Therefore, we choose to leave the biased error code
2436 * in errno so that _if_ someone looks up the code somewhere,
2437 * then it is at least the number that are usually listed.
2438 */
2439 errno = WSAGetLastError();
2440 return -1;
2441 }
2442 /* convert into a file descriptor */
2443 if ((sockfd = _open_osfhandle(s, O_RDWR|O_BINARY)) < 0) {
2444 closesocket(s);
2445 return error("unable to make a socket file descriptor: %s",
2446 strerror(errno));
2447 }
2448 return sockfd;
2449 }
2450
2451 #undef connect
2452 int mingw_connect(int sockfd, struct sockaddr *sa, size_t sz)
2453 {
2454 SOCKET s = (SOCKET)_get_osfhandle(sockfd);
2455 return connect(s, sa, sz);
2456 }
2457
2458 #undef bind
2459 int mingw_bind(int sockfd, struct sockaddr *sa, size_t sz)
2460 {
2461 SOCKET s = (SOCKET)_get_osfhandle(sockfd);
2462 return bind(s, sa, sz);
2463 }
2464
2465 #undef setsockopt
2466 int mingw_setsockopt(int sockfd, int lvl, int optname, void *optval, int optlen)
2467 {
2468 SOCKET s = (SOCKET)_get_osfhandle(sockfd);
2469 return setsockopt(s, lvl, optname, (const char*)optval, optlen);
2470 }
2471
2472 #undef shutdown
2473 int mingw_shutdown(int sockfd, int how)
2474 {
2475 SOCKET s = (SOCKET)_get_osfhandle(sockfd);
2476 return shutdown(s, how);
2477 }
2478
2479 #undef listen
2480 int mingw_listen(int sockfd, int backlog)
2481 {
2482 SOCKET s = (SOCKET)_get_osfhandle(sockfd);
2483 return listen(s, backlog);
2484 }
2485
2486 #undef accept
2487 int mingw_accept(int sockfd1, struct sockaddr *sa, socklen_t *sz)
2488 {
2489 int sockfd2;
2490
2491 SOCKET s1 = (SOCKET)_get_osfhandle(sockfd1);
2492 SOCKET s2 = accept(s1, sa, sz);
2493
2494 /* convert into a file descriptor */
2495 if ((sockfd2 = _open_osfhandle(s2, O_RDWR|O_BINARY)) < 0) {
2496 int err = errno;
2497 closesocket(s2);
2498 return error("unable to make a socket file descriptor: %s",
2499 strerror(err));
2500 }
2501 return sockfd2;
2502 }
2503
2504 #undef rename
2505 int mingw_rename(const char *pold, const char *pnew)
2506 {
2507 static int supports_file_rename_info_ex = 1;
2508 DWORD attrs = INVALID_FILE_ATTRIBUTES, gle;
2509 int tries = 0;
2510 wchar_t wpold[MAX_PATH], wpnew[MAX_PATH];
2511 int wpnew_len;
2512
2513 if (xutftowcs_path(wpold, pold) < 0)
2514 return -1;
2515 wpnew_len = xutftowcs_path(wpnew, pnew);
2516 if (wpnew_len < 0)
2517 return -1;
2518
2519 repeat:
2520 if (supports_file_rename_info_ex) {
2521 /*
2522 * Our minimum required Windows version is still set to Windows
2523 * 8.1. We thus have to declare required infrastructure for
2524 * FileRenameInfoEx ourselves until we bump _WIN32_WINNT to
2525 * 0x0A00. Furthermore, we have to handle cases where the
2526 * FileRenameInfoEx call isn't supported yet.
2527 */
2528 #define FILE_RENAME_FLAG_REPLACE_IF_EXISTS 0x00000001
2529 #define FILE_RENAME_FLAG_POSIX_SEMANTICS 0x00000002
2530 FILE_INFO_BY_HANDLE_CLASS FileRenameInfoEx = 22;
2531 struct {
2532 /*
2533 * This is usually an unnamed union, but that is not
2534 * part of ISO C99. We thus inline the field, as we
2535 * really only care for the Flags field anyway.
2536 */
2537 DWORD Flags;
2538 HANDLE RootDirectory;
2539 DWORD FileNameLength;
2540 /*
2541 * The actual structure is defined with a single-character
2542 * flex array so that the structure has to be allocated on
2543 * the heap. As we declare this structure ourselves though
2544 * we can avoid the allocation and define FileName to have
2545 * MAX_PATH bytes.
2546 */
2547 WCHAR FileName[MAX_PATH];
2548 } rename_info = { 0 };
2549 HANDLE old_handle = INVALID_HANDLE_VALUE;
2550 BOOL success;
2551
2552 old_handle = CreateFileW(wpold, DELETE,
2553 FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE,
2554 NULL, OPEN_EXISTING,
2555 FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT,
2556 NULL);
2557 if (old_handle == INVALID_HANDLE_VALUE) {
2558 errno = err_win_to_posix(GetLastError());
2559 return -1;
2560 }
2561
2562 rename_info.Flags = FILE_RENAME_FLAG_REPLACE_IF_EXISTS |
2563 FILE_RENAME_FLAG_POSIX_SEMANTICS;
2564 rename_info.FileNameLength = wpnew_len * sizeof(WCHAR);
2565 memcpy(rename_info.FileName, wpnew, wpnew_len * sizeof(WCHAR));
2566
2567 success = SetFileInformationByHandle(old_handle, FileRenameInfoEx,
2568 &rename_info, sizeof(rename_info));
2569 gle = GetLastError();
2570 CloseHandle(old_handle);
2571 if (success)
2572 return 0;
2573
2574 /*
2575 * When we see ERROR_INVALID_PARAMETER we can assume that the
2576 * current system doesn't support FileRenameInfoEx. Keep us
2577 * from using it in future calls and retry.
2578 */
2579 if (gle == ERROR_INVALID_PARAMETER ||
2580 gle == ERROR_NOT_SUPPORTED ||
2581 gle == ERROR_INVALID_FUNCTION) {
2582 supports_file_rename_info_ex = 0;
2583 goto repeat;
2584 }
2585
2586 /*
2587 * In theory, we shouldn't get ERROR_ACCESS_DENIED because we
2588 * always open files with FILE_SHARE_DELETE But in practice we
2589 * cannot assume that Git is the only one accessing files, and
2590 * other applications may not set FILE_SHARE_DELETE. So we have
2591 * to retry.
2592 */
2593 } else {
2594 if (MoveFileExW(wpold, wpnew,
2595 MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED))
2596 return 0;
2597 gle = GetLastError();
2598 }
2599
2600 /* revert file attributes on failure */
2601 if (attrs != INVALID_FILE_ATTRIBUTES)
2602 SetFileAttributesW(wpnew, attrs);
2603
2604 if (!is_file_in_use_error(gle)) {
2605 errno = err_win_to_posix(gle);
2606 return -1;
2607 }
2608
2609 if (attrs == INVALID_FILE_ATTRIBUTES &&
2610 (attrs = GetFileAttributesW(wpnew)) != INVALID_FILE_ATTRIBUTES) {
2611 if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
2612 DWORD attrsold = GetFileAttributesW(wpold);
2613 if (attrsold == INVALID_FILE_ATTRIBUTES ||
2614 !(attrsold & FILE_ATTRIBUTE_DIRECTORY))
2615 errno = EISDIR;
2616 else if (!_wrmdir(wpnew))
2617 goto repeat;
2618 return -1;
2619 }
2620 if ((attrs & FILE_ATTRIBUTE_READONLY) &&
2621 SetFileAttributesW(wpnew, attrs & ~FILE_ATTRIBUTE_READONLY))
2622 goto repeat;
2623 }
2624 if (retry_ask_yes_no(&tries, "Rename from '%s' to '%s' failed. "
2625 "Should I try again?", pold, pnew))
2626 goto repeat;
2627
2628 errno = EACCES;
2629 return -1;
2630 }
2631
2632 /*
2633 * Note that this doesn't return the actual pagesize, but
2634 * the allocation granularity. If future Windows specific git code
2635 * needs the real getpagesize function, we need to find another solution.
2636 */
2637 int mingw_getpagesize(void)
2638 {
2639 SYSTEM_INFO si;
2640 GetSystemInfo(&si);
2641 return si.dwAllocationGranularity;
2642 }
2643
2644 /* See https://msdn.microsoft.com/en-us/library/windows/desktop/ms724435.aspx */
2645 enum EXTENDED_NAME_FORMAT {
2646 NameDisplay = 3,
2647 NameUserPrincipal = 8
2648 };
2649
2650 static char *get_extended_user_info(enum EXTENDED_NAME_FORMAT type)
2651 {
2652 DECLARE_PROC_ADDR(secur32.dll, BOOL, SEC_ENTRY, GetUserNameExW,
2653 enum EXTENDED_NAME_FORMAT, LPCWSTR, PULONG);
2654 static wchar_t wbuffer[1024];
2655 DWORD len;
2656
2657 if (!INIT_PROC_ADDR(GetUserNameExW))
2658 return NULL;
2659
2660 len = ARRAY_SIZE(wbuffer);
2661 if (GetUserNameExW(type, wbuffer, &len)) {
2662 char *converted = xmalloc((len *= 3));
2663 if (xwcstoutf(converted, wbuffer, len) >= 0)
2664 return converted;
2665 free(converted);
2666 }
2667
2668 return NULL;
2669 }
2670
2671 char *mingw_query_user_email(void)
2672 {
2673 return get_extended_user_info(NameUserPrincipal);
2674 }
2675
2676 struct passwd *getpwuid(int uid UNUSED)
2677 {
2678 static unsigned initialized;
2679 static char user_name[100];
2680 static struct passwd *p;
2681 wchar_t buf[100];
2682 DWORD len;
2683
2684 if (initialized)
2685 return p;
2686
2687 len = ARRAY_SIZE(buf);
2688 if (!GetUserNameW(buf, &len)) {
2689 initialized = 1;
2690 return NULL;
2691 }
2692
2693 if (xwcstoutf(user_name, buf, sizeof(user_name)) < 0) {
2694 initialized = 1;
2695 return NULL;
2696 }
2697
2698 p = xmalloc(sizeof(*p));
2699 p->pw_name = user_name;
2700 p->pw_gecos = get_extended_user_info(NameDisplay);
2701 if (!p->pw_gecos)
2702 /*
2703 * Data returned by getpwuid(3P) is treated as internal and
2704 * must never be written to or freed.
2705 */
2706 p->pw_gecos = (char *) "unknown";
2707 p->pw_dir = NULL;
2708
2709 initialized = 1;
2710 return p;
2711 }
2712
2713 static HANDLE timer_event;
2714 static HANDLE timer_thread;
2715 static int timer_interval;
2716 static int one_shot;
2717 static sig_handler_t timer_fn = SIG_DFL, sigint_fn = SIG_DFL;
2718
2719 /* The timer works like this:
2720 * The thread, ticktack(), is a trivial routine that most of the time
2721 * only waits to receive the signal to terminate. The main thread tells
2722 * the thread to terminate by setting the timer_event to the signalled
2723 * state.
2724 * But ticktack() interrupts the wait state after the timer's interval
2725 * length to call the signal handler.
2726 */
2727
2728 static unsigned __stdcall ticktack(void *dummy UNUSED)
2729 {
2730 while (WaitForSingleObject(timer_event, timer_interval) == WAIT_TIMEOUT) {
2731 mingw_raise(SIGALRM);
2732 if (one_shot)
2733 break;
2734 }
2735 return 0;
2736 }
2737
2738 static int start_timer_thread(void)
2739 {
2740 timer_event = CreateEvent(NULL, FALSE, FALSE, NULL);
2741 if (timer_event) {
2742 timer_thread = (HANDLE) _beginthreadex(NULL, 0, ticktack, NULL, 0, NULL);
2743 if (!timer_thread ) {
2744 errno = ENOMEM;
2745 return error("cannot start timer thread");
2746 }
2747 } else {
2748 errno = ENOMEM;
2749 return error("cannot allocate resources for timer");
2750 }
2751 return 0;
2752 }
2753
2754 static void stop_timer_thread(void)
2755 {
2756 if (timer_event)
2757 SetEvent(timer_event); /* tell thread to terminate */
2758 if (timer_thread) {
2759 int rc = WaitForSingleObject(timer_thread, 10000);
2760 if (rc == WAIT_TIMEOUT)
2761 error("timer thread did not terminate timely");
2762 else if (rc != WAIT_OBJECT_0)
2763 error("waiting for timer thread failed: %lu",
2764 GetLastError());
2765 CloseHandle(timer_thread);
2766 }
2767 if (timer_event)
2768 CloseHandle(timer_event);
2769 timer_event = NULL;
2770 timer_thread = NULL;
2771 }
2772
2773 static inline int is_timeval_eq(const struct timeval *i1, const struct timeval *i2)
2774 {
2775 return i1->tv_sec == i2->tv_sec && i1->tv_usec == i2->tv_usec;
2776 }
2777
2778 int setitimer(int type UNUSED, struct itimerval *in, struct itimerval *out)
2779 {
2780 static const struct timeval zero;
2781 static int atexit_done;
2782
2783 if (out) {
2784 errno = EINVAL;
2785 return error("setitimer param 3 != NULL not implemented");
2786 }
2787 if (!is_timeval_eq(&in->it_interval, &zero) &&
2788 !is_timeval_eq(&in->it_interval, &in->it_value)) {
2789 errno = EINVAL;
2790 return error("setitimer: it_interval must be zero or eq it_value");
2791 }
2792
2793 if (timer_thread)
2794 stop_timer_thread();
2795
2796 if (is_timeval_eq(&in->it_value, &zero) &&
2797 is_timeval_eq(&in->it_interval, &zero))
2798 return 0;
2799
2800 timer_interval = in->it_value.tv_sec * 1000 + in->it_value.tv_usec / 1000;
2801 one_shot = is_timeval_eq(&in->it_interval, &zero);
2802 if (!atexit_done) {
2803 atexit(stop_timer_thread);
2804 atexit_done = 1;
2805 }
2806 return start_timer_thread();
2807 }
2808
2809 int sigaction(int sig, struct sigaction *in, struct sigaction *out)
2810 {
2811 if (sig == SIGCHLD)
2812 return -1;
2813 else if (sig != SIGALRM) {
2814 errno = EINVAL;
2815 return error("sigaction only implemented for SIGALRM");
2816 }
2817 if (out) {
2818 errno = EINVAL;
2819 return error("sigaction: param 3 != NULL not implemented");
2820 }
2821
2822 timer_fn = in->sa_handler;
2823 return 0;
2824 }
2825
2826 #undef signal
2827 sig_handler_t mingw_signal(int sig, sig_handler_t handler)
2828 {
2829 sig_handler_t old;
2830
2831 switch (sig) {
2832 case SIGALRM:
2833 old = timer_fn;
2834 timer_fn = handler;
2835 break;
2836
2837 case SIGINT:
2838 old = sigint_fn;
2839 sigint_fn = handler;
2840 break;
2841
2842 default:
2843 return signal(sig, handler);
2844 }
2845
2846 return old;
2847 }
2848
2849 #undef raise
2850 int mingw_raise(int sig)
2851 {
2852 switch (sig) {
2853 case SIGALRM:
2854 if (timer_fn == SIG_DFL) {
2855 if (isatty(STDERR_FILENO))
2856 fputs("Alarm clock\n", stderr);
2857 exit(128 + SIGALRM);
2858 } else if (timer_fn != SIG_IGN)
2859 timer_fn(SIGALRM);
2860 return 0;
2861
2862 case SIGINT:
2863 if (sigint_fn == SIG_DFL)
2864 exit(128 + SIGINT);
2865 else if (sigint_fn != SIG_IGN)
2866 sigint_fn(SIGINT);
2867 return 0;
2868
2869 #if defined(_MSC_VER)
2870 case SIGILL:
2871 case SIGFPE:
2872 case SIGSEGV:
2873 case SIGTERM:
2874 case SIGBREAK:
2875 case SIGABRT:
2876 case SIGABRT_COMPAT:
2877 /*
2878 * The <signal.h> header in the MS C Runtime defines 8 signals
2879 * as being supported on the platform. Anything else causes an
2880 * "Invalid signal or error" (which in DEBUG builds causes the
2881 * Abort/Retry/Ignore dialog). We by-pass the CRT for things we
2882 * already know will fail.
2883 */
2884 return raise(sig);
2885 default:
2886 errno = EINVAL;
2887 return -1;
2888
2889 #else
2890
2891 default:
2892 return raise(sig);
2893
2894 #endif
2895
2896 }
2897 }
2898
2899 int link(const char *oldpath, const char *newpath)
2900 {
2901 wchar_t woldpath[MAX_PATH], wnewpath[MAX_PATH];
2902 if (xutftowcs_path(woldpath, oldpath) < 0 ||
2903 xutftowcs_path(wnewpath, newpath) < 0)
2904 return -1;
2905
2906 if (!CreateHardLinkW(wnewpath, woldpath, NULL)) {
2907 errno = err_win_to_posix(GetLastError());
2908 return -1;
2909 }
2910 return 0;
2911 }
2912
2913 int symlink(const char *target, const char *link)
2914 {
2915 wchar_t wtarget[MAX_PATH], wlink[MAX_PATH];
2916 int len;
2917
2918 /* fail if symlinks are disabled or API is not supported (WinXP) */
2919 if (!has_symlinks) {
2920 errno = ENOSYS;
2921 return -1;
2922 }
2923
2924 if ((len = xutftowcs_path(wtarget, target)) < 0
2925 || xutftowcs_path(wlink, link) < 0)
2926 return -1;
2927
2928 /* convert target dir separators to backslashes */
2929 while (len--)
2930 if (wtarget[len] == '/')
2931 wtarget[len] = '\\';
2932
2933 /* create file symlink */
2934 if (!CreateSymbolicLinkW(wlink, wtarget, symlink_file_flags)) {
2935 errno = err_win_to_posix(GetLastError());
2936 return -1;
2937 }
2938
2939 /* convert to directory symlink if target exists */
2940 switch (process_phantom_symlink(wtarget, wlink)) {
2941 case PHANTOM_SYMLINK_RETRY: {
2942 /* if target doesn't exist, add to phantom symlinks list */
2943 wchar_t wfullpath[MAX_PATH];
2944 struct phantom_symlink_info *psi;
2945
2946 /* convert to absolute path to be independent of cwd */
2947 len = GetFullPathNameW(wlink, MAX_PATH, wfullpath, NULL);
2948 if (!len || len >= MAX_PATH) {
2949 errno = err_win_to_posix(GetLastError());
2950 return -1;
2951 }
2952
2953 /* over-allocate and fill phantom_symlink_info structure */
2954 psi = xmalloc(sizeof(struct phantom_symlink_info)
2955 + sizeof(wchar_t) * (len + wcslen(wtarget) + 2));
2956 psi->wlink = (wchar_t *)(psi + 1);
2957 wcscpy(psi->wlink, wfullpath);
2958 psi->wtarget = psi->wlink + len + 1;
2959 wcscpy(psi->wtarget, wtarget);
2960
2961 EnterCriticalSection(&phantom_symlinks_cs);
2962 psi->next = phantom_symlinks;
2963 phantom_symlinks = psi;
2964 LeaveCriticalSection(&phantom_symlinks_cs);
2965 break;
2966 }
2967 case PHANTOM_SYMLINK_DIRECTORY:
2968 /* if we created a dir symlink, process other phantom symlinks */
2969 process_phantom_symlinks();
2970 break;
2971 default:
2972 break;
2973 }
2974 return 0;
2975 }
2976
2977 int readlink(const char *path, char *buf, size_t bufsiz)
2978 {
2979 WCHAR wpath[MAX_PATH];
2980 char tmpbuf[MAX_PATH];
2981 int len;
2982 DWORD tag;
2983
2984 if (xutftowcs_path(wpath, path) < 0)
2985 return -1;
2986
2987 if (read_reparse_point(wpath, TRUE, tmpbuf, &len, &tag) < 0)
2988 return -1;
2989
2990 /*
2991 * Adapt to strange readlink() API: Copy up to bufsiz *bytes*, potentially
2992 * cutting off a UTF-8 sequence. Insufficient bufsize is *not* a failure
2993 * condition. There is no conversion function that produces invalid UTF-8,
2994 * so convert to a (hopefully large enough) temporary buffer, then memcpy
2995 * the requested number of bytes (including '\0' for robustness).
2996 */
2997 memcpy(buf, tmpbuf, min(bufsiz, len + 1));
2998 return min(bufsiz, len);
2999 }
3000
3001 pid_t waitpid(pid_t pid, int *status, int options)
3002 {
3003 HANDLE h = OpenProcess(SYNCHRONIZE | PROCESS_QUERY_INFORMATION,
3004 FALSE, pid);
3005 if (!h) {
3006 errno = ECHILD;
3007 return -1;
3008 }
3009
3010 if (pid > 0 && options & WNOHANG) {
3011 if (WAIT_OBJECT_0 != WaitForSingleObject(h, 0)) {
3012 CloseHandle(h);
3013 return 0;
3014 }
3015 options &= ~WNOHANG;
3016 }
3017
3018 if (options == 0) {
3019 struct pinfo_t **ppinfo;
3020 if (WaitForSingleObject(h, INFINITE) != WAIT_OBJECT_0) {
3021 CloseHandle(h);
3022 return 0;
3023 }
3024
3025 if (status)
3026 GetExitCodeProcess(h, (LPDWORD)status);
3027
3028 EnterCriticalSection(&pinfo_cs);
3029
3030 ppinfo = &pinfo;
3031 while (*ppinfo) {
3032 struct pinfo_t *info = *ppinfo;
3033 if (info->pid == pid) {
3034 CloseHandle(info->proc);
3035 *ppinfo = info->next;
3036 free(info);
3037 break;
3038 }
3039 ppinfo = &info->next;
3040 }
3041
3042 LeaveCriticalSection(&pinfo_cs);
3043
3044 CloseHandle(h);
3045 return pid;
3046 }
3047 CloseHandle(h);
3048
3049 errno = EINVAL;
3050 return -1;
3051 }
3052
3053 int xutftowcsn(wchar_t *wcs, const char *utfs, size_t wcslen, int utflen)
3054 {
3055 int upos = 0, wpos = 0;
3056 const unsigned char *utf = (const unsigned char*) utfs;
3057 if (!utf || !wcs || wcslen < 1) {
3058 errno = EINVAL;
3059 return -1;
3060 }
3061 /* reserve space for \0 */
3062 wcslen--;
3063 if (utflen < 0)
3064 utflen = INT_MAX;
3065
3066 while (upos < utflen) {
3067 int c = utf[upos++] & 0xff;
3068 if (utflen == INT_MAX && c == 0)
3069 break;
3070
3071 if (wpos >= wcslen) {
3072 wcs[wpos] = 0;
3073 errno = ERANGE;
3074 return -1;
3075 }
3076
3077 if (c < 0x80) {
3078 /* ASCII */
3079 wcs[wpos++] = c;
3080 } else if (c >= 0xc2 && c < 0xe0 && upos < utflen &&
3081 (utf[upos] & 0xc0) == 0x80) {
3082 /* 2-byte utf-8 */
3083 c = ((c & 0x1f) << 6);
3084 c |= (utf[upos++] & 0x3f);
3085 wcs[wpos++] = c;
3086 } else if (c >= 0xe0 && c < 0xf0 && upos + 1 < utflen &&
3087 !(c == 0xe0 && utf[upos] < 0xa0) && /* over-long encoding */
3088 (utf[upos] & 0xc0) == 0x80 &&
3089 (utf[upos + 1] & 0xc0) == 0x80) {
3090 /* 3-byte utf-8 */
3091 c = ((c & 0x0f) << 12);
3092 c |= ((utf[upos++] & 0x3f) << 6);
3093 c |= (utf[upos++] & 0x3f);
3094 wcs[wpos++] = c;
3095 } else if (c >= 0xf0 && c < 0xf5 && upos + 2 < utflen &&
3096 wpos + 1 < wcslen &&
3097 !(c == 0xf0 && utf[upos] < 0x90) && /* over-long encoding */
3098 !(c == 0xf4 && utf[upos] >= 0x90) && /* > \u10ffff */
3099 (utf[upos] & 0xc0) == 0x80 &&
3100 (utf[upos + 1] & 0xc0) == 0x80 &&
3101 (utf[upos + 2] & 0xc0) == 0x80) {
3102 /* 4-byte utf-8: convert to \ud8xx \udcxx surrogate pair */
3103 c = ((c & 0x07) << 18);
3104 c |= ((utf[upos++] & 0x3f) << 12);
3105 c |= ((utf[upos++] & 0x3f) << 6);
3106 c |= (utf[upos++] & 0x3f);
3107 c -= 0x10000;
3108 wcs[wpos++] = 0xd800 | (c >> 10);
3109 wcs[wpos++] = 0xdc00 | (c & 0x3ff);
3110 } else if (c >= 0xa0) {
3111 /* invalid utf-8 byte, printable unicode char: convert 1:1 */
3112 wcs[wpos++] = c;
3113 } else {
3114 /* invalid utf-8 byte, non-printable unicode: convert to hex */
3115 static const char *hex = "0123456789abcdef";
3116 wcs[wpos++] = hex[c >> 4];
3117 if (wpos < wcslen)
3118 wcs[wpos++] = hex[c & 0x0f];
3119 }
3120 }
3121 wcs[wpos] = 0;
3122 return wpos;
3123 }
3124
3125 int xwcstoutf(char *utf, const wchar_t *wcs, size_t utflen)
3126 {
3127 if (!wcs || !utf || utflen < 1) {
3128 errno = EINVAL;
3129 return -1;
3130 }
3131 utflen = WideCharToMultiByte(CP_UTF8, 0, wcs, -1, utf, utflen, NULL, NULL);
3132 if (utflen)
3133 return utflen - 1;
3134 errno = ERANGE;
3135 return -1;
3136 }
3137
3138 static void setup_windows_environment(void)
3139 {
3140 char *tmp = getenv("TMPDIR");
3141
3142 /* on Windows it is TMP and TEMP */
3143 if (!tmp) {
3144 if (!(tmp = getenv("TMP")))
3145 tmp = getenv("TEMP");
3146 if (tmp) {
3147 setenv("TMPDIR", tmp, 1);
3148 tmp = getenv("TMPDIR");
3149 }
3150 }
3151
3152 if (tmp) {
3153 /*
3154 * Convert all dir separators to forward slashes,
3155 * to help shell commands called from the Git
3156 * executable (by not mistaking the dir separators
3157 * for escape characters).
3158 */
3159 convert_slashes(tmp);
3160 }
3161
3162 /* simulate TERM to enable auto-color (see color.c) */
3163 if (!getenv("TERM"))
3164 setenv("TERM", "cygwin", 1);
3165
3166 /* calculate HOME if not set */
3167 if (!getenv("HOME")) {
3168 /*
3169 * try $HOMEDRIVE$HOMEPATH - the home share may be a network
3170 * location, thus also check if the path exists (i.e. is not
3171 * disconnected)
3172 */
3173 if ((tmp = getenv("HOMEDRIVE"))) {
3174 struct strbuf buf = STRBUF_INIT;
3175 strbuf_addstr(&buf, tmp);
3176 if ((tmp = getenv("HOMEPATH"))) {
3177 strbuf_addstr(&buf, tmp);
3178 if (is_directory(buf.buf))
3179 setenv("HOME", buf.buf, 1);
3180 else
3181 tmp = NULL; /* use $USERPROFILE */
3182 }
3183 strbuf_release(&buf);
3184 }
3185 /* use $USERPROFILE if the home share is not available */
3186 if (!tmp && (tmp = getenv("USERPROFILE")))
3187 setenv("HOME", tmp, 1);
3188 }
3189
3190 /*
3191 * Change 'core.symlinks' default to false, unless native symlinks are
3192 * enabled in MSys2 (via 'MSYS=winsymlinks:nativestrict'). Thus we can
3193 * run the test suite (which doesn't obey config files) with or without
3194 * symlink support.
3195 */
3196 if (!(tmp = getenv("MSYS")) || !strstr(tmp, "winsymlinks:nativestrict"))
3197 has_symlinks = 0;
3198 }
3199
3200 static void get_current_user_sid(PSID *sid, HANDLE *linked_token)
3201 {
3202 HANDLE token;
3203 DWORD len = 0;
3204 TOKEN_ELEVATION_TYPE elevationType;
3205 DWORD size;
3206
3207 *sid = NULL;
3208 *linked_token = NULL;
3209
3210 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token))
3211 return;
3212
3213 if (!GetTokenInformation(token, TokenUser, NULL, 0, &len)) {
3214 TOKEN_USER *info = xmalloc((size_t)len);
3215 if (GetTokenInformation(token, TokenUser, info, len, &len)) {
3216 len = GetLengthSid(info->User.Sid);
3217 *sid = xmalloc(len);
3218 if (!CopySid(len, *sid, info->User.Sid)) {
3219 error(_("failed to copy SID (%ld)"),
3220 GetLastError());
3221 FREE_AND_NULL(*sid);
3222 }
3223 }
3224 FREE_AND_NULL(info);
3225 }
3226
3227 if (GetTokenInformation(token, TokenElevationType, &elevationType, sizeof(elevationType), &size) &&
3228 elevationType == TokenElevationTypeLimited) {
3229 /*
3230 * The current process is run by a member of the Administrators
3231 * group, but is not running elevated.
3232 */
3233 if (!GetTokenInformation(token, TokenLinkedToken, linked_token, sizeof(*linked_token), &size))
3234 linked_token = NULL; /* there is no linked token */
3235 }
3236
3237 CloseHandle(token);
3238 }
3239
3240 static BOOL user_sid_to_user_name(PSID sid, LPSTR *str)
3241 {
3242 SID_NAME_USE pe_use;
3243 DWORD len_user = 0, len_domain = 0;
3244 BOOL translate_sid_to_user;
3245
3246 /*
3247 * returns only FALSE, because the string pointers are NULL
3248 */
3249 LookupAccountSidA(NULL, sid, NULL, &len_user, NULL, &len_domain,
3250 &pe_use);
3251 /*
3252 * Alloc needed space of the strings
3253 */
3254 ALLOC_ARRAY((*str), (size_t)len_domain + (size_t)len_user);
3255 translate_sid_to_user = LookupAccountSidA(NULL, sid,
3256 (*str) + len_domain, &len_user, *str, &len_domain, &pe_use);
3257 if (!translate_sid_to_user)
3258 FREE_AND_NULL(*str);
3259 else
3260 (*str)[len_domain] = '/';
3261 return translate_sid_to_user;
3262 }
3263
3264 static int acls_supported(const char *path)
3265 {
3266 size_t offset = offset_1st_component(path);
3267 WCHAR wroot[MAX_PATH];
3268 DWORD file_system_flags;
3269
3270 if (offset &&
3271 xutftowcsn(wroot, path, MAX_PATH, offset) > 0 &&
3272 GetVolumeInformationW(wroot, NULL, 0, NULL, NULL,
3273 &file_system_flags, NULL, 0))
3274 return !!(file_system_flags & FILE_PERSISTENT_ACLS);
3275
3276 return 0;
3277 }
3278
3279 int is_path_owned_by_current_sid(const char *path, struct strbuf *report)
3280 {
3281 WCHAR wpath[MAX_PATH];
3282 PSID sid = NULL;
3283 PSECURITY_DESCRIPTOR descriptor = NULL;
3284 DWORD err;
3285
3286 static wchar_t home[MAX_PATH];
3287
3288 int result = 0;
3289
3290 if (xutftowcs_path(wpath, path) < 0)
3291 return 0;
3292
3293 /*
3294 * On Windows, the home directory is owned by the administrator, but for
3295 * all practical purposes, it belongs to the user. Do pretend that it is
3296 * owned by the user.
3297 */
3298 if (!*home) {
3299 DWORD size = ARRAY_SIZE(home);
3300 DWORD len = GetEnvironmentVariableW(L"HOME", home, size);
3301 if (!len || len > size)
3302 wcscpy(home, L"::N/A::");
3303 }
3304 if (!wcsicmp(wpath, home))
3305 return 1;
3306
3307 /* Get the owner SID */
3308 err = GetNamedSecurityInfoW(wpath, SE_FILE_OBJECT,
3309 OWNER_SECURITY_INFORMATION |
3310 DACL_SECURITY_INFORMATION,
3311 &sid, NULL, NULL, NULL, &descriptor);
3312
3313 if (err != ERROR_SUCCESS)
3314 error(_("failed to get owner for '%s' (%ld)"), path, err);
3315 else if (sid && IsValidSid(sid)) {
3316 /* Now, verify that the SID matches the current user's */
3317 static PSID current_user_sid;
3318 static HANDLE linked_token;
3319 BOOL is_member;
3320
3321 if (!current_user_sid)
3322 get_current_user_sid(&current_user_sid, &linked_token);
3323
3324 if (current_user_sid &&
3325 IsValidSid(current_user_sid) &&
3326 EqualSid(sid, current_user_sid))
3327 result = 1;
3328 else if (IsWellKnownSid(sid, WinBuiltinAdministratorsSid) &&
3329 ((CheckTokenMembership(NULL, sid, &is_member) &&
3330 is_member) ||
3331 (linked_token &&
3332 CheckTokenMembership(linked_token, sid, &is_member) &&
3333 is_member)))
3334 /*
3335 * If owned by the Administrators group, and the
3336 * current user is an administrator, we consider that
3337 * okay, too.
3338 */
3339 result = 1;
3340 else if (report &&
3341 IsWellKnownSid(sid, WinWorldSid) &&
3342 !acls_supported(path)) {
3343 /*
3344 * On FAT32 volumes, ownership is not actually recorded.
3345 */
3346 strbuf_addf(report, "'%s' is on a file system that does "
3347 "not record ownership\n", path);
3348 } else if (report) {
3349 PCSTR str1, str2, str3, str4;
3350 LPSTR to_free1 = NULL, to_free3 = NULL,
3351 to_local_free2 = NULL, to_local_free4 = NULL;
3352
3353 if (user_sid_to_user_name(sid, &to_free1))
3354 str1 = to_free1;
3355 else
3356 str1 = "(inconvertible)";
3357 if (ConvertSidToStringSidA(sid, &to_local_free2))
3358 str2 = to_local_free2;
3359 else
3360 str2 = "(inconvertible)";
3361
3362 if (!current_user_sid) {
3363 str3 = "(none)";
3364 str4 = "(none)";
3365 }
3366 else if (!IsValidSid(current_user_sid)) {
3367 str3 = "(invalid)";
3368 str4 = "(invalid)";
3369 } else {
3370 if (user_sid_to_user_name(current_user_sid,
3371 &to_free3))
3372 str3 = to_free3;
3373 else
3374 str3 = "(inconvertible)";
3375 if (ConvertSidToStringSidA(current_user_sid,
3376 &to_local_free4))
3377 str4 = to_local_free4;
3378 else
3379 str4 = "(inconvertible)";
3380 }
3381 strbuf_addf(report,
3382 "'%s' is owned by:\n"
3383 "\t%s (%s)\nbut the current user is:\n"
3384 "\t%s (%s)\n",
3385 path, str1, str2, str3, str4);
3386 free(to_free1);
3387 LocalFree(to_local_free2);
3388 free(to_free3);
3389 LocalFree(to_local_free4);
3390 }
3391 }
3392
3393 /*
3394 * We can release the security descriptor struct only now because `sid`
3395 * actually points into this struct.
3396 */
3397 if (descriptor)
3398 LocalFree(descriptor);
3399
3400 return result;
3401 }
3402
3403 int is_valid_win32_path(const char *path, int allow_literal_nul)
3404 {
3405 const char *p = path;
3406 int preceding_space_or_period = 0, i = 0, periods = 0;
3407
3408 if (!protect_ntfs)
3409 return 1;
3410
3411 skip_dos_drive_prefix((char **)&path);
3412 goto segment_start;
3413
3414 for (;;) {
3415 char c = *(path++);
3416 switch (c) {
3417 case '\0':
3418 case '/': case '\\':
3419 /* cannot end in ` ` or `.`, except for `.` and `..` */
3420 if (preceding_space_or_period &&
3421 (i != periods || periods > 2))
3422 return 0;
3423 if (!c)
3424 return 1;
3425
3426 i = periods = preceding_space_or_period = 0;
3427
3428 segment_start:
3429 switch (*path) {
3430 case 'a': case 'A': /* AUX */
3431 if (((c = path[++i]) != 'u' && c != 'U') ||
3432 ((c = path[++i]) != 'x' && c != 'X')) {
3433 not_a_reserved_name:
3434 path += i;
3435 continue;
3436 }
3437 break;
3438 case 'c': case 'C':
3439 /* COM1 ... COM9, CON, CONIN$, CONOUT$ */
3440 if ((c = path[++i]) != 'o' && c != 'O')
3441 goto not_a_reserved_name;
3442 c = path[++i];
3443 if (c == 'm' || c == 'M') { /* COM1 ... COM9 */
3444 c = path[++i];
3445 if (c < '1' || c > '9')
3446 goto not_a_reserved_name;
3447 } else if (c == 'n' || c == 'N') { /* CON */
3448 c = path[i + 1];
3449 if ((c == 'i' || c == 'I') &&
3450 ((c = path[i + 2]) == 'n' ||
3451 c == 'N') &&
3452 path[i + 3] == '$')
3453 i += 3; /* CONIN$ */
3454 else if ((c == 'o' || c == 'O') &&
3455 ((c = path[i + 2]) == 'u' ||
3456 c == 'U') &&
3457 ((c = path[i + 3]) == 't' ||
3458 c == 'T') &&
3459 path[i + 4] == '$')
3460 i += 4; /* CONOUT$ */
3461 } else
3462 goto not_a_reserved_name;
3463 break;
3464 case 'l': case 'L': /* LPT<N> */
3465 if (((c = path[++i]) != 'p' && c != 'P') ||
3466 ((c = path[++i]) != 't' && c != 'T') ||
3467 !isdigit(path[++i]))
3468 goto not_a_reserved_name;
3469 break;
3470 case 'n': case 'N': /* NUL */
3471 if (((c = path[++i]) != 'u' && c != 'U') ||
3472 ((c = path[++i]) != 'l' && c != 'L') ||
3473 (allow_literal_nul &&
3474 !path[i + 1] && p == path))
3475 goto not_a_reserved_name;
3476 break;
3477 case 'p': case 'P': /* PRN */
3478 if (((c = path[++i]) != 'r' && c != 'R') ||
3479 ((c = path[++i]) != 'n' && c != 'N'))
3480 goto not_a_reserved_name;
3481 break;
3482 default:
3483 continue;
3484 }
3485
3486 /*
3487 * So far, this looks like a reserved name. Let's see
3488 * whether it actually is one: trailing spaces, a file
3489 * extension, or an NTFS Alternate Data Stream do not
3490 * matter, the name is still reserved if any of those
3491 * follow immediately after the actual name.
3492 */
3493 i++;
3494 if (path[i] == ' ') {
3495 preceding_space_or_period = 1;
3496 while (path[++i] == ' ')
3497 ; /* skip all spaces */
3498 }
3499
3500 c = path[i];
3501 if (c && c != '.' && c != ':' && !is_xplatform_dir_sep(c))
3502 goto not_a_reserved_name;
3503
3504 /* contains reserved name */
3505 return 0;
3506 case '.':
3507 periods++;
3508 /* fallthru */
3509 case ' ':
3510 preceding_space_or_period = 1;
3511 i++;
3512 continue;
3513 case ':': /* DOS drive prefix was already skipped */
3514 case '<': case '>': case '"': case '|': case '?': case '*':
3515 /* illegal character */
3516 return 0;
3517 default:
3518 if (c > '\0' && c < '\x20')
3519 /* illegal character */
3520 return 0;
3521 }
3522 preceding_space_or_period = 0;
3523 i++;
3524 }
3525 }
3526
3527 #if !defined(_MSC_VER)
3528 /*
3529 * Disable MSVCRT command line wildcard expansion (__getmainargs called from
3530 * mingw startup code, see init.c in mingw runtime).
3531 */
3532 int _CRT_glob = 0;
3533 #endif
3534
3535 static NORETURN void die_startup(void)
3536 {
3537 fputs("fatal: not enough memory for initialization", stderr);
3538 exit(128);
3539 }
3540
3541 static void *malloc_startup(size_t size)
3542 {
3543 void *result = malloc(size);
3544 if (!result)
3545 die_startup();
3546 return result;
3547 }
3548
3549 static char *wcstoutfdup_startup(char *buffer, const wchar_t *wcs, size_t len)
3550 {
3551 len = xwcstoutf(buffer, wcs, len) + 1;
3552 return memcpy(malloc_startup(len), buffer, len);
3553 }
3554
3555 static void maybe_redirect_std_handle(const wchar_t *key, DWORD std_id, int fd,
3556 DWORD desired_access, DWORD flags)
3557 {
3558 DWORD create_flag = fd ? OPEN_ALWAYS : OPEN_EXISTING;
3559 wchar_t buf[MAX_PATH];
3560 DWORD max = ARRAY_SIZE(buf);
3561 HANDLE handle;
3562 DWORD ret = GetEnvironmentVariableW(key, buf, max);
3563
3564 if (!ret || ret >= max)
3565 return;
3566
3567 /* make sure this does not leak into child processes */
3568 SetEnvironmentVariableW(key, NULL);
3569 if (!wcscmp(buf, L"off")) {
3570 close(fd);
3571 handle = GetStdHandle(std_id);
3572 if (handle != INVALID_HANDLE_VALUE)
3573 CloseHandle(handle);
3574 return;
3575 }
3576 if (std_id == STD_ERROR_HANDLE && !wcscmp(buf, L"2>&1")) {
3577 handle = GetStdHandle(STD_OUTPUT_HANDLE);
3578 if (handle == INVALID_HANDLE_VALUE) {
3579 close(fd);
3580 handle = GetStdHandle(std_id);
3581 if (handle != INVALID_HANDLE_VALUE)
3582 CloseHandle(handle);
3583 } else {
3584 int new_fd = _open_osfhandle((intptr_t)handle, O_BINARY);
3585 SetStdHandle(std_id, handle);
3586 dup2(new_fd, fd);
3587 /* do *not* close the new_fd: that would close stdout */
3588 }
3589 return;
3590 }
3591 handle = CreateFileW(buf, desired_access, 0, NULL, create_flag,
3592 flags, NULL);
3593 if (handle != INVALID_HANDLE_VALUE) {
3594 int new_fd = _open_osfhandle((intptr_t)handle, O_BINARY);
3595 SetStdHandle(std_id, handle);
3596 dup2(new_fd, fd);
3597 close(new_fd);
3598 }
3599 }
3600
3601 static void maybe_redirect_std_handles(void)
3602 {
3603 maybe_redirect_std_handle(L"GIT_REDIRECT_STDIN", STD_INPUT_HANDLE, 0,
3604 GENERIC_READ, FILE_ATTRIBUTE_NORMAL);
3605 maybe_redirect_std_handle(L"GIT_REDIRECT_STDOUT", STD_OUTPUT_HANDLE, 1,
3606 GENERIC_WRITE, FILE_ATTRIBUTE_NORMAL);
3607 maybe_redirect_std_handle(L"GIT_REDIRECT_STDERR", STD_ERROR_HANDLE, 2,
3608 GENERIC_WRITE, FILE_FLAG_NO_BUFFERING);
3609 }
3610
3611 static void adjust_symlink_flags(void)
3612 {
3613 /*
3614 * Starting with Windows 10 Build 14972, symbolic links can be created
3615 * using CreateSymbolicLink() without elevation by passing the flag
3616 * SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE (0x02) as last
3617 * parameter, provided the Developer Mode has been enabled. Some
3618 * earlier Windows versions complain about this flag with an
3619 * ERROR_INVALID_PARAMETER, hence we have to test the build number
3620 * specifically.
3621 */
3622 if (GetVersion() >= 14972 << 16) {
3623 symlink_file_flags |= 2;
3624 symlink_directory_flags |= 2;
3625 }
3626 }
3627
3628 static BOOL WINAPI handle_ctrl_c(DWORD ctrl_type)
3629 {
3630 if (ctrl_type != CTRL_C_EVENT)
3631 return FALSE; /* we did not handle this */
3632 mingw_raise(SIGINT);
3633 return TRUE; /* we did handle this */
3634 }
3635
3636 #ifdef _MSC_VER
3637 #ifdef _DEBUG
3638 #include <crtdbg.h>
3639 #endif
3640 #endif
3641
3642 /*
3643 * We implement wmain() and compile with -municode, which would
3644 * normally ignore main(), but we call the latter from the former
3645 * so that we can handle non-ASCII command-line parameters
3646 * appropriately.
3647 *
3648 * To be more compatible with the core git code, we convert
3649 * argv into UTF8 and pass them directly to main().
3650 */
3651 int wmain(int argc, const wchar_t **wargv)
3652 {
3653 int i, exit_status;
3654 size_t maxlen;
3655 char *buffer, **save;
3656 const char **argv;
3657
3658 trace2_initialize_clock();
3659
3660 #ifdef _MSC_VER
3661 #ifdef _DEBUG
3662 _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG);
3663 #endif
3664
3665 #ifdef USE_MSVC_CRTDBG
3666 _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
3667 #endif
3668 #endif
3669
3670 SetConsoleCtrlHandler(handle_ctrl_c, TRUE);
3671
3672 maybe_redirect_std_handles();
3673 adjust_symlink_flags();
3674
3675 /* determine size of argv and environ conversion buffer */
3676 maxlen = wcslen(wargv[0]);
3677 for (i = 1; i < argc; i++)
3678 maxlen = max(maxlen, wcslen(wargv[i]));
3679
3680 /* allocate buffer (wchar_t encodes to max 3 UTF-8 bytes) */
3681 maxlen = 3 * maxlen + 1;
3682 buffer = malloc_startup(maxlen);
3683
3684 /*
3685 * Create a UTF-8 version of w_argv. Also create a "save" copy
3686 * to remember all the string pointers because parse_options()
3687 * will remove claimed items from the argv that we pass down.
3688 */
3689 ALLOC_ARRAY(argv, argc + 1);
3690 ALLOC_ARRAY(save, argc + 1);
3691 for (i = 0; i < argc; i++)
3692 argv[i] = save[i] = wcstoutfdup_startup(buffer, wargv[i], maxlen);
3693 argv[i] = save[i] = NULL;
3694 free(buffer);
3695
3696 /* fix Windows specific environment settings */
3697 setup_windows_environment();
3698
3699 unset_environment_variables = xstrdup("PERL5LIB");
3700
3701 /* initialize critical section for waitpid pinfo_t list */
3702 InitializeCriticalSection(&pinfo_cs);
3703 InitializeCriticalSection(&phantom_symlinks_cs);
3704
3705 /* set up default file mode and file modes for stdin/out/err */
3706 _fmode = _O_BINARY;
3707 _setmode(_fileno(stdin), _O_BINARY);
3708 _setmode(_fileno(stdout), _O_BINARY);
3709 _setmode(_fileno(stderr), _O_BINARY);
3710
3711 /* initialize Unicode console */
3712 winansi_init();
3713
3714 /* invoke the real main() using our utf8 version of argv. */
3715 exit_status = main(argc, argv);
3716
3717 for (i = 0; i < argc; i++)
3718 free(save[i]);
3719 free(save);
3720 free(argv);
3721
3722 return exit_status;
3723 }
3724
3725 int uname(struct utsname *buf)
3726 {
3727 unsigned v = (unsigned)GetVersion();
3728 memset(buf, 0, sizeof(*buf));
3729 xsnprintf(buf->sysname, sizeof(buf->sysname), "Windows");
3730 xsnprintf(buf->release, sizeof(buf->release),
3731 "%u.%u", v & 0xff, (v >> 8) & 0xff);
3732 /* assuming NT variants only.. */
3733 xsnprintf(buf->version, sizeof(buf->version),
3734 "%u", (v >> 16) & 0x7fff);
3735 return 0;
3736 }
3737
3738 #ifndef NO_UNIX_SOCKETS
3739 int mingw_have_unix_sockets(void)
3740 {
3741 SC_HANDLE scm, srvc;
3742 SERVICE_STATUS_PROCESS status;
3743 DWORD bytes;
3744 int ret = 0;
3745 scm = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT);
3746 if (scm) {
3747 srvc = OpenServiceA(scm, "afunix", SERVICE_QUERY_STATUS);
3748 if (srvc) {
3749 if(QueryServiceStatusEx(srvc, SC_STATUS_PROCESS_INFO, (LPBYTE)&status, sizeof(SERVICE_STATUS_PROCESS), &bytes))
3750 ret = status.dwCurrentState == SERVICE_RUNNING;
3751 CloseServiceHandle(srvc);
3752 }
3753 CloseServiceHandle(scm);
3754 }
3755 return ret;
3756 }
3757 #endif