summaryrefslogtreecommitdiff
path: root/compat/mingw.c
diff options
context:
space:
mode:
Diffstat (limited to 'compat/mingw.c')
-rw-r--r--compat/mingw.c71
1 files changed, 63 insertions, 8 deletions
diff --git a/compat/mingw.c b/compat/mingw.c
index d14065d60e..a43599841c 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -18,8 +18,8 @@ void open_in_gdb(void)
static struct child_process cp = CHILD_PROCESS_INIT;
extern char *_pgmptr;
- argv_array_pushl(&cp.args, "mintty", "gdb", NULL);
- argv_array_pushf(&cp.args, "--pid=%d", getpid());
+ strvec_pushl(&cp.args, "mintty", "gdb", NULL);
+ strvec_pushf(&cp.args, "--pid=%d", getpid());
cp.clean_on_exit = 1;
if (start_command(&cp) < 0)
die_errno("Could not start gdb");
@@ -290,6 +290,9 @@ int mingw_unlink(const char *pathname)
if (xutftowcs_path(wpathname, pathname) < 0)
return -1;
+ if (DeleteFileW(wpathname))
+ return 0;
+
/* read-only files cannot be removed */
_wchmod(wpathname, 0666);
while ((ret = _wunlink(wpathname)) == -1 && tries < ARRAY_SIZE(delay)) {
@@ -364,6 +367,8 @@ int mingw_rmdir(const char *pathname)
ask_yes_no_if_possible("Deletion of directory '%s' failed. "
"Should I try again?", pathname))
ret = _wrmdir(wpathname);
+ if (!ret)
+ invalidate_lstat_cache();
return ret;
}
@@ -460,8 +465,21 @@ static int mingw_open_append(wchar_t const *wfilename, int oflags, ...)
handle = CreateFileW(wfilename, FILE_APPEND_DATA,
FILE_SHARE_WRITE | FILE_SHARE_READ,
NULL, create, FILE_ATTRIBUTE_NORMAL, NULL);
- if (handle == INVALID_HANDLE_VALUE)
- return errno = err_win_to_posix(GetLastError()), -1;
+ if (handle == INVALID_HANDLE_VALUE) {
+ DWORD err = GetLastError();
+
+ /*
+ * Some network storage solutions (e.g. Isilon) might return
+ * ERROR_INVALID_PARAMETER instead of expected error
+ * ERROR_PATH_NOT_FOUND, which results in an unknown error. If
+ * so, let's turn the error to ERROR_PATH_NOT_FOUND instead.
+ */
+ if (err == ERROR_INVALID_PARAMETER)
+ err = ERROR_PATH_NOT_FOUND;
+
+ errno = err_win_to_posix(err);
+ return -1;
+ }
/*
* No O_APPEND here, because the CRT uses it only to reset the
@@ -964,7 +982,16 @@ revert_attrs:
size_t mingw_strftime(char *s, size_t max,
const char *format, const struct tm *tm)
{
- size_t ret = strftime(s, max, format, tm);
+ /* a pointer to the original strftime in case we can't find the UCRT version */
+ static size_t (*fallback)(char *, size_t, const char *, const struct tm *) = strftime;
+ size_t ret;
+ DECLARE_PROC_ADDR(ucrtbase.dll, size_t, strftime, char *, size_t,
+ const char *, const struct tm *);
+
+ if (INIT_PROC_ADDR(strftime))
+ ret = strftime(s, max, format, tm);
+ else
+ ret = fallback(s, max, format, tm);
if (!ret && errno == EINVAL)
die("invalid strftime format: '%s'", format);
@@ -1479,6 +1506,7 @@ static pid_t mingw_spawnve_fd(const char *cmd, const char **argv, char **deltaen
const char *(*quote_arg)(const char *arg) =
is_msys2_sh(cmd ? cmd : *argv) ?
quote_arg_msys2 : quote_arg_msvc;
+ const char *strace_env;
/* Make sure to override previous errors, if any */
errno = 0;
@@ -1562,6 +1590,31 @@ static pid_t mingw_spawnve_fd(const char *cmd, const char **argv, char **deltaen
free(quoted);
}
+ strace_env = getenv("GIT_STRACE_COMMANDS");
+ if (strace_env) {
+ char *p = path_lookup("strace.exe", 1);
+ if (!p)
+ return error("strace not found!");
+ if (xutftowcs_path(wcmd, p) < 0) {
+ free(p);
+ return -1;
+ }
+ free(p);
+ if (!strcmp("1", strace_env) ||
+ !strcasecmp("yes", strace_env) ||
+ !strcasecmp("true", strace_env))
+ strbuf_insert(&args, 0, "strace ", 7);
+ else {
+ const char *quoted = quote_arg(strace_env);
+ struct strbuf buf = STRBUF_INIT;
+ strbuf_addf(&buf, "strace -o %s ", quoted);
+ if (quoted != strace_env)
+ free((char *)quoted);
+ strbuf_insert(&args, 0, buf.buf, buf.len);
+ strbuf_release(&buf);
+ }
+ }
+
ALLOC_ARRAY(wargs, st_add(st_mult(2, args.len), 1));
xutftowcs(wargs, args.buf, 2 * args.len + 1);
strbuf_release(&args);
@@ -2581,12 +2634,14 @@ not_a_reserved_name:
continue;
}
break;
- case 'c': case 'C': /* COM<N>, CON, CONIN$, CONOUT$ */
+ case 'c': case 'C':
+ /* COM1 ... COM9, CON, CONIN$, CONOUT$ */
if ((c = path[++i]) != 'o' && c != 'O')
goto not_a_reserved_name;
c = path[++i];
- if (c == 'm' || c == 'M') { /* COM<N> */
- if (!isdigit(path[++i]))
+ if (c == 'm' || c == 'M') { /* COM1 ... COM9 */
+ c = path[++i];
+ if (c < '1' || c > '9')
goto not_a_reserved_name;
} else if (c == 'n' || c == 'N') { /* CON */
c = path[i + 1];