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