Skip to content

Conversation

@joshtrichards
Copy link
Member

@joshtrichards joshtrichards commented Jan 8, 2026

Summary

During rename operations, if something already exists in the destination path, it gets deleted prior to the forbidden items check. If the check doesn't pass, the operation is aborted but deletion has already occurred.

This PR moves the forbidden items check up so it takes place before any destructive activities occur (see checkTreeForForbiddenItems).

The 2nd commit also addresses an edge case where the copy+unlink fallback could still be triggered for case-only renames on case-insensitive filesystems.

Also included throughout:

  • checks success/failure of removals
  • logs removal fails
  • eliminates duplicate code by using remove()
  • adds a logging helper to tidy up readability
  • moves source existence check to the top

TODO

Checklist

On case-insensitive filesystems, the copy+unlink fallback shouldn't be attempted since source/destination can "overlap".

Also adds some additional logging for error conditions + one at debug level for a more common scenario.

Otherwise just some additional tidying for readability.

Signed-off-by: Josh <[email protected]>
@joshtrichards joshtrichards changed the title fix(storage/local): check forbidden items before target deletion fix(storage/local): stop deleting prior to forbidden items check Jan 8, 2026
@joshtrichards joshtrichards added this to the Nextcloud 33 milestone Jan 8, 2026
@joshtrichards joshtrichards marked this pull request as ready for review January 8, 2026 15:56
@joshtrichards joshtrichards requested a review from a team as a code owner January 8, 2026 15:56
@joshtrichards joshtrichards requested review from Altahrim, artonge, nfebe and provokateurin and removed request for a team January 8, 2026 15:56
return false;
}

$dstParent = dirname($target);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe also rename this variable $targetParent

$this->rmdir($target);
} elseif ($this->is_file($target)) {
$this->unlink($target);
if (!$this->remove($target)) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even if it's current behaviour, I am not sure we need to remove the target when it's a file.
It should be overwritten by the rename. Not sure if it's dependant from filesystem…

Comment on lines +379 to +380
}
if ($copySuccess && !$unlinkSuccess) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
}
if ($copySuccess && !$unlinkSuccess) {
} elseif (!$unlinkSuccess) {

Or maybe with early returns?

@nextcloud-bot nextcloud-bot mentioned this pull request Jan 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants