Skip to content

Commit 957049a

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 8b4557b commit 957049a

File tree

1 file changed

+80
-72
lines changed

1 file changed

+80
-72
lines changed

winsup/cygwin/path.cc

Lines changed: 80 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -2156,6 +2156,77 @@ 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+
/* we need a larger UNICODE_STRING MaximumLength than
2192+
get_nt_native_path allocates for the recursive copy */
2193+
UNICODE_STRING u_oldpath, u_newpath;
2194+
RtlCopyUnicodeString (tp.u_get (&u_oldpath), w_oldpath);
2195+
RtlCopyUnicodeString (tp.u_get (&u_newpath), w_newpath);
2196+
return recursiveCopy (&u_oldpath, &u_newpath,
2197+
u_oldpath.Length, u_newpath.Length);
2198+
}
2199+
else
2200+
{
2201+
bool isdirlink = false;
2202+
if (win32_oldpath.issymlink () &&
2203+
win32_oldpath.is_known_reparse_point ())
2204+
{
2205+
/* Is there a better way to know this? */
2206+
DWORD attr = getfileattr (win32_oldpath.get_win32 (),
2207+
!!win32_oldpath.objcaseinsensitive ());
2208+
if (attr == INVALID_FILE_ATTRIBUTES)
2209+
{
2210+
__seterrno ();
2211+
return -1;
2212+
}
2213+
isdirlink = attr & FILE_ATTRIBUTE_DIRECTORY;
2214+
}
2215+
if (!CopyFileExW (w_oldpath->Buffer, w_newpath->Buffer,
2216+
NULL, NULL, NULL,
2217+
COPY_FILE_COPY_SYMLINK|
2218+
(isdirlink ? COPY_FILE_DIRECTORY : 0)))
2219+
{
2220+
__seterrno ();
2221+
return -1;
2222+
}
2223+
else
2224+
{
2225+
return 0;
2226+
}
2227+
}
2228+
}
2229+
21592230
int
21602231
symlink_worker (const char *oldpath, path_conv &win32_newpath, bool isdevice)
21612232
{
@@ -2224,6 +2295,13 @@ symlink_worker (const char *oldpath, path_conv &win32_newpath, bool isdevice)
22242295
case WSYM_nfs:
22252296
res = symlink_nfs (oldpath, win32_newpath);
22262297
__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;
22272305
case WSYM_native:
22282306
case WSYM_nativestrict:
22292307
res = symlink_native (oldpath, win32_newpath);
@@ -2240,6 +2318,7 @@ symlink_worker (const char *oldpath, path_conv &win32_newpath, bool isdevice)
22402318
wsym_type = WSYM_default;
22412319
fallthrough;
22422320
case WSYM_default:
2321+
handle_default:
22432322
if (win32_newpath.fs_flags () & FILE_SUPPORTS_REPARSE_POINTS)
22442323
{
22452324
res = symlink_wsl (oldpath, win32_newpath);
@@ -2376,79 +2455,8 @@ symlink_worker (const char *oldpath, path_conv &win32_newpath, bool isdevice)
23762455
* sizeof (WCHAR);
23772456
cp += *plen;
23782457
}
2379-
else
2458+
else /* wsym_type == WSYM_sysfile */
23802459
{
2381-
if (wsym_type == WSYM_deepcopy)
2382-
{
2383-
path_conv win32_oldpath;
2384-
/* The symlink target is relative to the directory in which the
2385-
symlink gets created, not relative to the cwd. Therefore we
2386-
have to mangle the path quite a bit before calling path_conv.*/
2387-
mangle_symlink_target (oldpath, win32_newpath, win32_oldpath);
2388-
if (win32_oldpath.error)
2389-
{
2390-
set_errno (win32_oldpath.error);
2391-
__leave;
2392-
}
2393-
if (!win32_oldpath.isspecial ())
2394-
{
2395-
/* MSYS copy file instead make symlink */
2396-
/* As a MSYS limitation, the source path must exist. */
2397-
if (!win32_oldpath.exists ())
2398-
{
2399-
set_errno (ENOENT);
2400-
__leave;
2401-
}
2402-
2403-
PUNICODE_STRING w_oldpath = win32_oldpath.get_nt_native_path ();
2404-
PUNICODE_STRING w_newpath = win32_newpath.get_nt_native_path ();
2405-
if (w_oldpath->Buffer[1] == L'?')
2406-
w_oldpath->Buffer[1] = L'\\';
2407-
if (w_newpath->Buffer[1] == L'?')
2408-
w_newpath->Buffer[1] = L'\\';
2409-
if (win32_oldpath.isdir ())
2410-
{
2411-
/* we need a larger UNICODE_STRING MaximumLength than
2412-
get_nt_native_path allocates for the recursive copy */
2413-
UNICODE_STRING u_oldpath, u_newpath;
2414-
RtlCopyUnicodeString (tp.u_get (&u_oldpath), w_oldpath);
2415-
RtlCopyUnicodeString (tp.u_get (&u_newpath), w_newpath);
2416-
res = recursiveCopy (&u_oldpath, &u_newpath,
2417-
u_oldpath.Length, u_newpath.Length);
2418-
}
2419-
else
2420-
{
2421-
bool isdirlink = false;
2422-
if (win32_oldpath.issymlink () &&
2423-
win32_oldpath.is_known_reparse_point ())
2424-
{
2425-
/* Is there a better way to know this? */
2426-
DWORD attr = getfileattr (win32_oldpath.get_win32 (),
2427-
!!win32_oldpath.objcaseinsensitive ());
2428-
if (attr == INVALID_FILE_ATTRIBUTES)
2429-
{
2430-
__seterrno ();
2431-
__leave;
2432-
}
2433-
isdirlink = attr & FILE_ATTRIBUTE_DIRECTORY;
2434-
}
2435-
if (!CopyFileExW (w_oldpath->Buffer, w_newpath->Buffer,
2436-
NULL, NULL, NULL,
2437-
COPY_FILE_COPY_SYMLINK|
2438-
(isdirlink ? COPY_FILE_DIRECTORY : 0)))
2439-
{
2440-
__seterrno ();
2441-
}
2442-
else
2443-
{
2444-
res = 0;
2445-
}
2446-
}
2447-
__leave;
2448-
}
2449-
}
2450-
2451-
/* wsym_type == WSYM_sysfile */
24522460
/* Default technique creating a symlink. */
24532461
buf = tp.t_get ();
24542462
cp = stpcpy (buf, SYMLINK_COOKIE);

0 commit comments

Comments
 (0)