From 2d37782c282e374477fa5d537cc19d89f32d1ff9 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Thu, 29 Jan 2026 15:45:53 +0100 Subject: [PATCH 1/4] fix: still setup for user when setting up root path with children Signed-off-by: Robin Appelman --- lib/private/Files/SetupManager.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/private/Files/SetupManager.php b/lib/private/Files/SetupManager.php index df0fd5a2d52d9..d23314ace2199 100644 --- a/lib/private/Files/SetupManager.php +++ b/lib/private/Files/SetupManager.php @@ -434,8 +434,8 @@ public function setupRoot(): void { * @param string $path * @return IUser|null */ - private function getUserForPath(string $path): ?IUser { - if ($path === '' || $path === '/') { + private function getUserForPath(string $path, bool $includeChildren = false): ?IUser { + if (($path === '' || $path === '/') && !$includeChildren) { return null; } elseif (str_starts_with($path, '/__groupfolders')) { return null; @@ -456,7 +456,7 @@ private function getUserForPath(string $path): ?IUser { #[Override] public function setupForPath(string $path, bool $includeChildren = false): void { - $user = $this->getUserForPath($path); + $user = $this->getUserForPath($path, $includeChildren); if (!$user) { $this->setupRoot(); return; From bcbfffe23e17f0d580d86d2ac3c420c1d0c63f48 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Thu, 29 Jan 2026 16:33:27 +0100 Subject: [PATCH 2/4] fix: make sure all mounts are setup in getById Signed-off-by: Robin Appelman --- lib/private/Files/Node/Root.php | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/lib/private/Files/Node/Root.php b/lib/private/Files/Node/Root.php index 9b0a48fa296fd..c94eadcedb3f6 100644 --- a/lib/private/Files/Node/Root.php +++ b/lib/private/Files/Node/Root.php @@ -405,6 +405,7 @@ public function getFirstNodeByIdInPath(int $id, string $path): ?INode { */ public function getByIdInPath(int $id, string $path): array { $mountCache = $this->getUserMountCache(); + $setupManager = $this->mountManager->getSetupManager(); if ($path !== '' && strpos($path, '/', 1) > 0) { [, $user] = explode('/', $path); } else { @@ -414,7 +415,7 @@ public function getByIdInPath(int $id, string $path): array { // if the mount isn't in the cache yet, perform a setup first, then try again if (count($mountsContainingFile) === 0) { - $this->mountManager->getSetupManager()->setupForPath($path, true); + $setupManager->setupForPath($path, true); $mountsContainingFile = $mountCache->getMountsForFileId($id, $user); } @@ -436,11 +437,7 @@ public function getByIdInPath(int $id, string $path): array { }, $mountsContainingFile)); $mountRoots = array_combine($mountRootIds, $mountRootPaths); - $mounts = $this->mountManager->getMountsByMountProvider($path, $mountProviders); - - $mountsContainingFile = array_filter($mounts, function ($mount) use ($mountRoots) { - return isset($mountRoots[$mount->getStorageRootId()]); - }); + $mountsContainingFile = array_filter(array_map($this->mountManager->getMountFromMountInfo(...), $mountsContainingFile)); if (count($mountsContainingFile) === 0) { if ($user === $this->getAppDataDirectoryName()) { From 0462de92d15270ceb789a421636498f67336d1fa Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Thu, 29 Jan 2026 17:32:37 +0100 Subject: [PATCH 3/4] test: adjust tests to new getById Signed-off-by: Robin Appelman --- tests/lib/Files/Node/FolderTest.php | 34 ++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/tests/lib/Files/Node/FolderTest.php b/tests/lib/Files/Node/FolderTest.php index ad60cb535558c..19374fee6c128 100644 --- a/tests/lib/Files/Node/FolderTest.php +++ b/tests/lib/Files/Node/FolderTest.php @@ -29,6 +29,7 @@ use OC\Files\View; use OCP\Constants; use OCP\Files\Cache\ICacheEntry; +use OCP\Files\Config\ICachedMountInfo; use OCP\Files\InvalidPathException; use OCP\Files\IRootFolder; use OCP\Files\Mount\IMountPoint; @@ -538,8 +539,8 @@ public function testGetById(): void { ->with('/bar/foo') ->willReturn([]); - $manager->method('getMountsByMountProvider') - ->willReturn([$mount]); + $manager->method('getMountFromMountInfo') + ->willReturn($mount); $node = new Folder($root, $view, '/bar/foo'); $result = $node->getById(1); @@ -583,8 +584,8 @@ public function testGetByIdMountRoot(): void { ->with(1) ->willReturn($fileInfo); - $manager->method('getMountsByMountProvider') - ->willReturn([$mount]); + $manager->method('getMountFromMountInfo') + ->willReturn($mount); $node = new Folder($root, $view, '/bar'); $result = $node->getById(1); @@ -628,8 +629,8 @@ public function testGetByIdOutsideFolder(): void { ->with(1) ->willReturn($fileInfo); - $manager->method('getMountsByMountProvider') - ->willReturn([$mount]); + $manager->method('getMountFromMountInfo') + ->willReturn($mount); $node = new Folder($root, $view, '/bar/foo'); $result = $node->getById(1); @@ -668,14 +669,31 @@ public function testGetByIdMultipleStorages(): void { 1, '' ), + new CachedMountInfo( + $this->user, + 1, + 0, + '/bar/foo/asd/', + 'test', + 1, + '' + ), ]); $cache->method('get') ->with(1) ->willReturn($fileInfo); - $manager->method('getMountsByMountProvider') - ->willReturn([$mount1, $mount2]); + $manager->method('getMountFromMountInfo') + ->willReturnCallback(function (ICachedMountInfo $mountInfo) use ($mount1, $mount2) { + if ($mountInfo->getMountPoint() === $mount1->getMountPoint()) { + return $mount1; + } + if ($mountInfo->getMountPoint() === $mount2->getMountPoint()) { + return $mount2; + } + return null; + }); $node = new Folder($root, $view, '/bar/foo'); $result = $node->getById(1); From 502567d750554e9c48671e63adb45e47d9355fde Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Fri, 30 Jan 2026 17:38:56 +0100 Subject: [PATCH 4/4] fix: getById: don't setup for all users with access by default Signed-off-by: Robin Appelman --- lib/private/Files/Mount/Manager.php | 4 ++-- lib/private/Files/Node/Root.php | 20 +++++++++++++------- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/lib/private/Files/Mount/Manager.php b/lib/private/Files/Mount/Manager.php index b763697387dd7..72b38f38575b7 100644 --- a/lib/private/Files/Mount/Manager.php +++ b/lib/private/Files/Mount/Manager.php @@ -230,11 +230,11 @@ public function getSetupManager(): SetupManager { } /** - * Return all mounts in a path from a specific mount provider + * Return all mounts in a path from a specific mount provider, indexed by mount point * * @param string $path * @param string[] $mountProviders - * @return IMountPoint[] + * @return array */ public function getMountsByMountProvider(string $path, array $mountProviders) { $this->getSetupManager()->setupForProvider($path, $mountProviders); diff --git a/lib/private/Files/Node/Root.php b/lib/private/Files/Node/Root.php index c94eadcedb3f6..81587fe99c1b8 100644 --- a/lib/private/Files/Node/Root.php +++ b/lib/private/Files/Node/Root.php @@ -19,6 +19,7 @@ use OCP\Cache\CappedMemoryCache; use OCP\EventDispatcher\IEventDispatcher; use OCP\Files\Cache\ICacheEntry; +use OCP\Files\Config\ICachedMountInfo; use OCP\Files\Config\IUserMountCache; use OCP\Files\Events\Node\FilesystemTornDownEvent; use OCP\Files\IRootFolder; @@ -411,12 +412,12 @@ public function getByIdInPath(int $id, string $path): array { } else { $user = null; } - $mountsContainingFile = $mountCache->getMountsForFileId($id, $user); + $mountsContainingFileInfos = $mountCache->getMountsForFileId($id, $user); // if the mount isn't in the cache yet, perform a setup first, then try again - if (count($mountsContainingFile) === 0) { + if (count($mountsContainingFileInfos) === 0) { $setupManager->setupForPath($path, true); - $mountsContainingFile = $mountCache->getMountsForFileId($id, $user); + $mountsContainingFileInfos = $mountCache->getMountsForFileId($id, $user); } // when a user has access through the same storage through multiple paths @@ -428,16 +429,21 @@ public function getByIdInPath(int $id, string $path): array { $mountRootIds = array_map(function ($mount) { return $mount->getRootId(); - }, $mountsContainingFile); + }, $mountsContainingFileInfos); $mountRootPaths = array_map(function ($mount) { return $mount->getRootInternalPath(); - }, $mountsContainingFile); + }, $mountsContainingFileInfos); $mountProviders = array_unique(array_map(function ($mount) { return $mount->getMountProvider(); - }, $mountsContainingFile)); + }, $mountsContainingFileInfos)); + $mountPoints = array_map(fn(ICachedMountInfo $mountInfo) => $mountInfo->getMountPoint(), $mountsContainingFileInfos); $mountRoots = array_combine($mountRootIds, $mountRootPaths); - $mountsContainingFile = array_filter(array_map($this->mountManager->getMountFromMountInfo(...), $mountsContainingFile)); + $mounts = $this->mountManager->getMountsByMountProvider($path, $mountProviders); + $mountsContainingFile = array_filter($mounts, fn (IMountPoint $mount) => in_array($mount->getMountPoint(), $mountPoints)); + if (count($mountsContainingFile) == 0) { + $mountsContainingFile = array_filter(array_map($this->mountManager->getMountFromMountInfo(...), $mountsContainingFileInfos)); + } if (count($mountsContainingFile) === 0) { if ($user === $this->getAppDataDirectoryName()) {