aboutsummaryrefslogtreecommitdiffstats
path: root/lib/private/Files/Utils
diff options
context:
space:
mode:
Diffstat (limited to 'lib/private/Files/Utils')
-rw-r--r--lib/private/Files/Utils/PathHelper.php22
-rw-r--r--lib/private/Files/Utils/Scanner.php56
2 files changed, 29 insertions, 49 deletions
diff --git a/lib/private/Files/Utils/PathHelper.php b/lib/private/Files/Utils/PathHelper.php
index 0fb7ba663cc..db1294bcc10 100644
--- a/lib/private/Files/Utils/PathHelper.php
+++ b/lib/private/Files/Utils/PathHelper.php
@@ -2,25 +2,9 @@
declare(strict_types=1);
/**
- * @copyright Copyright (c) 2022 Robin Appelman <robin@icewind.nl>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
*/
-
namespace OC\Files\Utils;
class PathHelper {
@@ -53,6 +37,8 @@ class PathHelper {
if ($path === '' or $path === '/') {
return '/';
}
+ // No null bytes
+ $path = str_replace(chr(0), '', $path);
//no windows style slashes
$path = str_replace('\\', '/', $path);
//add leading slash
diff --git a/lib/private/Files/Utils/Scanner.php b/lib/private/Files/Utils/Scanner.php
index 997d6e1a34e..576cb66b3cf 100644
--- a/lib/private/Files/Utils/Scanner.php
+++ b/lib/private/Files/Utils/Scanner.php
@@ -1,33 +1,10 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Blaok <i@blaok.me>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Jörn Friedrich Dreyer <jfd@butonic.de>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Olivier Paroz <github@oparoz.com>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License, version 3,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
-
namespace OC\Files\Utils;
use OC\Files\Cache\Cache;
@@ -46,11 +23,13 @@ use OCP\Files\Events\FileScannedEvent;
use OCP\Files\Events\FolderScannedEvent;
use OCP\Files\Events\NodeAddedToCache;
use OCP\Files\Events\NodeRemovedFromCache;
+use OCP\Files\Mount\IMountPoint;
use OCP\Files\NotFoundException;
use OCP\Files\Storage\IStorage;
use OCP\Files\StorageNotAvailableException;
use OCP\IDBConnection;
use OCP\Lock\ILockingProvider;
+use OCP\Lock\LockedException;
use Psr\Log\LoggerInterface;
/**
@@ -108,7 +87,7 @@ class Scanner extends PublicEmitter {
* get all storages for $dir
*
* @param string $dir
- * @return \OC\Files\Mount\MountPoint[]
+ * @return array<string, IMountPoint>
*/
protected function getMounts($dir) {
//TODO: move to the node based fileapi once that's done
@@ -119,8 +98,9 @@ class Scanner extends PublicEmitter {
$mounts = $mountManager->findIn($dir);
$mounts[] = $mountManager->find($dir);
$mounts = array_reverse($mounts); //start with the mount of $dir
+ $mountPoints = array_map(fn ($mount) => $mount->getMountPoint(), $mounts);
- return $mounts;
+ return array_combine($mountPoints, $mounts);
}
/**
@@ -129,6 +109,7 @@ class Scanner extends PublicEmitter {
* @param \OC\Files\Mount\MountPoint $mount
*/
protected function attachListener($mount) {
+ /** @var \OC\Files\Cache\Scanner $scanner */
$scanner = $mount->getStorage()->getScanner();
$scanner->listen('\OC\Files\Cache\Scanner', 'scanFile', function ($path) use ($mount) {
$this->emit('\OC\Files\Utils\Scanner', 'scanFile', [$mount->getMountPoint() . $path]);
@@ -168,6 +149,7 @@ class Scanner extends PublicEmitter {
continue;
}
+ /** @var \OC\Files\Cache\Scanner $scanner */
$scanner = $storage->getScanner();
$this->attachListener($mount);
@@ -223,7 +205,10 @@ class Scanner extends PublicEmitter {
foreach (['', 'files'] as $path) {
if (!$storage->isCreatable($path)) {
$fullPath = $storage->getSourcePath($path);
- if (!$storage->is_dir($path) && $storage->getCache()->inCache($path)) {
+ if (isset($mounts[$mount->getMountPoint() . $path . '/'])) {
+ // /<user>/files is overwritten by a mountpoint, so this check is irrelevant
+ break;
+ } elseif (!$storage->is_dir($path) && $storage->getCache()->inCache($path)) {
throw new NotFoundException("User folder $fullPath exists in cache but not on disk");
} elseif ($storage->is_dir($path)) {
$ownerUid = fileowner($fullPath);
@@ -244,6 +229,7 @@ class Scanner extends PublicEmitter {
continue;
}
$relativePath = $mount->getInternalPath($dir);
+ /** @var \OC\Files\Cache\Scanner $scanner */
$scanner = $storage->getScanner();
$scanner->setUseTransactions(false);
$this->attachListener($mount);
@@ -275,7 +261,15 @@ class Scanner extends PublicEmitter {
try {
$propagator = $storage->getPropagator();
$propagator->beginBatch();
- $scanner->scan($relativePath, $recursive, \OC\Files\Cache\Scanner::REUSE_ETAG | \OC\Files\Cache\Scanner::REUSE_SIZE);
+ try {
+ $scanner->scan($relativePath, $recursive, \OC\Files\Cache\Scanner::REUSE_ETAG | \OC\Files\Cache\Scanner::REUSE_SIZE);
+ } catch (LockedException $e) {
+ if (is_string($e->getReadablePath()) && str_starts_with($e->getReadablePath(), 'scanner::')) {
+ throw new LockedException("scanner::$dir", $e, $e->getExistingLock());
+ } else {
+ throw $e;
+ }
+ }
$cache = $storage->getCache();
if ($cache instanceof Cache) {
// only re-calculate for the root folder we scanned, anything below that is taken care of by the scanner