FIX: Copy WSL/Cygwin symbolic links (issue #2171)

This commit is contained in:
Alexander Koblov 2025-02-28 20:00:34 +03:00
commit 39cbab00eb

View file

@ -190,25 +190,37 @@ begin
end;
end;
procedure FillLinkProperty(const AFilePath: String; dwAttrs: DWORD; LinkProperty: TFileLinkProperty);
procedure FillLinkProperty(const AFilePath: String; AFile: TFile; FindData: PWin32FindDataW);
var
LinkAttrs: TFileAttrs;
begin
LinkProperty.LinkTo := ReadSymLink(AFilePath);
if StrBegins(LinkProperty.LinkTo, 'Volume{') then
with AFile do
begin
LinkProperty.IsLinkToDirectory := True;
LinkProperty.IsValid:= mbDriveReady(AFilePath + PathDelim);
end
else begin
LinkAttrs := mbFileGetAttrNoLinks(AFilePath);
LinkProperty.IsValid := LinkAttrs <> faInvalidAttributes;
if LinkProperty.IsValid then
LinkProperty.IsLinkToDirectory := fpS_ISDIR(LinkAttrs)
LinkProperty.LinkTo := ReadSymLink(AFilePath);
if (FindData^.dwReserved0 = IO_REPARSE_TAG_SYMLINK) or
(FindData^.dwReserved0 = IO_REPARSE_TAG_MOUNT_POINT) then
begin
if (FindData^.dwReserved0 = IO_REPARSE_TAG_MOUNT_POINT) and
(StrBegins(LinkProperty.LinkTo, 'Volume{')) then
begin
LinkProperty.IsLinkToDirectory := True;
LinkProperty.IsValid:= mbDriveReady(AFilePath + PathDelim);
end
else begin
LinkAttrs := mbFileGetAttrNoLinks(AFilePath);
LinkProperty.IsValid := LinkAttrs <> faInvalidAttributes;
if LinkProperty.IsValid then
LinkProperty.IsLinkToDirectory := fpS_ISDIR(LinkAttrs)
else begin
// On Windows links to directories are marked with Directory flag on the link.
LinkProperty.IsLinkToDirectory := fpS_ISDIR(FindData^.dwFileAttributes);
end;
end;
end
// Unknown reparse point type
else begin
// On Windows links to directories are marked with Directory flag on the link.
LinkProperty.IsLinkToDirectory := fpS_ISDIR(dwAttrs);
AttributesProperty.Value:= AttributesProperty.Value - FILE_ATTRIBUTE_REPARSE_POINT;
end;
end;
end;
@ -221,7 +233,7 @@ begin
with AFile do
begin
AttributesProperty := TNtfsFileAttributesProperty.Create(
pFindData^.dwFileAttributes);
ExtractFileAttributes(pFindData^));
SizeProperty := TFileSizeProperty.Create(
QWord(pFindData^.nFileSizeHigh) shl 32 + pFindData^.nFileSizeLow);
@ -237,9 +249,9 @@ begin
LinkProperty := TFileLinkProperty.Create;
if fpS_ISLNK(pFindData^.dwFileAttributes) then
if fpS_ISLNK(AttributesProperty.Value) then
begin
FillLinkProperty(AFilePath, pFindData^.dwFileAttributes, LinkProperty);
FillLinkProperty(AFilePath, AFile, pFindData);
end;
end;
end;
@ -406,29 +418,21 @@ begin
LinkProperty := TFileLinkProperty.Create;
AFilePath:= Path + pSearchRecord^.Name;
if fpS_ISLNK(pSearchRecord^.Attr) then
begin
{$IF DEFINED(MSWINDOWS)}
FillLinkProperty(AFilePath, Result, @pSearchRecord^.FindData);
{$ELSE}
LinkAttrs := mbFileGetAttrNoLinks(AFilePath);
LinkProperty.LinkTo := ReadSymLink(AFilePath);
LinkProperty.IsValid := LinkAttrs <> faInvalidAttributes;
{$IF DEFINED(UNIX)}
if LinkProperty.IsValid then
begin
LinkProperty.IsLinkToDirectory := fpS_ISDIR(LinkAttrs);
if LinkProperty.IsLinkToDirectory then SizeProperty.Value := 0;
end;
{$ELSE}
if StrBegins(LinkProperty.LinkTo, 'Volume{') then
begin
LinkProperty.IsLinkToDirectory := True;
LinkProperty.IsValid:= mbDriveReady(AFilePath + PathDelim);
end
else if LinkProperty.IsValid then
LinkProperty.IsLinkToDirectory := fpS_ISDIR(LinkAttrs)
else begin
// On Windows links to directories are marked with Directory flag on the link.
LinkProperty.IsLinkToDirectory := fpS_ISDIR(pSearchRecord^.Attr);
end;
{$ENDIF}
end;
{$IFDEF DARWIN}
@ -609,7 +613,7 @@ begin
if fpS_ISLNK(Attrs) then
begin
FillLinkProperty(sFullPath, Attrs, LinkProperty);
FillLinkProperty(sFullPath, AFile, @FindData);
end;
end;