Skip to content

Commit 1dd5f9d

Browse files
kbleesdscho
authored andcommitted
mingw: implement basic symlink() functionality (file symlinks only)
Implement `symlink()`. This implementation always creates _file_ symlinks (remember: Windows discerns between symlinks pointing to directories and those pointing to files). Support for directory symlinks will be added in a subseqeuent commit. This implementation fails with `ENOSYS` if symlinks are disabled or unsupported. Signed-off-by: Karsten Blees <blees@dcon.de> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
1 parent 8fef822 commit 1dd5f9d

File tree

2 files changed

+29
-2
lines changed

2 files changed

+29
-2
lines changed

compat/mingw-posix.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,8 +121,6 @@ struct utsname {
121121
* trivial stubs
122122
*/
123123

124-
static inline int symlink(const char *oldpath UNUSED, const char *newpath UNUSED)
125-
{ errno = ENOSYS; return -1; }
126124
static inline int fchmod(int fildes UNUSED, mode_t mode UNUSED)
127125
{ errno = ENOSYS; return -1; }
128126
#ifndef __MINGW64_VERSION_MAJOR
@@ -195,6 +193,7 @@ int setitimer(int type, struct itimerval *in, struct itimerval *out);
195193
int sigaction(int sig, struct sigaction *in, struct sigaction *out);
196194
int link(const char *oldpath, const char *newpath);
197195
int uname(struct utsname *buf);
196+
int symlink(const char *target, const char *link);
198197
int readlink(const char *path, char *buf, size_t bufsiz);
199198

200199
/*

compat/mingw.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2698,6 +2698,34 @@ int link(const char *oldpath, const char *newpath)
26982698
return 0;
26992699
}
27002700

2701+
int symlink(const char *target, const char *link)
2702+
{
2703+
wchar_t wtarget[MAX_PATH], wlink[MAX_PATH];
2704+
int len;
2705+
2706+
/* fail if symlinks are disabled or API is not supported (WinXP) */
2707+
if (!has_symlinks) {
2708+
errno = ENOSYS;
2709+
return -1;
2710+
}
2711+
2712+
if ((len = xutftowcs_path(wtarget, target)) < 0
2713+
|| xutftowcs_path(wlink, link) < 0)
2714+
return -1;
2715+
2716+
/* convert target dir separators to backslashes */
2717+
while (len--)
2718+
if (wtarget[len] == '/')
2719+
wtarget[len] = '\\';
2720+
2721+
/* create file symlink */
2722+
if (!CreateSymbolicLinkW(wlink, wtarget, 0)) {
2723+
errno = err_win_to_posix(GetLastError());
2724+
return -1;
2725+
}
2726+
return 0;
2727+
}
2728+
27012729
int readlink(const char *path, char *buf, size_t bufsiz)
27022730
{
27032731
WCHAR wpath[MAX_PATH];

0 commit comments

Comments
 (0)