From: Junio C Hamano Date: Fri, 26 Oct 2018 05:22:15 +0000 (+0900) Subject: Merge branch 'js/mingw-default-ident' X-Git-Tag: v2.20.0-rc0~131 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/16ce0b92bdaa50ca8ebb318829e8fde65299d676?ds=inline;hp=-c Merge branch 'js/mingw-default-ident' The logic to select the default user name and e-mail on Windows has been improved. * js/mingw-default-ident: mingw: use domain information for default email getpwuid(mingw): provide a better default for the user name getpwuid(mingw): initialize the structure only once --- 16ce0b92bdaa50ca8ebb318829e8fde65299d676 diff --combined compat/mingw.c index 18caf21969,45c8046c7c..44264fe3fd --- a/compat/mingw.c +++ b/compat/mingw.c @@@ -5,6 -5,7 +5,7 @@@ #include "../strbuf.h" #include "../run-command.h" #include "../cache.h" + #include "win32/lazyload.h" #define HCAST(type, handle) ((type)(intptr_t)handle) @@@ -341,19 -342,6 +342,19 @@@ int mingw_mkdir(const char *path, int m return ret; } +/* + * Calling CreateFile() using FILE_APPEND_DATA and without FILE_WRITE_DATA + * is documented in [1] as opening a writable file handle in append mode. + * (It is believed that) this is atomic since it is maintained by the + * kernel unlike the O_APPEND flag which is racily maintained by the CRT. + * + * [1] https://docs.microsoft.com/en-us/windows/desktop/fileio/file-access-rights-constants + * + * This trick does not appear to work for named pipes. Instead it creates + * a named pipe client handle that cannot be written to. Callers should + * just use the regular _wopen() for them. (And since client handle gets + * bound to a unique server handle, it isn't really an issue.) + */ static int mingw_open_append(wchar_t const *wfilename, int oflags, ...) { HANDLE handle; @@@ -373,12 -361,10 +374,12 @@@ NULL, create, FILE_ATTRIBUTE_NORMAL, NULL); if (handle == INVALID_HANDLE_VALUE) return errno = err_win_to_posix(GetLastError()), -1; + /* * No O_APPEND here, because the CRT uses it only to reset the - * file pointer to EOF on write(); but that is not necessary - * for a file created with FILE_APPEND_DATA. + * file pointer to EOF before each write(); but that is not + * necessary (and may lead to races) for a file created with + * FILE_APPEND_DATA. */ fd = _open_osfhandle((intptr_t)handle, O_BINARY); if (fd < 0) @@@ -386,21 -372,6 +387,21 @@@ return fd; } +/* + * Does the pathname map to the local named pipe filesystem? + * That is, does it have a "//./pipe/" prefix? + */ +static int is_local_named_pipe_path(const char *filename) +{ + return (is_dir_sep(filename[0]) && + is_dir_sep(filename[1]) && + filename[2] == '.' && + is_dir_sep(filename[3]) && + !strncasecmp(filename+4, "pipe", 4) && + is_dir_sep(filename[8]) && + filename[9]); +} + int mingw_open (const char *filename, int oflags, ...) { typedef int (*open_fn_t)(wchar_t const *wfilename, int oflags, ...); @@@ -417,7 -388,7 +418,7 @@@ if (filename && !strcmp(filename, "/dev/null")) filename = "nul"; - if (oflags & O_APPEND) + if ((oflags & O_APPEND) && !is_local_named_pipe_path(filename)) open_fn = mingw_open_append; else open_fn = _wopen; @@@ -1798,18 -1769,63 +1799,63 @@@ int mingw_getpagesize(void return si.dwAllocationGranularity; } + /* See https://msdn.microsoft.com/en-us/library/windows/desktop/ms724435.aspx */ + enum EXTENDED_NAME_FORMAT { + NameDisplay = 3, + NameUserPrincipal = 8 + }; + + static char *get_extended_user_info(enum EXTENDED_NAME_FORMAT type) + { + DECLARE_PROC_ADDR(secur32.dll, BOOL, GetUserNameExW, + enum EXTENDED_NAME_FORMAT, LPCWSTR, PULONG); + static wchar_t wbuffer[1024]; + DWORD len; + + if (!INIT_PROC_ADDR(GetUserNameExW)) + return NULL; + + len = ARRAY_SIZE(wbuffer); + if (GetUserNameExW(type, wbuffer, &len)) { + char *converted = xmalloc((len *= 3)); + if (xwcstoutf(converted, wbuffer, len) >= 0) + return converted; + free(converted); + } + + return NULL; + } + + char *mingw_query_user_email(void) + { + return get_extended_user_info(NameUserPrincipal); + } + struct passwd *getpwuid(int uid) { + static unsigned initialized; static char user_name[100]; - static struct passwd p; + static struct passwd *p; + DWORD len; + + if (initialized) + return p; - DWORD len = sizeof(user_name); - if (!GetUserName(user_name, &len)) + len = sizeof(user_name); + if (!GetUserName(user_name, &len)) { + initialized = 1; return NULL; - p.pw_name = user_name; - p.pw_gecos = "unknown"; - p.pw_dir = NULL; - return &p; + } + + p = xmalloc(sizeof(*p)); + p->pw_name = user_name; + p->pw_gecos = get_extended_user_info(NameDisplay); + if (!p->pw_gecos) + p->pw_gecos = "unknown"; + p->pw_dir = NULL; + + initialized = 1; + return p; } static HANDLE timer_event; diff --combined git-compat-util.h index 48c955541e,71779cb0ae..95cfcc1aeb --- a/git-compat-util.h +++ b/git-compat-util.h @@@ -146,8 -146,8 +146,8 @@@ #define _SGI_SOURCE 1 #if defined(WIN32) && !defined(__CYGWIN__) /* Both MinGW and MSVC */ -# if defined (_MSC_VER) && !defined(_WIN32_WINNT) -# define _WIN32_WINNT 0x0502 +# if !defined(_WIN32_WINNT) +# define _WIN32_WINNT 0x0600 # endif #define WIN32_LEAN_AND_MEAN /* stops windows.h including winsock.h */ #include @@@ -382,6 -382,10 +382,10 @@@ static inline char *git_find_last_dir_s #define find_last_dir_sep git_find_last_dir_sep #endif + #ifndef query_user_email + #define query_user_email() NULL + #endif + #if defined(__HP_cc) && (__HP_cc >= 61000) #define NORETURN __attribute__((noreturn)) #define NORETURN_PTR