aboutsummaryrefslogtreecommitdiffstats
path: root/apps/files_external/lib/Lib
diff options
context:
space:
mode:
authorRobin Appelman <robin@icewind.nl>2023-08-29 16:33:06 +0200
committerAndy Scherzinger <info@andy-scherzinger.de>2025-02-05 20:50:19 +0100
commit1871296041d4fa0a5e9459d16347121b1e20cc5b (patch)
treef7034a838cd6254502eedca12567684846a22161 /apps/files_external/lib/Lib
parentd6007918055be45d91c7d81b3e08fa092c55f9c2 (diff)
downloadnextcloud-server-1871296041d4fa0a5e9459d16347121b1e20cc5b.tar.gz
nextcloud-server-1871296041d4fa0a5e9459d16347121b1e20cc5b.zip
fix: don't believe sftp when it tells us the mtime is less than we know it issftp-known-mtime
Signed-off-by: Robin Appelman <robin@icewind.nl>
Diffstat (limited to 'apps/files_external/lib/Lib')
-rw-r--r--apps/files_external/lib/Lib/Storage/SFTP.php25
1 files changed, 22 insertions, 3 deletions
diff --git a/apps/files_external/lib/Lib/Storage/SFTP.php b/apps/files_external/lib/Lib/Storage/SFTP.php
index 44073beedec..aebc61806fc 100644
--- a/apps/files_external/lib/Lib/Storage/SFTP.php
+++ b/apps/files_external/lib/Lib/Storage/SFTP.php
@@ -6,11 +6,13 @@
*/
namespace OCA\Files_External\Lib\Storage;
+use Icewind\Streams\CallbackWrapper;
use Icewind\Streams\CountWrapper;
use Icewind\Streams\IteratorDirectory;
use Icewind\Streams\RetryWrapper;
use OC\Files\Storage\Common;
use OC\Files\View;
+use OCP\Cache\CappedMemoryCache;
use OCP\Constants;
use OCP\Files\FileInfo;
use OCP\Files\IMimeTypeDetector;
@@ -32,6 +34,8 @@ class SFTP extends Common {
* @var \phpseclib\Net\SFTP
*/
protected $client;
+ private CappedMemoryCache $knownMTimes;
+
private IMimeTypeDetector $mimeTypeDetector;
public const COPY_CHUNK_SIZE = 8 * 1024 * 1024;
@@ -87,6 +91,9 @@ class SFTP extends Common {
$this->root = '/' . ltrim($this->root, '/');
$this->root = rtrim($this->root, '/') . '/';
+
+ $this->knownMTimes = new CappedMemoryCache();
+
$this->mimeTypeDetector = \OC::$server->get(IMimeTypeDetector::class);
}
@@ -297,6 +304,7 @@ class SFTP extends Common {
}
public function fopen(string $path, string $mode) {
+ $path = $this->cleanPath($path);
try {
$absPath = $this->absPath($path);
$connection = $this->getConnection();
@@ -317,7 +325,13 @@ class SFTP extends Common {
// the SFTPWriteStream doesn't go through the "normal" methods so it doesn't clear the stat cache.
$connection->_remove_from_stat_cache($absPath);
$context = stream_context_create(['sftp' => ['session' => $connection]]);
- return fopen('sftpwrite://' . trim($absPath, '/'), 'w', false, $context);
+ $fh = fopen('sftpwrite://' . trim($absPath, '/'), 'w', false, $context);
+ if ($fh) {
+ $fh = CallbackWrapper::wrap($fh, null, null, function () use ($path) {
+ $this->knownMTimes->set($path, time());
+ });
+ }
+ return $fh;
case 'a':
case 'ab':
case 'r+':
@@ -343,14 +357,13 @@ class SFTP extends Common {
return false;
}
if (!$this->file_exists($path)) {
- $this->getConnection()->put($this->absPath($path), '');
+ return $this->getConnection()->put($this->absPath($path), '');
} else {
return false;
}
} catch (\Exception $e) {
return false;
}
- return true;
}
/**
@@ -379,11 +392,17 @@ class SFTP extends Common {
*/
public function stat(string $path): array|false {
try {
+ $path = $this->cleanPath($path);
$stat = $this->getConnection()->stat($this->absPath($path));
$mtime = isset($stat['mtime']) ? (int)$stat['mtime'] : -1;
$size = isset($stat['size']) ? (int)$stat['size'] : 0;
+ // the mtime can't be less than when we last touched it
+ if ($knownMTime = $this->knownMTimes->get($path)) {
+ $mtime = max($mtime, $knownMTime);
+ }
+
return [
'mtime' => $mtime,
'size' => $size,