diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ae75e156..bcf8160c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,10 @@ v0.25 + 1 ### API additions +* You can now set the default share mode on Windows for opening files using + `GIT_OPT_SET_WINDOWS_SHAREMODE` option with `git_libgit2_opts()`. + You can query the current share mode with `GIT_OPT_GET_WINDOWS_SHAREMODE`. + ### API removals ### Breaking API changes diff --git a/include/git2/common.h b/include/git2/common.h index c909f86ca..6d2092028 100644 --- a/include/git2/common.h +++ b/include/git2/common.h @@ -180,6 +180,8 @@ typedef enum { GIT_OPT_GET_USER_AGENT, GIT_OPT_ENABLE_OFS_DELTA, GIT_OPT_ENABLE_SYNCHRONOUS_OBJECT_CREATION, + GIT_OPT_GET_WINDOWS_SHAREMODE, + GIT_OPT_SET_WINDOWS_SHAREMODE, } git_libgit2_opt_t; /** @@ -284,6 +286,17 @@ typedef enum { * > - `user_agent` is the value that will be delivered as the * > User-Agent header on HTTP requests. * + * * opts(GIT_OPT_SET_WINDOWS_SHAREMODE, unsigned long value) + * + * > Set the share mode used when opening files on Windows. + * > For more information, see the documentation for CreateFile. + * > The default is: FILE_SHARE_READ | FILE_SHARE_WRITE. This is + * > ignored and unused on non-Windows platforms. + * + * * opts(GIT_OPT_GET_WINDOWS_SHAREMODE, unsigned long *value) + * + * > Get the share mode used when opening files on Windows. + * * * opts(GIT_OPT_ENABLE_STRICT_OBJECT_CREATION, int enabled) * * > Enable strict input validation when creating new objects diff --git a/src/settings.c b/src/settings.c index 24e549ec1..07ac16a8f 100644 --- a/src/settings.c +++ b/src/settings.c @@ -231,6 +231,18 @@ int git_libgit2_opts(int key, ...) git_object__synchronous_writing = (va_arg(ap, int) != 0); break; + case GIT_OPT_GET_WINDOWS_SHAREMODE: +#ifdef GIT_WIN32 + *(va_arg(ap, unsigned long *)) = git_win32__createfile_sharemode; +#endif + break; + + case GIT_OPT_SET_WINDOWS_SHAREMODE: +#ifdef GIT_WIN32 + git_win32__createfile_sharemode = va_arg(ap, unsigned long); +#endif + break; + default: giterr_set(GITERR_INVALID, "invalid option key"); error = -1; diff --git a/src/win32/posix.h b/src/win32/posix.h index 73705fb2b..0ba05a16f 100644 --- a/src/win32/posix.h +++ b/src/win32/posix.h @@ -14,6 +14,8 @@ #include "utf-conv.h" #include "dir.h" +extern unsigned long git_win32__createfile_sharemode; + typedef SOCKET GIT_SOCKET; #define p_lseek(f,n,w) _lseeki64(f, n, w) diff --git a/src/win32/posix_w32.c b/src/win32/posix_w32.c index 28cd3e2e9..4943ce202 100644 --- a/src/win32/posix_w32.c +++ b/src/win32/posix_w32.c @@ -26,15 +26,6 @@ #define IO_REPARSE_TAG_SYMLINK (0xA000000CL) #endif -/* Options which we always provide to _wopen. - * - * _O_BINARY - Raw access; no translation of CR or LF characters - * _O_NOINHERIT - Do not mark the created handle as inheritable by child processes. - * The Windows default is 'not inheritable', but the CRT's default (following - * POSIX convention) is 'inheritable'. We have no desire for our handles to be - * inheritable on Windows, so specify the flag to get default behavior back. */ -#define STANDARD_OPEN_FLAGS (_O_BINARY | _O_NOINHERIT) - /* Allowable mode bits on Win32. Using mode bits that are not supported on * Win32 (eg S_IRWXU) is generally ignored, but Wine warns loudly about it * so we simply remove them. @@ -44,6 +35,9 @@ /* GetFinalPathNameByHandleW signature */ typedef DWORD(WINAPI *PFGetFinalPathNameByHandleW)(HANDLE, LPWSTR, DWORD, DWORD); +unsigned long git_win32__createfile_sharemode = + FILE_SHARE_READ | FILE_SHARE_WRITE; + GIT_INLINE(void) set_errno(void) { switch (GetLastError()) { @@ -489,7 +483,7 @@ int p_open(const char *path, int flags, ...) break; } - sharing = FILE_SHARE_READ | FILE_SHARE_WRITE; + sharing = (DWORD)git_win32__createfile_sharemode; switch (flags & (O_CREAT | O_TRUNC | O_EXCL)) { case O_CREAT | O_EXCL: @@ -510,7 +504,8 @@ int p_open(const char *path, int flags, ...) break; } - attributes = (mode & S_IWRITE) ? FILE_ATTRIBUTE_NORMAL : FILE_ATTRIBUTE_READONLY; + attributes = ((flags & O_CREAT) && !(mode & S_IWRITE)) ? + FILE_ATTRIBUTE_READONLY : FILE_ATTRIBUTE_NORMAL; osf_flags = flags & (O_RDONLY | O_APPEND); do_with_retries(