fix: attempt to make share conflict resolution more resilient to false positives

Signed-off-by: Robin Appelman <robin@icewind.nl>
This commit is contained in:
Robin Appelman 2026-01-14 16:59:54 +01:00
parent d71c6796ca
commit 43a9335355
No known key found for this signature in database
GPG key ID: 42B69D8A64526EFB

View file

@ -85,6 +85,7 @@ class ShareTargetValidator {
}
$newAbsoluteMountPoint = $this->generateUniqueTarget(
$share,
Filesystem::normalizePath($absoluteParent . '/' . $mountPoint),
$parentMount,
$allCachedMounts,
@ -107,7 +108,12 @@ class ShareTargetValidator {
/**
* @param ICachedMountInfo[] $allCachedMounts
*/
private function generateUniqueTarget(string $absolutePath, IMountPoint $parentMount, array $allCachedMounts): string {
private function generateUniqueTarget(
IShare $share,
string $absolutePath,
IMountPoint $parentMount,
array $allCachedMounts,
): string {
$pathInfo = pathinfo($absolutePath);
$ext = isset($pathInfo['extension']) ? '.' . $pathInfo['extension'] : '';
$name = $pathInfo['filename'];
@ -116,7 +122,7 @@ class ShareTargetValidator {
$i = 2;
$parentCache = $parentMount->getStorage()->getCache();
$internalPath = $parentMount->getInternalPath($absolutePath);
while ($parentCache->inCache($internalPath) || isset($allCachedMounts[$absolutePath . '/'])) {
while ($parentCache->inCache($internalPath) || $this->hasConflictingMount($share, $allCachedMounts, $absolutePath)) {
$absolutePath = Filesystem::normalizePath($dir . '/' . $name . ' (' . $i . ')' . $ext);
$internalPath = $parentMount->getInternalPath($absolutePath);
$i++;
@ -125,6 +131,23 @@ class ShareTargetValidator {
return $absolutePath;
}
/**
* @param ICachedMountInfo[] $allCachedMounts
*/
private function hasConflictingMount(IShare $share, array $allCachedMounts, string $absolutePath): bool {
if (!isset($allCachedMounts[$absolutePath . '/'])) {
return false;
}
$mount = $allCachedMounts[$absolutePath . '/'];
if ($mount->getMountProvider() === MountProvider::class && $mount->getRootId() === $share->getNodeId()) {
// "conflicting" mount is a mount for the current share
return false;
}
return true;
}
/**
* update fileTarget in the database if the mount point changed
*