[PATCH v2 1/3] git clone <url> C:\cygwin\home\USER\repo' is working (again)
From: <hidden>
Date: 2018-12-07 17:05:04
Subsystem:
the rest · Maintainer:
Linus Torvalds
From: Torsten Bögershausen <redacted>
A regression for cygwin users was introduced with commit 05b458c,
"real_path: resolve symlinks by hand".
In the the commit message we read:
The current implementation of real_path uses chdir() in order to resolve
symlinks. Unfortunately this isn't thread-safe as chdir() affects a
process as a whole...
The old (and non-thread-save) OS calls chdir()/pwd() had been
replaced by a string operation.
The cygwin layer "knows" that "C:\cygwin" is an absolute path,
but the new string operation does not.
"git clone <url> C:\cygwin\home\USER\repo" fails like this:
fatal: Invalid path '/home/USER/repo/C:\cygwin\home\USER\repo'
The solution is to implement has_dos_drive_prefix(), skip_dos_drive_prefix()
is_dir_sep(), offset_1st_component() and convert_slashes() for cygwin
in the same way as it is done in 'Git for Windows' in compat/mingw.[ch]
Instead of duplicating the code, it is extracted into compat/mingw-cygwin.[ch]
Some need for refactoring and cleanup came up in the review, they are adressed
in a seperate commit.
Reported-By: Steven Penny <redacted>
Signed-off-by: Torsten Bögershausen <redacted>
---
compat/cygwin.c | 19 -------------------
compat/cygwin.h | 2 --
compat/mingw-cygwin.c | 28 ++++++++++++++++++++++++++++
compat/mingw-cygwin.h | 20 ++++++++++++++++++++
compat/mingw.c | 29 +----------------------------
compat/mingw.h | 20 --------------------
config.mak.uname | 4 ++--
git-compat-util.h | 3 ++-
8 files changed, 53 insertions(+), 72 deletions(-)
delete mode 100644 compat/cygwin.c
delete mode 100644 compat/cygwin.h
create mode 100644 compat/mingw-cygwin.c
create mode 100644 compat/mingw-cygwin.h
diff --git a/compat/cygwin.c b/compat/cygwin.c
deleted file mode 100644
index b9862d606d..0000000000
--- a/compat/cygwin.c
+++ /dev/null@@ -1,19 +0,0 @@ -#include "../git-compat-util.h" -#include "../cache.h" - -int cygwin_offset_1st_component(const char *path) -{ - const char *pos = path; - /* unc paths */ - if (is_dir_sep(pos[0]) && is_dir_sep(pos[1])) { - /* skip server name */ - pos = strchr(pos + 2, '/'); - if (!pos) - return 0; /* Error: malformed unc path */ - - do { - pos++; - } while (*pos && pos[0] != '/'); - } - return pos + is_dir_sep(*pos) - path; -}
diff --git a/compat/cygwin.h b/compat/cygwin.h
deleted file mode 100644
index 8e52de4644..0000000000
--- a/compat/cygwin.h
+++ /dev/null@@ -1,2 +0,0 @@ -int cygwin_offset_1st_component(const char *path); -#define offset_1st_component cygwin_offset_1st_component
diff --git a/compat/mingw-cygwin.c b/compat/mingw-cygwin.c
new file mode 100644
index 0000000000..c63d7acb9c
--- /dev/null
+++ b/compat/mingw-cygwin.c@@ -0,0 +1,28 @@ +#include "../git-compat-util.h" + +int mingw_cygwin_skip_dos_drive_prefix(char **path) +{ + int ret = has_dos_drive_prefix(*path); + *path += ret; + return ret; +} + +int mingw_cygwin_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; +}
diff --git a/compat/mingw-cygwin.h b/compat/mingw-cygwin.h
new file mode 100644
index 0000000000..66ccc909ae
--- /dev/null
+++ b/compat/mingw-cygwin.h@@ -0,0 +1,20 @@ +#define has_dos_drive_prefix(path) \ + (isalpha(*(path)) && (path)[1] == ':' ? 2 : 0) +int mingw_cygwin_skip_dos_drive_prefix(char **path); +#define skip_dos_drive_prefix mingw_cygwin_skip_dos_drive_prefix +static inline int mingw_cygwin_is_dir_sep(int c) +{ + return c == '/' || c == '\\'; +} +#define is_dir_sep mingw_cygwin_is_dir_sep +static inline char *mingw_cygwin_find_last_dir_sep(const char *path) +{ + char *ret = NULL; + for (; *path; ++path) + if (is_dir_sep(*path)) + ret = (char *)path; + return ret; +} +#define find_last_dir_sep mingw_cygwin_find_last_dir_sep +int mingw_cygwin_offset_1st_component(const char *path); +#define offset_1st_component mingw_cygwin_offset_1st_component
diff --git a/compat/mingw.c b/compat/mingw.c
index 34b3880b29..038e96af9d 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c@@ -350,7 +350,7 @@ static inline int needs_hiding(const char *path) return 0; /* We cannot use basename(), as it would remove trailing slashes */ - mingw_skip_dos_drive_prefix((char **)&path); + mingw_cygwin_skip_dos_drive_prefix((char **)&path); if (!*path) return 0;
@@ -2275,33 +2275,6 @@ pid_t waitpid(pid_t pid, int *status, int options) return -1; } -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;
diff --git a/compat/mingw.h b/compat/mingw.h
index 8c24ddaa3e..30d9fb3e36 100644
--- a/compat/mingw.h
+++ b/compat/mingw.h@@ -443,32 +443,12 @@ HANDLE winansi_get_osfhandle(int fd); * git specific compatibility */ -#define has_dos_drive_prefix(path) \ - (isalpha(*(path)) && (path)[1] == ':' ? 2 : 0) -int mingw_skip_dos_drive_prefix(char **path); -#define skip_dos_drive_prefix mingw_skip_dos_drive_prefix -static inline int mingw_is_dir_sep(int c) -{ - return c == '/' || c == '\\'; -} -#define is_dir_sep mingw_is_dir_sep -static inline char *mingw_find_last_dir_sep(const char *path) -{ - char *ret = NULL; - for (; *path; ++path) - if (is_dir_sep(*path)) - ret = (char *)path; - return ret; -} static inline void convert_slashes(char *path) { for (; *path; path++) if (*path == '\\') *path = '/'; } -#define find_last_dir_sep mingw_find_last_dir_sep -int mingw_offset_1st_component(const char *path); -#define offset_1st_component mingw_offset_1st_component #define PATH_SEP ';' extern char *mingw_query_user_email(void); #define query_user_email mingw_query_user_email
diff --git a/config.mak.uname b/config.mak.uname
index 3ee7da0e23..9346f67922 100644
--- a/config.mak.uname
+++ b/config.mak.uname@@ -187,7 +187,7 @@ ifeq ($(uname_O),Cygwin) UNRELIABLE_FSTAT = UnfortunatelyYes OBJECT_CREATION_USES_RENAMES = UnfortunatelyNeedsTo MMAP_PREVENTS_DELETE = UnfortunatelyYes - COMPAT_OBJS += compat/cygwin.o + COMPAT_OBJS += compat/mingw-cygwin.o FREAD_READS_DIRECTORIES = UnfortunatelyYes endif ifeq ($(uname_S),FreeBSD)
@@ -526,7 +526,7 @@ ifneq (,$(findstring MINGW,$(uname_S))) DEFAULT_HELP_FORMAT = html COMPAT_CFLAGS += -DNOGDI -Icompat -Icompat/win32 COMPAT_CFLAGS += -DSTRIP_EXTENSION=\".exe\" - COMPAT_OBJS += compat/mingw.o compat/winansi.o \ + COMPAT_OBJS += compat/mingw.o compat/mingw-cygwin.o compat/winansi.o \ compat/win32/pthread.o compat/win32/syslog.o \ compat/win32/dirent.o BASIC_CFLAGS += -DWIN32 -DPROTECT_NTFS_DEFAULT=1
diff --git a/git-compat-util.h b/git-compat-util.h
index 09b0102cae..7ece969b22 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h@@ -193,10 +193,11 @@ #endif #if defined(__CYGWIN__) -#include "compat/cygwin.h" +#include "compat/mingw-cygwin.h" #endif #if defined(__MINGW32__) /* pull in Windows compatibility stuff */ +#include "compat/mingw-cygwin.h" #include "compat/mingw.h" #elif defined(_MSC_VER) #include "compat/msvc.h"
--
2.19.0.271.gfe8321ec05