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 24, 2024
1 parent 7cbbc7e commit d9676dc
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
Original file line number Diff line number Diff line change
Expand Up @@ -2758,6 +2758,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
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,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 @@ -220,6 +218,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 d9676dc

Please sign in to comment.