@@ -1711,6 +1711,7 @@ symlink_native (const char *oldpath, path_conv &win32_newpath)
1711
1711
path_conv win32_oldpath;
1712
1712
PUNICODE_STRING final_oldpath, final_newpath;
1713
1713
UNICODE_STRING final_oldpath_buf;
1714
+ bool isdir;
1714
1715
1715
1716
if (isabspath (oldpath))
1716
1717
{
@@ -1771,14 +1772,37 @@ symlink_native (const char *oldpath, path_conv &win32_newpath)
1771
1772
wcpcpy (e_old, c_old);
1772
1773
}
1773
1774
}
1774
- /* If the symlink target doesn't exist, don't create native symlink.
1775
- Otherwise the directory flag in the symlink is potentially wrong
1776
- when the target comes into existence, and native tools will fail.
1777
- This is so screwball. This is no problem on AFS, fortunately . */
1778
- if (! win32_oldpath.exists () && ! win32_oldpath.fs_is_afs ())
1775
+
1776
+ /* The directory flag in the symlink must match the target type,
1777
+ otherwise native tools will fail (fortunately this is no problem
1778
+ on AFS). Do our best to guess the symlink type correctly . */
1779
+ if (win32_oldpath.exists () || win32_oldpath.fs_is_afs ())
1779
1780
{
1780
- SetLastError (ERROR_FILE_NOT_FOUND);
1781
- return -1 ;
1781
+ /* If the target exists (or on AFS), check the target type. Note
1782
+ that this may still be wrong if the target is changed after
1783
+ creating the symlink (e.g. in bulk operations such as rsync,
1784
+ unpacking archives or VCS checkouts). */
1785
+ isdir = win32_oldpath.isdir ();
1786
+ }
1787
+ else
1788
+ {
1789
+ if (allow_winsymlinks == WSYM_nativestrict)
1790
+ {
1791
+ /* In nativestrict mode, if the target does not exist, use
1792
+ trailing '/' in the target path as hint to create a
1793
+ directory symlink. */
1794
+ ssize_t len = strlen (oldpath);
1795
+ isdir = len && isdirsep (oldpath[len - 1 ]);
1796
+ }
1797
+ else
1798
+ {
1799
+ /* In native mode, if the target does not exist, fall back
1800
+ to creating a Cygwin symlink file (or in case of MSys:
1801
+ try to copy the (non-existing) target, which will of
1802
+ course fail). */
1803
+ SetLastError (ERROR_FILE_NOT_FOUND);
1804
+ return -1 ;
1805
+ }
1782
1806
}
1783
1807
/* Don't allow native symlinks to Cygwin special files. However, the
1784
1808
caller shoud know because this case shouldn't be covered by the
@@ -1809,8 +1833,7 @@ symlink_native (const char *oldpath, path_conv &win32_newpath)
1809
1833
}
1810
1834
/* Try to create native symlink. */
1811
1835
if (!CreateSymbolicLinkW (final_newpath->Buffer , final_oldpath->Buffer ,
1812
- win32_oldpath.isdir ()
1813
- ? SYMBOLIC_LINK_FLAG_DIRECTORY : 0 ))
1836
+ isdir ? SYMBOLIC_LINK_FLAG_DIRECTORY : 0 ))
1814
1837
{
1815
1838
/* Repair native newpath, we still need it. */
1816
1839
final_newpath->Buffer [1 ] = L' ?' ;
0 commit comments