1<?php 2 3declare(strict_types=1); 4 5/** 6 * @copyright Copyright (c) 2016, ownCloud, Inc. 7 * 8 * @author Björn Schießle <bjoern@schiessle.org> 9 * @author Morris Jobke <hey@morrisjobke.de> 10 * @author Robin Appelman <robin@icewind.nl> 11 * @author Robin McCorkell <robin@mccorkell.me.uk> 12 * @author Roeland Jago Douma <roeland@famdouma.nl> 13 * 14 * @license AGPL-3.0 15 * 16 * This code is free software: you can redistribute it and/or modify 17 * it under the terms of the GNU Affero General Public License, version 3, 18 * as published by the Free Software Foundation. 19 * 20 * This program is distributed in the hope that it will be useful, 21 * but WITHOUT ANY WARRANTY; without even the implied warranty of 22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 * GNU Affero General Public License for more details. 24 * 25 * You should have received a copy of the GNU Affero General Public License, version 3, 26 * along with this program. If not, see <http://www.gnu.org/licenses/> 27 * 28 */ 29namespace OC\Files\Mount; 30 31use OC\Cache\CappedMemoryCache; 32use OC\Files\Filesystem; 33use OCP\Files\Mount\IMountManager; 34use OCP\Files\Mount\IMountPoint; 35 36class Manager implements IMountManager { 37 /** @var MountPoint[] */ 38 private $mounts = []; 39 40 /** @var CappedMemoryCache */ 41 private $pathCache; 42 43 /** @var CappedMemoryCache */ 44 private $inPathCache; 45 46 public function __construct() { 47 $this->pathCache = new CappedMemoryCache(); 48 $this->inPathCache = new CappedMemoryCache(); 49 } 50 51 /** 52 * @param IMountPoint $mount 53 */ 54 public function addMount(IMountPoint $mount) { 55 $this->mounts[$mount->getMountPoint()] = $mount; 56 $this->pathCache->clear(); 57 $this->inPathCache->clear(); 58 } 59 60 /** 61 * @param string $mountPoint 62 */ 63 public function removeMount(string $mountPoint) { 64 $mountPoint = Filesystem::normalizePath($mountPoint); 65 if (\strlen($mountPoint) > 1) { 66 $mountPoint .= '/'; 67 } 68 unset($this->mounts[$mountPoint]); 69 $this->pathCache->clear(); 70 $this->inPathCache->clear(); 71 } 72 73 /** 74 * @param string $mountPoint 75 * @param string $target 76 */ 77 public function moveMount(string $mountPoint, string $target) { 78 $this->mounts[$target] = $this->mounts[$mountPoint]; 79 unset($this->mounts[$mountPoint]); 80 $this->pathCache->clear(); 81 $this->inPathCache->clear(); 82 } 83 84 /** 85 * Find the mount for $path 86 * 87 * @param string $path 88 * @return MountPoint|null 89 */ 90 public function find(string $path) { 91 \OC_Util::setupFS(); 92 $path = Filesystem::normalizePath($path); 93 94 if (isset($this->pathCache[$path])) { 95 return $this->pathCache[$path]; 96 } 97 98 $current = $path; 99 while (true) { 100 $mountPoint = $current . '/'; 101 if (isset($this->mounts[$mountPoint])) { 102 $this->pathCache[$path] = $this->mounts[$mountPoint]; 103 return $this->mounts[$mountPoint]; 104 } 105 106 if ($current === '') { 107 return null; 108 } 109 110 $current = dirname($current); 111 if ($current === '.' || $current === '/') { 112 $current = ''; 113 } 114 } 115 } 116 117 /** 118 * Find all mounts in $path 119 * 120 * @param string $path 121 * @return MountPoint[] 122 */ 123 public function findIn(string $path): array { 124 \OC_Util::setupFS(); 125 $path = $this->formatPath($path); 126 127 if (isset($this->inPathCache[$path])) { 128 return $this->inPathCache[$path]; 129 } 130 131 $result = []; 132 $pathLength = \strlen($path); 133 $mountPoints = array_keys($this->mounts); 134 foreach ($mountPoints as $mountPoint) { 135 if (substr($mountPoint, 0, $pathLength) === $path && \strlen($mountPoint) > $pathLength) { 136 $result[] = $this->mounts[$mountPoint]; 137 } 138 } 139 140 $this->inPathCache[$path] = $result; 141 return $result; 142 } 143 144 public function clear() { 145 $this->mounts = []; 146 $this->pathCache->clear(); 147 $this->inPathCache->clear(); 148 } 149 150 /** 151 * Find mounts by storage id 152 * 153 * @param string $id 154 * @return MountPoint[] 155 */ 156 public function findByStorageId(string $id): array { 157 \OC_Util::setupFS(); 158 if (\strlen($id) > 64) { 159 $id = md5($id); 160 } 161 $result = []; 162 foreach ($this->mounts as $mount) { 163 if ($mount->getStorageId() === $id) { 164 $result[] = $mount; 165 } 166 } 167 return $result; 168 } 169 170 /** 171 * @return MountPoint[] 172 */ 173 public function getAll(): array { 174 return $this->mounts; 175 } 176 177 /** 178 * Find mounts by numeric storage id 179 * 180 * @param int $id 181 * @return MountPoint[] 182 */ 183 public function findByNumericId(int $id): array { 184 $storageId = \OC\Files\Cache\Storage::getStorageId($id); 185 return $this->findByStorageId($storageId); 186 } 187 188 /** 189 * @param string $path 190 * @return string 191 */ 192 private function formatPath(string $path): string { 193 $path = Filesystem::normalizePath($path); 194 if (\strlen($path) > 1) { 195 $path .= '/'; 196 } 197 return $path; 198 } 199} 200