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