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)) {