Merge branch 'js/mingw-default-ident'
authorJunio C Hamano <gitster@pobox.com>
Fri, 26 Oct 2018 05:22:15 +0000 (14:22 +0900)
committerJunio C Hamano <gitster@pobox.com>
Fri, 26 Oct 2018 05:22:15 +0000 (14:22 +0900)
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

1  2 
compat/mingw.c
git-compat-util.h
diff --combined compat/mingw.c
index 18caf21969a5917e8e6c6d754beffbba2741e6c2,45c8046c7cc34ff53ed506af303a1874ca35d67b..44264fe3fd8fd8da4af6f17d7376634a47a92d8f
@@@ -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;
                        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)
        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, ...);
        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 48c955541e2000239f861bdf7dd5043fa741674c,71779cb0aeb6f34de974cc1f7b81d13ce137b941..95cfcc1aeb3ec51e602f378bc9e94dd5cccb123c
  #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 <winsock2.h>
@@@ -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