{"thread":{"id":"33278","subject":"[PATCH 1/2] Make core.sharedRepository work under cygwin 1.7","startedAt":"2013-03-25T15:53:17Z","lastAt":"2013-03-25T15:53:17Z","messageCount":1,"participants":["Torsten Bögershausen"],"isPatch":true,"patchVersion":1,"patchTotal":2},"messages":[{"id":"212170","messageId":"201303251653.18517.tboegi@web.de","threadId":"33278","inReplyTo":null,"subject":"[PATCH 1/2] Make core.sharedRepository work under cygwin 1.7","fromName":"Torsten Bögershausen","fromEmail":"tboegi@web.de","sentAt":"2013-03-25T15:53:17Z","receivedAt":"2013-03-25T15:53:17Z","isPatch":true,"sender":{"key":"tboegi@web.de","avatar":"https://avatars.githubusercontent.com/u/7138363?v=4"},"body":"When core.sharedRepository is used, set_shared_perm() in path.c\nneeds lstat() to return the correct POSIX permissions.\n\nThe default for cygwin is core.ignoreCygwinFSTricks = false, which\nmeans that the fast implementation in do_stat() is used instead of lstat().\n\nlstat() under cygwin uses the Windows security model to implement\nPOSIX-like permissions.\nThe user, group or everyone bits can be set individually.\n\ndo_stat() simplifes the file permission bits, and may return a wrong value:\nThe read-only attribute of a file is used to calculate\nthe permissions, resulting in either rw-r--r-- or r--r--r--\n\nOne effect of the simplified do_stat() is that t1301 fails.\n\nAdd a function cygwin_get_st_mode_bits() which returns the POSIX permissions.\nWhen not compiling for cygwin, true_mode_bits() in path.c is used.\n\nSide note:\nt1301 passes under cygwin 1.5.\nThe \"user write\" bit is synchronized with the \"read only\" attribute of a file:\n\n$ chmod 444 x\n$ attrib x\nA    R     C:\\temp\\pt\\x\n\ncygwin 1.7 would show\nA          C:\\temp\\pt\\x\n\nSigned-off-by: Torsten Bögershausen <tboegi@web.de>\n---\n compat/cygwin.c   | 13 +++++++++++++\n compat/cygwin.h   |  5 +++++\n git-compat-util.h |  1 +\n path.c            | 20 +++++++++++++++++---\n 4 files changed, 36 insertions(+), 3 deletions(-)\n\ndiff --git a/compat/cygwin.c b/compat/cygwin.c\nindex 5428858..871b41d 100644\n--- a/compat/cygwin.c\n+++ b/compat/cygwin.c\n@@ -1,3 +1,4 @@\n+#define CYGWIN_C\n #define WIN32_LEAN_AND_MEAN\n #ifdef CYGWIN_V15_WIN32API\n #include \"../git-compat-util.h\"\n@@ -10,6 +11,18 @@\n #endif\n #include \"../cache.h\" /* to read configuration */\n \n+/*\n+ * Return POSIX permission bits, regardless of core.ignorecygwinfstricks\n+ */\n+int cygwin_get_st_mode_bits(const char *path, int *mode)\n+{\n+\tstruct stat st;\n+\tif (lstat(path, &st) < 0)\n+\t\treturn -1;\n+\t*mode = st.st_mode;\n+\treturn 0;\n+}\n+\n static inline void filetime_to_timespec(const FILETIME *ft, struct timespec *ts)\n {\n \tlong long winTime = ((long long)ft->dwHighDateTime << 32) +\ndiff --git a/compat/cygwin.h b/compat/cygwin.h\nindex a3229f5..c04965a 100644\n--- a/compat/cygwin.h\n+++ b/compat/cygwin.h\n@@ -4,6 +4,11 @@\n typedef int (*stat_fn_t)(const char*, struct stat*);\n extern stat_fn_t cygwin_stat_fn;\n extern stat_fn_t cygwin_lstat_fn;\n+int cygwin_get_st_mode_bits(const char *path, int *mode);\n \n+#define get_st_mode_bits(p,m) cygwin_get_st_mode_bits((p),(m))\n+#ifndef CYGWIN_C\n+/* cygwin.c needs the original lstat() */\n #define stat(path, buf) (*cygwin_stat_fn)(path, buf)\n #define lstat(path, buf) (*cygwin_lstat_fn)(path, buf)\n+#endif\ndiff --git a/git-compat-util.h b/git-compat-util.h\nindex 90e0372..cde442f 100644\n--- a/git-compat-util.h\n+++ b/git-compat-util.h\n@@ -163,6 +163,7 @@\n typedef long intptr_t;\n typedef unsigned long uintptr_t;\n #endif\n+int get_st_mode_bits(const char *path, int *mode);\n #if defined(__CYGWIN__)\n #undef _XOPEN_SOURCE\n #include <grp.h>\ndiff --git a/path.c b/path.c\nindex d3d3f8b..2fdccc2 100644\n--- a/path.c\n+++ b/path.c\n@@ -14,6 +14,22 @@\n #include \"strbuf.h\"\n #include \"string-list.h\"\n \n+#ifndef get_st_mode_bits\n+/*\n+ * The replacement lstat(2) we use on Cygwin is incomplete and\n+ * may return wrong permission bits. Most of the time we do not care,\n+ * but the callsites of this wrapper do care.\n+ */\n+int get_st_mode_bits(const char *path, int *mode)\n+{\n+\tstruct stat st;\n+\tif (lstat(path, &st) < 0)\n+\t\treturn -1;\n+\t*mode = st.st_mode;\n+\treturn 0;\n+}\n+#endif\n+\n static char bad_path[] = \"/bad-path/\";\n \n static char *get_pathname(void)\n@@ -391,7 +407,6 @@ const char *enter_repo(const char *path, int strict)\n \n int set_shared_perm(const char *path, int mode)\n {\n-\tstruct stat st;\n \tint tweak, shared, orig_mode;\n \n \tif (!shared_repository) {\n@@ -400,9 +415,8 @@ int set_shared_perm(const char *path, int mode)\n \t\treturn 0;\n \t}\n \tif (!mode) {\n-\t\tif (lstat(path, &st) < 0)\n+\t\tif (get_st_mode_bits(path, &mode) < 0)\n \t\t\treturn -1;\n-\t\tmode = st.st_mode;\n \t\torig_mode = mode;\n \t} else\n \t\torig_mode = 0;\n-- \n1.8.2.341.g543621f\n"}]}