Skip to content

Commit

Permalink
fixup! Instead of creating Cygwin symlinks, use deep copy by default
Browse files Browse the repository at this point in the history
Don't attempt to recurse into directory symlinks, but instead copy them
as symlinks.

The COPY_FILE_DIRECTORY flag is documented as only supported on Windows
10 build 19041 and later, but without it copying a directory symlink
fails anyway.
  • Loading branch information
jeremyd2019 committed Jan 31, 2025
1 parent cc64c33 commit 3de5500
Showing 1 changed file with 37 additions and 21 deletions.
58 changes: 37 additions & 21 deletions winsup/cygwin/path.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1735,32 +1735,42 @@ recursiveCopy (PUNICODE_STRING src, PUNICODE_STRING dst, PCWSTR origpath)
findfiles = FindNextFileW (dH, &dHfile);
while (findfiles)
{
bool isdirlink = false;
/* Append the directory item filename to both source and destination */
debug_printf ("dHfile(3): %W", dHfile.cFileName);
src->Length = srcpos + sizeof (WCHAR);
dst->Length = dstpos + sizeof (WCHAR);
RtlAppendUnicodeToString (src, dHfile.cFileName);
RtlAppendUnicodeToString (dst, dHfile.cFileName);
debug_printf ("%S -> %S", src, dst);
if (dHfile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
/* Recurse into the child directory */
debug_printf ("%S <-> %W", src, origpath);
if ((dHfile.dwFileAttributes &
(FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_REPARSE_POINT)) ==
(FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_REPARSE_POINT))
{
/* this sucks hard */
path_conv pc (src, PC_SYM_NOFOLLOW|PC_SYM_NOFOLLOW_REP);
isdirlink = pc.issymlink ();
}
if ((dHfile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && !isdirlink)
{
/* Recurse into the child directory */
debug_printf ("%S <-> %W", src, origpath);
// avoids endless recursion
if (wcsncmp (src->Buffer, origpath, src->Length / sizeof (WCHAR)))
if (recursiveCopy (src, dst, origpath))
goto done;
}
if (wcsncmp (src->Buffer, origpath, src->Length / sizeof (WCHAR)))
if (recursiveCopy (src, dst, origpath))
goto done;
}
else
{
/* Just copy the file */
if (!CopyFileExW (src->Buffer, dst->Buffer, NULL, NULL, NULL,
COPY_FILE_COPY_SYMLINK))
{
__seterrno ();
goto done;
}
}
{
/* Just copy the file */
if (!CopyFileExW (src->Buffer, dst->Buffer, NULL, NULL, NULL,
COPY_FILE_COPY_SYMLINK|
(isdirlink ? COPY_FILE_DIRECTORY : 0)))
{
__seterrno ();
goto done;
}
}
findfiles = FindNextFileW (dH, &dHfile);
}
if (GetLastError() != ERROR_NO_MORE_FILES)
Expand Down Expand Up @@ -2314,7 +2324,7 @@ symlink_worker (const char *oldpath, path_conv &win32_newpath, bool isdevice)
}
else /* wsym_type == WSYM_sysfile */
{
if (wsym_type == WSYM_deepcopy)
if (wsym_type == WSYM_deepcopy)
{
path_conv win32_oldpath;
/* The symlink target is relative to the directory in which the
Expand All @@ -2341,7 +2351,7 @@ symlink_worker (const char *oldpath, path_conv &win32_newpath, bool isdevice)
__leave;
}
if (!win32_oldpath.isspecial ())
{
{
/* MSYS copy file instead make symlink */
/* As a MSYS limitation, the source path must exist. */
if (!win32_oldpath.exists ())
Expand All @@ -2361,17 +2371,23 @@ symlink_worker (const char *oldpath, path_conv &win32_newpath, bool isdevice)
PWCHAR origpath =
win32_oldpath.get_wide_win32_path (tp.w_get ());
/* we need a larger UNICODE_STRING MaximumLength than
get_nt_native_path allocates for the recursive copy */
get_nt_native_path allocates for the recursive copy */
UNICODE_STRING u_oldpath, u_newpath;
RtlCopyUnicodeString (tp.u_get (&u_oldpath), w_oldpath);
RtlCopyUnicodeString (tp.u_get (&u_newpath), w_newpath);
res = recursiveCopy (&u_oldpath, &u_newpath, origpath);
}
else
{
/* I don't know if there's a better way to know this */
DWORD attr = getfileattr (win32_oldpath.get_win32 (),
win32_oldpath.obcaseinsensitive ());
bool isdirlink = attr != INVALID_FILE_ATTRIBUTES &&
(attr & FILE_ATTRIBUTE_DIRECTORY);
if (!CopyFileExW (w_oldpath->Buffer, w_newpath->Buffer,
NULL, NULL, NULL,
COPY_FILE_COPY_SYMLINK))
COPY_FILE_COPY_SYMLINK|
(isdirlink ? COPY_FILE_DIRECTORY : 0)))
{
__seterrno ();
}
Expand Down

0 comments on commit 3de5500

Please sign in to comment.