123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235 |
- <?php
- declare(strict_types=1);
- /**
- * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
- * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
- * SPDX-License-Identifier: AGPL-3.0-only
- */
- namespace OC\Files\Mount;
- use OC\Files\Filesystem;
- use OC\Files\SetupManager;
- use OC\Files\SetupManagerFactory;
- use OCP\Cache\CappedMemoryCache;
- use OCP\Files\Config\ICachedMountInfo;
- use OCP\Files\Mount\IMountManager;
- use OCP\Files\Mount\IMountPoint;
- use OCP\Files\NotFoundException;
- class Manager implements IMountManager {
- /** @var MountPoint[] */
- 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);
- }
- /**
- * @param IMountPoint $mount
- */
- public function addMount(IMountPoint $mount) {
- $this->mounts[$mount->getMountPoint()] = $mount;
- $this->pathCache->clear();
- $this->inPathCache->clear();
- }
- /**
- * @param string $mountPoint
- */
- public function removeMount(string $mountPoint) {
- $mountPoint = Filesystem::normalizePath($mountPoint);
- if (\strlen($mountPoint) > 1) {
- $mountPoint .= '/';
- }
- unset($this->mounts[$mountPoint]);
- $this->pathCache->clear();
- $this->inPathCache->clear();
- }
- /**
- * @param string $mountPoint
- * @param string $target
- */
- public function moveMount(string $mountPoint, string $target) {
- $this->mounts[$target] = $this->mounts[$mountPoint];
- unset($this->mounts[$mountPoint]);
- $this->pathCache->clear();
- $this->inPathCache->clear();
- }
- /**
- * Find the mount for $path
- *
- * @param string $path
- * @return IMountPoint
- */
- public function find(string $path): IMountPoint {
- $this->setupManager->setupForPath($path);
- $path = Filesystem::normalizePath($path);
- if (isset($this->pathCache[$path])) {
- return $this->pathCache[$path];
- }
- if (count($this->mounts) === 0) {
- $this->setupManager->setupRoot();
- if (count($this->mounts) === 0) {
- throw new \Exception("No mounts even after explicitly setting up the root mounts");
- }
- }
- $current = $path;
- while (true) {
- $mountPoint = $current . '/';
- if (isset($this->mounts[$mountPoint])) {
- $this->pathCache[$path] = $this->mounts[$mountPoint];
- return $this->mounts[$mountPoint];
- } elseif ($current === '') {
- break;
- }
- $current = dirname($current);
- if ($current === '.' || $current === '/') {
- $current = '';
- }
- }
- throw new NotFoundException("No mount for path " . $path . " existing mounts (" . count($this->mounts) ."): " . implode(",", array_keys($this->mounts)));
- }
- /**
- * Find all mounts in $path
- *
- * @param string $path
- * @return IMountPoint[]
- */
- public function findIn(string $path): array {
- $this->setupManager->setupForPath($path, true);
- $path = $this->formatPath($path);
- if (isset($this->inPathCache[$path])) {
- return $this->inPathCache[$path];
- }
- $result = [];
- $pathLength = \strlen($path);
- $mountPoints = array_keys($this->mounts);
- foreach ($mountPoints as $mountPoint) {
- if (substr($mountPoint, 0, $pathLength) === $path && \strlen($mountPoint) > $pathLength) {
- $result[] = $this->mounts[$mountPoint];
- }
- }
- $this->inPathCache[$path] = $result;
- return $result;
- }
- public function clear() {
- $this->mounts = [];
- $this->pathCache->clear();
- $this->inPathCache->clear();
- }
- /**
- * Find mounts by storage id
- *
- * @param string $id
- * @return IMountPoint[]
- */
- public function findByStorageId(string $id): array {
- if (\strlen($id) > 64) {
- $id = md5($id);
- }
- $result = [];
- foreach ($this->mounts as $mount) {
- if ($mount->getStorageId() === $id) {
- $result[] = $mount;
- }
- }
- return $result;
- }
- /**
- * @return IMountPoint[]
- */
- public function getAll(): array {
- return $this->mounts;
- }
- /**
- * Find mounts by numeric storage id
- *
- * @param int $id
- * @return IMountPoint[]
- */
- public function findByNumericId(int $id): array {
- $result = [];
- foreach ($this->mounts as $mount) {
- if ($mount->getNumericStorageId() === $id) {
- $result[] = $mount;
- }
- }
- return $result;
- }
- /**
- * @param string $path
- * @return string
- */
- private function formatPath(string $path): string {
- $path = Filesystem::normalizePath($path);
- if (\strlen($path) > 1) {
- $path .= '/';
- }
- return $path;
- }
- public function getSetupManager(): SetupManager {
- return $this->setupManager;
- }
- /**
- * Return all mounts in a path from a specific mount provider
- *
- * @param string $path
- * @param string[] $mountProviders
- * @return MountPoint[]
- */
- public function getMountsByMountProvider(string $path, array $mountProviders) {
- $this->getSetupManager()->setupForProvider($path, $mountProviders);
- if (in_array('', $mountProviders)) {
- return $this->mounts;
- } else {
- return array_filter($this->mounts, function ($mount) use ($mountProviders) {
- return in_array($mount->getMountProvider(), $mountProviders);
- });
- }
- }
- /**
- * Return the mount matching a cached mount info (or mount file info)
- *
- * @param ICachedMountInfo $info
- *
- * @return IMountPoint|null
- */
- public function getMountFromMountInfo(ICachedMountInfo $info): ?IMountPoint {
- $this->setupManager->setupForPath($info->getMountPoint());
- foreach ($this->mounts as $mount) {
- if ($mount->getMountPoint() === $info->getMountPoint()) {
- return $mount;
- }
- }
- return null;
- }
- }
|