Details
-
Bug
-
Status: Resolved
-
Major
-
Resolution: Fixed
-
2.5.1, 2.7.0
-
None
Description
When calling
sftpClient.write(remoteFileName, OpenMode.Create, OpenMode.Write, OpenMode.Exclusive);
I expect the operation to succeed if no file with that name exists and fail if a file with that name exists. This works as expected when using a SftpVersionSelector to force version 3 or 4. Version 5 or 6 will overwrite the existing file.
Similarly I expect the line below to fail when newName already exists.
sftpClient.rename(oldName, newName);
This works as expected in version 3 or 4. In version 5 or 6 the existing file is overwritten.
I expect the following line which is not supported in version 3 or 4 to fail when the newName file already exists when using 5 or 6 but it still overwrites any existing file:
sftpClient.rename(oldName, newName, CopyMode.Atomic);
I'm using 2.5 but issue seems to be the same in 2.7.
I have tested this using apache mina server & client, including a quick and dirty test to demonstrate the OpenMode issue:
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import java.io.IOException; import java.time.Duration; import java.util.Collections; import java.util.HashMap; import java.util.Map; import org.apache.sshd.client.SshClient; import org.apache.sshd.client.session.ClientSession; import org.apache.sshd.client.subsystem.sftp.SftpClient; import org.apache.sshd.client.subsystem.sftp.SftpClientFactory; import org.apache.sshd.client.subsystem.sftp.SftpVersionSelector; import org.apache.sshd.common.file.virtualfs.VirtualFileSystemFactory; import org.apache.sshd.server.SshServer; import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider; import org.apache.sshd.server.subsystem.sftp.SftpSubsystemFactory; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; public class BugMVP { @Rule public TemporaryFolder testFolder = new TemporaryFolder(); private static final String USERNAME = "username"; private static final String PASSWORD = "password"; private SshServer sshd; @Before public void prepare() throws IOException { Map<String, String> roots = new HashMap<>(); roots.put(USERNAME, testFolder.getRoot().getAbsolutePath()); sshd = SshServer.setUpDefaultServer(); sshd.setFileSystemFactory(new VirtualFileSystemFactory(testFolder.getRoot().toPath())); sshd.setPort(42414); sshd.setSubsystemFactories(Collections.singletonList(new SftpSubsystemFactory())); sshd.setKeyPairProvider(new SimpleGeneratorHostKeyProvider(testFolder.newFile("hostkey.ser").toPath())); sshd.setPasswordAuthenticator((username, password, session) -> username.equals(USERNAME) && password.equals(PASSWORD)); sshd.start(); testFolder.newFolder("somefolder"); testFolder.newFile("somefolder/foo.bar"); } @Test public void testUploadingFileUsingDefaultVersion6_shouldFail() throws IOException { SshClient client = SshClient.setUpDefaultClient(); client.start(); ClientSession clientSession = client.connect(USERNAME, "localhost", 42414) .verify(Duration.ofSeconds(10)) .getSession(); clientSession.addPasswordIdentity(PASSWORD); clientSession.auth().verify(Duration.ofSeconds(10)); SftpClientFactory factory = SftpClientFactory.instance(); SftpClient sftpClient = factory.createSftpClient(clientSession); try (sftpClient; clientSession) { sftpClient.write("somefolder/foo.bar", SftpClient.OpenMode.Write, SftpClient.OpenMode.Create, SftpClient.OpenMode.Exclusive); assertFalse(true); } catch (IOException e){ assertEquals("File/Directory already exists",e.getMessage()); } } @Test public void testUploadingFileUsingV4_shouldFail() throws IOException { SshClient client = SshClient.setUpDefaultClient(); client.start(); ClientSession clientSession = client.connect(USERNAME, "localhost", 42414) .verify(Duration.ofSeconds(10)) .getSession(); clientSession.addPasswordIdentity(PASSWORD); clientSession.auth().verify(Duration.ofSeconds(10)); SftpVersionSelector versionSelector = (session, initial, current, available) -> { return 4; }; SftpClientFactory factory = SftpClientFactory.instance(); SftpClient sftpClient = factory.createSftpClient(clientSession, versionSelector); try (sftpClient; clientSession) { sftpClient.write("somefolder/foo.bar", SftpClient.OpenMode.Write, SftpClient.OpenMode.Create, SftpClient.OpenMode.Exclusive); assertFalse(true); } catch (IOException e){ assertEquals("File/Directory already exists",e.getMessage()); } } }