summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArthur Schiwon <blizzz@arthur-schiwon.de>2023-10-12 09:14:04 +0200
committerGitHub <noreply@github.com>2023-10-12 09:14:04 +0200
commit33994b2d81234280ac5dbaefd1921c1012223c4a (patch)
treeceee69946ff423cb91f9e94cd71468bccdfdbca1
parent3b5e854e8f5d654b5b29ccc8548043d76cc4cba4 (diff)
parent96eca4a3ea328bf3a9764fe9e4bfc01a8c36d780 (diff)
downloadnextcloud-server-33994b2d81234280ac5dbaefd1921c1012223c4a.tar.gz
nextcloud-server-33994b2d81234280ac5dbaefd1921c1012223c4a.zip
Merge pull request #38555 from nextcloud/backport/36857/stable26
[stable26] fix unencrypted_size for folders when scanning the filesystem with encryption enabled
-rw-r--r--lib/private/Files/Cache/Cache.php31
-rw-r--r--lib/private/Files/Cache/HomeCache.php34
-rw-r--r--lib/private/Files/Cache/Scanner.php22
-rw-r--r--lib/private/Files/Cache/Wrapper/CacheJail.php2
-rw-r--r--lib/private/Files/Cache/Wrapper/CacheWrapper.php2
-rw-r--r--lib/private/Files/Storage/Wrapper/Encryption.php5
6 files changed, 55 insertions, 41 deletions
diff --git a/lib/private/Files/Cache/Cache.php b/lib/private/Files/Cache/Cache.php
index 9e475057a36..5a89e73410f 100644
--- a/lib/private/Files/Cache/Cache.php
+++ b/lib/private/Files/Cache/Cache.php
@@ -882,10 +882,23 @@ 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 array|null|ICacheEntry $entry (optional) meta data of the folder
* @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|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|float
+ */
+ protected function calculateFolderSizeInner(string $path, $entry = null, bool $ignoreUnknown = false) {
$totalSize = 0;
if (is_null($entry) || !isset($entry['fileid'])) {
$entry = $this->get($path);
@@ -897,6 +910,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();
@@ -937,9 +953,16 @@ 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 || $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..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) {
@@ -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;
}
/**
diff --git a/lib/private/Files/Cache/Scanner.php b/lib/private/Files/Cache/Scanner.php
index 42f8f1b375b..228f5d4056e 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;
@@ -207,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;
}
@@ -219,7 +228,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 +399,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;
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) {
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