Skip to content

Commit feecd91

Browse files
dschojeremyd2019
authored andcommitted
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 67b9ddd commit feecd91

File tree

4 files changed

+24
-2
lines changed

4 files changed

+24
-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: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2287,6 +2287,9 @@ symlink_worker (const char *oldpath, path_conv &win32_newpath, bool isdevice)
22872287
else if ((wsym_type == WSYM_native || wsym_type == WSYM_nativestrict)
22882288
&& !(win32_newpath.fs_flags () & FILE_SUPPORTS_REPARSE_POINTS))
22892289
wsym_type = WSYM_default;
2290+
else if (wsym_type == WSYM_native_or_deepcopy
2291+
&& !(win32_newpath.fs_flags () & FILE_SUPPORTS_REPARSE_POINTS))
2292+
wsym_type = WSYM_deepcopy;
22902293

22912294
/* Attach .lnk suffix when shortcut is requested. */
22922295
if (wsym_type == WSYM_lnk && !win32_newpath.exists ()
@@ -2319,6 +2322,7 @@ symlink_worker (const char *oldpath, path_conv &win32_newpath, bool isdevice)
23192322
res = symlink_nfs (oldpath, win32_newpath);
23202323
__leave;
23212324
case WSYM_deepcopy:
2325+
case_WSYM_deepcopy:
23222326
res = symlink_deepcopy (oldpath, win32_newpath);
23232327
if (!res || res == -1)
23242328
__leave;
@@ -2327,6 +2331,7 @@ symlink_worker (const char *oldpath, path_conv &win32_newpath, bool isdevice)
23272331
break;
23282332
case WSYM_native:
23292333
case WSYM_nativestrict:
2334+
case WSYM_native_or_deepcopy:
23302335
res = symlink_native (oldpath, win32_newpath);
23312336
if (!res)
23322337
__leave;
@@ -2337,6 +2342,12 @@ symlink_worker (const char *oldpath, path_conv &win32_newpath, bool isdevice)
23372342
__seterrno ();
23382343
__leave;
23392344
}
2345+
/* With deepcopy fall back? Let's do that, then */
2346+
if (res == -1 && wsym_type == WSYM_native_or_deepcopy)
2347+
{
2348+
wsym_type = WSYM_deepcopy;
2349+
goto case_WSYM_deepcopy;
2350+
}
23402351
/* Otherwise, fall back to default symlink type. */
23412352
wsym_type = WSYM_default;
23422353
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)