@@ -1720,7 +1720,7 @@ symlink_native (const char *oldpath, path_conv &win32_newpath)
1720
1720
path_conv win32_oldpath;
1721
1721
PUNICODE_STRING final_oldpath, final_newpath;
1722
1722
UNICODE_STRING final_oldpath_buf;
1723
- DWORD flags;
1723
+ DWORD flags = 0 ;
1724
1724
1725
1725
if (isabspath (oldpath))
1726
1726
{
@@ -1781,14 +1781,39 @@ symlink_native (const char *oldpath, path_conv &win32_newpath)
1781
1781
wcpcpy (e_old, c_old);
1782
1782
}
1783
1783
}
1784
- /* If the symlink target doesn't exist, don't create native symlink.
1785
- Otherwise the directory flag in the symlink is potentially wrong
1786
- when the target comes into existence, and native tools will fail.
1787
- This is so screwball. This is no problem on AFS, fortunately . */
1788
- if (! win32_oldpath.exists () && ! win32_oldpath.fs_is_afs ())
1784
+
1785
+ /* The directory flag in the symlink must match the target type,
1786
+ otherwise native tools will fail (fortunately this is no problem
1787
+ on AFS). Do our best to guess the symlink type correctly . */
1788
+ if (win32_oldpath.exists () || win32_oldpath.fs_is_afs ())
1789
1789
{
1790
- SetLastError (ERROR_FILE_NOT_FOUND);
1791
- return -1 ;
1790
+ /* If the target exists (or on AFS), check the target type. Note
1791
+ that this may still be wrong if the target is changed after
1792
+ creating the symlink (e.g. in bulk operations such as rsync,
1793
+ unpacking archives or VCS checkouts). */
1794
+ if (win32_oldpath.isdir ())
1795
+ flags |= SYMBOLIC_LINK_FLAG_DIRECTORY;
1796
+ }
1797
+ else
1798
+ {
1799
+ if (allow_winsymlinks == WSYM_nativestrict)
1800
+ {
1801
+ /* In nativestrict mode, if the target does not exist, use
1802
+ trailing '/' in the target path as hint to create a
1803
+ directory symlink. */
1804
+ ssize_t len = strlen (oldpath);
1805
+ if (len && isdirsep (oldpath[len - 1 ]))
1806
+ flags |= SYMBOLIC_LINK_FLAG_DIRECTORY;
1807
+ }
1808
+ else
1809
+ {
1810
+ /* In native mode, if the target does not exist, fall back
1811
+ to creating a Cygwin symlink file (or in case of MSys:
1812
+ try to copy the (non-existing) target, which will of
1813
+ course fail). */
1814
+ SetLastError (ERROR_FILE_NOT_FOUND);
1815
+ return -1 ;
1816
+ }
1792
1817
}
1793
1818
/* Don't allow native symlinks to Cygwin special files. However, the
1794
1819
caller shoud know because this case shouldn't be covered by the
@@ -1817,7 +1842,6 @@ symlink_native (const char *oldpath, path_conv &win32_newpath)
1817
1842
final_oldpath->Buffer [1 ] = L' \\ ' ;
1818
1843
}
1819
1844
/* Try to create native symlink. */
1820
- flags = win32_oldpath.isdir () ? SYMBOLIC_LINK_FLAG_DIRECTORY : 0 ;
1821
1845
if (wincap.has_unprivileged_createsymlink ())
1822
1846
flags |= SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
1823
1847
if (!CreateSymbolicLinkW (final_newpath->Buffer , final_oldpath->Buffer ,
0 commit comments