diff options
Diffstat (limited to 'lib/private/Files')
-rw-r--r-- | lib/private/Files/SetupManager.php | 8 | ||||
-rw-r--r-- | lib/private/Files/Storage/Wrapper/Quota.php | 71 | ||||
-rw-r--r-- | lib/private/Files/Stream/HashWrapper.php | 11 |
3 files changed, 65 insertions, 25 deletions
diff --git a/lib/private/Files/SetupManager.php b/lib/private/Files/SetupManager.php index 5782a5a72a6..d52a291cd99 100644 --- a/lib/private/Files/SetupManager.php +++ b/lib/private/Files/SetupManager.php @@ -172,10 +172,10 @@ class SetupManager { */ 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']); - } + $user = $storage->getUser(); + return new Quota(['storage' => $storage, 'quotaCallback' => function () use ($user) { + return OC_Util::getUserQuota($user); + }, 'root' => 'files']); } } diff --git a/lib/private/Files/Storage/Wrapper/Quota.php b/lib/private/Files/Storage/Wrapper/Quota.php index 4cd0a5e0b4a..8b129472eb0 100644 --- a/lib/private/Files/Storage/Wrapper/Quota.php +++ b/lib/private/Files/Storage/Wrapper/Quota.php @@ -33,40 +33,47 @@ namespace OC\Files\Storage\Wrapper; use OC\Files\Filesystem; +use OC\SystemConfig; use OCP\Files\Cache\ICacheEntry; +use OCP\Files\FileInfo; use OCP\Files\Storage\IStorage; class Quota extends Wrapper { - - /** - * @var int $quota - */ - protected $quota; - - /** - * @var string $sizeRoot - */ - protected $sizeRoot; - - private $config; + /** @var callable|null */ + protected $quotaCallback; + protected ?int $quota; + protected string $sizeRoot; + private SystemConfig $config; /** * @param array $parameters */ public function __construct($parameters) { parent::__construct($parameters); - $this->quota = $parameters['quota']; - $this->sizeRoot = isset($parameters['root']) ? $parameters['root'] : ''; - $this->config = \OC::$server->getSystemConfig(); + $this->quota = $parameters['quota'] ?? null; + $this->quotaCallback = $parameters['quotaCallback'] ?? null; + $this->sizeRoot = $parameters['root'] ?? ''; + $this->config = \OC::$server->get(SystemConfig::class); } /** * @return int quota value */ - public function getQuota() { + public function getQuota(): int { + if ($this->quota === null) { + $quotaCallback = $this->quotaCallback; + if ($quotaCallback === null) { + throw new \Exception("No quota or quota callback provider"); + } + $this->quota = $quotaCallback(); + } return $this->quota; } + private function hasQuota(): bool { + return $this->getQuota() !== FileInfo::SPACE_UNLIMITED; + } + /** * @param string $path * @param \OC\Files\Storage\Storage $storage @@ -100,7 +107,10 @@ class Quota extends Wrapper { * @return int|bool */ public function free_space($path) { - if ($this->quota < 0 || strpos($path, 'cache') === 0 || strpos($path, 'uploads') === 0) { + if (!$this->hasQuota()) { + return $this->storage->free_space($path); + } + if ($this->getQuota() < 0 || strpos($path, 'cache') === 0 || strpos($path, 'uploads') === 0) { return $this->storage->free_space($path); } else { $used = $this->getSize($this->sizeRoot); @@ -108,7 +118,7 @@ class Quota extends Wrapper { return \OCP\Files\FileInfo::SPACE_NOT_COMPUTED; } else { $free = $this->storage->free_space($path); - $quotaFree = max($this->quota - $used, 0); + $quotaFree = max($this->getQuota() - $used, 0); // if free space is known if ($free >= 0) { $free = min($free, $quotaFree); @@ -128,6 +138,9 @@ class Quota extends Wrapper { * @return int|false */ public function file_put_contents($path, $data) { + if (!$this->hasQuota()) { + return $this->storage->file_put_contents($path, $data); + } $free = $this->free_space($path); if ($free < 0 or strlen($data) < $free) { return $this->storage->file_put_contents($path, $data); @@ -144,6 +157,9 @@ class Quota extends Wrapper { * @return bool */ public function copy($source, $target) { + if (!$this->hasQuota()) { + return $this->storage->copy($source, $target); + } $free = $this->free_space($target); if ($free < 0 or $this->getSize($source) < $free) { return $this->storage->copy($source, $target); @@ -160,6 +176,9 @@ class Quota extends Wrapper { * @return resource|bool */ public function fopen($path, $mode) { + if (!$this->hasQuota()) { + return $this->storage->fopen($path, $mode); + } $source = $this->storage->fopen($path, $mode); // don't apply quota for part files @@ -202,6 +221,9 @@ class Quota extends Wrapper { * @return bool */ public function copyFromStorage(IStorage $sourceStorage, $sourceInternalPath, $targetInternalPath) { + if (!$this->hasQuota()) { + return $this->storage->copyFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath); + } $free = $this->free_space($targetInternalPath); if ($free < 0 or $this->getSize($sourceInternalPath, $sourceStorage) < $free) { return $this->storage->copyFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath); @@ -217,6 +239,9 @@ class Quota extends Wrapper { * @return bool */ public function moveFromStorage(IStorage $sourceStorage, $sourceInternalPath, $targetInternalPath) { + if (!$this->hasQuota()) { + return $this->storage->moveFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath); + } $free = $this->free_space($targetInternalPath); if ($free < 0 or $this->getSize($sourceInternalPath, $sourceStorage) < $free) { return $this->storage->moveFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath); @@ -226,8 +251,11 @@ class Quota extends Wrapper { } public function mkdir($path) { + if (!$this->hasQuota()) { + return $this->storage->mkdir($path); + } $free = $this->free_space($path); - if ($this->shouldApplyQuota($path) && $free === 0.0) { + if ($this->shouldApplyQuota($path) && $free == 0) { return false; } @@ -235,8 +263,11 @@ class Quota extends Wrapper { } public function touch($path, $mtime = null) { + if (!$this->hasQuota()) { + return $this->storage->touch($path, $mtime); + } $free = $this->free_space($path); - if ($free === 0.0) { + if ($free == 0) { return false; } diff --git a/lib/private/Files/Stream/HashWrapper.php b/lib/private/Files/Stream/HashWrapper.php index fd9bb3cdd0b..4060d74de7d 100644 --- a/lib/private/Files/Stream/HashWrapper.php +++ b/lib/private/Files/Stream/HashWrapper.php @@ -67,7 +67,16 @@ class HashWrapper extends Wrapper { public function stream_close() { if (is_callable($this->callback)) { - call_user_func($this->callback, hash_final($this->hash)); + // if the stream is closed as a result of the end-of-request GC, the hash context might be cleaned up before this stream + if ($this->hash instanceof \HashContext) { + try { + $hash = @hash_final($this->hash); + if ($hash) { + call_user_func($this->callback, $hash); + } + } catch (\Throwable $e) { + } + } // prevent further calls by potential PHP 7 GC ghosts $this->callback = null; } |