This is an automated email from the ASF dual-hosted git repository.

twolf pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mina-sshd.git

commit c603b21efbb8f9e69687e5938678251bd7c8e3eb
Author: Thomas Wolf <tw...@apache.org>
AuthorDate: Wed Mar 12 19:07:18 2025 +0100

    GH-690: Handle append mode for buggy SFTP v3 servers
    
    Some SFTP v3 servers have trouble with append mode for file uploads.
    OpenSSH < 6.3 didn't have append mode implemented, and some server
    identifying as "7.9.0.0_openssh" apparently also cannot do it.
    
    As a work-around get the file size first, then use that as base offset
    for writing. This is at best an approximation of true append mode. We
    still send the "append" flag, so for correct servers there will be no
    change, but with the work-around appending may work as expected in most
    cases even for servers that get append mode wrong.
---
 CHANGES.md                                         |  1 +
 .../sshd/sftp/client/impl/AbstractSftpClient.java  | 24 ++++++++++++++++++++++
 2 files changed, 25 insertions(+)

diff --git a/CHANGES.md b/CHANGES.md
index 466a11286..ff9710dca 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -32,6 +32,7 @@
 * [GH-663](https://github.com/apache/mina-sshd/issues/663) Fix racy 
`IoSession` creation
 * [GH-664](https://github.com/apache/mina-sshd/issues/664) Skip MAC 
negotiation if an AEAD cipher was negotiated
 * [GH-678](https://github.com/apache/mina-sshd/issues/678) `ScpShell`: write 
month names in English for WinSCP
+* [GH-690](https://github.com/apache/mina-sshd/issues/690) Handle append mode 
for buggy SFTP v3 servers
 
 ## New Features
 
diff --git 
a/sshd-sftp/src/main/java/org/apache/sshd/sftp/client/impl/AbstractSftpClient.java
 
b/sshd-sftp/src/main/java/org/apache/sshd/sftp/client/impl/AbstractSftpClient.java
index ba5964d4b..e5f8ab172 100644
--- 
a/sshd-sftp/src/main/java/org/apache/sshd/sftp/client/impl/AbstractSftpClient.java
+++ 
b/sshd-sftp/src/main/java/org/apache/sshd/sftp/client/impl/AbstractSftpClient.java
@@ -1248,9 +1248,33 @@ public abstract class AbstractSftpClient
             throw new IOException("write(" + path + ")[" + mode + "] size=" + 
bufferSize + ": client is closed");
         }
 
+        if (getVersion() <= SftpConstants.SFTP_V3 && 
mode.contains(OpenMode.Append)) {
+            // Some buggy SFTP v3 servers cannot properly handle append mode 
and always write at the offset
+            // passed in SSH_FXF_WRITE commands. (In append mode, a correct 
server should ignore that offset.)
+            //
+            // As a work-around, get the file size and use it as a base offset 
for the stream.
+            Attributes attrs = safeStat(path);
+            long fileSize = attrs == null ? 0 : attrs.getSize();
+            SftpOutputStreamAsync stream = new SftpOutputStreamAsync(this, 
bufferSize, path, mode);
+            if (fileSize > 0) {
+                stream.setOffset(fileSize);
+            }
+            return stream;
+        }
         return new SftpOutputStreamAsync(this, bufferSize, path, mode);
     }
 
+    private Attributes safeStat(String path) throws IOException {
+        try {
+            return stat(path);
+        } catch (SftpException e) {
+            if (e.getStatus() == SftpConstants.SSH_FX_NO_SUCH_FILE) {
+                return null;
+            }
+            throw e;
+        }
+    }
+
     @Override
     public void put(InputStream stream, int bufferSize, String path, 
Collection<OpenMode> modes) throws IOException {
         try (SftpOutputStreamAsync out = write(path, bufferSize, modes)) {

Reply via email to