summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorRobin Appelman <robin@icewind.nl>2022-03-08 14:50:25 +0000
committerGitHub <noreply@github.com>2022-03-08 14:50:25 +0000
commite8872f01ae850bcbf66220beba44463f68e3d673 (patch)
tree9b2b1d01992d26368ff456af0440d0a2965308a6 /lib
parent23e8ae15aaea30359a927492155de13c97b311ce (diff)
parent917c74e214094e321ff96e1aa067ae60d22e2c58 (diff)
downloadnextcloud-server-e8872f01ae850bcbf66220beba44463f68e3d673.tar.gz
nextcloud-server-e8872f01ae850bcbf66220beba44463f68e3d673.zip
Merge pull request #31431 from nextcloud/fs-setup-manager
Unify/cleanup filesystem setup
Diffstat (limited to 'lib')
-rw-r--r--lib/composer/composer/autoload_classmap.php3
-rw-r--r--lib/composer/composer/autoload_static.php3
-rw-r--r--lib/private/Cache/CappedMemoryCache.php28
-rw-r--r--lib/private/Files/Config/CachedMountFileInfo.php3
-rw-r--r--lib/private/Files/Config/CachedMountInfo.php55
-rw-r--r--lib/private/Files/Config/LazyStorageMountInfo.php16
-rw-r--r--lib/private/Files/Config/MountProviderCollection.php16
-rw-r--r--lib/private/Files/Filesystem.php147
-rw-r--r--lib/private/Files/Mount/Manager.php62
-rw-r--r--lib/private/Files/Node/Root.php60
-rw-r--r--lib/private/Files/SetupManager.php283
-rw-r--r--lib/private/Files/SetupManagerFactory.php66
-rw-r--r--lib/private/Files/View.php23
-rw-r--r--lib/private/Server.php10
-rw-r--r--lib/private/legacy/OC_Util.php150
-rw-r--r--lib/public/Files/Config/ICachedMountFileInfo.php4
-rw-r--r--lib/public/Files/Config/ICachedMountInfo.php16
-rw-r--r--lib/public/Files/Events/Node/FilesystemTornDownEvent.php34
-rw-r--r--lib/public/Files/Mount/IMountManager.php14
19 files changed, 569 insertions, 424 deletions
diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php
index 6fd3d9207db..86efab3ad52 100644
--- a/lib/composer/composer/autoload_classmap.php
+++ b/lib/composer/composer/autoload_classmap.php
@@ -271,6 +271,7 @@ return array(
'OCP\\Files\\Events\\Node\\BeforeNodeRenamedEvent' => $baseDir . '/lib/public/Files/Events/Node/BeforeNodeRenamedEvent.php',
'OCP\\Files\\Events\\Node\\BeforeNodeTouchedEvent' => $baseDir . '/lib/public/Files/Events/Node/BeforeNodeTouchedEvent.php',
'OCP\\Files\\Events\\Node\\BeforeNodeWrittenEvent' => $baseDir . '/lib/public/Files/Events/Node/BeforeNodeWrittenEvent.php',
+ 'OCP\\Files\\Events\\Node\\FilesystemTornDownEvent' => $baseDir . '/lib/public/Files/Events/Node/FilesystemTornDownEvent.php',
'OCP\\Files\\Events\\Node\\NodeCopiedEvent' => $baseDir . '/lib/public/Files/Events/Node/NodeCopiedEvent.php',
'OCP\\Files\\Events\\Node\\NodeCreatedEvent' => $baseDir . '/lib/public/Files/Events/Node/NodeCreatedEvent.php',
'OCP\\Files\\Events\\Node\\NodeDeletedEvent' => $baseDir . '/lib/public/Files/Events/Node/NodeDeletedEvent.php',
@@ -1162,6 +1163,8 @@ return array(
'OC\\Files\\Search\\SearchComparison' => $baseDir . '/lib/private/Files/Search/SearchComparison.php',
'OC\\Files\\Search\\SearchOrder' => $baseDir . '/lib/private/Files/Search/SearchOrder.php',
'OC\\Files\\Search\\SearchQuery' => $baseDir . '/lib/private/Files/Search/SearchQuery.php',
+ 'OC\\Files\\SetupManager' => $baseDir . '/lib/private/Files/SetupManager.php',
+ 'OC\\Files\\SetupManagerFactory' => $baseDir . '/lib/private/Files/SetupManagerFactory.php',
'OC\\Files\\SimpleFS\\NewSimpleFile' => $baseDir . '/lib/private/Files/SimpleFS/NewSimpleFile.php',
'OC\\Files\\SimpleFS\\SimpleFile' => $baseDir . '/lib/private/Files/SimpleFS/SimpleFile.php',
'OC\\Files\\SimpleFS\\SimpleFolder' => $baseDir . '/lib/private/Files/SimpleFS/SimpleFolder.php',
diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php
index c8c0e7df381..ea37771d63c 100644
--- a/lib/composer/composer/autoload_static.php
+++ b/lib/composer/composer/autoload_static.php
@@ -300,6 +300,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OCP\\Files\\Events\\Node\\BeforeNodeRenamedEvent' => __DIR__ . '/../../..' . '/lib/public/Files/Events/Node/BeforeNodeRenamedEvent.php',
'OCP\\Files\\Events\\Node\\BeforeNodeTouchedEvent' => __DIR__ . '/../../..' . '/lib/public/Files/Events/Node/BeforeNodeTouchedEvent.php',
'OCP\\Files\\Events\\Node\\BeforeNodeWrittenEvent' => __DIR__ . '/../../..' . '/lib/public/Files/Events/Node/BeforeNodeWrittenEvent.php',
+ 'OCP\\Files\\Events\\Node\\FilesystemTornDownEvent' => __DIR__ . '/../../..' . '/lib/public/Files/Events/Node/FilesystemTornDownEvent.php',
'OCP\\Files\\Events\\Node\\NodeCopiedEvent' => __DIR__ . '/../../..' . '/lib/public/Files/Events/Node/NodeCopiedEvent.php',
'OCP\\Files\\Events\\Node\\NodeCreatedEvent' => __DIR__ . '/../../..' . '/lib/public/Files/Events/Node/NodeCreatedEvent.php',
'OCP\\Files\\Events\\Node\\NodeDeletedEvent' => __DIR__ . '/../../..' . '/lib/public/Files/Events/Node/NodeDeletedEvent.php',
@@ -1191,6 +1192,8 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OC\\Files\\Search\\SearchComparison' => __DIR__ . '/../../..' . '/lib/private/Files/Search/SearchComparison.php',
'OC\\Files\\Search\\SearchOrder' => __DIR__ . '/../../..' . '/lib/private/Files/Search/SearchOrder.php',
'OC\\Files\\Search\\SearchQuery' => __DIR__ . '/../../..' . '/lib/private/Files/Search/SearchQuery.php',
+ 'OC\\Files\\SetupManager' => __DIR__ . '/../../..' . '/lib/private/Files/SetupManager.php',
+ 'OC\\Files\\SetupManagerFactory' => __DIR__ . '/../../..' . '/lib/private/Files/SetupManagerFactory.php',
'OC\\Files\\SimpleFS\\NewSimpleFile' => __DIR__ . '/../../..' . '/lib/private/Files/SimpleFS/NewSimpleFile.php',
'OC\\Files\\SimpleFS\\SimpleFile' => __DIR__ . '/../../..' . '/lib/private/Files/SimpleFS/SimpleFile.php',
'OC\\Files\\SimpleFS\\SimpleFolder' => __DIR__ . '/../../..' . '/lib/private/Files/SimpleFS/SimpleFolder.php',
diff --git a/lib/private/Cache/CappedMemoryCache.php b/lib/private/Cache/CappedMemoryCache.php
index 584a53f0ff2..9260bf1f6b3 100644
--- a/lib/private/Cache/CappedMemoryCache.php
+++ b/lib/private/Cache/CappedMemoryCache.php
@@ -27,30 +27,42 @@ use OCP\ICache;
* In-memory cache with a capacity limit to keep memory usage in check
*
* Uses a simple FIFO expiry mechanism
+ * @template T
*/
class CappedMemoryCache implements ICache, \ArrayAccess {
private $capacity;
+ /** @var T[] */
private $cache = [];
public function __construct($capacity = 512) {
$this->capacity = $capacity;
}
- public function hasKey($key) {
+ public function hasKey($key): bool {
return isset($this->cache[$key]);
}
+ /**
+ * @return ?T
+ */
public function get($key) {
- return isset($this->cache[$key]) ? $this->cache[$key] : null;
+ return $this->cache[$key] ?? null;
}
- public function set($key, $value, $ttl = 0) {
+ /**
+ * @param string $key
+ * @param T $value
+ * @param int $ttl
+ * @return bool
+ */
+ public function set($key, $value, $ttl = 0): bool {
if (is_null($key)) {
$this->cache[] = $value;
} else {
$this->cache[$key] = $value;
}
$this->garbageCollect();
+ return true;
}
public function remove($key) {
@@ -68,13 +80,18 @@ class CappedMemoryCache implements ICache, \ArrayAccess {
}
/**
- * @return mixed
+ * @return T
*/
#[\ReturnTypeWillChange]
public function &offsetGet($offset) {
return $this->cache[$offset];
}
+ /**
+ * @param string $key
+ * @param T $value
+ * @return void
+ */
public function offsetSet($offset, $value): void {
$this->set($offset, $value);
}
@@ -83,6 +100,9 @@ class CappedMemoryCache implements ICache, \ArrayAccess {
$this->remove($offset);
}
+ /**
+ * @return T[]
+ */
public function getData() {
return $this->cache;
}
diff --git a/lib/private/Files/Config/CachedMountFileInfo.php b/lib/private/Files/Config/CachedMountFileInfo.php
index 71a6ddb9ea9..11a9a505808 100644
--- a/lib/private/Files/Config/CachedMountFileInfo.php
+++ b/lib/private/Files/Config/CachedMountFileInfo.php
@@ -27,8 +27,7 @@ use OCP\Files\Config\ICachedMountFileInfo;
use OCP\IUser;
class CachedMountFileInfo extends CachedMountInfo implements ICachedMountFileInfo {
- /** @var string */
- private $internalPath;
+ private string $internalPath;
public function __construct(
IUser $user,
diff --git a/lib/private/Files/Config/CachedMountInfo.php b/lib/private/Files/Config/CachedMountInfo.php
index c70dba100a4..43c9fae63ec 100644
--- a/lib/private/Files/Config/CachedMountInfo.php
+++ b/lib/private/Files/Config/CachedMountInfo.php
@@ -28,38 +28,13 @@ use OCP\Files\Node;
use OCP\IUser;
class CachedMountInfo implements ICachedMountInfo {
- /**
- * @var IUser
- */
- protected $user;
-
- /**
- * @var int
- */
- protected $storageId;
-
- /**
- * @var int
- */
- protected $rootId;
-
- /**
- * @var string
- */
- protected $mountPoint;
-
- /**
- * @var int|null
- */
- protected $mountId;
-
- /**
- * @var string
- */
- protected $rootInternalPath;
-
- /** @var string */
- protected $mountProvider;
+ protected IUser $user;
+ protected int $storageId;
+ protected int $rootId;
+ protected string $mountPoint;
+ protected ?int $mountId;
+ protected string $rootInternalPath;
+ protected string $mountProvider;
/**
* CachedMountInfo constructor.
@@ -95,28 +70,28 @@ class CachedMountInfo implements ICachedMountInfo {
/**
* @return IUser
*/
- public function getUser() {
+ public function getUser(): IUser {
return $this->user;
}
/**
* @return int the numeric storage id of the mount
*/
- public function getStorageId() {
+ public function getStorageId(): int {
return $this->storageId;
}
/**
* @return int the fileid of the root of the mount
*/
- public function getRootId() {
+ public function getRootId(): int {
return $this->rootId;
}
/**
- * @return Node the root node of the mount
+ * @return Node|null the root node of the mount
*/
- public function getMountPointNode() {
+ public function getMountPointNode(): ?Node {
// TODO injection etc
Filesystem::initMountPoints($this->getUser()->getUID());
$userNode = \OC::$server->getUserFolder($this->getUser()->getUID());
@@ -131,7 +106,7 @@ class CachedMountInfo implements ICachedMountInfo {
/**
* @return string the mount point of the mount for the user
*/
- public function getMountPoint() {
+ public function getMountPoint(): string {
return $this->mountPoint;
}
@@ -141,7 +116,7 @@ class CachedMountInfo implements ICachedMountInfo {
* @return int|null mount id or null if not applicable
* @since 9.1.0
*/
- public function getMountId() {
+ public function getMountId(): ?int {
return $this->mountId;
}
@@ -150,7 +125,7 @@ class CachedMountInfo implements ICachedMountInfo {
*
* @return string
*/
- public function getRootInternalPath() {
+ public function getRootInternalPath(): string {
return $this->rootInternalPath;
}
diff --git a/lib/private/Files/Config/LazyStorageMountInfo.php b/lib/private/Files/Config/LazyStorageMountInfo.php
index fd3bbcbe0fb..78055a2cdb8 100644
--- a/lib/private/Files/Config/LazyStorageMountInfo.php
+++ b/lib/private/Files/Config/LazyStorageMountInfo.php
@@ -25,8 +25,7 @@ use OCP\Files\Mount\IMountPoint;
use OCP\IUser;
class LazyStorageMountInfo extends CachedMountInfo {
- /** @var IMountPoint */
- private $mount;
+ private IMountPoint $mount;
/**
* CachedMountInfo constructor.
@@ -37,12 +36,15 @@ class LazyStorageMountInfo extends CachedMountInfo {
public function __construct(IUser $user, IMountPoint $mount) {
$this->user = $user;
$this->mount = $mount;
+ $this->rootId = 0;
+ $this->storageId = 0;
+ $this->mountPoint = '';
}
/**
* @return int the numeric storage id of the mount
*/
- public function getStorageId() {
+ public function getStorageId(): int {
if (!$this->storageId) {
$this->storageId = $this->mount->getNumericStorageId();
}
@@ -52,7 +54,7 @@ class LazyStorageMountInfo extends CachedMountInfo {
/**
* @return int the fileid of the root of the mount
*/
- public function getRootId() {
+ public function getRootId(): int {
if (!$this->rootId) {
$this->rootId = $this->mount->getStorageRootId();
}
@@ -62,14 +64,14 @@ class LazyStorageMountInfo extends CachedMountInfo {
/**
* @return string the mount point of the mount for the user
*/
- public function getMountPoint() {
+ public function getMountPoint(): string {
if (!$this->mountPoint) {
$this->mountPoint = $this->mount->getMountPoint();
}
return parent::getMountPoint();
}
- public function getMountId() {
+ public function getMountId(): ?int {
return $this->mount->getMountId();
}
@@ -78,7 +80,7 @@ class LazyStorageMountInfo extends CachedMountInfo {
*
* @return string
*/
- public function getRootInternalPath() {
+ public function getRootInternalPath(): string {
return $this->mount->getInternalPath($this->mount->getMountPoint());
}
diff --git a/lib/private/Files/Config/MountProviderCollection.php b/lib/private/Files/Config/MountProviderCollection.php
index ba70e29ab8d..cd8a2a2e29f 100644
--- a/lib/private/Files/Config/MountProviderCollection.php
+++ b/lib/private/Files/Config/MountProviderCollection.php
@@ -184,16 +184,6 @@ class MountProviderCollection implements IMountProviderCollection, Emitter {
}
/**
- * Cache mounts for user
- *
- * @param IUser $user
- * @param IMountPoint[] $mountPoints
- */
- public function registerMounts(IUser $user, array $mountPoints) {
- $this->mountCache->registerMounts($user, $mountPoints);
- }
-
- /**
* Get the mount cache which can be used to search for mounts without setting up the filesystem
*
* @return IUserMountCache
@@ -222,4 +212,10 @@ class MountProviderCollection implements IMountProviderCollection, Emitter {
}, []);
return $mounts;
}
+
+ public function clearProviders() {
+ $this->providers = [];
+ $this->homeProviders = [];
+ $this->rootProviders = [];
+ }
}
diff --git a/lib/private/Files/Filesystem.php b/lib/private/Files/Filesystem.php
index e439b746bf6..1aedad93aa1 100644
--- a/lib/private/Files/Filesystem.php
+++ b/lib/private/Files/Filesystem.php
@@ -38,13 +38,12 @@
namespace OC\Files;
use OC\Cache\CappedMemoryCache;
-use OC\Files\Config\MountProviderCollection;
use OC\Files\Mount\MountPoint;
-use OC\Lockdown\Filesystem\NullStorage;
-use OCP\Files\Config\IMountProvider;
+use OC\User\NoUserException;
+use OCP\EventDispatcher\IEventDispatcher;
+use OCP\Files\Events\Node\FilesystemTornDownEvent;
use OCP\Files\NotFoundException;
use OCP\Files\Storage\IStorageFactory;
-use OCP\ILogger;
use OCP\IUser;
use OCP\IUserManager;
@@ -259,11 +258,7 @@ class Filesystem {
\OC_Util::setupFS();
}
$mount = self::$mounts->find($path);
- if ($mount) {
- return $mount->getMountPoint();
- } else {
- return '';
- }
+ return $mount->getMountPoint();
}
/**
@@ -319,11 +314,7 @@ class Filesystem {
*/
public static function resolvePath($path) {
$mount = self::getMountManager()->find($path);
- if ($mount) {
- return [$mount->getStorage(), rtrim($mount->getInternalPath($path), '/')];
- } else {
- return [null, null];
- }
+ return [$mount->getStorage(), rtrim($mount->getInternalPath($path), '/')];
}
public static function init($user, $root) {
@@ -332,6 +323,13 @@ class Filesystem {
}
self::getLoader();
self::$defaultInstance = new View($root);
+ /** @var IEventDispatcher $eventDispatcher */
+ $eventDispatcher = \OC::$server->get(IEventDispatcher::class);
+ $eventDispatcher->addListener(FilesystemTornDownEvent::class, function () {
+ self::$defaultInstance = null;
+ self::$usersSetup = [];
+ self::$loaded = false;
+ });
if (!self::$mounts) {
self::$mounts = \OC::$server->getMountManager();
@@ -358,106 +356,16 @@ class Filesystem {
* @throws \OC\User\NoUserException if the user is not available
*/
public static function initMountPoints($user = '') {
- $userManager = \OC::$server->getUserManager();
- if (is_string($user)) {
- if ($user === '') {
- $user = \OC_User::getUser();
- }
-
- $userObject = $userManager->get($user);
- } elseif ($user instanceof IUser) {
- $userObject = $user;
- $user = $userObject->getUID();
- } else {
- $userObject = null;
- }
-
- if ($userObject === null || $user === false || $user === '') {
- throw new \OC\User\NoUserException('Attempted to initialize mount points for null user and no user in session');
- }
-
- if (isset(self::$usersSetup[$user])) {
- return;
- }
-
- self::$usersSetup[$user] = true;
-
- if (is_null($userObject)) {
- \OCP\Util::writeLog('files', ' Backends provided no user object for ' . $user, ILogger::ERROR);
- // reset flag, this will make it possible to rethrow the exception if called again
- unset(self::$usersSetup[$user]);
- throw new \OC\User\NoUserException('Backends provided no user object for ' . $user);
- }
-
- $realUid = $userObject->getUID();
- // workaround in case of different casings
- if ($user !== $realUid) {
- $stack = json_encode(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 50));
- \OCP\Util::writeLog('files', 'initMountPoints() called with wrong user casing. This could be a bug. Expected: "' . $realUid . '" got "' . $user . '". Stack: ' . $stack, ILogger::WARN);
- $user = $realUid;
-
- // again with the correct casing
- if (isset(self::$usersSetup[$user])) {
- return;
- }
-
- self::$usersSetup[$user] = true;
- }
-
- if (\OC::$server->getLockdownManager()->canAccessFilesystem()) {
- /** @var \OC\Files\Config\MountProviderCollection $mountConfigManager */
- $mountConfigManager = \OC::$server->getMountProviderCollection();
-
- // home mounts are handled seperate since we need to ensure this is mounted before we call the other mount providers
- $homeMount = $mountConfigManager->getHomeMountForUser($userObject);
- self::getMountManager()->addMount($homeMount);
-
- if ($homeMount->getStorageRootId() === -1) {
- $homeMount->getStorage()->mkdir('');
- $homeMount->getStorage()->getScanner()->scan('');
- }
-
- \OC\Files\Filesystem::getStorage($user);
-
- // Chance to mount for other storages
- if ($userObject) {
- $mounts = $mountConfigManager->addMountForUser($userObject, self::getMountManager());
- $mounts[] = $homeMount;
- $mountConfigManager->registerMounts($userObject, $mounts);
- }
-
- self::listenForNewMountProviders($mountConfigManager, $userManager);
+ /** @var IUserManager $userManager */
+ $userManager = \OC::$server->get(IUserManager::class);
+
+ $userObject = ($user instanceof IUser) ? $user : $userManager->get($user);
+ if ($userObject) {
+ /** @var SetupManager $setupManager */
+ $setupManager = \OC::$server->get(SetupManager::class);
+ $setupManager->setupForUser($userObject);
} else {
- self::getMountManager()->addMount(new MountPoint(
- new NullStorage([]),
- '/' . $user
- ));
- self::getMountManager()->addMount(new MountPoint(
- new NullStorage([]),
- '/' . $user . '/files'
- ));
- }
- \OC_Hook::emit('OC_Filesystem', 'post_initMountPoints', ['user' => $user]);
- }
-
- /**
- * Get mounts from mount providers that are registered after setup
- *
- * @param MountProviderCollection $mountConfigManager
- * @param IUserManager $userManager
- */
- private static function listenForNewMountProviders(MountProviderCollection $mountConfigManager, IUserManager $userManager) {
- if (!self::$listeningForProviders) {
- self::$listeningForProviders = true;
- $mountConfigManager->listen('\OC\Files\Config', 'registerMountProvider', function (IMountProvider $provider) use ($userManager) {
- foreach (Filesystem::$usersSetup as $user => $setup) {
- $userObject = $userManager->get($user);
- if ($userObject) {
- $mounts = $provider->getMountsForUser($userObject, Filesystem::getLoader());
- array_walk($mounts, [self::$mounts, 'addMount']);
- }
- }
- });
+ throw new NoUserException();
}
}
@@ -474,8 +382,7 @@ class Filesystem {
* tear down the filesystem, removing all storage providers
*/
public static function tearDown() {
- self::clearMounts();
- self::$defaultInstance = null;
+ \OC_Util::tearDownFS();
}
/**
@@ -493,16 +400,6 @@ class Filesystem {
}
/**
- * clear all mounts and storage backends
- */
- public static function clearMounts() {
- if (self::$mounts) {
- self::$usersSetup = [];
- self::$mounts->clear();
- }
- }
-
- /**
* mount an \OC\Files\Storage\Storage in our virtual filesystem
*
* @param \OC\Files\Storage\Storage|string $class
diff --git a/lib/private/Files/Mount/Manager.php b/lib/private/Files/Mount/Manager.php
index 22b05b1f384..66832690363 100644
--- a/lib/private/Files/Mount/Manager.php
+++ b/lib/private/Files/Mount/Manager.php
@@ -26,26 +26,30 @@ declare(strict_types=1);
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
+
namespace OC\Files\Mount;
use OC\Cache\CappedMemoryCache;
use OC\Files\Filesystem;
+use OC\Files\SetupManager;
+use OC\Files\SetupManagerFactory;
use OCP\Files\Mount\IMountManager;
use OCP\Files\Mount\IMountPoint;
+use OCP\Files\NotFoundException;
class Manager implements IMountManager {
/** @var MountPoint[] */
- private $mounts = [];
-
- /** @var CappedMemoryCache */
- private $pathCache;
-
- /** @var CappedMemoryCache */
- private $inPathCache;
-
- public function __construct() {
+ private array $mounts = [];
+ /** @var CappedMemoryCache<IMountPoint> */
+ private CappedMemoryCache $pathCache;
+ /** @var CappedMemoryCache<IMountPoint[]> */
+ private CappedMemoryCache $inPathCache;
+ private SetupManager $setupManager;
+
+ public function __construct(SetupManagerFactory $setupManagerFactory) {
$this->pathCache = new CappedMemoryCache();
$this->inPathCache = new CappedMemoryCache();
+ $this->setupManager = $setupManagerFactory->create($this);
}
/**
@@ -81,26 +85,14 @@ class Manager implements IMountManager {
$this->inPathCache->clear();
}
- private function setupForFind(string $path) {
- if (strpos($path, '/appdata_' . \OC_Util::getInstanceId()) === 0) {
- // for appdata, we only setup the root bits, not the user bits
- \OC_Util::setupRootFS();
- } elseif (strpos($path, '/files_external/uploads/') === 0) {
- // for OC\Security\CertificateManager, we only setup the root bits, not the user bits
- \OC_Util::setupRootFS();
- } else {
- \OC_Util::setupFS();
- }
- }
-
/**
* Find the mount for $path
*
* @param string $path
- * @return MountPoint|null
+ * @return IMountPoint
*/
- public function find(string $path) {
- $this->setupForFind($path);
+ public function find(string $path): IMountPoint {
+ $this->setupManager->setupForPath($path);
$path = Filesystem::normalizePath($path);
if (isset($this->pathCache[$path])) {
@@ -113,10 +105,8 @@ class Manager implements IMountManager {
if (isset($this->mounts[$mountPoint])) {
$this->pathCache[$path] = $this->mounts[$mountPoint];
return $this->mounts[$mountPoint];
- }
-
- if ($current === '') {
- return null;
+ } elseif ($current === '') {
+ break;
}
$current = dirname($current);
@@ -124,16 +114,18 @@ class Manager implements IMountManager {
$current = '';
}
}
+
+ throw new NotFoundException("No mount for path " . $path . " existing mounts: " . implode(",", array_keys($this->mounts)));
}
/**
* Find all mounts in $path
*
* @param string $path
- * @return MountPoint[]
+ * @return IMountPoint[]
*/
public function findIn(string $path): array {
- $this->setupForFind($path);
+ $this->setupManager->setupForPath($path);
$path = $this->formatPath($path);
if (isset($this->inPathCache[$path])) {
@@ -163,7 +155,7 @@ class Manager implements IMountManager {
* Find mounts by storage id
*
* @param string $id
- * @return MountPoint[]
+ * @return IMountPoint[]
*/
public function findByStorageId(string $id): array {
\OC_Util::setupFS();
@@ -180,7 +172,7 @@ class Manager implements IMountManager {
}
/**
- * @return MountPoint[]
+ * @return IMountPoint[]
*/
public function getAll(): array {
return $this->mounts;
@@ -190,7 +182,7 @@ class Manager implements IMountManager {
* Find mounts by numeric storage id
*
* @param int $id
- * @return MountPoint[]
+ * @return IMountPoint[]
*/
public function findByNumericId(int $id): array {
$storageId = \OC\Files\Cache\Storage::getStorageId($id);
@@ -208,4 +200,8 @@ class Manager implements IMountManager {
}
return $path;
}
+
+ public function getSetupManager(): SetupManager {
+ return $this->setupManager;
+ }
}
diff --git a/lib/private/Files/Node/Root.php b/lib/private/Files/Node/Root.php
index b5707c87543..88ac4a31d34 100644
--- a/lib/private/Files/Node/Root.php
+++ b/lib/private/Files/Node/Root.php
@@ -35,13 +35,17 @@ namespace OC\Files\Node;
use OC\Cache\CappedMemoryCache;
use OC\Files\Mount\Manager;
use OC\Files\Mount\MountPoint;
+use OC\Files\View;
use OC\Hooks\PublicEmitter;
use OC\User\NoUserException;
+use OCP\EventDispatcher\IEventDispatcher;
use OCP\Files\Config\IUserMountCache;
+use OCP\Files\Events\Node\FilesystemTornDownEvent;
use OCP\Files\IRootFolder;
use OCP\Files\NotFoundException;
use OCP\Files\NotPermittedException;
use OCP\ILogger;
+use OCP\IUser;
use OCP\IUserManager;
/**
@@ -64,35 +68,32 @@ use OCP\IUserManager;
* @package OC\Files\Node
*/
class Root extends Folder implements IRootFolder {
- /** @var Manager */
- private $mountManager;
- /** @var PublicEmitter */
- private $emitter;
- /** @var null|\OC\User\User */
- private $user;
- /** @var CappedMemoryCache */
- private $userFolderCache;
- /** @var IUserMountCache */
- private $userMountCache;
- /** @var ILogger */
- private $logger;
- /** @var IUserManager */
- private $userManager;
+ private Manager $mountManager;
+ private PublicEmitter $emitter;
+ private ?IUser $user;
+ private CappedMemoryCache $userFolderCache;
+ private IUserMountCache $userMountCache;
+ private ILogger $logger;
+ private IUserManager $userManager;
+ private IEventDispatcher $eventDispatcher;
/**
- * @param \OC\Files\Mount\Manager $manager
- * @param \OC\Files\View $view
- * @param \OC\User\User|null $user
+ * @param Manager $manager
+ * @param View $view
+ * @param IUser|null $user
* @param IUserMountCache $userMountCache
* @param ILogger $logger
* @param IUserManager $userManager
*/
- public function __construct($manager,
+ public function __construct(
+ $manager,
$view,
$user,
- IUserMountCache $userMountCache,
- ILogger $logger,
- IUserManager $userManager) {
+ IUserMountCache $userMountCache,
+ ILogger $logger,
+ IUserManager $userManager,
+ IEventDispatcher $eventDispatcher
+ ) {
parent::__construct($this, $view, '');
$this->mountManager = $manager;
$this->user = $user;
@@ -101,6 +102,9 @@ class Root extends Folder implements IRootFolder {
$this->userMountCache = $userMountCache;
$this->logger = $logger;
$this->userManager = $userManager;
+ $eventDispatcher->addListener(FilesystemTornDownEvent::class, function () {
+ $this->userFolderCache = new CappedMemoryCache();
+ });
}
/**
@@ -267,21 +271,21 @@ class Root extends Folder implements IRootFolder {
* @return int
*/
public function getId() {
- return null;
+ return 0;
}
/**
* @return array
*/
public function stat() {
- return null;
+ return [];
}
/**
* @return int
*/
public function getMTime() {
- return null;
+ return 0;
}
/**
@@ -289,14 +293,14 @@ class Root extends Folder implements IRootFolder {
* @return int
*/
public function getSize($includeMounts = true) {
- return null;
+ return 0;
}
/**
* @return string
*/
public function getEtag() {
- return null;
+ return '';
}
/**
@@ -393,10 +397,6 @@ class Root extends Folder implements IRootFolder {
return $this->userFolderCache->get($userId);
}
- public function clearCache() {
- $this->userFolderCache = new CappedMemoryCache();
- }
-
public function getUserMountCache() {
return $this->userMountCache;
}
diff --git a/lib/private/Files/SetupManager.php b/lib/private/Files/SetupManager.php
new file mode 100644
index 00000000000..f9276ef4171
--- /dev/null
+++ b/lib/private/Files/SetupManager.php
@@ -0,0 +1,283 @@
+<?php
+
+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/>.
+ *
+ */
+
+namespace OC\Files;
+
+use OC\Files\Config\MountProviderCollection;
+use OC\Files\Mount\MountPoint;
+use OC\Files\ObjectStore\HomeObjectStoreStorage;
+use OC\Files\Storage\Common;
+use OC\Files\Storage\Home;
+use OC\Files\Storage\Storage;
+use OC\Files\Storage\Wrapper\Availability;
+use OC\Files\Storage\Wrapper\Encoding;
+use OC\Files\Storage\Wrapper\PermissionsMask;
+use OC\Files\Storage\Wrapper\Quota;
+use OC\Lockdown\Filesystem\NullStorage;
+use OC_App;
+use OC_Hook;
+use OC_Util;
+use OCP\Constants;
+use OCP\Diagnostics\IEventLogger;
+use OCP\EventDispatcher\IEventDispatcher;
+use OCP\Files\Config\IMountProvider;
+use OCP\Files\Config\IUserMountCache;
+use OCP\Files\Events\Node\FilesystemTornDownEvent;
+use OCP\Files\Mount\IMountManager;
+use OCP\Files\Mount\IMountPoint;
+use OCP\Files\Storage\IStorage;
+use OCP\IUser;
+use OCP\IUserManager;
+use OCP\Lockdown\ILockdownManager;
+
+class SetupManager {
+ private bool $rootSetup = false;
+ private IEventLogger $eventLogger;
+ private MountProviderCollection $mountProviderCollection;
+ private IMountManager $mountManager;
+ private IUserManager $userManager;
+ private array $setupUsers = [];
+ private IEventDispatcher $eventDispatcher;
+ private IUserMountCache $userMountCache;
+ private ILockdownManager $lockdownManager;
+ private bool $listeningForProviders;
+
+ public function __construct(
+ IEventLogger $eventLogger,
+ MountProviderCollection $mountProviderCollection,
+ IMountManager $mountManager,
+ IUserManager $userManager,
+ IEventDispatcher $eventDispatcher,
+ IUserMountCache $userMountCache,
+ ILockdownManager $lockdownManager
+ ) {
+ $this->eventLogger = $eventLogger;
+ $this->mountProviderCollection = $mountProviderCollection;
+ $this->mountManager = $mountManager;
+ $this->userManager = $userManager;
+ $this->eventDispatcher = $eventDispatcher;
+ $this->userMountCache = $userMountCache;
+ $this->lockdownManager = $lockdownManager;
+ $this->listeningForProviders = false;
+ }
+
+ private function setupBuiltinWrappers() {
+ Filesystem::addStorageWrapper('mount_options', function ($mountPoint, IStorage $storage, IMountPoint $mount) {
+ if ($storage->instanceOfStorage(Common::class)) {
+ $storage->setMountOptions($mount->getOptions());
+ }
+ return $storage;
+ });
+
+ Filesystem::addStorageWrapper('enable_sharing', function ($mountPoint, IStorage $storage, IMountPoint $mount) {
+ if (!$mount->getOption('enable_sharing', true)) {
+ return new PermissionsMask([
+ 'storage' => $storage,
+ 'mask' => Constants::PERMISSION_ALL - Constants::PERMISSION_SHARE,
+ ]);
+ }
+ return $storage;
+ });
+
+ // install storage availability wrapper, before most other wrappers
+ Filesystem::addStorageWrapper('oc_availability', function ($mountPoint, IStorage $storage) {
+ if (!$storage->instanceOfStorage('\OCA\Files_Sharing\SharedStorage') && !$storage->isLocal()) {
+ return new Availability(['storage' => $storage]);
+ }
+ return $storage;
+ });
+
+ Filesystem::addStorageWrapper('oc_encoding', function ($mountPoint, IStorage $storage, IMountPoint $mount) {
+ if ($mount->getOption('encoding_compatibility', false) && !$storage->instanceOfStorage('\OCA\Files_Sharing\SharedStorage') && !$storage->isLocal()) {
+ return new Encoding(['storage' => $storage]);
+ }
+ return $storage;
+ });
+
+ Filesystem::addStorageWrapper('oc_quota', function ($mountPoint, $storage) {
+ // set up quota for home storages, even for other users
+ // which can happen when using sharing
+
+ /**
+ * @var Storage $storage
+ */
+ if ($storage->instanceOfStorage(HomeObjectStoreStorage::class) || $storage->instanceOfStorage(Home::class)) {
+ if (is_object($storage->getUser())) {
+ $quota = OC_Util::getUserQuota($storage->getUser());
+ if ($quota !== \OCP\Files\FileInfo::SPACE_UNLIMITED) {
+ return new Quota(['storage' => $storage, 'quota' => $quota, 'root' => 'files']);
+ }
+ }
+ }
+
+ return $storage;
+ });
+
+ Filesystem::addStorageWrapper('readonly', function ($mountPoint, IStorage $storage, IMountPoint $mount) {
+ /*
+ * Do not allow any operations that modify the storage
+ */
+ if ($mount->getOption('readonly', false)) {
+ return new PermissionsMask([
+ 'storage' => $storage,
+ 'mask' => Constants::PERMISSION_ALL & ~(
+ Constants::PERMISSION_UPDATE |
+ Constants::PERMISSION_CREATE |
+ Constants::PERMISSION_DELETE
+ ),
+ ]);
+ }
+ return $storage;
+ });
+ }
+
+ /**
+ * Setup the full filesystem for the specified user
+ */
+ public function setupForUser(IUser $user): void {
+ $this->setupRoot();
+
+ if (in_array($user->getUID(), $this->setupUsers, true)) {
+ return;
+ }
+ $this->setupUsers[] = $user->getUID();
+
+ $this->eventLogger->start('setup_fs', 'Setup filesystem');
+
+ $prevLogging = Filesystem::logWarningWhenAddingStorageWrapper(false);
+
+ OC_Hook::emit('OC_Filesystem', 'preSetup', ['user' => $user->getUID()]);
+
+ Filesystem::logWarningWhenAddingStorageWrapper($prevLogging);
+
+ $userDir = '/' . $user->getUID() . '/files';
+
+ Filesystem::init($user, $userDir);
+
+ if ($this->lockdownManager->canAccessFilesystem()) {
+ // home mounts are handled separate since we need to ensure this is mounted before we call the other mount providers
+ $homeMount = $this->mountProviderCollection->getHomeMountForUser($user);
+ $this->mountManager->addMount($homeMount);
+
+ if ($homeMount->getStorageRootId() === -1) {
+ $homeMount->getStorage()->mkdir('');
+ $homeMount->getStorage()->getScanner()->scan('');
+ }
+
+ // Chance to mount for other storages
+ $mounts = $this->mountProviderCollection->addMountForUser($user, $this->mountManager);
+ $mounts[] = $homeMount;
+ $this->userMountCache->registerMounts($user, $mounts);
+
+ $this->listenForNewMountProviders();
+ } else {
+ $this->mountManager->addMount(new MountPoint(
+ new NullStorage([]),
+ '/' . $user->getUID()
+ ));
+ $this->mountManager->addMount(new MountPoint(
+ new NullStorage([]),
+ '/' . $user->getUID() . '/files'
+ ));
+ }
+ \OC_Hook::emit('OC_Filesystem', 'post_initMountPoints', ['user' => $user->getUID()]);
+
+ OC_Hook::emit('OC_Filesystem', 'setup', ['user' => $user->getUID(), 'user_dir' => $userDir]);
+
+ $this->eventLogger->end('setup_fs');
+ }
+
+ /**
+ * Set up the root filesystem
+ */
+ public function setupRoot(): void {
+ //setting up the filesystem twice can only lead to trouble
+ if ($this->rootSetup) {
+ return;
+ }
+ $this->rootSetup = true;
+
+ $this->eventLogger->start('setup_root_fs', 'Setup root filesystem');
+
+ // load all filesystem apps before, so no setup-hook gets lost
+ OC_App::loadApps(['filesystem']);
+ $prevLogging = Filesystem::logWarningWhenAddingStorageWrapper(false);
+
+ $this->setupBuiltinWrappers();
+
+ Filesystem::logWarningWhenAddingStorageWrapper($prevLogging);
+
+ $rootMounts = $this->mountProviderCollection->getRootMounts();
+ foreach ($rootMounts as $rootMountProvider) {
+ $this->mountManager->addMount($rootMountProvider);
+ }
+
+ $this->eventLogger->end('setup_root_fs');
+ }
+
+ /**
+ * Set up the filesystem for the specified path
+ */
+ public function setupForPath(string $path): void {
+ if (substr_count($path, '/') < 2 || strpos($path, '/appdata_' . \OC_Util::getInstanceId()) === 0 || strpos($path, '/files_external/') === 0) {
+ $this->setupRoot();
+ return;
+ } else {
+ [, $userId] = explode('/', $path);
+ }
+
+ $user = $this->userManager->get($userId);
+
+ if (!$user) {
+ $this->setupRoot();
+ return;
+ }
+
+ $this->setupForUser($user);
+ }
+
+ public function tearDown() {
+ $this->setupUsers = [];
+ $this->rootSetup = false;
+ $this->mountManager->clear();
+ $this->eventDispatcher->dispatchTyped(new FilesystemTornDownEvent());
+ }
+
+ /**
+ * Get mounts from mount providers that are registered after setup
+ */
+ private function listenForNewMountProviders() {
+ if (!$this->listeningForProviders) {
+ $this->listeningForProviders = true;
+ $this->mountProviderCollection->listen('\OC\Files\Config', 'registerMountProvider', function (IMountProvider $provider) {
+ foreach ($this->setupUsers as $userId) {
+ $user = $this->userManager->get($userId);
+ if ($user) {
+ $mounts = $provider->getMountsForUser($user, Filesystem::getLoader());
+ array_walk($mounts, [$this->mountManager, 'addMount']);
+ }
+ }
+ });
+ }
+ }
+}
diff --git a/lib/private/Files/SetupManagerFactory.php b/lib/private/Files/SetupManagerFactory.php
new file mode 100644
index 00000000000..5dd1601570d
--- /dev/null
+++ b/lib/private/Files/SetupManagerFactory.php
@@ -0,0 +1,66 @@
+<?php
+
+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/>.
+ *
+ */
+
+namespace OC\Files;
+
+use OCP\Diagnostics\IEventLogger;
+use OCP\EventDispatcher\IEventDispatcher;
+use OCP\Files\Config\IMountProviderCollection;
+use OCP\Files\Config\IUserMountCache;
+use OCP\Files\Mount\IMountManager;
+use OCP\IUserManager;
+use OCP\Lockdown\ILockdownManager;
+
+class SetupManagerFactory {
+ private IEventLogger $eventLogger;
+ private IMountProviderCollection $mountProviderCollection;
+ private IUserManager $userManager;
+ private IEventDispatcher $eventDispatcher;
+ private IUserMountCache $userMountCache;
+ private ILockdownManager $lockdownManager;
+ private ?SetupManager $setupManager;
+
+ public function __construct(
+ IEventLogger $eventLogger,
+ IMountProviderCollection $mountProviderCollection,
+ IUserManager $userManager,
+ IEventDispatcher $eventDispatcher,
+ IUserMountCache $userMountCache,
+ ILockdownManager $lockdownManager
+ ) {
+ $this->eventLogger = $eventLogger;
+ $this->mountProviderCollection = $mountProviderCollection;
+ $this->userManager = $userManager;
+ $this->eventDispatcher = $eventDispatcher;
+ $this->userMountCache = $userMountCache;
+ $this->lockdownManager = $lockdownManager;
+ $this->setupManager = null;
+ }
+
+ public function create(IMountManager $mountManager): SetupManager {
+ if (!$this->setupManager) {
+ $this->setupManager = new SetupManager($this->eventLogger, $this->mountProviderCollection, $mountManager, $this->userManager, $this->eventDispatcher, $this->userMountCache, $this->lockdownManager);
+ }
+ return $this->setupManager;
+ }
+}
diff --git a/lib/private/Files/View.php b/lib/private/Files/View.php
index 3cdc6166840..779e0611591 100644
--- a/lib/private/Files/View.php
+++ b/lib/private/Files/View.php
@@ -274,7 +274,7 @@ class View {
/**
* remove mount point
*
- * @param \OC\Files\Mount\MoveableMount $mount
+ * @param IMountPoint $mount
* @param string $path relative to data/
* @return boolean
*/
@@ -719,7 +719,7 @@ class View {
$postFix = (substr($path, -1) === '/') ? '/' : '';
$absolutePath = Filesystem::normalizePath($this->getAbsolutePath($path));
$mount = Filesystem::getMountManager()->find($absolutePath . $postFix);
- if ($mount and $mount->getInternalPath($absolutePath) === '') {
+ if ($mount->getInternalPath($absolutePath) === '') {
return $this->removeMount($mount, $absolutePath);
}
if ($this->is_dir($path)) {
@@ -1383,10 +1383,6 @@ class View {
$path = Filesystem::normalizePath($this->fakeRoot . '/' . $path);
$mount = Filesystem::getMountManager()->find($path);
- if (!$mount) {
- \OC::$server->getLogger()->warning('Mountpoint not found for path: ' . $path);
- return false;
- }
$storage = $mount->getStorage();
$internalPath = $mount->getInternalPath($path);
if ($storage) {
@@ -1488,7 +1484,7 @@ class View {
$rootEntry = $subCache->get('');
if (!$rootEntry) {
- $subScanner = $subStorage->getScanner('');
+ $subScanner = $subStorage->getScanner();
try {
$subScanner->scanFile('');
} catch (\OCP\Files\StorageNotAvailableException $e) {
@@ -1739,12 +1735,13 @@ class View {
$manager = Filesystem::getMountManager();
$mounts = $manager->findIn($this->fakeRoot);
$mounts[] = $manager->find($this->fakeRoot);
- // reverse the array so we start with the storage this view is in
+ $mounts = array_filter($mounts);
+ // reverse the array, so we start with the storage this view is in
// which is the most likely to contain the file we're looking for
$mounts = array_reverse($mounts);
- // put non shared mounts in front of the shared mount
- // this prevent unneeded recursion into shares
+ // put non-shared mounts in front of the shared mount
+ // this prevents unneeded recursion into shares
usort($mounts, function (IMountPoint $a, IMountPoint $b) {
return $a instanceof SharedMount && (!$b instanceof SharedMount) ? 1 : -1;
});
@@ -1915,14 +1912,10 @@ class View {
* @param string $absolutePath absolute path
* @param bool $useParentMount true to return parent mount instead of whatever
* is mounted directly on the given path, false otherwise
- * @return \OC\Files\Mount\MountPoint mount point for which to apply locks
+ * @return IMountPoint mount point for which to apply locks
*/
private function getMountForLock($absolutePath, $useParentMount = false) {
- $results = [];
$mount = Filesystem::getMountManager()->find($absolutePath);
- if (!$mount) {
- return $results;
- }
if ($useParentMount) {
// find out if something is mounted directly on the path
diff --git a/lib/private/Server.php b/lib/private/Server.php
index 8d1f377251c..38720ab71c0 100644
--- a/lib/private/Server.php
+++ b/lib/private/Server.php
@@ -95,6 +95,7 @@ use OC\Files\Mount\RootMountProvider;
use OC\Files\Node\HookConnector;
use OC\Files\Node\LazyRoot;
use OC\Files\Node\Root;
+use OC\Files\SetupManager;
use OC\Files\Storage\StorageFactory;
use OC\Files\Template\TemplateManager;
use OC\Files\Type\Loader;
@@ -216,6 +217,7 @@ use OCP\L10N\IFactory;
use OCP\LDAP\ILDAPProvider;
use OCP\LDAP\ILDAPProviderFactory;
use OCP\Lock\ILockingProvider;
+use OCP\Lockdown\ILockdownManager;
use OCP\Log\ILogFactory;
use OCP\Mail\IMailer;
use OCP\Remote\Api\IApiFactory;
@@ -423,7 +425,8 @@ class Server extends ServerContainer implements IServerContainer {
null,
$c->get(IUserMountCache::class),
$this->get(ILogger::class),
- $this->get(IUserManager::class)
+ $this->get(IUserManager::class),
+ $this->get(IEventDispatcher::class),
);
$previewConnector = new \OC\Preview\WatcherConnector(
@@ -1091,6 +1094,11 @@ class Server extends ServerContainer implements IServerContainer {
/** @deprecated 19.0.0 */
$this->registerDeprecatedAlias('LockingProvider', ILockingProvider::class);
+ $this->registerAlias(ILockdownManager::class, 'LockdownManager');
+ $this->registerService(SetupManager::class, function ($c) {
+ // create the setupmanager through the mount manager to resolve the cyclic dependency
+ return $c->get(\OC\Files\Mount\Manager::class)->getSetupManager();
+ });
$this->registerAlias(IMountManager::class, \OC\Files\Mount\Manager::class);
/** @deprecated 19.0.0 */
$this->registerDeprecatedAlias('MountManager', IMountManager::class);
diff --git a/lib/private/legacy/OC_Util.php b/lib/private/legacy/OC_Util.php
index 40dcbb13b93..ceed79bc9d5 100644
--- a/lib/private/legacy/OC_Util.php
+++ b/lib/private/legacy/OC_Util.php
@@ -66,6 +66,7 @@
use bantu\IniGetWrapper\IniGetWrapper;
use OC\AppFramework\Http\Request;
+use OC\Files\SetupManager;
use OCP\Files\Template\ITemplateManager;
use OCP\IConfig;
use OCP\IGroupManager;
@@ -78,8 +79,6 @@ class OC_Util {
public static $scripts = [];
public static $styles = [];
public static $headers = [];
- private static $rootFsSetup = false;
- private static $fsSetup = false;
/** @var array Local cache of version.php */
private static $versionCache = null;
@@ -89,122 +88,6 @@ class OC_Util {
}
/**
- * Can be set up
- *
- * @param string $user
- * @return boolean
- * @description configure the initial filesystem based on the configuration
- * @suppress PhanDeprecatedFunction
- * @suppress PhanAccessMethodInternal
- */
- public static function setupRootFS(string $user = '') {
- //setting up the filesystem twice can only lead to trouble
- if (self::$rootFsSetup) {
- return false;
- }
-
- \OC::$server->getEventLogger()->start('setup_root_fs', 'Setup root filesystem');
-
- // load all filesystem apps before, so no setup-hook gets lost
- OC_App::loadApps(['filesystem']);
-
- self::$rootFsSetup = true;
-
- \OC\Files\Filesystem::initMountManager();
-
- $prevLogging = \OC\Files\Filesystem::logWarningWhenAddingStorageWrapper(false);
- \OC\Files\Filesystem::addStorageWrapper('mount_options', function ($mountPoint, \OCP\Files\Storage $storage, \OCP\Files\Mount\IMountPoint $mount) {
- if ($storage->instanceOfStorage('\OC\Files\Storage\Common')) {
- /** @var \OC\Files\Storage\Common $storage */
- $storage->setMountOptions($mount->getOptions());
- }
- return $storage;
- });
-
- \OC\Files\Filesystem::addStorageWrapper('enable_sharing', function ($mountPoint, \OCP\Files\Storage\IStorage $storage, \OCP\Files\Mount\IMountPoint $mount) {
- if (!$mount->getOption('enable_sharing', true)) {
- return new \OC\Files\Storage\Wrapper\PermissionsMask([
- 'storage' => $storage,
- 'mask' => \OCP\Constants::PERMISSION_ALL - \OCP\Constants::PERMISSION_SHARE
- ]);
- }
- return $storage;
- });
-
- // install storage availability wrapper, before most other wrappers
- \OC\Files\Filesystem::addStorageWrapper('oc_availability', function ($mountPoint, \OCP\Files\Storage\IStorage $storage) {
- if (!$storage->instanceOfStorage('\OCA\Files_Sharing\SharedStorage') && !$storage->isLocal()) {
- return new \OC\Files\Storage\Wrapper\Availability(['storage' => $storage]);
- }
- return $storage;
- });
-
- \OC\Files\Filesystem::addStorageWrapper('oc_encoding', function ($mountPoint, \OCP\Files\Storage $storage, \OCP\Files\Mount\IMountPoint $mount) {
- if ($mount->getOption('encoding_compatibility', false) && !$storage->instanceOfStorage('\OCA\Files_Sharing\SharedStorage') && !$storage->isLocal()) {
- return new \OC\Files\Storage\Wrapper\Encoding(['storage' => $storage]);
- }
- return $storage;
- });
-
- \OC\Files\Filesystem::addStorageWrapper('oc_quota', function ($mountPoint, $storage) {
- // set up quota for home storages, even for other users
- // which can happen when using sharing
-
- /**
- * @var \OC\Files\Storage\Storage $storage
- */
- if ($storage->instanceOfStorage('\OC\Files\Storage\Home')
- || $storage->instanceOfStorage('\OC\Files\ObjectStore\HomeObjectStoreStorage')
- ) {
- /** @var \OC\Files\Storage\Home $storage */
- if (is_object($storage->getUser())) {
- $quota = OC_Util::getUserQuota($storage->getUser());
- if ($quota !== \OCP\Files\FileInfo::SPACE_UNLIMITED) {
- return new \OC\Files\Storage\Wrapper\Quota(['storage' => $storage, 'quota' => $quota, 'root' => 'files']);
- }
- }
- }
-
- return $storage;
- });
-
- \OC\Files\Filesystem::addStorageWrapper('readonly', function ($mountPoint, \OCP\Files\Storage\IStorage $storage, \OCP\Files\Mount\IMountPoint $mount) {
- /*
- * Do not allow any operations that modify the storage
- */
- if ($mount->getOption('readonly', false)) {
- return new \OC\Files\Storage\Wrapper\PermissionsMask([
- 'storage' => $storage,
- 'mask' => \OCP\Constants::PERMISSION_ALL & ~(
- \OCP\Constants::PERMISSION_UPDATE |
- \OCP\Constants::PERMISSION_CREATE |
- \OCP\Constants::PERMISSION_DELETE
- ),
- ]);
- }
- return $storage;
- });
-
- OC_Hook::emit('OC_Filesystem', 'preSetup', ['user' => $user]);
-
- \OC\Files\Filesystem::logWarningWhenAddingStorageWrapper($prevLogging);
-
- /** @var \OCP\Files\Config\IMountProviderCollection $mountProviderCollection */
- $mountProviderCollection = \OC::$server->query(\OCP\Files\Config\IMountProviderCollection::class);
- $rootMountProviders = $mountProviderCollection->getRootMounts();
-
- /** @var \OC\Files\Mount\Manager $mountManager */
- $mountManager = \OC\Files\Filesystem::getMountManager();
- foreach ($rootMountProviders as $rootMountProvider) {
- $mountManager->addMount($rootMountProvider);
- }
-
- \OC::$server->getEventLogger()->end('setup_root_fs');
-
- return true;
- }
-
- /**
* Setup the file system
*
* @param string|null $user
@@ -214,14 +97,6 @@ class OC_Util {
* @suppress PhanAccessMethodInternal
*/
public static function setupFS(?string $user = '') {
- self::setupRootFS($user ?? '');
-
- if (self::$fsSetup) {
- return false;
- }
-
- \OC::$server->getEventLogger()->start('setup_fs', 'Setup filesystem');
-
// If we are not forced to load a specific user we load the one that is logged in
if ($user === '') {
$userObject = \OC::$server->get(\OCP\IUserSession::class)->getUser();
@@ -229,18 +104,14 @@ class OC_Util {
$userObject = \OC::$server->get(\OCP\IUserManager::class)->get($user);
}
- //if we aren't logged in, or the user doesn't exist, there is no use to set up the filesystem
- if ($userObject) {
- self::$fsSetup = true;
-
- $userDir = '/' . $userObject->getUID() . '/files';
-
- //jail the user into his "home" directory
- \OC\Files\Filesystem::init($userObject, $userDir);
+ /** @var SetupManager $setupManager */
+ $setupManager = \OC::$server->get(SetupManager::class);
- OC_Hook::emit('OC_Filesystem', 'setup', ['user' => $userObject->getUID(), 'user_dir' => $userDir]);
+ if ($userObject) {
+ $setupManager->setupForUser($userObject);
+ } else {
+ $setupManager->setupRoot();
}
- \OC::$server->getEventLogger()->end('setup_fs');
return true;
}
@@ -394,10 +265,9 @@ class OC_Util {
* @suppress PhanUndeclaredMethod
*/
public static function tearDownFS() {
- \OC\Files\Filesystem::tearDown();
- \OC::$server->getRootFolder()->clearCache();
- self::$fsSetup = false;
- self::$rootFsSetup = false;
+ /** @var SetupManager $setupManager */
+ $setupManager = \OC::$server->get(SetupManager::class);
+ $setupManager->tearDown();
}
/**
diff --git a/lib/public/Files/Config/ICachedMountFileInfo.php b/lib/public/Files/Config/ICachedMountFileInfo.php
index 4de0a1218b4..e6aa2ec38c8 100644
--- a/lib/public/Files/Config/ICachedMountFileInfo.php
+++ b/lib/public/Files/Config/ICachedMountFileInfo.php
@@ -34,11 +34,11 @@ interface ICachedMountFileInfo extends ICachedMountInfo {
* @return string
* @since 13.0.0
*/
- public function getInternalPath();
+ public function getInternalPath(): string;
/**
* @return string
* @since 13.0.0
*/
- public function getPath();
+ public function getPath(): string;
}
diff --git a/lib/public/Files/Config/ICachedMountInfo.php b/lib/public/Files/Config/ICachedMountInfo.php
index 812e79cdbc8..dafd2423fdc 100644
--- a/lib/public/Files/Config/ICachedMountInfo.php
+++ b/lib/public/Files/Config/ICachedMountInfo.php
@@ -35,31 +35,31 @@ interface ICachedMountInfo {
* @return IUser
* @since 9.0.0
*/
- public function getUser();
+ public function getUser(): IUser;
/**
* @return int the numeric storage id of the mount
* @since 9.0.0
*/
- public function getStorageId();
+ public function getStorageId(): int;
/**
* @return int the fileid of the root of the mount
* @since 9.0.0
*/
- public function getRootId();
+ public function getRootId(): int;
/**
- * @return Node the root node of the mount
+ * @return Node|null the root node of the mount
* @since 9.0.0
*/
- public function getMountPointNode();
+ public function getMountPointNode(): ?Node;
/**
* @return string the mount point of the mount for the user
* @since 9.0.0
*/
- public function getMountPoint();
+ public function getMountPoint(): string;
/**
* Get the id of the configured mount
@@ -67,7 +67,7 @@ interface ICachedMountInfo {
* @return int|null mount id or null if not applicable
* @since 9.1.0
*/
- public function getMountId();
+ public function getMountId(): ?int;
/**
* Get the internal path (within the storage) of the root of the mount
@@ -75,7 +75,7 @@ interface ICachedMountInfo {
* @return string
* @since 11.0.0
*/
- public function getRootInternalPath();
+ public function getRootInternalPath(): string;
/**
* Get the class of the mount provider that this mount originates from
diff --git a/lib/public/Files/Events/Node/FilesystemTornDownEvent.php b/lib/public/Files/Events/Node/FilesystemTornDownEvent.php
new file mode 100644
index 00000000000..3e7780c827e
--- /dev/null
+++ b/lib/public/Files/Events/Node/FilesystemTornDownEvent.php
@@ -0,0 +1,34 @@
+<?php
+
+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/>.
+ *
+ */
+
+namespace OCP\Files\Events\Node;
+
+use OCP\EventDispatcher\Event;
+
+/**
+ * Event fired after the filesystem has been torn down
+ *
+ * @since 24.0.0
+ */
+class FilesystemTornDownEvent extends Event {
+}
diff --git a/lib/public/Files/Mount/IMountManager.php b/lib/public/Files/Mount/IMountManager.php
index 1e8c674f8f5..aa760f53e96 100644
--- a/lib/public/Files/Mount/IMountManager.php
+++ b/lib/public/Files/Mount/IMountManager.php
@@ -37,7 +37,7 @@ interface IMountManager {
/**
* Add a new mount
*
- * @param \OCP\Files\Mount\IMountPoint $mount
+ * @param IMountPoint $mount
* @since 8.2.0
*/
public function addMount(IMountPoint $mount);
@@ -63,16 +63,16 @@ interface IMountManager {
* Find the mount for $path
*
* @param string $path
- * @return \OCP\Files\Mount\IMountPoint|null
+ * @return IMountPoint
* @since 8.2.0
*/
- public function find(string $path);
+ public function find(string $path): ?IMountPoint;
/**
* Find all mounts in $path
*
* @param string $path
- * @return \OCP\Files\Mount\IMountPoint[]
+ * @return IMountPoint[]
* @since 8.2.0
*/
public function findIn(string $path): array;
@@ -88,13 +88,13 @@ interface IMountManager {
* Find mounts by storage id
*
* @param string $id
- * @return \OCP\Files\Mount\IMountPoint[]
+ * @return IMountPoint[]
* @since 8.2.0
*/
public function findByStorageId(string $id): array;
/**
- * @return \OCP\Files\Mount\IMountPoint[]
+ * @return IMountPoint[]
* @since 8.2.0
*/
public function getAll(): array;
@@ -103,7 +103,7 @@ interface IMountManager {
* Find mounts by numeric storage id
*
* @param int $id
- * @return \OCP\Files\Mount\IMountPoint[]
+ * @return IMountPoint[]
* @since 8.2.0
*/
public function findByNumericId(int $id): array;