Repository: mina-sshd
Updated Branches:
  refs/heads/master b2240515a -> 862f4f029


Do not modify SCP file permissions if timestamp attribute should be preserved


Project: http://git-wip-us.apache.org/repos/asf/mina-sshd/repo
Commit: http://git-wip-us.apache.org/repos/asf/mina-sshd/commit/862f4f02
Tree: http://git-wip-us.apache.org/repos/asf/mina-sshd/tree/862f4f02
Diff: http://git-wip-us.apache.org/repos/asf/mina-sshd/diff/862f4f02

Branch: refs/heads/master
Commit: 862f4f0294268e7b496c5127596694eec4df2a25
Parents: b224051
Author: Goldstein Lyor <l...@c-b4.com>
Authored: Mon Aug 7 11:30:15 2017 +0300
Committer: Goldstein Lyor <l...@c-b4.com>
Committed: Mon Aug 7 11:31:08 2017 +0300

----------------------------------------------------------------------
 .../sshd/client/scp/DefaultScpClient.java       | 15 +++---
 .../subsystem/sftp/SftpFileSystemProvider.java  |  6 +--
 .../org/apache/sshd/common/scp/ScpHelper.java   | 16 ++++---
 .../org/apache/sshd/client/scp/ScpTest.java     | 50 +++++++++++++-------
 4 files changed, 54 insertions(+), 33 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/862f4f02/sshd-core/src/main/java/org/apache/sshd/client/scp/DefaultScpClient.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/main/java/org/apache/sshd/client/scp/DefaultScpClient.java 
b/sshd-core/src/main/java/org/apache/sshd/client/scp/DefaultScpClient.java
index 854929a..d69252c 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/scp/DefaultScpClient.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/scp/DefaultScpClient.java
@@ -114,21 +114,22 @@ public class DefaultScpClient extends AbstractScpClient {
     }
 
     @Override
