#include "../cache.h"
#include "win32/lazyload.h"
#include "../config.h"
+#include "dir.h"
#define HCAST(type, handle) ((type)(intptr_t)handle)
return 0;
/* We cannot use basename(), as it would remove trailing slashes */
- mingw_skip_dos_drive_prefix((char **)&path);
+ win32_skip_dos_drive_prefix((char **)&path);
if (!*path)
return 0;
{
int ret;
wchar_t wpath[MAX_PATH];
-
- if (!is_valid_win32_path(path)) {
- errno = EINVAL;
- return -1;
- }
-
if (xutftowcs_path(wpath, path) < 0)
return -1;
ret = _wmkdir(wpath);
typedef int (*open_fn_t)(wchar_t const *wfilename, int oflags, ...);
va_list args;
unsigned mode;
- int fd, create = (oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL);
+ int fd;
wchar_t wfilename[MAX_PATH];
open_fn_t open_fn;
mode = va_arg(args, int);
va_end(args);
- if (!is_valid_win32_path(filename)) {
- errno = create ? EINVAL : ENOENT;
- return -1;
- }
-
if (filename && !strcmp(filename, "/dev/null"))
filename = "nul";
int hide = needs_hiding(filename);
FILE *file;
wchar_t wfilename[MAX_PATH], wotype[4];
- if (!is_valid_win32_path(filename)) {
- int create = otype && strchr(otype, 'w');
- errno = create ? EINVAL : ENOENT;
- return NULL;
- }
if (filename && !strcmp(filename, "/dev/null"))
filename = "nul";
if (xutftowcs_path(wfilename, filename) < 0 ||
int hide = needs_hiding(filename);
FILE *file;
wchar_t wfilename[MAX_PATH], wotype[4];
- if (!is_valid_win32_path(filename)) {
- int create = otype && strchr(otype, 'w');
- errno = create ? EINVAL : ENOENT;
- return NULL;
- }
if (filename && !strcmp(filename, "/dev/null"))
filename = "nul";
if (xutftowcs_path(wfilename, filename) < 0 ||
* See "Parsing C++ Command-Line Arguments" at Microsoft's Docs:
* https://docs.microsoft.com/en-us/cpp/cpp/parsing-cpp-command-line-arguments
*/
-static const char *quote_arg(const char *arg)
+static const char *quote_arg_msvc(const char *arg)
{
/* count chars to quote */
int len = 0, n = 0;
p++;
len++;
}
- if (*p == '"' || !*p)
+ if (*p == '"')
n += count*2 + 1;
continue;
}
count++;
*d++ = *arg++;
}
- if (*arg == '"' || !*arg) {
+ if (*arg == '"') {
while (count-- > 0)
*d++ = '\\';
- /* don't escape the surrounding end quote */
- if (!*arg)
- break;
*d++ = '\\';
}
}
*d++ = *arg++;
}
*d++ = '"';
- *d++ = '\0';
+ *d++ = 0;
return q;
}
+#include "quote.h"
+
+static const char *quote_arg_msys2(const char *arg)
+{
+ struct strbuf buf = STRBUF_INIT;
+ const char *p2 = arg, *p;
+
+ for (p = arg; *p; p++) {
+ int ws = isspace(*p);
+ if (!ws && *p != '\\' && *p != '"' && *p != '{')
+ continue;
+ if (!buf.len)
+ strbuf_addch(&buf, '"');
+ if (p != p2)
+ strbuf_add(&buf, p2, p - p2);
+ if (!ws && *p != '{')
+ strbuf_addch(&buf, '\\');
+ p2 = p;
+ }
+
+ if (p == arg)
+ strbuf_addch(&buf, '"');
+ else if (!buf.len)
+ return arg;
+ else
+ strbuf_add(&buf, p2, p - p2),
+
+ strbuf_addch(&buf, '"');
+ return strbuf_detach(&buf, 0);
+}
+
static const char *parse_interpreter(const char *cmd)
{
static char buf[100];
static struct pinfo_t *pinfo = NULL;
CRITICAL_SECTION pinfo_cs;
+/* Used to match and chomp off path components */
+static inline int match_last_path_component(const char *path, size_t *len,
+ const char *component)
+{
+ size_t component_len = strlen(component);
+ if (*len < component_len + 1 ||
+ !is_dir_sep(path[*len - component_len - 1]) ||
+ fspathncmp(path + *len - component_len, component, component_len))
+ return 0;
+ *len -= component_len + 1;
+ /* chomp off repeated dir separators */
+ while (*len > 0 && is_dir_sep(path[*len - 1]))
+ (*len)--;
+ return 1;
+}
+
+static int is_msys2_sh(const char *cmd)
+{
+ if (cmd && !strcmp(cmd, "sh")) {
+ static int ret = -1;
+ char *p;
+
+ if (ret >= 0)
+ return ret;
+
+ p = path_lookup(cmd, 0);
+ if (!p)
+ ret = 0;
+ else {
+ size_t len = strlen(p);
+
+ ret = match_last_path_component(p, &len, "sh.exe") &&
+ match_last_path_component(p, &len, "bin") &&
+ match_last_path_component(p, &len, "usr");
+ free(p);
+ }
+ return ret;
+ }
+ return 0;
+}
+
static pid_t mingw_spawnve_fd(const char *cmd, const char **argv, char **deltaenv,
const char *dir,
int prepend_cmd, int fhin, int fhout, int fherr)
unsigned flags = CREATE_UNICODE_ENVIRONMENT;
BOOL ret;
HANDLE cons;
+ const char *(*quote_arg)(const char *arg) =
+ is_msys2_sh(*argv) ? quote_arg_msys2 : quote_arg_msvc;
do_unset_environment_variables();
*/
char *mingw_getenv(const char *name)
{
-#define GETENV_MAX_RETAIN 30
+#define GETENV_MAX_RETAIN 64
static char *values[GETENV_MAX_RETAIN];
static int value_counter;
int len_key, len_value;
if (timer_event)
SetEvent(timer_event); /* tell thread to terminate */
if (timer_thread) {
- int rc = WaitForSingleObject(timer_thread, 1000);
+ int rc = WaitForSingleObject(timer_thread, 10000);
if (rc == WAIT_TIMEOUT)
error("timer thread did not terminate timely");
else if (rc != WAIT_OBJECT_0)
return -1;
}
-int mingw_has_dos_drive_prefix(const char *path)
-{
- int i;
-
- /*
- * Does it start with an ASCII letter (i.e. highest bit not set),
- * followed by a colon?
- */
- if (!(0x80 & (unsigned char)*path))
- return *path && path[1] == ':' ? 2 : 0;
-
- /*
- * While drive letters must be letters of the English alphabet, it is
- * possible to assign virtually _any_ Unicode character via `subst` as
- * a drive letter to "virtual drives". Even `1`, or `ä`. Or fun stuff
- * like this:
- *
- * subst ֍: %USERPROFILE%\Desktop
- */
- for (i = 1; i < 4 && (0x80 & (unsigned char)path[i]); i++)
- ; /* skip first UTF-8 character */
- return path[i] == ':' ? i + 1 : 0;
-}
-
-int mingw_skip_dos_drive_prefix(char **path)
-{
- int ret = has_dos_drive_prefix(*path);
- *path += ret;
- return ret;
-}
-
-int mingw_offset_1st_component(const char *path)
-{
- char *pos = (char *)path;
-
- /* unc paths */
- if (!skip_dos_drive_prefix(&pos) &&
- is_dir_sep(pos[0]) && is_dir_sep(pos[1])) {
- /* skip server name */
- pos = strpbrk(pos + 2, "\\/");
- if (!pos)
- return 0; /* Error: malformed unc path */
-
- do {
- pos++;
- } while (*pos && !is_dir_sep(*pos));
- }
-
- return pos + is_dir_sep(*pos) - path;
-}
-
int xutftowcsn(wchar_t *wcs, const char *utfs, size_t wcslen, int utflen)
{
int upos = 0, wpos = 0;
setenv("TERM", "cygwin", 1);
}
-int is_valid_win32_path(const char *path)
-{
- int preceding_space_or_period = 0, i = 0, periods = 0;
-
- if (!protect_ntfs)
- return 1;
-
- skip_dos_drive_prefix((char **)&path);
-
- for (;;) {
- char c = *(path++);
- switch (c) {
- case '\0':
- case '/': case '\\':
- /* cannot end in ` ` or `.`, except for `.` and `..` */
- if (preceding_space_or_period &&
- (i != periods || periods > 2))
- return 0;
- if (!c)
- return 1;
-
- i = periods = preceding_space_or_period = 0;
- continue;
- case '.':
- periods++;
- /* fallthru */
- case ' ':
- preceding_space_or_period = 1;
- i++;
- continue;
- case ':': /* DOS drive prefix was already skipped */
- case '<': case '>': case '"': case '|': case '?': case '*':
- /* illegal character */
- return 0;
- default:
- if (c > '\0' && c < '\x20')
- /* illegal character */
- return 0;
- }
- preceding_space_or_period = 0;
- i++;
- }
-}
-
/*
* Disable MSVCRT command line wildcard expansion (__getmainargs called from
* mingw startup code, see init.c in mingw runtime).