Skip to content

Commit 33994b2

Browse files
authored
Merge pull request #38555 from nextcloud/backport/36857/stable26
[stable26] fix unencrypted_size for folders when scanning the filesystem with encryption enabled
2 parents 3b5e854 + 96eca4a commit 33994b2

6 files changed

Lines changed: 55 additions & 41 deletions

File tree

lib/private/Files/Cache/Cache.php

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -882,10 +882,23 @@ public function getIncompleteChildrenCount($fileId) {
882882
* calculate the size of a folder and set it in the cache
883883
*
884884
* @param string $path
885-
* @param array $entry (optional) meta data of the folder
885+
* @param array|null|ICacheEntry $entry (optional) meta data of the folder
886886
* @return int|float
887887
*/
888888
public function calculateFolderSize($path, $entry = null) {
889+
return $this->calculateFolderSizeInner($path, $entry);
890+
}
891+
892+
893+
/**
894+
* inner function because we can't add new params to the public function without breaking any child classes
895+
*
896+
* @param string $path
897+
* @param array|null|ICacheEntry $entry (optional) meta data of the folder
898+
* @param bool $ignoreUnknown don't mark the folder size as unknown if any of it's children are unknown
899+
* @return int|float
900+
*/
901+
protected function calculateFolderSizeInner(string $path, $entry = null, bool $ignoreUnknown = false) {
889902
$totalSize = 0;
890903
if (is_null($entry) || !isset($entry['fileid'])) {
891904
$entry = $this->get($path);
@@ -897,6 +910,9 @@ public function calculateFolderSize($path, $entry = null) {
897910
$query->select('size', 'unencrypted_size')
898911
->from('filecache')
899912
->whereParent($id);
913+
if ($ignoreUnknown) {
914+
$query->andWhere($query->expr()->gte('size', $query->createNamedParameter(0)));
915+
}
900916

901917
$result = $query->execute();
902918
$rows = $result->fetchAll();
@@ -937,9 +953,16 @@ public function calculateFolderSize($path, $entry = null) {
937953
$unencryptedTotal = 0;
938954
$unencryptedMax = 0;
939955
}
940-
if ($entry['size'] !== $totalSize) {
941-
// only set unencrypted size for a folder if any child entries have it set, or the folder is empty
942-
if ($unencryptedMax > 0 || $totalSize === 0) {
956+
957+
// only set unencrypted size for a folder if any child entries have it set, or the folder is empty
958+
$shouldWriteUnEncryptedSize = $unencryptedMax > 0 || $totalSize === 0 || $entry['unencrypted_size'] > 0;
959+
if ($entry['size'] !== $totalSize || ($entry['unencrypted_size'] !== $unencryptedTotal && $shouldWriteUnEncryptedSize)) {
960+
if ($shouldWriteUnEncryptedSize) {
961+
// if all children have an unencrypted size of 0, just set the folder unencrypted size to 0 instead of summing the sizes
962+
if ($unencryptedMax === 0) {
963+
$unencryptedTotal = 0;
964+
}
965+
943966
$this->update($id, [
944967
'size' => $totalSize,
945968
'unencrypted_size' => $unencryptedTotal,

lib/private/Files/Cache/HomeCache.php

Lines changed: 3 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ class HomeCache extends Cache {
3535
* get the size of a folder and set it in the cache
3636
*
3737
* @param string $path
38-
* @param array $entry (optional) meta data of the folder
38+
* @param array|null|ICacheEntry $entry (optional) meta data of the folder
3939
* @return int|float
4040
*/
4141
public function calculateFolderSize($path, $entry = null) {
@@ -44,37 +44,9 @@ public function calculateFolderSize($path, $entry = null) {
4444
} elseif ($path === '' or $path === '/') {
4545
// since the size of / isn't used (the size of /files is used instead) there is no use in calculating it
4646
return 0;
47+
} else {
48+
return $this->calculateFolderSizeInner($path, $entry, true);
4749
}
48-
49-
$totalSize = 0;
50-
if (is_null($entry)) {
51-
$entry = $this->get($path);
52-
}
53-
if ($entry && $entry['mimetype'] === 'httpd/unix-directory') {
54-
$id = $entry['fileid'];
55-
56-
$query = $this->connection->getQueryBuilder();
57-
$query->selectAlias($query->func()->sum('size'), 'f1')
58-
->from('filecache')
59-
->where($query->expr()->eq('parent', $query->createNamedParameter($id)))
60-
->andWhere($query->expr()->eq('storage', $query->createNamedParameter($this->getNumericStorageId())))
61-
->andWhere($query->expr()->gte('size', $query->createNamedParameter(0)));
62-
63-
$result = $query->execute();
64-
$row = $result->fetch();
65-
$result->closeCursor();
66-
67-
if ($row) {
68-
[$sum] = array_values($row);
69-
$totalSize = 0 + $sum;
70-
$entry['size'] += 0;
71-
if ($entry['size'] !== $totalSize) {
72-
$this->update($id, ['size' => $totalSize]);
73-
}
74-
}
75-
$result->closeCursor();
76-
}
77-
return $totalSize;
7850
}
7951

8052
/**

lib/private/Files/Cache/Scanner.php

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
namespace OC\Files\Cache;
3737

3838
use Doctrine\DBAL\Exception;
39+
use OC\Files\Storage\Wrapper\Encryption;
3940
use OCP\Files\Cache\IScanner;
4041
use OCP\Files\ForbiddenException;
4142
use OCP\Files\Storage\IReliableEtagStorage;
@@ -207,9 +208,17 @@ public function scanFile($file, $reuseExisting = 0, $parentId = -1, $cacheData =
207208
$data['etag'] = $etag;
208209
}
209210
}
211+
212+
// we only updated unencrypted_size if it's already set
213+
if ($cacheData['unencrypted_size'] === 0) {
214+
unset($data['unencrypted_size']);
215+
}
216+
210217
// Only update metadata that has changed
211218
$newData = array_diff_assoc($data, $cacheData->getData());
212219
} else {
220+
// we only updated unencrypted_size if it's already set
221+
unset($data['unencrypted_size']);
213222
$newData = $data;
214223
$fileId = -1;
215224
}
@@ -219,7 +228,7 @@ public function scanFile($file, $reuseExisting = 0, $parentId = -1, $cacheData =
219228
$newData['parent'] = $parentId;
220229
$data['fileid'] = $this->addToCache($file, $newData, $fileId);
221230
}
222-
231+
223232
$data['oldSize'] = ($cacheData && isset($cacheData['size'])) ? $cacheData['size'] : 0;
224233

225234
if ($cacheData && isset($cacheData['encrypted'])) {
@@ -390,8 +399,15 @@ protected function scanChildren($path, $recursive = self::SCAN_RECURSIVE, $reuse
390399
}
391400
}
392401
$oldSize = $data['size'] ?? null;
393-
if ($this->cacheActive && $oldSize !== $size) {
394-
$this->cache->update($folderId, ['size' => $size]);
402+
403+
// for encrypted storages, we trigger a regular folder size calculation instead of using the calculated size
404+
// to make sure we also updated the unencrypted-size where applicable
405+
if ($this->storage->instanceOfStorage(Encryption::class)) {
406+
$this->cache->calculateFolderSize($path);
407+
} else {
408+
if ($this->cacheActive && $oldSize !== $size) {
409+
$this->cache->update($folderId, ['size' => $size]);
410+
}
395411
}
396412
$this->emit('\OC\Files\Cache\Scanner', 'postScanFolder', [$path, $this->storageId]);
397413
return $size;

lib/private/Files/Cache/Wrapper/CacheJail.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ public function correctFolderSize($path, $data = null, $isBackgroundScan = false
239239
* get the size of a folder and set it in the cache
240240
*
241241
* @param string $path
242-
* @param array $entry (optional) meta data of the folder
242+
* @param array|null|ICacheEntry $entry (optional) meta data of the folder
243243
* @return int|float
244244
*/
245245
public function calculateFolderSize($path, $entry = null) {

lib/private/Files/Cache/Wrapper/CacheWrapper.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ public function correctFolderSize($path, $data = null, $isBackgroundScan = false
249249
* get the size of a folder and set it in the cache
250250
*
251251
* @param string $path
252-
* @param array $entry (optional) meta data of the folder
252+
* @param array|null|ICacheEntry $entry (optional) meta data of the folder
253253
* @return int|float
254254
*/
255255
public function calculateFolderSize($path, $entry = null) {

lib/private/Files/Storage/Wrapper/Encryption.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,10 +188,12 @@ private function modifyMetaData(string $path, array $data): array {
188188
if (isset($this->unencryptedSize[$fullPath])) {
189189
$data['encrypted'] = true;
190190
$data['size'] = $this->unencryptedSize[$fullPath];
191+
$data['unencrypted_size'] = $data['size'];
191192
} else {
192193
if (isset($info['fileid']) && $info['encrypted']) {
193194
$data['size'] = $this->verifyUnencryptedSize($path, $info->getUnencryptedSize());
194195
$data['encrypted'] = true;
196+
$data['unencrypted_size'] = $data['size'];
195197
}
196198
}
197199

@@ -502,7 +504,8 @@ protected function verifyUnencryptedSize(string $path, int $unencryptedSize): in
502504
$result = $unencryptedSize;
503505

504506
if ($unencryptedSize < 0 ||
505-
($size > 0 && $unencryptedSize === $size)
507+
($size > 0 && $unencryptedSize === $size) ||
508+
$unencryptedSize > $size
506509
) {
507510
// check if we already calculate the unencrypted size for the
508511
// given path to avoid recursions

0 commit comments

Comments
 (0)