FIX: copy - delete target when overwriting a regular file with a symlink

When the source is an (unfollowed) symlink and the destination is an
existing regular file, TargetExists/DoFileExists returned fsoterNotExists
on overwrite (expecting an in-place file overwrite) without deleting the
target. But a symlink source is recreated via CreateSymbolicLink, which
cannot overwrite an existing path, so it failed with "file exists"
(rsSymErrCreate). This broke "override" in folder sync for symlinks.

Treat an unfollowed-symlink source like the existing link/move cases:
delete the occupying target first and return fsoterDeleted, so the new
symlink can be created.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
heredie 2026-06-18 21:52:37 -06:00
commit 1c3b324ebf

View file

@ -1613,7 +1613,13 @@ var
begin
if FileIsReadOnly(Attrs) then
FileSetReadOnlyUAC(AbsoluteTargetFileName, False);
if FPS_ISLNK(Attrs) or (FMode = fsohmMove) then
// Delete the existing target first when it cannot be overwritten in
// place: an existing link, a move, or — crucially — when the source
// is an (unfollowed) symlink. A symlink source is recreated via
// CreateSymbolicLink, which fails with "file exists" if the target
// path is still occupied by the old regular file.
if FPS_ISLNK(Attrs) or (FMode = fsohmMove) or
(SourceFile.AttributesProperty.IsLink and (aNode.SubNodesCount = 0)) then
begin
DeleteFileUAC(AbsoluteTargetFileName);
Exit(fsoterDeleted);