Skip to content

Commit acae65f

Browse files
committed
fixup! Instead of creating Cygwin symlinks, use deep copy by default
Factor out deepcopy symlink to its own worker function, like wsl, native, and nfs. Move it up into the beginning switch with them, so the fallback behavior is more obvious. See also msys2#113/msys2#114.
1 parent f8b54d0 commit acae65f

File tree

1 file changed

+81
-72
lines changed

1 file changed

+81
-72
lines changed

winsup/cygwin/path.cc

Lines changed: 81 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -2156,6 +2156,78 @@ symlink_wsl (const char *oldpath, path_conv &win32_newpath)
21562156
return 0;
21572157
}
21582158

2159+
int
2160+
symlink_deepcopy (const char *oldpath, path_conv &win32_newpath)
2161+
{
2162+
path_conv win32_oldpath;
2163+
/* The symlink target is relative to the directory in which the
2164+
symlink gets created, not relative to the cwd. Therefore we
2165+
have to mangle the path quite a bit before calling path_conv.*/
2166+
mangle_symlink_target (oldpath, win32_newpath, win32_oldpath);
2167+
if (win32_oldpath.error)
2168+
{
2169+
set_errno (win32_oldpath.error);
2170+
return -1;
2171+
}
2172+
if (win32_oldpath.isspecial ())
2173+
return -2;
2174+
2175+
/* MSYS copy file instead make symlink */
2176+
/* As a MSYS limitation, the source path must exist. */
2177+
if (!win32_oldpath.exists ())
2178+
{
2179+
set_errno (ENOENT);
2180+
return -1;
2181+
}
2182+
2183+
PUNICODE_STRING w_oldpath = win32_oldpath.get_nt_native_path ();
2184+
PUNICODE_STRING w_newpath = win32_newpath.get_nt_native_path ();
2185+
if (w_oldpath->Buffer[1] == L'?')
2186+
w_oldpath->Buffer[1] = L'\\';
2187+
if (w_newpath->Buffer[1] == L'?')
2188+
w_newpath->Buffer[1] = L'\\';
2189+
if (win32_oldpath.isdir ())
2190+
{
2191+
tmp_pathbuf tp;
2192+
/* we need a larger UNICODE_STRING MaximumLength than
2193+
get_nt_native_path allocates for the recursive copy */
2194+
UNICODE_STRING u_oldpath, u_newpath;
2195+
RtlCopyUnicodeString (tp.u_get (&u_oldpath), w_oldpath);
2196+
RtlCopyUnicodeString (tp.u_get (&u_newpath), w_newpath);
2197+
return recursiveCopy (&u_oldpath, &u_newpath,
2198+
u_oldpath.Length, u_newpath.Length);
2199+
}
2200+
else
2201+
{
2202+
bool isdirlink = false;
2203+
if (win32_oldpath.issymlink () &&
2204+
win32_oldpath.is_known_reparse_point ())
2205+
{
2206+
/* Is there a better way to know this? */
2207+
DWORD attr = getfileattr (win32_oldpath.get_win32 (),
2208+
!!win32_oldpath.objcaseinsensitive ());
2209+
if (attr == INVALID_FILE_ATTRIBUTES)
2210+
{
2211+
__seterrno ();
2212+
return -1;
2213+
}
2214+
isdirlink = attr & FILE_ATTRIBUTE_DIRECTORY;
2215+
}
2216+
if (!CopyFileExW (w_oldpath->Buffer, w_newpath->Buffer,
2217+
NULL, NULL, NULL,
2218+
COPY_FILE_COPY_SYMLINK|
2219+
(isdirlink ? COPY_FILE_DIRECTORY : 0)))
2220+
{
2221+
__seterrno ();
2222+
return -1;
2223+
}
2224+
else
2225+
{
2226+
return 0;
2227+
}
2228+
}
2229+
}
2230+
21592231
int
21602232
symlink_worker (const char *oldpath, path_conv &win32_newpath, bool isdevice)
21612233
{
@@ -2223,6 +2295,13 @@ symlink_worker (const char *oldpath, path_conv &win32_newpath, bool isdevice)
22232295
case WSYM_nfs:
22242296
res = symlink_nfs (oldpath, win32_newpath);
22252297
__leave;
2298+
case WSYM_deepcopy:
2299+
res = symlink_deepcopy (oldpath, win32_newpath);
2300+
if (!res || res == -1)
2301+
__leave;
2302+
/* fall back to default symlink type */
2303+
wsym_type = WSYM_default;
2304+
goto handle_default;
22262305
case WSYM_native:
22272306
case WSYM_nativestrict:
22282307
res = symlink_native (oldpath, win32_newpath);
@@ -2239,6 +2318,7 @@ symlink_worker (const char *oldpath, path_conv &win32_newpath, bool isdevice)
22392318
wsym_type = WSYM_default;
22402319
fallthrough;
22412320
case WSYM_default:
2321+
handle_default:
22422322
if (win32_newpath.fs_flags () & FILE_SUPPORTS_REPARSE_POINTS)
22432323
{
22442324
res = symlink_wsl (oldpath, win32_newpath);
@@ -2375,79 +2455,8 @@ symlink_worker (const char *oldpath, path_conv &win32_newpath, bool isdevice)
23752455
* sizeof (WCHAR);
23762456
cp += *plen;
23772457
}
2378-
else
2458+
else /* wsym_type == WSYM_sysfile */
23792459
{
2380-
if (wsym_type == WSYM_deepcopy)
2381-
{
2382-
path_conv win32_oldpath;
2383-
/* The symlink target is relative to the directory in which the
2384-
symlink gets created, not relative to the cwd. Therefore we
2385-
have to mangle the path quite a bit before calling path_conv.*/
2386-
mangle_symlink_target (oldpath, win32_newpath, win32_oldpath);
2387-
if (win32_oldpath.error)
2388-
{
2389-
set_errno (win32_oldpath.error);
2390-
__leave;
2391-
}
2392-
if (!win32_oldpath.isspecial ())
2393-
{
2394-
/* MSYS copy file instead make symlink */
2395-
/* As a MSYS limitation, the source path must exist. */
2396-
if (!win32_oldpath.exists ())
2397-
{
2398-
set_errno (ENOENT);
2399-
__leave;
2400-
}
2401-
2402-
PUNICODE_STRING w_oldpath = win32_oldpath.get_nt_native_path ();
2403-
PUNICODE_STRING w_newpath = win32_newpath.get_nt_native_path ();
2404-
if (w_oldpath->Buffer[1] == L'?')
2405-
w_oldpath->Buffer[1] = L'\\';
2406-
if (w_newpath->Buffer[1] == L'?')
2407-
w_newpath->Buffer[1] = L'\\';
2408-
if (win32_oldpath.isdir ())
2409-
{
2410-
/* we need a larger UNICODE_STRING MaximumLength than
2411-
get_nt_native_path allocates for the recursive copy */
2412-
UNICODE_STRING u_oldpath, u_newpath;
2413-
RtlCopyUnicodeString (tp.u_get (&u_oldpath), w_oldpath);
2414-
RtlCopyUnicodeString (tp.u_get (&u_newpath), w_newpath);
2415-
res = recursiveCopy (&u_oldpath, &u_newpath,
2416-
u_oldpath.Length, u_newpath.Length);
2417-
}
2418-
else
2419-
{
2420-
bool isdirlink = false;
2421-
if (win32_oldpath.issymlink () &&
2422-
win32_oldpath.is_known_reparse_point ())
2423-
{
2424-
/* Is there a better way to know this? */
2425-
DWORD attr = getfileattr (win32_oldpath.get_win32 (),
2426-
!!win32_oldpath.objcaseinsensitive ());
2427-
if (attr == INVALID_FILE_ATTRIBUTES)
2428-
{
2429-
__seterrno ();
2430-
__leave;
2431-
}
2432-
isdirlink = attr & FILE_ATTRIBUTE_DIRECTORY;
2433-
}
2434-
if (!CopyFileExW (w_oldpath->Buffer, w_newpath->Buffer,
2435-
NULL, NULL, NULL,
2436-
COPY_FILE_COPY_SYMLINK|
2437-
(isdirlink ? COPY_FILE_DIRECTORY : 0)))
2438-
{
2439-
__seterrno ();
2440-
}
2441-
else
2442-
{
2443-
res = 0;
2444-
}
2445-
}
2446-
__leave;
2447-
}
2448-
}
2449-
2450-
/* wsym_type == WSYM_sysfile */
24512460
/* Default technique creating a symlink. */
24522461
buf = tp.t_get ();
24532462
cp = stpcpy (buf, SYMLINK_COOKIE);

0 commit comments

Comments
 (0)