diff options
| author | Edward Thomson <ethomson@edwardthomson.com> | 2018-11-15 09:17:51 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-11-15 09:17:51 +0000 |
| commit | 7321cff05df927c8d00755ef21289ec00d125c9c (patch) | |
| tree | cbc8f816d196c6e5642886bb632d524eecbfa137 /src/win32 | |
| parent | 9189a66a9eb99f13ee81da5913ade3a1ff64262a (diff) | |
| parent | da500cc607f1f30cea822087f3aaeb6b6727ff74 (diff) | |
| download | libgit2-7321cff05df927c8d00755ef21289ec00d125c9c.tar.gz | |
Merge pull request #4713 from libgit2/ethomson/win_symlinks
Support symlinks on Windows when core.symlinks=true
Diffstat (limited to 'src/win32')
| -rw-r--r-- | src/win32/posix_w32.c | 54 |
1 files changed, 18 insertions, 36 deletions
diff --git a/src/win32/posix_w32.c b/src/win32/posix_w32.c index 8c321ef3c..5d144936b 100644 --- a/src/win32/posix_w32.c +++ b/src/win32/posix_w32.c @@ -29,15 +29,16 @@ #define IO_REPARSE_TAG_SYMLINK (0xA000000CL) #endif +#ifndef SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE +# define SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE 0x02 +#endif + /* 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. */ #define WIN32_MODE_MASK (_S_IREAD | _S_IWRITE) -/* GetFinalPathNameByHandleW signature */ -typedef DWORD(WINAPI *PFGetFinalPathNameByHandleW)(HANDLE, LPWSTR, DWORD, DWORD); - unsigned long git_win32__createfile_sharemode = FILE_SHARE_READ | FILE_SHARE_WRITE; int git_win32__retries = 10; @@ -393,12 +394,20 @@ int p_readlink(const char *path, char *buf, size_t bufsiz) return (int)bufsiz; } -int p_symlink(const char *old, const char *new) +int p_symlink(const char *target, const char *path) { - /* Real symlinks on NTFS require admin privileges. Until this changes, - * libgit2 just creates a text file with the link target in the contents. - */ - return git_futils_fake_symlink(old, new); + git_win32_path target_w, path_w; + wchar_t *target_p; + + if (git_win32_path_from_utf8(path_w, path) < 0 || + git__utf8_to_16(target_w, MAX_PATH, target) < 0) + return -1; + + if (!CreateSymbolicLinkW(path_w, target_w, + SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE)) + return -1; + + return 0; } struct open_opts { @@ -598,40 +607,13 @@ int p_getcwd(char *buffer_out, size_t size) return 0; } -/* - * Returns the address of the GetFinalPathNameByHandleW function. - * This function is available on Windows Vista and higher. - */ -static PFGetFinalPathNameByHandleW get_fpnbyhandle(void) -{ - static PFGetFinalPathNameByHandleW pFunc = NULL; - PFGetFinalPathNameByHandleW toReturn = pFunc; - - if (!toReturn) { - HMODULE hModule = GetModuleHandleW(L"kernel32"); - - if (hModule) - toReturn = (PFGetFinalPathNameByHandleW)GetProcAddress(hModule, "GetFinalPathNameByHandleW"); - - pFunc = toReturn; - } - - assert(toReturn); - - return toReturn; -} - static int getfinalpath_w( git_win32_path dest, const wchar_t *path) { - PFGetFinalPathNameByHandleW pgfp = get_fpnbyhandle(); HANDLE hFile; DWORD dwChars; - if (!pgfp) - return -1; - /* Use FILE_FLAG_BACKUP_SEMANTICS so we can open a directory. Do not * specify FILE_FLAG_OPEN_REPARSE_POINT; we want to open a handle to the * target of the link. */ @@ -642,7 +624,7 @@ static int getfinalpath_w( return -1; /* Call GetFinalPathNameByHandle */ - dwChars = pgfp(hFile, dest, GIT_WIN_PATH_UTF16, FILE_NAME_NORMALIZED); + dwChars = GetFinalPathNameByHandleW(hFile, dest, GIT_WIN_PATH_UTF16, FILE_NAME_NORMALIZED); CloseHandle(hFile); if (!dwChars || dwChars >= GIT_WIN_PATH_UTF16) |
