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


The following commit(s) were added to refs/heads/master by this push:
     new 6a8e2ee  [SSHD-1182] Fix SftpInputStreamAsync.skip()
6a8e2ee is described below

commit 6a8e2eec37295367a34b6914c3de431b2520b075
Author: Pavel Stetsuk <pstet...@exadel.com>
AuthorDate: Tue Jun 15 09:35:35 2021 +0300

    [SSHD-1182] Fix SftpInputStreamAsync.skip()
    
    On an initial skip before the first read() both clientOffset and
    requestOffset need to be set.
---
 .../sftp/client/impl/SftpInputStreamAsync.java     |  2 ++
 .../java/org/apache/sshd/sftp/client/SftpTest.java | 30 ++++++++++++++++
 .../client/impl/SftpRemotePathChannelTest.java     | 41 ++++++++++++++++++++++
 3 files changed, 73 insertions(+)

diff --git 
a/sshd-sftp/src/main/java/org/apache/sshd/sftp/client/impl/SftpInputStreamAsync.java
 
b/sshd-sftp/src/main/java/org/apache/sshd/sftp/client/impl/SftpInputStreamAsync.java
index 6721c74..71d8251 100644
--- 
a/sshd-sftp/src/main/java/org/apache/sshd/sftp/client/impl/SftpInputStreamAsync.java
+++ 
b/sshd-sftp/src/main/java/org/apache/sshd/sftp/client/impl/SftpInputStreamAsync.java
@@ -79,6 +79,7 @@ public class SftpInputStreamAsync extends 
InputStreamWithChannel implements Sftp
         this.path = path;
         this.handle = handle;
         this.bufferSize = bufferSize;
+        this.requestOffset = clientOffset;
         this.clientOffset = clientOffset;
         this.fileSize = fileSize;
     }
@@ -207,6 +208,7 @@ public class SftpInputStreamAsync extends 
InputStreamWithChannel implements Sftp
             if (log.isDebugEnabled()) {
                 log.debug("skip({}) virtual skip of {} bytes", this, n);
             }
+            requestOffset = n;
             clientOffset = n;
             return n;
         }
diff --git a/sshd-sftp/src/test/java/org/apache/sshd/sftp/client/SftpTest.java 
b/sshd-sftp/src/test/java/org/apache/sshd/sftp/client/SftpTest.java
index ed67b0c..eb8ca4e 100644
--- a/sshd-sftp/src/test/java/org/apache/sshd/sftp/client/SftpTest.java
+++ b/sshd-sftp/src/test/java/org/apache/sshd/sftp/client/SftpTest.java
@@ -564,6 +564,36 @@ public class SftpTest extends 
AbstractSftpClientTestSupport {
         }
     }
 
