From 1a70ba642184e2055db087681901558ba1507e6b Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Fri, 24 Feb 2023 17:38:25 +0100 Subject: fix unencrypted_size for folders when scanning the filesystem with encryption enabled Signed-off-by: Robin Appelman --- lib/private/Files/Cache/Cache.php | 8 +++++--- lib/private/Files/Cache/Scanner.php | 14 +++++++++++--- 2 files changed, 16 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/private/Files/Cache/Cache.php b/lib/private/Files/Cache/Cache.php index 9e475057a36..7ad16e34a62 100644 --- a/lib/private/Files/Cache/Cache.php +++ b/lib/private/Files/Cache/Cache.php @@ -937,9 +937,11 @@ class Cache implements ICache { $unencryptedTotal = 0; $unencryptedMax = 0; } - if ($entry['size'] !== $totalSize) { - // only set unencrypted size for a folder if any child entries have it set, or the folder is empty - if ($unencryptedMax > 0 || $totalSize === 0) { + + // only set unencrypted size for a folder if any child entries have it set, or the folder is empty + $shouldWriteUnEncryptedSize = $unencryptedMax > 0 || $totalSize === 0; + if ($entry['size'] !== $totalSize || ($entry['unencrypted_size'] !== $unencryptedTotal && $shouldWriteUnEncryptedSize)) { + if ($shouldWriteUnEncryptedSize) { $this->update($id, [ 'size' => $totalSize, 'unencrypted_size' => $unencryptedTotal, diff --git a/lib/private/Files/Cache/Scanner.php b/lib/private/Files/Cache/Scanner.php index 42f8f1b375b..720428e9bd8 100644 --- a/lib/private/Files/Cache/Scanner.php +++ b/lib/private/Files/Cache/Scanner.php @@ -36,6 +36,7 @@ namespace OC\Files\Cache; use Doctrine\DBAL\Exception; +use OC\Files\Storage\Wrapper\Encryption; use OCP\Files\Cache\IScanner; use OCP\Files\ForbiddenException; use OCP\Files\Storage\IReliableEtagStorage; @@ -219,7 +220,7 @@ class Scanner extends BasicEmitter implements IScanner { $newData['parent'] = $parentId; $data['fileid'] = $this->addToCache($file, $newData, $fileId); } - + $data['oldSize'] = ($cacheData && isset($cacheData['size'])) ? $cacheData['size'] : 0; if ($cacheData && isset($cacheData['encrypted'])) { @@ -390,8 +391,15 @@ class Scanner extends BasicEmitter implements IScanner { } } $oldSize = $data['size'] ?? null; - if ($this->cacheActive && $oldSize !== $size) { - $this->cache->update($folderId, ['size' => $size]); + + // for encrypted storages, we trigger a regular folder size calculation instead of using the calculated size + // to make sure we also updated the unencrypted-size where applicable + if ($this->storage->instanceOfStorage(Encryption::class)) { + $this->cache->calculateFolderSize($path); + } else { + if ($this->cacheActive && $oldSize !== $size) { + $this->cache->update($folderId, ['size' => $size]); + } } $this->emit('\OC\Files\Cache\Scanner', 'postScanFolder', [$path, $this->storageId]); return $size; -- cgit v1.2.3 From ed6606e86be2c8f0b43142168a0f4eb763957faf Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Fri, 3 Mar 2023 17:10:56 +0100 Subject: fix unencrypted_size for files when scanning Signed-off-by: Robin Appelman --- lib/private/Files/Cache/Scanner.php | 8 ++++++++ lib/private/Files/Storage/Wrapper/Encryption.php | 5 ++++- 2 files changed, 12 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/private/Files/Cache/Scanner.php b/lib/private/Files/Cache/Scanner.php index 720428e9bd8..228f5d4056e 100644 --- a/lib/private/Files/Cache/Scanner.php +++ b/lib/private/Files/Cache/Scanner.php @@ -208,9 +208,17 @@ class Scanner extends BasicEmitter implements IScanner { $data['etag'] = $etag; } } + + // we only updated unencrypted_size if it's already set + if ($cacheData['unencrypted_size'] === 0) { + unset($data['unencrypted_size']); + } + // Only update metadata that has changed $newData = array_diff_assoc($data, $cacheData->getData()); } else { + // we only updated unencrypted_size if it's already set + unset($data['unencrypted_size']); $newData = $data; $fileId = -1; } diff --git a/lib/private/Files/Storage/Wrapper/Encryption.php b/lib/private/Files/Storage/Wrapper/Encryption.php index 2b4abbe917e..8b64697ed94 100644 --- a/lib/private/Files/Storage/Wrapper/Encryption.php +++ b/lib/private/Files/Storage/Wrapper/Encryption.php @@ -188,10 +188,12 @@ class Encryption extends Wrapper { if (isset($this->unencryptedSize[$fullPath])) { $data['encrypted'] = true; $data['size'] = $this->unencryptedSize[$fullPath]; + $data['unencrypted_size'] = $data['size']; } else { if (isset($info['fileid']) && $info['encrypted']) { $data['size'] = $this->verifyUnencryptedSize($path, $info->getUnencryptedSize()); $data['encrypted'] = true; + $data['unencrypted_size'] = $data['size']; } } @@ -502,7 +504,8 @@ class Encryption extends Wrapper { $result = $unencryptedSize; if ($unencryptedSize < 0 || - ($size > 0 && $unencryptedSize === $size) + ($size > 0 && $unencryptedSize === $size) || + $unencryptedSize > $size ) { // check if we already calculate the unencrypted size for the // given path to avoid recursions -- cgit v1.2.3 From 0fde24008960c05fa7c7342946fc0ddb3d212ef9 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Thu, 9 Mar 2023 15:25:46 +0100 Subject: fix unencrypted folder size when no children with unencrypted size set are left Signed-off-by: Robin Appelman --- lib/private/Files/Cache/Cache.php | 25 ++++++++++++++++++++++++- lib/private/Files/Cache/HomeCache.php | 32 ++------------------------------ 2 files changed, 26 insertions(+), 31 deletions(-) (limited to 'lib') diff --git a/lib/private/Files/Cache/Cache.php b/lib/private/Files/Cache/Cache.php index 7ad16e34a62..99f3602fe51 100644 --- a/lib/private/Files/Cache/Cache.php +++ b/lib/private/Files/Cache/Cache.php @@ -883,9 +883,23 @@ class Cache implements ICache { * * @param string $path * @param array $entry (optional) meta data of the folder + * @param bool $ignoreUnknown don't mark the folder size as unknown if any of it's children are unknown * @return int|float */ public function calculateFolderSize($path, $entry = null) { + return $this->calculateFolderSizeInner($path, $entry); + } + + + /** + * inner function because we can't add new params to the public function without breaking any child classes + * + * @param string $path + * @param array $entry (optional) meta data of the folder + * @param bool $ignoreUnknown don't mark the folder size as unknown if any of it's children are unknown + * @return int + */ + protected function calculateFolderSizeInner(string $path, array $entry = null, bool $ignoreUnknown = false) { $totalSize = 0; if (is_null($entry) || !isset($entry['fileid'])) { $entry = $this->get($path); @@ -897,6 +911,9 @@ class Cache implements ICache { $query->select('size', 'unencrypted_size') ->from('filecache') ->whereParent($id); + if ($ignoreUnknown) { + $query->andWhere($query->expr()->gte('size', $query->createNamedParameter(0))); + } $result = $query->execute(); $rows = $result->fetchAll(); @@ -939,9 +956,15 @@ class Cache implements ICache { } // only set unencrypted size for a folder if any child entries have it set, or the folder is empty - $shouldWriteUnEncryptedSize = $unencryptedMax > 0 || $totalSize === 0; + $shouldWriteUnEncryptedSize = $unencryptedMax > 0 || $totalSize === 0 || $entry['unencrypted_size'] > 0; if ($entry['size'] !== $totalSize || ($entry['unencrypted_size'] !== $unencryptedTotal && $shouldWriteUnEncryptedSize)) { if ($shouldWriteUnEncryptedSize) { + + // if all children have an unencrypted size of 0, just set the folder unencrypted size to 0 instead of summing the sizes + if ($unencryptedMax === 0) { + $unencryptedTotal = 0; + } + $this->update($id, [ 'size' => $totalSize, 'unencrypted_size' => $unencryptedTotal, diff --git a/lib/private/Files/Cache/HomeCache.php b/lib/private/Files/Cache/HomeCache.php index cd6408a86f6..ebf81c91385 100644 --- a/lib/private/Files/Cache/HomeCache.php +++ b/lib/private/Files/Cache/HomeCache.php @@ -44,37 +44,9 @@ class HomeCache extends Cache { } elseif ($path === '' or $path === '/') { // since the size of / isn't used (the size of /files is used instead) there is no use in calculating it return 0; + } else { + return $this->calculateFolderSizeInner($path, $entry, true); } - - $totalSize = 0; - if (is_null($entry)) { - $entry = $this->get($path); - } - if ($entry && $entry['mimetype'] === 'httpd/unix-directory') { - $id = $entry['fileid']; - - $query = $this->connection->getQueryBuilder(); - $query->selectAlias($query->func()->sum('size'), 'f1') - ->from('filecache') - ->where($query->expr()->eq('parent', $query->createNamedParameter($id))) - ->andWhere($query->expr()->eq('storage', $query->createNamedParameter($this->getNumericStorageId()))) - ->andWhere($query->expr()->gte('size', $query->createNamedParameter(0))); - - $result = $query->execute(); - $row = $result->fetch(); - $result->closeCursor(); - - if ($row) { - [$sum] = array_values($row); - $totalSize = 0 + $sum; - $entry['size'] += 0; - if ($entry['size'] !== $totalSize) { - $this->update($id, ['size' => $totalSize]); - } - } - $result->closeCursor(); - } - return $totalSize; } /** -- cgit v1.2.3 From 29c36f85b0a008e1dc677c612b472488bcdd5f5e Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Wed, 22 Mar 2023 19:35:05 +0100 Subject: fix type hints Signed-off-by: Robin Appelman --- lib/private/Files/Cache/Cache.php | 8 +++----- lib/private/Files/Cache/HomeCache.php | 2 +- lib/private/Files/Cache/Wrapper/CacheJail.php | 2 +- lib/private/Files/Cache/Wrapper/CacheWrapper.php | 2 +- 4 files changed, 6 insertions(+), 8 deletions(-) (limited to 'lib') diff --git a/lib/private/Files/Cache/Cache.php b/lib/private/Files/Cache/Cache.php index 99f3602fe51..5454e9eb56f 100644 --- a/lib/private/Files/Cache/Cache.php +++ b/lib/private/Files/Cache/Cache.php @@ -882,8 +882,7 @@ class Cache implements ICache { * calculate the size of a folder and set it in the cache * * @param string $path - * @param array $entry (optional) meta data of the folder - * @param bool $ignoreUnknown don't mark the folder size as unknown if any of it's children are unknown + * @param array|null|ICacheEntry $entry (optional) meta data of the folder * @return int|float */ public function calculateFolderSize($path, $entry = null) { @@ -895,11 +894,11 @@ class Cache implements ICache { * inner function because we can't add new params to the public function without breaking any child classes * * @param string $path - * @param array $entry (optional) meta data of the folder + * @param array|null|ICacheEntry $entry (optional) meta data of the folder * @param bool $ignoreUnknown don't mark the folder size as unknown if any of it's children are unknown * @return int */ - protected function calculateFolderSizeInner(string $path, array $entry = null, bool $ignoreUnknown = false) { + protected function calculateFolderSizeInner(string $path, $entry = null, bool $ignoreUnknown = false) { $totalSize = 0; if (is_null($entry) || !isset($entry['fileid'])) { $entry = $this->get($path); @@ -959,7 +958,6 @@ class Cache implements ICache { $shouldWriteUnEncryptedSize = $unencryptedMax > 0 || $totalSize === 0 || $entry['unencrypted_size'] > 0; if ($entry['size'] !== $totalSize || ($entry['unencrypted_size'] !== $unencryptedTotal && $shouldWriteUnEncryptedSize)) { if ($shouldWriteUnEncryptedSize) { - // if all children have an unencrypted size of 0, just set the folder unencrypted size to 0 instead of summing the sizes if ($unencryptedMax === 0) { $unencryptedTotal = 0; diff --git a/lib/private/Files/Cache/HomeCache.php b/lib/private/Files/Cache/HomeCache.php index ebf81c91385..3b0eaae4c5d 100644 --- a/lib/private/Files/Cache/HomeCache.php +++ b/lib/private/Files/Cache/HomeCache.php @@ -35,7 +35,7 @@ class HomeCache extends Cache { * get the size of a folder and set it in the cache * * @param string $path - * @param array $entry (optional) meta data of the folder + * @param array|null|ICacheEntry $entry (optional) meta data of the folder * @return int|float */ public function calculateFolderSize($path, $entry = null) { diff --git a/lib/private/Files/Cache/Wrapper/CacheJail.php b/lib/private/Files/Cache/Wrapper/CacheJail.php index 9649ae3541b..c4446473833 100644 --- a/lib/private/Files/Cache/Wrapper/CacheJail.php +++ b/lib/private/Files/Cache/Wrapper/CacheJail.php @@ -239,7 +239,7 @@ class CacheJail extends CacheWrapper { * get the size of a folder and set it in the cache * * @param string $path - * @param array $entry (optional) meta data of the folder + * @param array|null|ICacheEntry $entry (optional) meta data of the folder * @return int|float */ public function calculateFolderSize($path, $entry = null) { diff --git a/lib/private/Files/Cache/Wrapper/CacheWrapper.php b/lib/private/Files/Cache/Wrapper/CacheWrapper.php index f6bb949f968..6479ea793b0 100644 --- a/lib/private/Files/Cache/Wrapper/CacheWrapper.php +++ b/lib/private/Files/Cache/Wrapper/CacheWrapper.php @@ -249,7 +249,7 @@ class CacheWrapper extends Cache { * get the size of a folder and set it in the cache * * @param string $path - * @param array $entry (optional) meta data of the folder + * @param array|null|ICacheEntry $entry (optional) meta data of the folder * @return int|float */ public function calculateFolderSize($path, $entry = null) { -- cgit v1.2.3 From 96eca4a3ea328bf3a9764fe9e4bfc01a8c36d780 Mon Sep 17 00:00:00 2001 From: Arthur Schiwon Date: Wed, 11 Oct 2023 11:09:23 +0200 Subject: fix(ci): update return type in php doc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Côme Chilliet <91878298+come-nc@users.noreply.github.com> Signed-off-by: Arthur Schiwon --- lib/private/Files/Cache/Cache.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/private/Files/Cache/Cache.php b/lib/private/Files/Cache/Cache.php index 5454e9eb56f..5a89e73410f 100644 --- a/lib/private/Files/Cache/Cache.php +++ b/lib/private/Files/Cache/Cache.php @@ -896,7 +896,7 @@ class Cache implements ICache { * @param string $path * @param array|null|ICacheEntry $entry (optional) meta data of the folder * @param bool $ignoreUnknown don't mark the folder size as unknown if any of it's children are unknown - * @return int + * @return int|float */ protected function calculateFolderSizeInner(string $path, $entry = null, bool $ignoreUnknown = false) { $totalSize = 0; -- cgit v1.2.3