From f0d57f807eb7c80874bd2a767534caae1f0a2deb Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Mon, 7 Nov 2022 11:40:52 +0100 Subject: [PATCH 1/2] fixup! Instead of creating Cygwin symlinks, use deep copy by default This adds the missing documentation (in case we ever publish the information about the MSYS variable on msys2.org). Signed-off-by: Johannes Schindelin --- winsup/doc/cygwinenv.xml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/winsup/doc/cygwinenv.xml b/winsup/doc/cygwinenv.xml index 4ea63b407a..c4e9f3f9e7 100644 --- a/winsup/doc/cygwinenv.xml +++ b/winsup/doc/cygwinenv.xml @@ -104,7 +104,7 @@ back to the parent process. -winsymlinks:{lnk,native,nativestrict,sys} +winsymlinks:{lnk,native,nativestrict,sys,deepcopy} @@ -133,6 +133,14 @@ system call will immediately fail. plain files with the system attribute, containing a magic cookie followed by the path to which the link points. + + +If set to winsymlinks:deepcopy, a copy of the source +will be created at the target (a "deep" copy in the case of directories, i.e. +the source directory will be copied recursively). This mode makes a trade-off +between compatibility and interoperability with Win32 programs, favoring the +latter. + Note that this setting has no effect where Cygwin knows that the From b8e842ec649f473fc6ab3e06b07cd9a751fda626 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Mon, 7 Nov 2022 11:41:48 +0100 Subject: [PATCH 2/2] winsymlinks: add a mode preferring native symlinks with a deepcopy fallback When native symlinks are available, it is a shame to create deep copies by default. However, since there are many scenarios where symlinks are not available (e.g. when running on FAT, or on older Windows versions, or when Developer Mode is not enabled), we've got to have a fallback. In the regular Cygwin world, it is legitimate to fall back to WSL symlinks and/or to the system file emulation (where a file is created that is marked with the "system" attribute and with content that adheres to a specific, magic form that is recognized specifically by the Cygwin runtime). However, in the world of MSYS2, the assumption is that the result of the operation should be as interoperable with regular Win32 programs as possible. Hence the default to "deepcopy". As a "best of both worlds" mode, let's implement one that tries to create native symlinks by default, and if that fails, uses the "deepcopy" method as a fallback. This addresses https://github.com/msys2/msys2-runtime/issues/113. Signed-off-by: Johannes Schindelin --- winsup/cygwin/environ.cc | 2 ++ winsup/cygwin/globals.cc | 3 ++- winsup/cygwin/path.cc | 10 ++++++++++ winsup/doc/cygwinenv.xml | 10 +++++++++- 4 files changed, 23 insertions(+), 2 deletions(-) diff --git a/winsup/cygwin/environ.cc b/winsup/cygwin/environ.cc index 4e049211e9..955684e232 100644 --- a/winsup/cygwin/environ.cc +++ b/winsup/cygwin/environ.cc @@ -92,6 +92,8 @@ set_winsymlinks (const char *buf) ? WSYM_nativestrict : WSYM_native; else if (ascii_strncasematch (buf, "deepcopy", 8)) allow_winsymlinks = WSYM_deepcopy; + else if (ascii_strncasematch (buf, "nativeordeepcopy", 8)) + allow_winsymlinks = WSYM_native_or_deepcopy; else allow_winsymlinks = WSYM_sysfile; } diff --git a/winsup/cygwin/globals.cc b/winsup/cygwin/globals.cc index ab2c205609..f05bdb753e 100644 --- a/winsup/cygwin/globals.cc +++ b/winsup/cygwin/globals.cc @@ -57,7 +57,8 @@ enum winsym_t WSYM_nativestrict, WSYM_nfs, WSYM_sysfile, - WSYM_deepcopy + WSYM_deepcopy, + WSYM_native_or_deepcopy }; exit_states NO_COPY exit_state; diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc index 8806e59c7d..0d912e26a3 100644 --- a/winsup/cygwin/path.cc +++ b/winsup/cygwin/path.cc @@ -2110,6 +2110,9 @@ symlink_worker (const char *oldpath, path_conv &win32_newpath, bool isdevice) else if ((wsym_type == WSYM_native || wsym_type == WSYM_nativestrict) && !(win32_newpath.fs_flags () & FILE_SUPPORTS_REPARSE_POINTS)) wsym_type = WSYM_default; + else if (wsym_type == WSYM_native_or_deepcopy + && !(win32_newpath.fs_flags () & FILE_SUPPORTS_REPARSE_POINTS)) + wsym_type = WSYM_deepcopy; /* Attach .lnk suffix when shortcut is requested. */ if (wsym_type == WSYM_lnk && !win32_newpath.exists () @@ -2144,6 +2147,7 @@ symlink_worker (const char *oldpath, path_conv &win32_newpath, bool isdevice) __leave; case WSYM_native: case WSYM_nativestrict: + case WSYM_native_or_deepcopy: res = symlink_native (oldpath, win32_newpath); if (!res) __leave; @@ -2154,6 +2158,12 @@ symlink_worker (const char *oldpath, path_conv &win32_newpath, bool isdevice) __seterrno (); __leave; } + /* With deepcopy fall back? Let's do that, then */ + if (res == -1 && wsym_type == WSYM_native_or_deepcopy) + { + wsym_type = WSYM_deepcopy; + break; + } /* Otherwise, fall back to default symlink type. */ wsym_type = WSYM_default; fallthrough; diff --git a/winsup/doc/cygwinenv.xml b/winsup/doc/cygwinenv.xml index c4e9f3f9e7..754a9c1cfb 100644 --- a/winsup/doc/cygwinenv.xml +++ b/winsup/doc/cygwinenv.xml @@ -104,7 +104,7 @@ back to the parent process. -winsymlinks:{lnk,native,nativestrict,sys,deepcopy} +winsymlinks:{lnk,native,nativestrict,sys,deepcopy,nativeordeepcopy} @@ -141,6 +141,14 @@ the source directory will be copied recursively). This mode makes a trade-off between compatibility and interoperability with Win32 programs, favoring the latter. + + +If set to winsymlinks:nativeordeepcopy Cygwin creates +symlinks as native Windows symlinks if supported (i.e. on file systems +supporting symbolic links, and when the current user is permitted to create +symbolic links, e.g. in Windows 10's "Developer Mode"), and fall back to +creating a deep copy in case symlinks are not supported. + Note that this setting has no effect where Cygwin knows that the