@@ -2012,7 +2012,7 @@ symlink_native (const char *oldpath, path_conv &win32_newpath)
2012
2012
path_conv win32_oldpath;
2013
2013
PUNICODE_STRING final_oldpath, final_newpath;
2014
2014
UNICODE_STRING final_oldpath_buf;
2015
- DWORD flags;
2015
+ DWORD flags = 0 ;
2016
2016
2017
2017
if (resolve_symlink_target (oldpath, win32_newpath, win32_oldpath))
2018
2018
final_oldpath = win32_oldpath.get_nt_native_path ();
@@ -2060,14 +2060,39 @@ symlink_native (const char *oldpath, path_conv &win32_newpath)
2060
2060
wcpcpy (e_old, c_old);
2061
2061
}
2062
2062
}
2063
- /* If the symlink target doesn't exist, don't create native symlink.
2064
- Otherwise the directory flag in the symlink is potentially wrong
2065
- when the target comes into existence, and native tools will fail.
2066
- This is so screwball. This is no problem on AFS, fortunately . */
2067
- if (! win32_oldpath.exists () && ! win32_oldpath.fs_is_afs ())
2063
+
2064
+ /* The directory flag in the symlink must match the target type,
2065
+ otherwise native tools will fail (fortunately this is no problem
2066
+ on AFS). Do our best to guess the symlink type correctly . */
2067
+ if (win32_oldpath.exists () || win32_oldpath.fs_is_afs ())
2068
2068
{
2069
- SetLastError (ERROR_FILE_NOT_FOUND);
2070
- return -1 ;
2069
+ /* If the target exists (or on AFS), check the target type. Note
2070
+ that this may still be wrong if the target is changed after
2071
+ creating the symlink (e.g. in bulk operations such as rsync,
2072
+ unpacking archives or VCS checkouts). */
2073
+ if (win32_oldpath.isdir ())
2074
+ flags |= SYMBOLIC_LINK_FLAG_DIRECTORY;
2075
+ }
2076
+ else
2077
+ {
2078
+ if (allow_winsymlinks == WSYM_nativestrict)
2079
+ {
2080
+ /* In nativestrict mode, if the target does not exist, use
2081
+ trailing '/' in the target path as hint to create a
2082
+ directory symlink. */
2083
+ ssize_t len = strlen (oldpath);
2084
+ if (len && isdirsep (oldpath[len - 1 ]))
2085
+ flags |= SYMBOLIC_LINK_FLAG_DIRECTORY;
2086
+ }
2087
+ else
2088
+ {
2089
+ /* In native mode, if the target does not exist, fall back
2090
+ to creating a Cygwin symlink file (or in case of MSys:
2091
+ try to copy the (non-existing) target, which will of
2092
+ course fail). */
2093
+ SetLastError (ERROR_FILE_NOT_FOUND);
2094
+ return -1 ;
2095
+ }
2071
2096
}
2072
2097
/* Don't allow native symlinks to Cygwin special files. However, the
2073
2098
caller shoud know because this case shouldn't be covered by the
@@ -2096,7 +2121,6 @@ symlink_native (const char *oldpath, path_conv &win32_newpath)
2096
2121
final_oldpath->Buffer [1 ] = L' \\ ' ;
2097
2122
}
2098
2123
/* Try to create native symlink. */
2099
- flags = win32_oldpath.isdir () ? SYMBOLIC_LINK_FLAG_DIRECTORY : 0 ;
2100
2124
if (wincap.has_unprivileged_createsymlink ())
2101
2125
flags |= SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
2102
2126
if (!CreateSymbolicLinkW (final_newpath->Buffer , final_oldpath->Buffer ,
0 commit comments