Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement a winsymlinks mode that prefers native symlinks, falling back to the deep copy mode #114

Open
wants to merge 2 commits into
base: msys2-3.5.3
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions winsup/cygwin/environ.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
3 changes: 2 additions & 1 deletion winsup/cygwin/globals.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
10 changes: 10 additions & 0 deletions winsup/cygwin/path.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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 ()
Expand Down Expand Up @@ -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;
Expand All @@ -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)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that if target isspecial res will be -2, so will still fall back to default. This is probably reasonable, since deepcopy would just fall back to sysfile in that case. default will let it try wsl before falling back to sysfile. I'm thinking it might be best to make deepcopy fall back to default instead of sysfile anyway.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

making deepcopy fall back to wsl instead of sysfile breaks one git test which tries to commit a symlink to /dev/null. The result of doing so is almost certainly not helpful (I bet it commits the sysfile, not a symlink), but when it's a wsl symlink it fails with Function not implemented

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

when it's a wsl symlink it fails with Function not implemented

That's my fault, as I have not managed to spend time on upstreaming Git for Windows' symlink support: git/git@master...dscho:git:support-symlinks-on-windows

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had a quick look at those changes, and I didn't see any handling of wsl symlinks in there, so I don't think that would help.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Huh. I misremembered. A git grep IO_REPARSE_TAG_LX_SYMLINK indeed comes up empty...

{
wsym_type = WSYM_deepcopy;
break;
}
/* Otherwise, fall back to default symlink type. */
wsym_type = WSYM_default;
fallthrough;
Expand Down
18 changes: 17 additions & 1 deletion winsup/doc/cygwinenv.xml
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ back to the parent process.</para>
</listitem>

<listitem>
<para><envar>winsymlinks:{lnk,native,nativestrict,sys}</envar></para>
<para><envar>winsymlinks:{lnk,native,nativestrict,sys,deepcopy,nativeordeepcopy}</envar></para>

<itemizedlist mark="square">
<listitem>
Expand Down Expand Up @@ -133,6 +133,22 @@ system call will immediately fail.</para>
plain files with the <literal>system</literal> attribute, containing a magic
cookie followed by the path to which the link points.</para>
</listitem>

<listitem>
<para>If set to <literal>winsymlinks:deepcopy</literal>, 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.</para>
</listitem>

<listitem>
<para>If set to <literal>winsymlinks:nativeordeepcopy</literal> 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.</para>
</listitem>
</itemizedlist>

<para>Note that this setting has no effect where Cygwin knows that the
Expand Down
Loading