From 7e31d976faa8cc099632207ee911bc3d0fdc1a16 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 d9b000b2..3083e73c 100644 --- a/cmdline/mingw.c +++ b/cmdline/mingw.c @@ -1777,7 +1777,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]; @@ -1789,7 +1789,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) { @@ -1798,7 +1798,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; } @@ -1807,6 +1807,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 1ea1f4a4..6efd8842 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(). */