diff options
Diffstat (limited to 'win32')
-rw-r--r-- | win32/mingw.c | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/win32/mingw.c b/win32/mingw.c index 41dba9857..a6362333d 100644 --- a/win32/mingw.c +++ b/win32/mingw.c | |||
@@ -1063,6 +1063,41 @@ int link(const char *oldpath, const char *newpath) | |||
1063 | return 0; | 1063 | return 0; |
1064 | } | 1064 | } |
1065 | 1065 | ||
1066 | #ifndef SYMBOLIC_LINK_FLAG_DIRECTORY | ||
1067 | # define SYMBOLIC_LINK_FLAG_DIRECTORY (0x1) | ||
1068 | #endif | ||
1069 | #ifndef SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE | ||
1070 | # define SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE (0x2) | ||
1071 | #endif | ||
1072 | |||
1073 | int symlink(const char *target, const char *linkpath) | ||
1074 | { | ||
1075 | DWORD flag = SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE; | ||
1076 | struct stat st; | ||
1077 | DECLARE_PROC_ADDR(BOOL, CreateSymbolicLinkA, LPCSTR, LPCSTR, DWORD); | ||
1078 | |||
1079 | if (!INIT_PROC_ADDR(kernel32.dll, CreateSymbolicLinkA)) { | ||
1080 | return -1; | ||
1081 | } | ||
1082 | |||
1083 | if (stat(target, &st) != -1 && S_ISDIR(st.st_mode)) | ||
1084 | flag |= SYMBOLIC_LINK_FLAG_DIRECTORY; | ||
1085 | |||
1086 | retry: | ||
1087 | if (!CreateSymbolicLinkA(linkpath, target, flag)) { | ||
1088 | /* Old Windows versions see 'UNPRIVILEGED_CREATE' as an invalid | ||
1089 | * parameter. Retry without it. */ | ||
1090 | if ((flag & SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE) && | ||
1091 | GetLastError() == ERROR_INVALID_PARAMETER) { | ||
1092 | flag &= ~SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE; | ||
1093 | goto retry; | ||
1094 | } | ||
1095 | errno = err_win_to_posix(); | ||
1096 | return -1; | ||
1097 | } | ||
1098 | return 0; | ||
1099 | } | ||
1100 | |||
1066 | static char *normalize_ntpathA(char *buf) | 1101 | static char *normalize_ntpathA(char *buf) |
1067 | { | 1102 | { |
1068 | /* fix absolute path prefixes */ | 1103 | /* fix absolute path prefixes */ |