Skip to content

Commit

Permalink
Win32: implement basic symlink() functionality (file symlinks only)
Browse files Browse the repository at this point in the history
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 <blees@dcon.de>
  • Loading branch information
kblees authored and dscho committed Sep 22, 2022
1 parent 628e191 commit 2fa7c31
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 2 deletions.
28 changes: 28 additions & 0 deletions compat/mingw.c
Expand Up @@ -2694,6 +2694,34 @@ int link(const char *oldpath, const char *newpath)
return 0;
}

int symlink(const char *target, const char *link)
{
wchar_t wtarget[MAX_LONG_PATH], wlink[MAX_LONG_PATH];
int len;

/* fail if symlinks are disabled or API is not supported (WinXP) */
if (!has_symlinks) {
errno = ENOSYS;
return -1;
}

if ((len = xutftowcs_long_path(wtarget, target)) < 0
|| xutftowcs_long_path(wlink, link) < 0)
return -1;

/* convert target dir separators to backslashes */
while (len--)
if (wtarget[len] == '/')
wtarget[len] = '\\';

/* create file symlink */
if (!CreateSymbolicLinkW(wlink, wtarget, 0)) {
errno = err_win_to_posix(GetLastError());
return -1;
}
return 0;
}

#ifndef _WINNT_H
/*
* The REPARSE_DATA_BUFFER structure is defined in the Windows DDK (in
Expand Down
3 changes: 1 addition & 2 deletions compat/mingw.h
Expand Up @@ -123,8 +123,6 @@ struct utsname {
* trivial stubs
*/

static inline int symlink(const char *oldpath, const char *newpath)
{ errno = ENOSYS; return -1; }
static inline int fchmod(int fildes, mode_t mode)
{ errno = ENOSYS; return -1; }
#ifndef __MINGW64_VERSION_MAJOR
Expand Down Expand Up @@ -215,6 +213,7 @@ int setitimer(int type, struct itimerval *in, struct itimerval *out);
int sigaction(int sig, struct sigaction *in, struct sigaction *out);
int link(const char *oldpath, const char *newpath);
int uname(struct utsname *buf);
int symlink(const char *target, const char *link);
int readlink(const char *path, char *buf, size_t bufsiz);

/*
Expand Down

0 comments on commit 2fa7c31

Please sign in to comment.