Skip to content

Commit aea51f6

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 aea51f6

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
{
@@ -2223,6 +2294,13 @@ symlink_worker (const char *oldpath, path_conv &win32_newpath, bool isdevice)
22232294
case WSYM_nfs:
22242295
res = symlink_nfs (oldpath, win32_newpath);
22252296
__leave;
2297+
case WSYM_deepcopy:
2298+
res = symlink_deepcopy (oldpath, win32_newpath);
2299+
if (!res || res == -1)
2300+
__leave;
2301+
/* fall back to default symlink type */
2302+
wsym_type = WSYM_default;
2303+
goto handle_default;
22262304
case WSYM_native:
22272305
case WSYM_nativestrict:
22282306
res = symlink_native (oldpath, win32_newpath);
@@ -2239,6 +2317,7 @@ symlink_worker (const char *oldpath, path_conv &win32_newpath, bool isdevice)
22392317
wsym_type = WSYM_default;
22402318
fallthrough;
22412319
case WSYM_default:
2320+
handle_default:
22422321
if (win32_newpath.fs_flags () & FILE_SUPPORTS_REPARSE_POINTS)
22432322
{
22442323
res = symlink_wsl (oldpath, win32_newpath);
@@ -2375,79 +2454,8 @@ symlink_worker (const char *oldpath, path_conv &win32_newpath, bool isdevice)
23752454
* sizeof (WCHAR);
23762455
cp += *plen;
23772456
}
2378-
else
2457+
else /* wsym_type == WSYM_sysfile */
23792458
{
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 */
24512459
/* Default technique creating a symlink. */
24522460
buf = tp.t_get ();
24532461
cp = stpcpy (buf, SYMLINK_COOKIE);

0 commit comments

Comments
 (0)