Fix some sftp problems, tested with sshfs Project: http://git-wip-us.apache.org/repos/asf/mina-sshd/repo Commit: http://git-wip-us.apache.org/repos/asf/mina-sshd/commit/29262ca3 Tree: http://git-wip-us.apache.org/repos/asf/mina-sshd/tree/29262ca3 Diff: http://git-wip-us.apache.org/repos/asf/mina-sshd/diff/29262ca3
Branch: refs/heads/master Commit: 29262ca3d7f0469db1af1e54ac88d5e905ab5c41 Parents: 9c32a1f Author: Guillaume Nodet <[email protected]> Authored: Tue Jul 23 18:52:16 2013 +0200 Committer: Guillaume Nodet <[email protected]> Committed: Tue Jul 23 18:52:16 2013 +0200 ---------------------------------------------------------------------- .../common/file/nativefs/NativeSshFileNio.java | 14 ++++-- .../apache/sshd/server/sftp/SftpSubsystem.java | 53 ++++++++++++++++++-- 2 files changed, 60 insertions(+), 7 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/29262ca3/sshd-core/src/main/java/org/apache/sshd/common/file/nativefs/NativeSshFileNio.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/file/nativefs/NativeSshFileNio.java b/sshd-core/src/main/java/org/apache/sshd/common/file/nativefs/NativeSshFileNio.java index 765410c..bc83a97 100644 --- a/sshd-core/src/main/java/org/apache/sshd/common/file/nativefs/NativeSshFileNio.java +++ b/sshd-core/src/main/java/org/apache/sshd/common/file/nativefs/NativeSshFileNio.java @@ -20,7 +20,9 @@ package org.apache.sshd.common.file.nativefs; import java.io.File; +import java.io.FileOutputStream; import java.io.IOException; +import java.nio.channels.FileChannel; import java.nio.file.Files; import java.nio.file.LinkOption; import java.nio.file.Path; @@ -77,16 +79,22 @@ public class NativeSshFileNio extends NativeSshFile { for (Attribute attribute : attributes.keySet()) { String name = null; Object value = attributes.get(attribute); - switch (attribute) { + switch (attribute) { + case Size: { + long newSize = (Long) value; + FileChannel outChan = new FileOutputStream(file, true).getChannel(); + outChan.truncate(newSize); + outChan.close(); + continue; + } case Uid: name = "unix:uid"; break; case Owner: name = "unix:owner"; value = toUser((String) value); break; case Gid: name = "unix:gid"; break; case Group: name = "unix:group"; value = toGroup((String) value); break; + case Permissions: name = "unix:permissions"; value = toPerms((EnumSet<Permission>) value); break; case CreationTime: name = "unix:creationTime"; value = FileTime.fromMillis((Long) value); break; case LastModifiedTime: name = "unix:lastModifiedTime"; value = FileTime.fromMillis((Long) value); break; case LastAccessTime: name = "unix:lastAccessTime"; value = FileTime.fromMillis((Long) value); break; - case Permissions: name = "unix:permissions"; value = toPerms((EnumSet<Permission>) value); break; - case Size: throw new UnsupportedOperationException("Can not set Size attribute"); } if (name != null && value != null) { Files.setAttribute(file.toPath(), name, value, LinkOption.NOFOLLOW_LINKS); http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/29262ca3/sshd-core/src/main/java/org/apache/sshd/server/sftp/SftpSubsystem.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/server/sftp/SftpSubsystem.java b/sshd-core/src/main/java/org/apache/sshd/server/sftp/SftpSubsystem.java index dbbae10..e0a82e1 100644 --- a/sshd-core/src/main/java/org/apache/sshd/server/sftp/SftpSubsystem.java +++ b/sshd-core/src/main/java/org/apache/sshd/server/sftp/SftpSubsystem.java @@ -423,7 +423,9 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste if ((pflags & SSH_FXF_TRUNC) != 0) { file.truncate(); } - file.setAttributes(attrs); + if ((pflags & SSH_FXF_CREAT) != 0) { + file.setAttributes(attrs); + } String handle = UUID.randomUUID().toString(); handles.put(handle, new FileHandle(file)); sendHandle(id, handle); @@ -460,7 +462,7 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste sendStatus(id, SSH_FX_FAILURE, handle); } else { FileHandle fh = (FileHandle) p; - byte[] b = new byte[Math.min(len, 1024 * 32)]; + byte[] b = new byte[Math.min(len, Buffer.MAX_LEN)]; len = fh.read(b, offset); if (len >= 0) { Buffer buf = new Buffer(len + 5); @@ -481,7 +483,7 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste String handle = buffer.getString(); long offset = buffer.getLong(); byte[] data = buffer.getBytes(); - log.debug("Received SSH_FXP_WRITE (handle={}, offset={}, data=...)", handle, offset); + log.debug("Received SSH_FXP_WRITE (handle={}, offset={}, data=byte[{}])", new Object[] { handle, offset, data.length }); try { Handle p = handles.get(handle); if (!(p instanceof FileHandle)) { @@ -895,6 +897,49 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste return sb.toString(); } + protected Map<SshFile.Attribute, Object> getPermissions(int perms) { + Map<SshFile.Attribute, Object> attrs = new HashMap<SshFile.Attribute, Object>(); + if ((perms & S_IFMT) == S_IFREG) { + attrs.put(SshFile.Attribute.IsRegularFile, Boolean.TRUE); + } + if ((perms & S_IFMT) == S_IFDIR) { + attrs.put(SshFile.Attribute.IsDirectory, Boolean.TRUE); + } + if ((perms & S_IFMT) == S_IFLNK) { + attrs.put(SshFile.Attribute.IsSymbolicLink, Boolean.TRUE); + } + EnumSet<SshFile.Permission> p = EnumSet.noneOf(SshFile.Permission.class); + if ((perms & S_IRUSR) != 0) { + p.add(SshFile.Permission.UserRead); + } + if ((perms & S_IWUSR) != 0) { + p.add(SshFile.Permission.UserWrite); + } + if ((perms & S_IXUSR) != 0) { + p.add(SshFile.Permission.UserExecute); + } + if ((perms & S_IRGRP) != 0) { + p.add(SshFile.Permission.GroupRead); + } + if ((perms & S_IWGRP) != 0) { + p.add(SshFile.Permission.GroupWrite); + } + if ((perms & S_IXGRP) != 0) { + p.add(SshFile.Permission.GroupExecute); + } + if ((perms & S_IROTH) != 0) { + p.add(SshFile.Permission.OthersRead); + } + if ((perms & S_IWOTH) != 0) { + p.add(SshFile.Permission.OthersWrite); + } + if ((perms & S_IXOTH) != 0) { + p.add(SshFile.Permission.OthersExecute); + } + attrs.put(SshFile.Attribute.Permissions, p); + return attrs; + } + protected int getPermissions(Map<SshFile.Attribute, Object> attributes) { boolean isReg = (Boolean) attributes.get(SshFile.Attribute.IsRegularFile); boolean isDir = (Boolean) attributes.get(SshFile.Attribute.IsDirectory); @@ -973,7 +1018,7 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste attrs.put(SshFile.Attribute.Gid, buffer.getInt()); } if ((flags & SSH_FILEXFER_ATTR_PERMISSIONS) != 0) { - attrs.put(SshFile.Attribute.Permissions, buffer.getInt()); + attrs.putAll(getPermissions(buffer.getInt())); } if ((flags & SSH_FILEXFER_ATTR_ACMODTIME) != 0) { attrs.put(SshFile.Attribute.LastAccessTime, ((long) buffer.getInt()) * 1000);
