Skip to content

Commit eb56d3b

Browse files
kbleesdscho
authored andcommitted
Win32: implement basic symlink() functionality (file symlinks only)
Implement symlink() that always creates file symlinks. Fails with ENOSYS if symlinks are disabled or unsupported. Note: CreateSymbolicLinkW() was introduced with symlink support in Windows Vista. For compatibility with Windows XP, we need to load it dynamically and fail gracefully if it isnt's available. Signed-off-by: Karsten Blees <[email protected]>
1 parent 1419746 commit eb56d3b

File tree

2 files changed

+29
-2
lines changed

2 files changed

+29
-2
lines changed

compat/mingw.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2203,6 +2203,34 @@ int link(const char *oldpath, const char *newpath)
22032203
return 0;
22042204
}
22052205

2206+
int symlink(const char *target, const char *link)
2207+
{
2208+
wchar_t wtarget[MAX_LONG_PATH], wlink[MAX_LONG_PATH];
2209+
int len;
2210+
2211+
/* fail if symlinks are disabled or API is not supported (WinXP) */
2212+
if (!has_symlinks) {
2213+
errno = ENOSYS;
2214+
return -1;
2215+
}
2216+
2217+
if ((len = xutftowcs_long_path(wtarget, target)) < 0
2218+
|| xutftowcs_long_path(wlink, link) < 0)
2219+
return -1;
2220+
2221+
/* convert target dir separators to backslashes */
2222+
while (len--)
2223+
if (wtarget[len] == '/')
2224+
wtarget[len] = '\\';
2225+
2226+
/* create file symlink */
2227+
if (!CreateSymbolicLinkW(wlink, wtarget, 0)) {
2228+
errno = err_win_to_posix(GetLastError());
2229+
return -1;
2230+
}
2231+
return 0;
2232+
}
2233+
22062234
#ifndef _WINNT_H
22072235
/*
22082236
* The REPARSE_DATA_BUFFER structure is defined in the Windows DDK (in

compat/mingw.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,8 +142,6 @@ struct utsname {
142142
* trivial stubs
143143
*/
144144

145-
static inline int symlink(const char *oldpath, const char *newpath)
146-
{ errno = ENOSYS; return -1; }
147145
static inline int fchmod(int fildes, mode_t mode)
148146
{ errno = ENOSYS; return -1; }
149147
#ifndef __MINGW64_VERSION_MAJOR
@@ -235,6 +233,7 @@ int setitimer(int type, struct itimerval *in, struct itimerval *out);
235233
int sigaction(int sig, struct sigaction *in, struct sigaction *out);
236234
int link(const char *oldpath, const char *newpath);
237235
int uname(struct utsname *buf);
236+
int symlink(const char *target, const char *link);
238237
int readlink(const char *path, char *buf, size_t bufsiz);
239238

240239
/*

0 commit comments

Comments
 (0)