diff options
author | Nobuyoshi Nakada <nobu@ruby-lang.org> | 2019-08-19 14:34:13 +0900 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-08-19 14:34:13 +0900 |
commit | 574a9edfb3c20165c919d447902d1052165b2132 (patch) | |
tree | 8cf14616e9a6cfb66328addfee295dcae1276a83 /win32 | |
parent | bc1e2271af54087cb3b9e4a0cdceeead56ee3a1a (diff) |
Set flag to allow unprivileged users to create symlinks (#2381)
* [Win32] set flag to allow unprivileged users to create symlinks
Notes
Notes:
Merged-By: nobu <nobu@ruby-lang.org>
Diffstat (limited to 'win32')
-rw-r--r-- | win32/win32.c | 24 |
1 files changed, 22 insertions, 2 deletions
diff --git a/win32/win32.c b/win32/win32.c index 825b42399c..784f9099c7 100644 --- a/win32/win32.c +++ b/win32/win32.c @@ -5177,6 +5177,9 @@ readlink(const char *path, char *buf, size_t bufsize) #ifndef SYMBOLIC_LINK_FLAG_DIRECTORY #define SYMBOLIC_LINK_FLAG_DIRECTORY (0x1) #endif +#ifndef SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE +#define SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE (0x2) +#endif /* License: Ruby's */ static int @@ -5187,10 +5190,12 @@ w32_symlink(UINT cp, const char *src, const char *link) WCHAR *wsrc, *wlink; DWORD flag = 0; BOOLEAN ret; + int e; typedef BOOLEAN (WINAPI *create_symbolic_link_func)(WCHAR*, WCHAR*, DWORD); static create_symbolic_link_func create_symbolic_link = (create_symbolic_link_func)-1; + static DWORD create_flag = SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE; if (create_symbolic_link == (create_symbolic_link_func)-1) { create_symbolic_link = (create_symbolic_link_func) @@ -5201,6 +5206,14 @@ w32_symlink(UINT cp, const char *src, const char *link) return -1; } + if (!*link) { + errno = ENOENT; + return -1; + } + if (!*src) { + errno = EINVAL; + return -1; + } len1 = MultiByteToWideChar(cp, 0, src, -1, NULL, 0); len2 = MultiByteToWideChar(cp, 0, link, -1, NULL, 0); wsrc = ALLOCV_N(WCHAR, buf, len1+len2); @@ -5212,11 +5225,18 @@ w32_symlink(UINT cp, const char *src, const char *link) atts = GetFileAttributesW(wsrc); if (atts != -1 && atts & FILE_ATTRIBUTE_DIRECTORY) flag = SYMBOLIC_LINK_FLAG_DIRECTORY; - ret = create_symbolic_link(wlink, wsrc, flag); + ret = create_symbolic_link(wlink, wsrc, flag |= create_flag); + if (!ret && + (e = GetLastError()) == ERROR_INVALID_PARAMETER && + (flag & SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE)) { + create_flag = 0; + flag &= ~SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE; + ret = create_symbolic_link(wlink, wsrc, flag); + if (!ret) e = GetLastError(); + } ALLOCV_END(buf); if (!ret) { - int e = GetLastError(); errno = map_errno(e); return -1; } |