-    public void upload(final InputStream local, final String remote, final 
long size, final Collection<PosixFilePermission> perms, final ScpTimestamp 
time) throws IOException {
+    public void upload(InputStream local, String remote, long size, 
Collection<PosixFilePermission> perms, ScpTimestamp time) throws IOException {
         int namePos = ValidateUtils.checkNotNullAndNotEmpty(remote, "No remote 
location specified").lastIndexOf('/');
-        final String name = (namePos < 0)
-                ? remote
-                : 
ValidateUtils.checkNotNullAndNotEmpty(remote.substring(namePos + 1), "No name 
value in remote=%s", remote);
-        final String cmd = ScpClient.createSendCommand(remote, (time != null) 
? EnumSet.of(Option.PreserveAttributes) : Collections.emptySet());
+        String name = (namePos < 0)
+            ? remote
+            : ValidateUtils.checkNotNullAndNotEmpty(remote.substring(namePos + 
1), "No name value in remote=%s", remote);
+        Collection<Option> options = (time != null) ? 
EnumSet.of(Option.PreserveAttributes) : Collections.emptySet();
+        String cmd = ScpClient.createSendCommand(remote, options);
         ClientSession session = getClientSession();
         ChannelExec channel = openCommandChannel(session, cmd);
         try (InputStream invOut = channel.getInvertedOut();
              OutputStream invIn = channel.getInvertedIn()) {
             // NOTE: we use a mock file system since we expect no invocations 
for it
             ScpHelper helper = new ScpHelper(session, invOut, invIn, new 
MockFileSystem(remote), opener, listener);
-            final Path mockPath = new MockPath(remote);
+            Path mockPath = new MockPath(remote);
             helper.sendStream(new DefaultScpStreamResolver(name, mockPath, 
perms, time, size, local, cmd),
-                              time != null, 
ScpHelper.DEFAULT_SEND_BUFFER_SIZE);
+                    options.contains(Option.PreserveAttributes), 
ScpHelper.DEFAULT_SEND_BUFFER_SIZE);
             handleCommandExitStatus(cmd, channel);
         } finally {
             channel.close(false);

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/862f4f02/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpFileSystemProvider.java
----------------------------------------------------------------------
diff --git 
a/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpFileSystemProvider.java
 
b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpFileSystemProvider.java
index fb24d73..f8af4f5 100644
--- 
a/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpFileSystemProvider.java
+++ 
b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpFileSystemProvider.java
@@ -60,7 +60,6 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.EnumSet;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
@@ -1089,11 +1088,12 @@ public class SftpFileSystemProvider extends 
FileSystemProvider {
     }
 
     public static String getOctalPermissions(int perms) {
-        return getOctalPermissions(permissionsToAttributes(perms));
+        Collection<PosixFilePermission> attrs = permissionsToAttributes(perms);
+        return getOctalPermissions(attrs);
     }
 
     public static Set<PosixFilePermission> permissionsToAttributes(int perms) {
-        Set<PosixFilePermission> p = new HashSet<>();
+        Set<PosixFilePermission> p = EnumSet.noneOf(PosixFilePermission.class);
         if ((perms & SftpConstants.S_IRUSR) == SftpConstants.S_IRUSR) {
             p.add(PosixFilePermission.OWNER_READ);
         }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/862f4f02/sshd-core/src/main/java/org/apache/sshd/common/scp/ScpHelper.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/scp/ScpHelper.java 
b/sshd-core/src/main/java/org/apache/sshd/common/scp/ScpHelper.java
index 56f03de..3f584d2 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/scp/ScpHelper.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/scp/ScpHelper.java
@@ -97,6 +97,9 @@ public class ScpHelper extends AbstractLoggingBean implements 
SessionHolder<Sess
     public static final int S_IWOTH = 0000002;
     public static final int S_IXOTH = 0000001;
 
+    public static final String DEFAULT_DIR_OCTAL_PERMISSIONS = "0755";
+    public static final String DEFAULT_FILE_OCTAL_PERMISSIONS = "0644";
+
     protected final InputStream in;
     protected final OutputStream out;
     protected final FileSystem fileSystem;
@@ -120,7 +123,7 @@ public class ScpHelper extends AbstractLoggingBean 
implements SessionHolder<Sess
         return sessionInstance;
     }
 
-    public void receiveFileStream(final OutputStream local, final int 
bufferSize) throws IOException {
+    public void receiveFileStream(OutputStream local, int bufferSize) throws 
IOException {
         receive((line, isDir, timestamp) -> {
             if (isDir) {
                 throw new StreamCorruptedException("Cannot download a 
directory into a file stream: " + line);
@@ -161,7 +164,7 @@ public class ScpHelper extends AbstractLoggingBean 
implements SessionHolder<Sess
         });
     }
 
-    public void receive(Path local, final boolean recursive, boolean 
shouldBeDir, final boolean preserve, final int bufferSize) throws IOException {
+    public void receive(Path local, boolean recursive, boolean shouldBeDir, 
boolean preserve, final int bufferSize) throws IOException {
         Path path = Objects.requireNonNull(local, "No local 
path").normalize().toAbsolutePath();
         if (shouldBeDir) {
             LinkOption[] options = IoUtils.getLinkOptions(true);
@@ -602,7 +605,7 @@ public class ScpHelper extends AbstractLoggingBean 
implements SessionHolder<Sess
         }
 
         Set<PosixFilePermission> perms = 
EnumSet.copyOf(resolver.getPermissions());
-        String octalPerms = preserve ? getOctalPermissions(perms) : "0644";
+        String octalPerms = GenericUtils.isEmpty(perms) ? 
DEFAULT_FILE_OCTAL_PERMISSIONS : getOctalPermissions(perms);
         String fileName = resolver.getFileName();
         String cmd = "C" + octalPerms + " " + fileSize + " " + fileName;
         if (log.isDebugEnabled()) {
@@ -697,8 +700,8 @@ public class ScpHelper extends AbstractLoggingBean 
implements SessionHolder<Sess
 
         LinkOption[] options = IoUtils.getLinkOptions(true);
         Set<PosixFilePermission> perms = IoUtils.getPermissions(path, options);
-        String cmd = "D" + (preserve ? getOctalPermissions(perms) : "0755") + 
" "
-                + "0" + " " + path.getFileName().toString();
+        String octalPerms = GenericUtils.isEmpty(perms) ? 
DEFAULT_DIR_OCTAL_PERMISSIONS : getOctalPermissions(perms);
+        String cmd = "D" + octalPerms + " " + "0" + " " + 
Objects.toString(path.getFileName(), null);
         if (log.isDebugEnabled()) {
             log.debug("sendDir({})[{}] send 'D' command: {}", this, path, cmd);
         }
@@ -747,7 +750,8 @@ public class ScpHelper extends AbstractLoggingBean 
implements SessionHolder<Sess
     }
 
     public static String getOctalPermissions(Path path, LinkOption... options) 
throws IOException {
-        return getOctalPermissions(IoUtils.getPermissions(path, options));
+        Collection<PosixFilePermission> perms = IoUtils.getPermissions(path, 
options);
+        return getOctalPermissions(perms);
     }
 
     public static String getOctalPermissions(Collection<PosixFilePermission> 
perms) {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/862f4f02/sshd-core/src/test/java/org/apache/sshd/client/scp/ScpTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/client/scp/ScpTest.java 
b/sshd-core/src/test/java/org/apache/sshd/client/scp/ScpTest.java
index bbe1166..42907d6 100644
--- a/sshd-core/src/test/java/org/apache/sshd/client/scp/ScpTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/client/scp/ScpTest.java
@@ -901,24 +901,24 @@ public class ScpTest extends BaseTestSupport {
             File target = new File(unixPath);
             Utils.deleteRecursive(root);
             root.mkdirs();
-            assertTrue(root.exists());
+            assertTrue("Failed to ensure existence of " + root, root.exists());
 
             target.delete();
-            assertFalse(target.exists());
-            sendFile(session, unixPath, fileName, data);
+            assertFalse("Failed to delete 1st time: " + target, 
target.exists());
+            sendFile(session, unixPath, target, data);
             assertFileLength(target, data.length(), 
TimeUnit.SECONDS.toMillis(5L));
 
             target.delete();
-            assertFalse(target.exists());
-            sendFile(session, unixDir, fileName, data);
+            assertFalse("Failed to delete 2nd time: " + target, 
target.exists());
+            sendFile(session, unixDir, target, data);
             assertFileLength(target, data.length(), 
TimeUnit.SECONDS.toMillis(5L));
 
             sendFileError(session, "target", ScpHelper.SCP_COMMAND_PREFIX, 
data);
 
             readFileError(session, unixDir);
 
-            assertEquals("Mismatched file data", data, readFile(session, 
unixPath, target.length()));
-            assertEquals("Mismatched dir data", data, readDir(session, 
unixDir, fileName, target.length()));
+            assertEquals("Mismatched file data", data, readFile(session, 
unixPath, target));
+            assertEquals("Mismatched dir data", data, readDir(session, 
unixDir, target));
 
             target.delete();
             root.delete();
@@ -989,22 +989,26 @@ public class ScpTest extends BaseTestSupport {
         }
     }
 
-    protected String readFile(com.jcraft.jsch.Session session, String path, 
long expectedSize) throws Exception {
+    protected String readFile(com.jcraft.jsch.Session session, String path, 
File target) throws Exception {
         ChannelExec c = (ChannelExec) 
session.openChannel(Channel.CHANNEL_EXEC);
         c.setCommand("scp -f " + path);
         c.connect();
 
-        int namePos = path.lastIndexOf('/');
-        String fileName = (namePos >= 0) ? path.substring(namePos + 1) : path;
+        String fileName = target.getName();
         try (OutputStream os = c.getOutputStream();
              InputStream is = c.getInputStream()) {
 
             os.write(0);
             os.flush();
+
             String header = readLine(is);
-            assertEquals("Mismatched header for " + path, "C0644 " + 
expectedSize + " " + fileName, header);
+            Collection<PosixFilePermission> perms = 
IoUtils.getPermissions(target.toPath());
+            String octalPerms = ScpHelper.getOctalPermissions(perms);
+            String expHeader = "C" + octalPerms + " " + target.length() + " " 
+ fileName;
+            assertEquals("Mismatched header for " + path, expHeader, header);
 
-            int length = Integer.parseInt(header.substring(6, header.indexOf(' 
', 6)));
+            String lenValue = header.substring(6, header.indexOf(' ', 6));
+            int length = Integer.parseInt(lenValue);
             os.write(0);
             os.flush();
 
@@ -1022,7 +1026,7 @@ public class ScpTest extends BaseTestSupport {
         }
     }
 
-    protected String readDir(com.jcraft.jsch.Session session, String path, 
String fileName, long expectedSize) throws Exception {
+    protected String readDir(com.jcraft.jsch.Session session, String path, 
File target) throws Exception {
         ChannelExec c = (ChannelExec) 
session.openChannel(Channel.CHANNEL_EXEC);
         c.setCommand("scp -r -f " + path);
         c.connect();
@@ -1033,12 +1037,19 @@ public class ScpTest extends BaseTestSupport {
             os.flush();
 
             String header = readLine(is);
-            assertTrue("Bad header prefix for " + path + ": " + header, 
header.startsWith("D0755 0 "));
+            File parent = target.getParentFile();
+            Collection<PosixFilePermission> perms = 
IoUtils.getPermissions(parent.toPath());
+            String octalPerms = ScpHelper.getOctalPermissions(perms);
+            String expPrefix = "D" + octalPerms + " 0 ";
+            assertTrue("Bad header prefix for " + path + ": " + header, 
header.startsWith(expPrefix));
             os.write(0);
             os.flush();
 
             header = readLine(is);
-            assertEquals("Mismatched dir header for " + path, "C0644 " + 
expectedSize + " " + fileName, header);
+            perms = IoUtils.getPermissions(target.toPath());
+            octalPerms = ScpHelper.getOctalPermissions(perms);
+            String expHeader = "C" + octalPerms + " " + target.length() + " " 
+ target.getName();
+            assertEquals("Mismatched dir header for " + path, expHeader, 
header);
             int length = Integer.parseInt(header.substring(6, header.indexOf(' 
', 6)));
             os.write(0);
             os.flush();
@@ -1079,7 +1090,7 @@ public class ScpTest extends BaseTestSupport {
         }
     }
 
-    protected void sendFile(com.jcraft.jsch.Session session, String path, 
String name, String data) throws Exception {
+    protected void sendFile(com.jcraft.jsch.Session session, String path, File 
target, String data) throws Exception {
         ChannelExec c = (ChannelExec) 
session.openChannel(Channel.CHANNEL_EXEC);
         String command = "scp -t " + path;
         c.setCommand(command);
@@ -1089,7 +1100,12 @@ public class ScpTest extends BaseTestSupport {
              InputStream is = c.getInputStream()) {
 
             assertAckReceived(is, command);
-            assertAckReceived(os, is, "C7777 " + data.length() + " " + name);
+
+            File parent = target.getParentFile();
+            Collection<PosixFilePermission> perms = 
IoUtils.getPermissions(parent.toPath());
+            String octalPerms = ScpHelper.getOctalPermissions(perms);
+            String name = target.getName();
+            assertAckReceived(os, is, "C" + octalPerms + " " + data.length() + 
" " + name);
 
             os.write(data.getBytes(StandardCharsets.UTF_8));
             os.flush();

Reply via email to