+    @Test // see SSHD-1182
+    public void testInputStreamSkipBeforeRead() throws Exception {
+        Path targetPath = detectTargetFolder();
+        Path parentPath = targetPath.getParent();
+        Path localFile = CommonTestSupportUtils.resolve(
+                targetPath, SftpConstants.SFTP_SUBSYSTEM_NAME, 
getClass().getSimpleName(), getCurrentTestName());
+        Files.createDirectories(localFile.getParent());
+        byte[] data
+                = (getClass().getName() + "#" + getCurrentTestName() + "[" + 
localFile + "]").getBytes(StandardCharsets.UTF_8);
+        Files.write(localFile, data, StandardOpenOption.CREATE);
+        try (SftpClient sftp = createSingleSessionClient();
+             InputStream stream = sftp.read(
+                     
CommonTestSupportUtils.resolveRelativeRemotePath(parentPath, localFile), 
OpenMode.Read)) {
+            int toSkip = data.length / 4;
+            int readLen = data.length / 2;
+            byte[] expected = new byte[readLen];
+            byte[] actual = new byte[readLen];
+
+            System.arraycopy(data, toSkip, expected, 0, readLen);
+
+            long skipped = stream.skip(toSkip);
+            assertEquals("Mismatched skipped forward size", toSkip, skipped);
+
+            int actuallyRead = IoUtils.read(stream, actual);
+            assertEquals("Failed to read fully skipped forward data", readLen, 
actuallyRead);
+
+            assertArrayEquals("Unexpected data read after skipping", expected, 
actual);
+        }
+    }
+
     @Test
     public void testSftpFileSystemAccessor() throws Exception {
         List<? extends SubsystemFactory> factories = 
sshd.getSubsystemFactories();
diff --git 
a/sshd-sftp/src/test/java/org/apache/sshd/sftp/client/impl/SftpRemotePathChannelTest.java
 
b/sshd-sftp/src/test/java/org/apache/sshd/sftp/client/impl/SftpRemotePathChannelTest.java
index a69e3db..bdabd91 100644
--- 
a/sshd-sftp/src/test/java/org/apache/sshd/sftp/client/impl/SftpRemotePathChannelTest.java
+++ 
b/sshd-sftp/src/test/java/org/apache/sshd/sftp/client/impl/SftpRemotePathChannelTest.java
@@ -139,6 +139,47 @@ public class SftpRemotePathChannelTest extends 
AbstractSftpClientTestSupport {
         assertArrayEquals("Mismatched transferred data", expected, actual);
     }
 
+    @Test // see SSHD-1182
+    public void testTransferToFileChannelWithOffset() throws IOException {
+        Path targetPath = detectTargetFolder();
+        Path lclSftp = CommonTestSupportUtils.resolve(
+                targetPath, SftpConstants.SFTP_SUBSYSTEM_NAME, 
getClass().getSimpleName());
+        Path srcFile = 
assertHierarchyTargetFolderExists(lclSftp).resolve(getCurrentTestName() + 
"-src.txt");
+        Path parentPath = targetPath.getParent();
+
+        Files.deleteIfExists(srcFile);
+        try (Writer output = Files.newBufferedWriter(srcFile, 
StandardCharsets.UTF_8)) {
+            String seed = getClass().getName() + "#" + getCurrentTestName() + 
"(" + new Date() + ")";
+            for (long totalWritten = 0L;
+                 totalWritten <= 
SftpModuleProperties.COPY_BUF_SIZE.getRequiredDefault();
+                 totalWritten += seed.length()) {
+                output.append(seed).append(System.lineSeparator());
+            }
+        }
+
+        byte[] data = Files.readAllBytes(srcFile);
+        int offset = data.length / 4;
+        byte[] expected = new byte[data.length - offset];
+        System.arraycopy(data, offset, expected, 0, expected.length);
+
+        Path dstFile = srcFile.getParent().resolve(getCurrentTestName() + 
"-dst.txt");
+        Files.deleteIfExists(dstFile);
+
+        String remFilePath = 
CommonTestSupportUtils.resolveRelativeRemotePath(parentPath, srcFile);
+        try (SftpClient sftp = createSingleSessionClient();
+             FileChannel srcChannel = sftp.openRemotePathChannel(
+                     remFilePath, EnumSet.of(StandardOpenOption.READ));
+             FileChannel dstChannel = FileChannel.open(dstFile,
+                     StandardOpenOption.CREATE, StandardOpenOption.WRITE)) {
+            long numXfered = srcChannel.transferTo(offset, expected.length, 
dstChannel);
+            assertEquals("Mismatched reported transfer count", 
expected.length, numXfered);
+        }
+
+        byte[] actual = Files.readAllBytes(dstFile);
+        assertEquals("Mismatched transferred size", expected.length, 
actual.length);
+        assertArrayEquals("Mismatched transferred data", expected, actual);
+    }
+
     @Test(timeout = 10000) // see SSHD-970
     public void testTransferToFileChannelLoopFile() throws IOException {
         Path targetPath = detectTargetFolder();

Reply via email to