From 38f78154f9ebecd595aaf561b3cd389a085806c0 Mon Sep 17 00:00:00 2001 From: Andrea Mazzoleni Date: Fri, 8 May 2026 09:05:47 +0200 Subject: [PATCH] Add Windows support for symlink of directories --- cmdline/mingw.c | 16 +++++++++++++--- cmdline/mingw.h | 6 ++++++ 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/cmdline/mingw.c b/cmdline/mingw.c index 77e02930..0c2b402e 100644 --- a/cmdline/mingw.c +++ b/cmdline/mingw.c @@ -1802,7 +1802,7 @@ int windows_link(const char* existing, const char* file) #define SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE 0x2 #endif -int windows_symlink(const char* existing, const char* file) +static int windows_symlink_flags(const char* existing, const char* file, DWORD flags) { wchar_t conv_buf_file[CONV_MAX]; wchar_t conv_buf_existing[CONV_MAX]; @@ -1814,7 +1814,7 @@ int windows_symlink(const char* existing, const char* file) * user symlinks different than they were before */ if (!CreateSymbolicLinkW(convert(conv_buf_file, file), convert_if_required(conv_buf_existing, existing), - SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE) + flags | SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE) ) { DWORD error = GetLastError(); if (GetLastError() != ERROR_INVALID_PARAMETER) { @@ -1823,7 +1823,7 @@ int windows_symlink(const char* existing, const char* file) } /* retry without the new flag SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE */ - if (!CreateSymbolicLinkW(convert(conv_buf_file, file), convert_if_required(conv_buf_existing, existing), 0)) { + if (!CreateSymbolicLinkW(convert(conv_buf_file, file), convert_if_required(conv_buf_existing, existing), flags)) { windows_errno(GetLastError()); return -1; } @@ -1832,6 +1832,16 @@ int windows_symlink(const char* existing, const char* file) return 0; } +int windows_symlink(const char* existing, const char* file) +{ + return windows_symlink_flags(existing, file, 0); +} + +int windows_symlink_directory(const char* existing, const char* file) +{ + return windows_symlink_flags(existing, file, SYMBOLIC_LINK_FLAG_DIRECTORY); +} + /* Adds missing definitions in MingW winnt.h */ #ifndef FSCTL_GET_REPARSE_POINT #define FSCTL_GET_REPARSE_POINT 0x000900a8 diff --git a/cmdline/mingw.h b/cmdline/mingw.h index 3b0f1f9a..b1ac26a1 100644 --- a/cmdline/mingw.h +++ b/cmdline/mingw.h @@ -341,6 +341,12 @@ int windows_readlink(const char* file, char* buffer, size_t size); */ int windows_symlink(const char* existing, const char* file); +/** + * Like symlink(). + * Return ENOSYS if symlinks are not supported. + */ +int windows_symlink_directory(const char* existing, const char* file); + /** * Like link(). */