You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by lg...@apache.org on 2015/08/02 11:55:23 UTC
mina-sshd git commit: [SSHD-547] Ignore offset in SFTP SSH_FXP_WRITE
if file opened with SSH_FXF_APPEND_DATA access
Repository: mina-sshd
Updated Branches:
refs/heads/master 61e637c48 -> 3eefdb3f8
[SSHD-547] Ignore offset in SFTP SSH_FXP_WRITE if file opened with SSH_FXF_APPEND_DATA access
Project: http://git-wip-us.apache.org/repos/asf/mina-sshd/repo
Commit: http://git-wip-us.apache.org/repos/asf/mina-sshd/commit/3eefdb3f
Tree: http://git-wip-us.apache.org/repos/asf/mina-sshd/tree/3eefdb3f
Diff: http://git-wip-us.apache.org/repos/asf/mina-sshd/diff/3eefdb3f
Branch: refs/heads/master
Commit: 3eefdb3f8cdf015f8f147572ed83de6390ff4bc0
Parents: 61e637c
Author: Lyor Goldstein <lg...@vmware.com>
Authored: Sun Aug 2 12:55:13 2015 +0300
Committer: Lyor Goldstein <lg...@vmware.com>
Committed: Sun Aug 2 12:55:13 2015 +0300
----------------------------------------------------------------------
.../sshd/server/subsystem/sftp/FileHandle.java | 16 +++++
.../server/subsystem/sftp/SftpSubsystem.java | 6 +-
.../sshd/client/subsystem/sftp/SftpTest.java | 64 ++++++++++++++++++--
3 files changed, 80 insertions(+), 6 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/3eefdb3f/sshd-core/src/main/java/org/apache/sshd/server/subsystem/sftp/FileHandle.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/subsystem/sftp/FileHandle.java b/sshd-core/src/main/java/org/apache/sshd/server/subsystem/sftp/FileHandle.java
index 92f9346..49379de 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/subsystem/sftp/FileHandle.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/subsystem/sftp/FileHandle.java
@@ -33,10 +33,12 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
+import static org.apache.sshd.common.subsystem.sftp.SftpConstants.ACE4_APPEND_DATA;
import static org.apache.sshd.common.subsystem.sftp.SftpConstants.ACE4_READ_ATTRIBUTES;
import static org.apache.sshd.common.subsystem.sftp.SftpConstants.ACE4_READ_DATA;
import static org.apache.sshd.common.subsystem.sftp.SftpConstants.ACE4_WRITE_ATTRIBUTES;
import static org.apache.sshd.common.subsystem.sftp.SftpConstants.ACE4_WRITE_DATA;
+
import static org.apache.sshd.common.subsystem.sftp.SftpConstants.SSH_FXF_ACCESS_DISPOSITION;
import static org.apache.sshd.common.subsystem.sftp.SftpConstants.SSH_FXF_APPEND_DATA;
import static org.apache.sshd.common.subsystem.sftp.SftpConstants.SSH_FXF_CREATE_NEW;
@@ -123,6 +125,10 @@ public class FileHandle extends Handle {
return access;
}
+ public boolean isOpenAppend() {
+ return ACE4_APPEND_DATA == (getAccessMask() & ACE4_APPEND_DATA);
+ }
+
public int read(byte[] data, long offset) throws IOException {
return read(data, 0, data.length, offset);
}
@@ -138,6 +144,15 @@ public class FileHandle extends Handle {
return read;
}
+ public void append(byte[] data) throws IOException {
+ append(data, 0, data.length);
+ }
+
+ public void append(byte[] data, int doff, int length) throws IOException {
+ FileChannel channel = getFileChannel();
+ write(data, doff, length, channel.size());
+ }
+
public void write(byte[] data, long offset) throws IOException {
write(data, 0, data.length, offset);
}
@@ -148,6 +163,7 @@ public class FileHandle extends Handle {
channel.position(offset);
pos = offset;
}
+
channel.write(ByteBuffer.wrap(data, doff, length));
pos += length;
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/3eefdb3f/sshd-core/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystem.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystem.java b/sshd-core/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystem.java
index 1ae19ee..607a9b8 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystem.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/subsystem/sftp/SftpSubsystem.java
@@ -1879,7 +1879,11 @@ public class SftpSubsystem extends AbstractLoggingBean implements Command, Runna
throw new IllegalStateException("Not enough buffer data for writing to " + fh + ": required=" + length + ", available=" + remaining);
}
- fh.write(data, doff, length, offset);
+ if (fh.isOpenAppend()) {
+ fh.append(data, doff, length);
+ } else {
+ fh.write(data, doff, length, offset);
+ }
}
protected void doRead(Buffer buffer, int id) throws IOException {
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/3eefdb3f/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/SftpTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/SftpTest.java b/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/SftpTest.java
index 6fd49d8..d551113 100644
--- a/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/SftpTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/SftpTest.java
@@ -35,6 +35,7 @@ import java.nio.file.FileSystem;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
+import java.util.Arrays;
import java.util.Collection;
import java.util.EnumSet;
import java.util.Iterator;
@@ -116,6 +117,59 @@ public class SftpTest extends AbstractSftpClientTestSupport {
Thread.sleep(5 * 60000);
}
+ @Test // see SSHD-547
+ public void testWriteOffsetIgnoredForAppendMode() throws IOException {
+ Path targetPath = detectTargetFolder().toPath();
+ Path parentPath = targetPath.getParent();
+ Path lclSftp = Utils.resolve(targetPath, SftpConstants.SFTP_SUBSYSTEM_NAME, getClass().getSimpleName(), getCurrentTestName());
+ Path testFile = assertHierarchyTargetFolderExists(lclSftp).resolve("file.txt");
+ Files.deleteIfExists(testFile);
+
+ byte[] expectedRandom = new byte[Byte.MAX_VALUE];
+ Factory<? extends Random> factory = sshd.getRandomFactory();
+ Random rnd = factory.create();
+ rnd.fill(expectedRandom);
+
+ byte[] expectedText = (getClass().getName() + "#" + getCurrentTestName()).getBytes(StandardCharsets.UTF_8);
+ try (SshClient client = SshClient.setUpDefaultClient()) {
+ client.start();
+
+ try (ClientSession session = client.connect(getCurrentTestName(), "localhost", port).verify(7L, TimeUnit.SECONDS).getSession()) {
+ session.addPasswordIdentity(getCurrentTestName());
+ session.auth().verify(5L, TimeUnit.SECONDS);
+
+ try (SftpClient sftp = session.createSftpClient()) {
+ String file = Utils.resolveRelativeRemotePath(parentPath, testFile);
+
+ try (CloseableHandle handle = sftp.open(file, OpenMode.Create, OpenMode.Write, OpenMode.Read, OpenMode.Append)) {
+ sftp.write(handle, 7365L, expectedRandom);
+ byte[] actualRandom = new byte[expectedRandom.length];
+ int readLen = sftp.read(handle, 0L, actualRandom);
+ assertEquals("Incomplete random data read", expectedRandom.length, readLen);
+ assertArrayEquals("Mismatched read random data", expectedRandom, actualRandom);
+
+ sftp.write(handle, 3777347L, expectedText);
+ byte[] actualText = new byte[expectedText.length];
+ readLen = sftp.read(handle, actualRandom.length, actualText);
+ assertEquals("Incomplete text data read", actualText.length, readLen);
+ assertArrayEquals("Mismatched read text data", expectedText, actualText);
+ }
+ }
+ } finally {
+ client.stop();
+ }
+ }
+
+ byte[] actualBytes = Files.readAllBytes(testFile);
+ assertEquals("Mismatched result file size", expectedRandom.length + expectedText.length, actualBytes.length);
+
+ byte[] actualRandom = Arrays.copyOfRange(actualBytes, 0, expectedRandom.length);
+ assertArrayEquals("Mismatched random part", expectedRandom, actualRandom);
+
+ byte[] actualText = Arrays.copyOfRange(actualBytes, expectedRandom.length, actualBytes.length);
+ assertArrayEquals("Mismatched text part", expectedText, actualText);
+ }
+
@Test // see SSHD-545
public void testReadBufferLimit() throws Exception {
Path targetPath = detectTargetFolder().toPath();
@@ -145,7 +199,7 @@ public class SftpTest extends AbstractSftpClientTestSupport {
try(CloseableHandle handle = sftp.open(file, OpenMode.Read)) {
int readLen = sftp.read(handle, 0L, actual);
assertEquals("Mismatched read len", maxAllowed, readLen);
-
+
for (int index = 0; index < readLen; index++) {
byte expByte = expected[index], actByte = actual[index];
if (expByte != actByte) {
@@ -868,13 +922,13 @@ public class SftpTest extends AbstractSftpClientTestSupport {
/*
* NOTE !!! according to Jsch documentation
* (see http://epaul.github.io/jsch-documentation/simple.javadoc/com/jcraft/jsch/ChannelSftp.html#current-directory)
- *
- *
+ *
+ *
* This sftp client has the concept of a current local directory and
* a current remote directory. These are not inherent to the protocol,
* but are used implicitly for all path-based commands sent to the server
* for the remote directory) or accessing the local file system (for the local directory).
- *
+ *
* Therefore we are using "absolute" remote files for this test
*/
Path parentPath = targetPath.getParent();
@@ -897,7 +951,7 @@ public class SftpTest extends AbstractSftpClientTestSupport {
assertTrue("Symlink not created: " + linkPath, Files.exists(linkPath));
assertEquals("Mismatched link data in " + remLinkPath, data, readFile(remLinkPath));
-
+
String str1 = c.readlink(remLinkPath);
String str2 = c.realpath(remSrcPath);
assertEquals("Mismatched link vs. real path", str1, str2);