Skip to content

Commit b8e842e

Browse files
committed
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 #113. Signed-off-by: Johannes Schindelin <[email protected]>
1 parent f0d57f8 commit b8e842e

File tree

4 files changed

+23
-2
lines changed

4 files changed

+23
-2
lines changed

winsup/cygwin/environ.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,8 @@ set_winsymlinks (const char *buf)
9292
? WSYM_nativestrict : WSYM_native;
9393
else if (ascii_strncasematch (buf, "deepcopy", 8))
9494
allow_winsymlinks = WSYM_deepcopy;
95+
else if (ascii_strncasematch (buf, "nativeordeepcopy", 8))
96+
allow_winsymlinks = WSYM_native_or_deepcopy;
9597
else
9698
allow_winsymlinks = WSYM_sysfile;
9799
}

winsup/cygwin/globals.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,8 @@ enum winsym_t
5757
WSYM_nativestrict,
5858
WSYM_nfs,
5959
WSYM_sysfile,
60-
WSYM_deepcopy
60+
WSYM_deepcopy,
61+
WSYM_native_or_deepcopy
6162
};
6263

6364
exit_states NO_COPY exit_state;

winsup/cygwin/path.cc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2110,6 +2110,9 @@ symlink_worker (const char *oldpath, path_conv &win32_newpath, bool isdevice)
21102110
else if ((wsym_type == WSYM_native || wsym_type == WSYM_nativestrict)
21112111
&& !(win32_newpath.fs_flags () & FILE_SUPPORTS_REPARSE_POINTS))
21122112
wsym_type = WSYM_default;
2113+
else if (wsym_type == WSYM_native_or_deepcopy
2114+
&& !(win32_newpath.fs_flags () & FILE_SUPPORTS_REPARSE_POINTS))
2115+
wsym_type = WSYM_deepcopy;
21132116

21142117
/* Attach .lnk suffix when shortcut is requested. */
21152118
if (wsym_type == WSYM_lnk && !win32_newpath.exists ()
@@ -2144,6 +2147,7 @@ symlink_worker (const char *oldpath, path_conv &win32_newpath, bool isdevice)
21442147
__leave;
21452148
case WSYM_native:
21462149
case WSYM_nativestrict:
2150+
case WSYM_native_or_deepcopy:
21472151
res = symlink_native (oldpath, win32_newpath);
21482152
if (!res)
21492153
__leave;
@@ -2154,6 +2158,12 @@ symlink_worker (const char *oldpath, path_conv &win32_newpath, bool isdevice)
21542158
__seterrno ();
21552159
__leave;
21562160
}
2161+
/* With deepcopy fall back? Let's do that, then */
2162+
if (res == -1 && wsym_type == WSYM_native_or_deepcopy)
2163+
{
2164+
wsym_type = WSYM_deepcopy;
2165+
break;
2166+
}
21572167
/* Otherwise, fall back to default symlink type. */
21582168
wsym_type = WSYM_default;
21592169
fallthrough;

winsup/doc/cygwinenv.xml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ back to the parent process.</para>
104104
</listitem>
105105

106106
<listitem>
107-
<para><envar>winsymlinks:{lnk,native,nativestrict,sys,deepcopy}</envar></para>
107+
<para><envar>winsymlinks:{lnk,native,nativestrict,sys,deepcopy,nativeordeepcopy}</envar></para>
108108

109109
<itemizedlist mark="square">
110110
<listitem>
@@ -141,6 +141,14 @@ the source directory will be copied recursively). This mode makes a trade-off
141141
between compatibility and interoperability with Win32 programs, favoring the
142142
latter.</para>
143143
</listitem>
144+
145+
<listitem>
146+
<para>If set to <literal>winsymlinks:nativeordeepcopy</literal> Cygwin creates
147+
symlinks as native Windows symlinks if supported (i.e. on file systems
148+
supporting symbolic links, and when the current user is permitted to create
149+
symbolic links, e.g. in Windows 10's "Developer Mode"), and fall back to
150+
creating a deep copy in case symlinks are not supported.</para>
151+
</listitem>
144152
</itemizedlist>
145153

146154
<para>Note that this setting has no effect where Cygwin knows that the

0 commit comments

Comments
 (0)