diff options
Diffstat (limited to 'lib/private/Files')
-rw-r--r-- | lib/private/Files/ObjectStore/ObjectStoreStorage.php | 21 | ||||
-rw-r--r-- | lib/private/Files/Storage/DAV.php | 18 | ||||
-rw-r--r-- | lib/private/Files/Stream/Close.php | 119 | ||||
-rw-r--r-- | lib/private/Files/Stream/Quota.php | 94 | ||||
-rw-r--r-- | lib/private/Files/Utils/Scanner.php | 21 | ||||
-rw-r--r-- | lib/private/Files/View.php | 25 |
6 files changed, 61 insertions, 237 deletions
diff --git a/lib/private/Files/ObjectStore/ObjectStoreStorage.php b/lib/private/Files/ObjectStore/ObjectStoreStorage.php index 2dcf830cc1e..ab77c21e6c4 100644 --- a/lib/private/Files/ObjectStore/ObjectStoreStorage.php +++ b/lib/private/Files/ObjectStore/ObjectStoreStorage.php @@ -25,16 +25,12 @@ namespace OC\Files\ObjectStore; +use Icewind\Streams\CallbackWrapper; use Icewind\Streams\IteratorDirectory; use OC\Files\Cache\CacheEntry; use OCP\Files\ObjectStore\IObjectStore; class ObjectStoreStorage extends \OC\Files\Storage\Common { - - /** - * @var array - */ - private static $tmpFiles = array(); /** * @var \OCP\Files\ObjectStore\IObjectStore $objectStore */ @@ -291,14 +287,14 @@ class ObjectStoreStorage extends \OC\Files\Storage\Common { $ext = ''; } $tmpFile = \OC::$server->getTempManager()->getTemporaryFile($ext); - \OC\Files\Stream\Close::registerCallback($tmpFile, array($this, 'writeBack')); if ($this->file_exists($path)) { $source = $this->fopen($path, 'r'); file_put_contents($tmpFile, $source); } - self::$tmpFiles[$tmpFile] = $path; - - return fopen('close://' . $tmpFile, $mode); + $handle = fopen($tmpFile, $mode); + return CallbackWrapper::wrap($handle, null, null, function () use ($path, $tmpFile) { + $this->writeBack($tmpFile, $path); + }); } return false; } @@ -368,12 +364,7 @@ class ObjectStoreStorage extends \OC\Files\Storage\Common { return true; } - public function writeBack($tmpFile) { - if (!isset(self::$tmpFiles[$tmpFile])) { - return; - } - - $path = self::$tmpFiles[$tmpFile]; + public function writeBack($tmpFile, $path) { $stat = $this->stat($path); if (empty($stat)) { // create new file diff --git a/lib/private/Files/Storage/DAV.php b/lib/private/Files/Storage/DAV.php index 2f821b218fc..abe219f99f2 100644 --- a/lib/private/Files/Storage/DAV.php +++ b/lib/private/Files/Storage/DAV.php @@ -36,6 +36,7 @@ namespace OC\Files\Storage; use Exception; use GuzzleHttp\Exception\RequestException; use GuzzleHttp\Message\ResponseInterface; +use Icewind\Streams\CallbackWrapper; use OC\Files\Filesystem; use OC\Files\Stream\Close; use Icewind\Streams\IteratorDirectory; @@ -76,8 +77,6 @@ class DAV extends Common { private $client; /** @var ArrayCache */ private $statCache; - /** @var array */ - private static $tempFiles = []; /** @var \OCP\Http\Client\IClientService */ private $httpClientService; @@ -395,20 +394,19 @@ class DAV extends Common { } $tmpFile = $tempManager->getTemporaryFile($ext); } - Close::registerCallback($tmpFile, array($this, 'writeBack')); - self::$tempFiles[$tmpFile] = $path; - return fopen('close://' . $tmpFile, $mode); + $handle = fopen($tmpFile, $mode); + return CallbackWrapper::wrap($handle, null, null, function () use ($path, $tmpFile) { + $this->writeBack($tmpFile, $path); + }); } } /** * @param string $tmpFile */ - public function writeBack($tmpFile) { - if (isset(self::$tempFiles[$tmpFile])) { - $this->uploadFile($tmpFile, self::$tempFiles[$tmpFile]); - unlink($tmpFile); - } + public function writeBack($tmpFile, $path) { + $this->uploadFile($tmpFile, $path); + unlink($tmpFile); } /** {@inheritdoc} */ diff --git a/lib/private/Files/Stream/Close.php b/lib/private/Files/Stream/Close.php deleted file mode 100644 index 7cc9903c912..00000000000 --- a/lib/private/Files/Stream/Close.php +++ /dev/null @@ -1,119 +0,0 @@ -<?php -/** - * @copyright Copyright (c) 2016, ownCloud, Inc. - * - * @author Jörn Friedrich Dreyer <jfd@butonic.de> - * @author Morris Jobke <hey@morrisjobke.de> - * @author Robin Appelman <robin@icewind.nl> - * - * @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/> - * - */ - -namespace OC\Files\Stream; - -/** - * stream wrapper that provides a callback on stream close - */ -class Close { - private static $callBacks = array(); - private $path = ''; - private $source; - private static $open = array(); - - public function stream_open($path, $mode, $options, &$opened_path) { - $path = substr($path, strlen('close://')); - $this->path = $path; - $this->source = fopen($path, $mode); - if (is_resource($this->source)) { - $this->meta = stream_get_meta_data($this->source); - } - self::$open[] = $path; - return is_resource($this->source); - } - - public function stream_seek($offset, $whence = SEEK_SET) { - return fseek($this->source, $offset, $whence) === 0; - } - - public function stream_tell() { - return ftell($this->source); - } - - public function stream_read($count) { - return fread($this->source, $count); - } - - public function stream_write($data) { - return fwrite($this->source, $data); - } - - public function stream_set_option($option, $arg1, $arg2) { - switch ($option) { - case STREAM_OPTION_BLOCKING: - stream_set_blocking($this->source, $arg1); - break; - case STREAM_OPTION_READ_TIMEOUT: - stream_set_timeout($this->source, $arg1, $arg2); - break; - case STREAM_OPTION_WRITE_BUFFER: - stream_set_write_buffer($this->source, $arg1, $arg2); - } - } - - public function stream_stat() { - return fstat($this->source); - } - - public function stream_lock($mode) { - flock($this->source, $mode); - } - - public function stream_flush() { - return fflush($this->source); - } - - public function stream_eof() { - return feof($this->source); - } - - public function url_stat($path) { - $path = substr($path, strlen('close://')); - if (file_exists($path)) { - return stat($path); - } else { - return false; - } - } - - public function stream_close() { - fclose($this->source); - if (isset(self::$callBacks[$this->path])) { - call_user_func(self::$callBacks[$this->path], $this->path); - } - } - - public function unlink($path) { - $path = substr($path, strlen('close://')); - return unlink($path); - } - - /** - * @param string $path - */ - public static function registerCallback($path, $callback) { - self::$callBacks[$path] = $callback; - } -} diff --git a/lib/private/Files/Stream/Quota.php b/lib/private/Files/Stream/Quota.php index f064ca6c011..624a2021b9c 100644 --- a/lib/private/Files/Stream/Quota.php +++ b/lib/private/Files/Stream/Quota.php @@ -25,61 +25,44 @@ namespace OC\Files\Stream; +use Icewind\Streams\Wrapper; + /** * stream wrapper limits the amount of data that can be written to a stream * - * usage: void \OC\Files\Stream\Quota::register($id, $stream, $limit) - * or: resource \OC\Files\Stream\Quota::wrap($stream, $limit) + * usage: resource \OC\Files\Stream\Quota::wrap($stream, $limit) */ -class Quota { - private static $streams = array(); - - /** - * @var resource $source - */ - private $source; - +class Quota extends Wrapper { /** * @var int $limit */ private $limit; /** - * @param string $id - * @param resource $stream - * @param int $limit - */ - public static function register($id, $stream, $limit) { - self::$streams[$id] = array($stream, $limit); - } - - /** - * remove all registered streams - */ - public static function clear() { - self::$streams = array(); - } - - /** * @param resource $stream * @param int $limit * @return resource */ static public function wrap($stream, $limit) { - $id = uniqid(); - self::register($id, $stream, $limit); - $meta = stream_get_meta_data($stream); - return fopen('quota://' . $id, $meta['mode']); + $context = stream_context_create(array( + 'quota' => array( + 'source' => $stream, + 'limit' => $limit + ) + )); + return Wrapper::wrapSource($stream, $context, 'quota', self::class); } public function stream_open($path, $mode, $options, &$opened_path) { - $id = substr($path, strlen('quota://')); - if (isset(self::$streams[$id])) { - list($this->source, $this->limit) = self::$streams[$id]; - return true; - } else { - return false; - } + $context = $this->loadContext('quota'); + $this->source = $context['source']; + $this->limit = $context['limit']; + + return true; + } + + public function dir_opendir($path, $options) { + return false; } public function stream_seek($offset, $whence = SEEK_SET) { @@ -103,10 +86,6 @@ class Quota { return fseek($this->source, $offset, $whence) === 0; } - public function stream_tell() { - return ftell($this->source); - } - public function stream_read($count) { $this->limit -= $count; return fread($this->source, $count); @@ -121,37 +100,4 @@ class Quota { $this->limit -= $size; return fwrite($this->source, $data); } - - public function stream_set_option($option, $arg1, $arg2) { - switch ($option) { - case STREAM_OPTION_BLOCKING: - stream_set_blocking($this->source, $arg1); - break; - case STREAM_OPTION_READ_TIMEOUT: - stream_set_timeout($this->source, $arg1, $arg2); - break; - case STREAM_OPTION_WRITE_BUFFER: - stream_set_write_buffer($this->source, $arg1, $arg2); - } - } - - public function stream_stat() { - return fstat($this->source); - } - - public function stream_lock($mode) { - return flock($this->source, $mode); - } - - public function stream_flush() { - return fflush($this->source); - } - - public function stream_eof() { - return feof($this->source); - } - - public function stream_close() { - fclose($this->source); - } } diff --git a/lib/private/Files/Utils/Scanner.php b/lib/private/Files/Utils/Scanner.php index d26c601be1a..98e2c3c8ca2 100644 --- a/lib/private/Files/Utils/Scanner.php +++ b/lib/private/Files/Utils/Scanner.php @@ -31,6 +31,7 @@ use OC\Files\Filesystem; use OC\ForbiddenException; use OC\Hooks\PublicEmitter; use OC\Lock\DBLockingProvider; +use OCA\Files_Sharing\SharedStorage; use OCP\Files\Storage\IStorage; use OCP\Files\StorageNotAvailableException; use OCP\ILogger; @@ -118,14 +119,19 @@ class Scanner extends PublicEmitter { public function backgroundScan($dir) { $mounts = $this->getMounts($dir); foreach ($mounts as $mount) { - if (is_null($mount->getStorage())) { + $storage = $mount->getStorage(); + if (is_null($storage)) { continue; } // don't scan the root storage - if ($mount->getStorage()->instanceOfStorage('\OC\Files\Storage\Local') && $mount->getMountPoint() === '/') { + if ($storage->instanceOfStorage('\OC\Files\Storage\Local') && $mount->getMountPoint() === '/') { + continue; + } + + // don't scan received local shares, these can be scanned when scanning the owner's storage + if ($storage->instanceOfStorage(SharedStorage::class)) { continue; } - $storage = $mount->getStorage(); $scanner = $storage->getScanner(); $this->attachListener($mount); @@ -156,10 +162,10 @@ class Scanner extends PublicEmitter { } $mounts = $this->getMounts($dir); foreach ($mounts as $mount) { - if (is_null($mount->getStorage())) { + $storage = $mount->getStorage(); + if (is_null($storage)) { continue; } - $storage = $mount->getStorage(); // if the home storage isn't writable then the scanner is run as the wrong user if ($storage->instanceOfStorage('\OC\Files\Storage\Home') and (!$storage->isCreatable('') or !$storage->isCreatable('files')) @@ -171,6 +177,11 @@ class Scanner extends PublicEmitter { } } + + // don't scan received local shares, these can be scanned when scanning the owner's storage + if ($storage->instanceOfStorage(SharedStorage::class)) { + continue; + } $relativePath = $mount->getInternalPath($dir); $scanner = $storage->getScanner(); $scanner->setUseTransactions(false); diff --git a/lib/private/Files/View.php b/lib/private/Files/View.php index 6facc7b9462..909c49197b8 100644 --- a/lib/private/Files/View.php +++ b/lib/private/Files/View.php @@ -931,39 +931,36 @@ class View { /** * @param string $path - * @param string $mode + * @param string $mode 'r' or 'w' * @return resource */ public function fopen($path, $mode) { + $mode = str_replace('b', '', $mode); // the binary flag is a windows only feature which we do not support $hooks = array(); switch ($mode) { case 'r': - case 'rb': $hooks[] = 'read'; break; case 'r+': - case 'rb+': case 'w+': - case 'wb+': case 'x+': - case 'xb+': case 'a+': - case 'ab+': $hooks[] = 'read'; $hooks[] = 'write'; break; case 'w': - case 'wb': case 'x': - case 'xb': case 'a': - case 'ab': $hooks[] = 'write'; break; default: \OCP\Util::writeLog('core', 'invalid mode (' . $mode . ') for ' . $path, \OCP\Util::ERROR); } + if ($mode !== 'r' && $mode !== 'w') { + \OC::$server->getLogger()->info('Trying to open a file with a mode other than "r" or "w" can cause severe performance issues with some backends'); + } + return $this->basicOperation('fopen', $path, $hooks, $mode); } @@ -1005,7 +1002,7 @@ class View { // Create the directories if any if (!$this->file_exists($filePath)) { $result = $this->createParentDirectories($filePath); - if($result === false) { + if ($result === false) { return false; } } @@ -1357,7 +1354,7 @@ class View { //add the sizes of other mount points to the folder $extOnly = ($includeMountPoints === 'ext'); $mounts = Filesystem::getMountManager()->findIn($path); - $info->setSubMounts(array_filter($mounts, function(IMountPoint $mount) use ($extOnly) { + $info->setSubMounts(array_filter($mounts, function (IMountPoint $mount) use ($extOnly) { $subStorage = $mount->getStorage(); return !($extOnly && $subStorage instanceof \OCA\Files_Sharing\SharedStorage); })); @@ -2106,13 +2103,13 @@ class View { private function createParentDirectories($filePath) { $directoryParts = explode('/', $filePath); $directoryParts = array_filter($directoryParts); - foreach($directoryParts as $key => $part) { + foreach ($directoryParts as $key => $part) { $currentPathElements = array_slice($directoryParts, 0, $key); $currentPath = '/' . implode('/', $currentPathElements); - if($this->is_file($currentPath)) { + if ($this->is_file($currentPath)) { return false; } - if(!$this->file_exists($currentPath)) { + if (!$this->file_exists($currentPath)) { $this->mkdir($currentPath); } } |