From 574a9edfb3c20165c919d447902d1052165b2132 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Mon, 19 Aug 2019 14:34:13 +0900 Subject: Set flag to allow unprivileged users to create symlinks (#2381) * [Win32] set flag to allow unprivileged users to create symlinks --- win32/win32.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) (limited to 'win32') 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; } -- cgit v1.2.3