@@ -1693,6 +1693,7 @@ symlink_native (const char *oldpath, path_conv &win32_newpath)
1693
1693
path_conv win32_oldpath;
1694
1694
PUNICODE_STRING final_oldpath, final_newpath;
1695
1695
UNICODE_STRING final_oldpath_buf;
1696
+ bool isdir;
1696
1697
1697
1698
if (isabspath (oldpath))
1698
1699
{
@@ -1753,14 +1754,37 @@ symlink_native (const char *oldpath, path_conv &win32_newpath)
1753
1754
wcpcpy (e_old, c_old);
1754
1755
}
1755
1756
}
1756
- /* If the symlink target doesn't exist, don't create native symlink.
1757
- Otherwise the directory flag in the symlink is potentially wrong
1758
- when the target comes into existence, and native tools will fail.
1759
- This is so screwball. This is no problem on AFS, fortunately . */
1760
- if (! win32_oldpath.exists () && ! win32_oldpath.fs_is_afs ())
1757
+
1758
+ /* The directory flag in the symlink must match the target type,
1759
+ otherwise native tools will fail (fortunately this is no problem
1760
+ on AFS). Do our best to guess the symlink type correctly . */
1761
+ if (win32_oldpath.exists () || win32_oldpath.fs_is_afs ())
1761
1762
{
1762
- SetLastError (ERROR_FILE_NOT_FOUND);
1763
- return -1 ;
1763
+ /* If the target exists (or on AFS), check the target type. Note
1764
+ that this may still be wrong if the target is changed after
1765
+ creating the symlink (e.g. in bulk operations such as rsync,
1766
+ unpacking archives or VCS checkouts). */
1767
+ isdir = win32_oldpath.isdir ();
1768
+ }
1769
+ else
1770
+ {
1771
+ if (allow_winsymlinks == WSYM_nativestrict)
1772
+ {
1773
+ /* In nativestrict mode, if the target does not exist, use
1774
+ trailing '/' in the target path as hint to create a
1775
+ directory symlink. */
1776
+ ssize_t len = strlen (oldpath);
1777
+ isdir = len && isdirsep (oldpath[len - 1 ]);
1778
+ }
1779
+ else
1780
+ {
1781
+ /* In native mode, if the target does not exist, fall back
1782
+ to creating a Cygwin symlink file (or in case of MSys:
1783
+ try to copy the (non-existing) target, which will of
1784
+ course fail). */
1785
+ SetLastError (ERROR_FILE_NOT_FOUND);
1786
+ return -1 ;
1787
+ }
1764
1788
}
1765
1789
/* Don't allow native symlinks to Cygwin special files. However, the
1766
1790
caller shoud know because this case shouldn't be covered by the
@@ -1791,8 +1815,7 @@ symlink_native (const char *oldpath, path_conv &win32_newpath)
1791
1815
}
1792
1816
/* Try to create native symlink. */
1793
1817
if (!CreateSymbolicLinkW (final_newpath->Buffer , final_oldpath->Buffer ,
1794
- win32_oldpath.isdir ()
1795
- ? SYMBOLIC_LINK_FLAG_DIRECTORY : 0 ))
1818
+ isdir ? SYMBOLIC_LINK_FLAG_DIRECTORY : 0 ))
1796
1819
{
1797
1820
/* Repair native newpath, we still need it. */
1798
1821
final_newpath->Buffer [1 ] = L' ?' ;
0 commit comments