You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by gn...@apache.org on 2015/03/02 13:08:54 UTC
[3/4] mina-sshd git commit: [SSHD-425] Fix SFTP permission handling
issues for Windows-based SSHD
[SSHD-425] Fix SFTP permission handling issues for Windows-based SSHD
Project: http://git-wip-us.apache.org/repos/asf/mina-sshd/repo
Commit: http://git-wip-us.apache.org/repos/asf/mina-sshd/commit/ef86ae54
Tree: http://git-wip-us.apache.org/repos/asf/mina-sshd/tree/ef86ae54
Diff: http://git-wip-us.apache.org/repos/asf/mina-sshd/diff/ef86ae54
Branch: refs/heads/master
Commit: ef86ae549598eb4393433b5d666c368415c15b30
Parents: 687e771
Author: Guillaume Nodet <gn...@apache.org>
Authored: Mon Mar 2 11:03:26 2015 +0100
Committer: Guillaume Nodet <gn...@apache.org>
Committed: Mon Mar 2 13:00:48 2015 +0100
----------------------------------------------------------------------
.../sshd/client/sftp/DefaultSftpClient.java | 26 +++-
.../client/sftp/SftpFileSystemProvider.java | 6 +-
.../org/apache/sshd/common/util/IoUtils.java | 94 ++++++++++++++
.../apache/sshd/server/sftp/SftpSubsystem.java | 115 +++++++++--------
.../src/test/java/org/apache/sshd/SftpTest.java | 125 ++++++++++---------
5 files changed, 248 insertions(+), 118 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ef86ae54/sshd-core/src/main/java/org/apache/sshd/client/sftp/DefaultSftpClient.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/sftp/DefaultSftpClient.java b/sshd-core/src/main/java/org/apache/sshd/client/sftp/DefaultSftpClient.java
index 062ab55..0389f6f 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/sftp/DefaultSftpClient.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/sftp/DefaultSftpClient.java
@@ -109,6 +109,16 @@ public class DefaultSftpClient implements SftpClient {
public static final int SSH_FXF_TRUNC = 0x00000010;
public static final int SSH_FXF_EXCL = 0x00000020;
+ public static final int SSH_FILEXFER_TYPE_REGULAR = 1;
+ public static final int SSH_FILEXFER_TYPE_DIRECTORY = 2;
+ public static final int SSH_FILEXFER_TYPE_SYMLINK = 3;
+ public static final int SSH_FILEXFER_TYPE_SPECIAL = 4;
+ public static final int SSH_FILEXFER_TYPE_UNKNOWN = 5;
+ public static final int SSH_FILEXFER_TYPE_SOCKET = 6; // v5
+ public static final int SSH_FILEXFER_TYPE_CHAR_DEVICE = 7; // v5
+ public static final int SSH_FILEXFER_TYPE_BLOCK_DEVICE = 8; // v5
+ public static final int SSH_FILEXFER_TYPE_FIFO = 9; // v5
+
public static final int SSH_FXF_ACCESS_DISPOSITION = 0x00000007;
public static final int SSH_FXF_CREATE_NEW = 0x00000000;
public static final int SSH_FXF_CREATE_TRUNCATE = 0x00000001;
@@ -468,6 +478,20 @@ public class DefaultSftpClient implements SftpClient {
attrs.flags.add(Attribute.Perms);
attrs.perms = buffer.getInt();
}
+
+ // update the permissions according to the type
+ switch (attrs.type) {
+ case SSH_FILEXFER_TYPE_REGULAR:
+ attrs.perms |= S_IFREG;
+ break;
+ case SSH_FILEXFER_TYPE_DIRECTORY:
+ attrs.perms |= S_IFDIR;
+ break;
+ case SSH_FILEXFER_TYPE_SYMLINK:
+ attrs.perms |= S_IFLNK;
+ break;
+ }
+
if ((flags & SSH_FILEXFER_ATTR_ACCESSTIME) != 0) {
attrs.flags.add(Attribute.AccessTime);
attrs.accessTime = readTime(buffer, flags);
@@ -485,7 +509,7 @@ public class DefaultSftpClient implements SftpClient {
}
// TODO: acl
} else {
- throw new IllegalStateException();
+ throw new IllegalStateException("readAttributes - unsupported version: " + version);
}
return attrs;
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ef86ae54/sshd-core/src/main/java/org/apache/sshd/client/sftp/SftpFileSystemProvider.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/sftp/SftpFileSystemProvider.java b/sshd-core/src/main/java/org/apache/sshd/client/sftp/SftpFileSystemProvider.java
index 00d3d8a..c9f9a70 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/sftp/SftpFileSystemProvider.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/sftp/SftpFileSystemProvider.java
@@ -272,8 +272,7 @@ public class SftpFileSystemProvider extends FileSystemProvider {
copyAttributes |= opt == StandardCopyOption.COPY_ATTRIBUTES;
noFollowLinks |= opt == LinkOption.NOFOLLOW_LINKS;
}
- LinkOption[] linkOptions = noFollowLinks ? new LinkOption[] { LinkOption.NOFOLLOW_LINKS }
- : new LinkOption[0];
+ LinkOption[] linkOptions = IoUtils.getLinkOptions(!noFollowLinks);
// attributes of source file
BasicFileAttributes attrs = readAttributes(source,
@@ -334,8 +333,7 @@ public class SftpFileSystemProvider extends FileSystemProvider {
copyAttributes |= opt == StandardCopyOption.COPY_ATTRIBUTES;
noFollowLinks |= opt == LinkOption.NOFOLLOW_LINKS;
}
- LinkOption[] linkOptions = noFollowLinks ? new LinkOption[] { LinkOption.NOFOLLOW_LINKS }
- : new LinkOption[0];
+ LinkOption[] linkOptions = IoUtils.getLinkOptions(noFollowLinks);
// attributes of source file
BasicFileAttributes attrs = readAttributes(source,
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ef86ae54/sshd-core/src/main/java/org/apache/sshd/common/util/IoUtils.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/IoUtils.java b/sshd-core/src/main/java/org/apache/sshd/common/util/IoUtils.java
index 5a74cc3..cb21985 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/util/IoUtils.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/util/IoUtils.java
@@ -19,9 +19,18 @@
package org.apache.sshd.common.util;
import java.io.Closeable;
+import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.nio.file.LinkOption;
+import java.nio.file.attribute.PosixFilePermission;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.List;
+import java.util.Set;
/**
* TODO Add javadoc
@@ -30,6 +39,18 @@ import java.io.OutputStream;
*/
public class IoUtils {
+ public static final LinkOption[] EMPTY_OPTIONS = new LinkOption[0];
+
+ private static final LinkOption[] NO_FOLLOW_OPTIONS = new LinkOption[] { LinkOption.NOFOLLOW_LINKS };
+
+ public static LinkOption[] getLinkOptions(boolean followLinks) {
+ if (followLinks) {
+ return EMPTY_OPTIONS;
+ } else { // return a clone that modifications to the array will not affect others
+ return NO_FOLLOW_OPTIONS.clone();
+ }
+ }
+
public static long copy(InputStream source, OutputStream sink) throws IOException {
return copy(source, sink, 8192);
}
@@ -57,4 +78,77 @@ public class IoUtils {
}
}
+ public static final List<String> WINDOWS_EXECUTABLE_EXTENSIONS = Collections.unmodifiableList(Arrays.asList(".bat", ".exe", ".cmd"));
+
+ /**
+ * @param fileName The file name to be evaluated - ignored if {@code null}/empty
+ * @return {@code true} if the file ends in one of the {@link #WINDOWS_EXECUTABLE_EXTENSIONS}
+ */
+ public static boolean isWindowsExecutable(String fileName) {
+ if ((fileName == null) || (fileName.length() <= 0)) {
+ return false;
+ }
+ for (String suffix : WINDOWS_EXECUTABLE_EXTENSIONS) {
+ if (fileName.endsWith(suffix)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * @param f The {@link File} to be checked
+ * @return A {@link Set} of {@link PosixFilePermission}s based on whether
+ * the file is readable/writable/executable. If so, then <U>all</U> the
+ * relevant permissions are set (i.e., owner, group and others)
+ */
+ public static Set<PosixFilePermission> getPermissionsFromFile(File f) {
+ Set<PosixFilePermission> perms = EnumSet.noneOf(PosixFilePermission.class);
+ if (f.canRead()) {
+ perms.add(PosixFilePermission.OWNER_READ);
+ perms.add(PosixFilePermission.GROUP_READ);
+ perms.add(PosixFilePermission.OTHERS_READ);
+ }
+
+ if (f.canWrite()) {
+ perms.add(PosixFilePermission.OWNER_WRITE);
+ perms.add(PosixFilePermission.GROUP_WRITE);
+ perms.add(PosixFilePermission.OTHERS_WRITE);
+ }
+
+ if (f.canExecute() || (OsUtils.isWin32() && isWindowsExecutable(f.getName()))) {
+ perms.add(PosixFilePermission.OWNER_EXECUTE);
+ perms.add(PosixFilePermission.GROUP_EXECUTE);
+ perms.add(PosixFilePermission.OTHERS_EXECUTE);
+ }
+
+ return perms;
+ }
+
+ /**
+ * @param f The {@link File}
+ * @param perms A {@link Collection} of {@link PosixFilePermission}s to set on it.
+ * <B>Note:</B> the file is set to readable/writable/executable not only by the
+ * owner if <U>any</U> of relevant the owner/group/others permission is set
+ */
+ public static void setPermissionsToFile(File f, Collection<PosixFilePermission> perms) {
+ boolean readable = perms != null &&
+ (perms.contains(PosixFilePermission.OWNER_READ)
+ || perms.contains(PosixFilePermission.GROUP_READ)
+ || perms.contains(PosixFilePermission.OTHERS_READ));
+ f.setReadable(readable, false);
+
+ boolean writable = perms != null &&
+ (perms.contains(PosixFilePermission.OWNER_WRITE)
+ || perms.contains(PosixFilePermission.GROUP_WRITE)
+ || perms.contains(PosixFilePermission.OTHERS_WRITE));
+ f.setWritable(writable, false);
+
+ boolean executable = perms != null &&
+ (perms.contains(PosixFilePermission.OWNER_EXECUTE)
+ || perms.contains(PosixFilePermission.GROUP_EXECUTE)
+ || perms.contains(PosixFilePermission.OTHERS_EXECUTE));
+ f.setExecutable(executable, false);
+ }
+
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ef86ae54/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 0f0e9d8..963f90a 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
@@ -78,6 +78,8 @@ import java.util.concurrent.TimeUnit;
import org.apache.sshd.common.NamedFactory;
import org.apache.sshd.common.file.FileSystemAware;
import org.apache.sshd.common.util.Buffer;
+import org.apache.sshd.common.util.IoUtils;
+import org.apache.sshd.common.util.OsUtils;
import org.apache.sshd.common.util.SelectorUtils;
import org.apache.sshd.common.util.ThreadUtils;
import org.apache.sshd.server.Command;
@@ -1589,12 +1591,8 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste
return sb.toString();
}
- protected int attributesToPermissions(Map<String, Object> attributes) {
- boolean isReg = getBool((Boolean) attributes.get("isRegularFile"));
- boolean isDir = getBool((Boolean) attributes.get("isDirectory"));
- boolean isLnk = getBool((Boolean) attributes.get("isSymbolicLink"));
+ protected int attributesToPermissions(boolean isReg, boolean isDir, boolean isLnk, Collection<PosixFilePermission> perms) {
int pf = 0;
- Set<PosixFilePermission> perms = (Set<PosixFilePermission>) attributes.get("permissions");
if (perms != null) {
for (PosixFilePermission p : perms) {
switch (p) {
@@ -1635,7 +1633,7 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste
}
protected void writeAttrs(Buffer buffer, Path file, int flags, boolean followLinks) throws IOException {
- LinkOption[] options = followLinks ? new LinkOption[0] : new LinkOption[] { LinkOption.NOFOLLOW_LINKS };
+ LinkOption[] options = IoUtils.getLinkOptions(followLinks);
if (!Files.exists(file, options)) {
throw new FileNotFoundException(file.toString());
}
@@ -1644,79 +1642,69 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste
}
protected void writeAttrs(Buffer buffer, Map<String, Object> attributes) throws IOException {
+ boolean isReg = getBool((Boolean) attributes.get("isRegularFile"));
+ boolean isDir = getBool((Boolean) attributes.get("isDirectory"));
+ boolean isLnk = getBool((Boolean) attributes.get("isSymbolicLink"));
+ @SuppressWarnings("unchecked")
+ Collection<PosixFilePermission> perms = (Collection<PosixFilePermission>) attributes.get("permissions");
+ Number size = (Number) attributes.get("size");
+ FileTime lastModifiedTime = (FileTime) attributes.get("lastModifiedTime");
+ FileTime lastAccessTime = (FileTime) attributes.get("lastAccessTime");
+
if (version == SFTP_V3) {
- boolean isReg = getBool((Boolean) attributes.get("isRegularFile"));
- boolean isDir = getBool((Boolean) attributes.get("isDirectory"));
- boolean isLnk = getBool((Boolean) attributes.get("isSymbolicLink"));
int flags =
- ((isReg || isLnk) && attributes.containsKey("size") ? SSH_FILEXFER_ATTR_SIZE : 0) |
+ ((isReg || isLnk) && (size != null) ? SSH_FILEXFER_ATTR_SIZE : 0) |
(attributes.containsKey("uid") && attributes.containsKey("gid") ? SSH_FILEXFER_ATTR_UIDGID : 0) |
- (attributes.containsKey("permissions") ? SSH_FILEXFER_ATTR_PERMISSIONS : 0) |
- (attributes.containsKey("lastModifiedTime") && attributes.containsKey("lastAccessTime") ? SSH_FILEXFER_ATTR_ACMODTIME : 0);
+ ((perms != null) ? SSH_FILEXFER_ATTR_PERMISSIONS : 0) |
+ (((lastModifiedTime != null) && (lastAccessTime != null)) ? SSH_FILEXFER_ATTR_ACMODTIME : 0);
buffer.putInt(flags);
if ((flags & SSH_FILEXFER_ATTR_SIZE) != 0) {
- buffer.putLong((Long) attributes.get("size"));
+ buffer.putLong(size.longValue());
}
if ((flags & SSH_FILEXFER_ATTR_UIDGID) != 0) {
- buffer.putInt((Integer) attributes.get("uid"));
- buffer.putInt((Integer) attributes.get("gid"));
+ buffer.putInt(((Number) attributes.get("uid")).intValue());
+ buffer.putInt(((Number) attributes.get("gid")).intValue());
}
if ((flags & SSH_FILEXFER_ATTR_PERMISSIONS) != 0) {
- buffer.putInt(attributesToPermissions(attributes));
+ buffer.putInt(attributesToPermissions(isReg, isDir, isLnk, perms));
}
if ((flags & SSH_FILEXFER_ATTR_ACMODTIME) != 0) {
- buffer.putInt(((FileTime) attributes.get("lastAccessTime")).to(TimeUnit.SECONDS));
- buffer.putInt(((FileTime) attributes.get("lastModifiedTime")).to(TimeUnit.SECONDS));
+ buffer.putInt(lastAccessTime.to(TimeUnit.SECONDS));
+ buffer.putInt(lastModifiedTime.to(TimeUnit.SECONDS));
}
} else if (version >= SFTP_V4) {
- boolean isReg = getBool((Boolean) attributes.get("isRegularFile"));
- boolean isDir = getBool((Boolean) attributes.get("isDirectory"));
- boolean isLnk = getBool((Boolean) attributes.get("isSymbolicLink"));
- int flags =
- ((isReg || isLnk) && attributes.containsKey("size") ? SSH_FILEXFER_ATTR_SIZE : 0) |
- (attributes.containsKey("owner") && attributes.containsKey("group") ? SSH_FILEXFER_ATTR_OWNERGROUP : 0) |
- (attributes.containsKey("permissions") ? SSH_FILEXFER_ATTR_PERMISSIONS : 0) |
- (attributes.containsKey("lastModifiedTime") ? SSH_FILEXFER_ATTR_MODIFYTIME : 0) |
- (attributes.containsKey("creationTime") ? SSH_FILEXFER_ATTR_CREATETIME : 0) |
- (attributes.containsKey("lastAccessTime") ? SSH_FILEXFER_ATTR_ACCESSTIME : 0);
+ FileTime creationTime = (FileTime) attributes.get("creationTime");
+ int flags = (((isReg || isLnk) && (size != null)) ? SSH_FILEXFER_ATTR_SIZE : 0) |
+ ((attributes.containsKey("owner") && attributes.containsKey("group")) ? SSH_FILEXFER_ATTR_OWNERGROUP : 0) |
+ ((perms != null) ? SSH_FILEXFER_ATTR_PERMISSIONS : 0) |
+ ((lastModifiedTime != null) ? SSH_FILEXFER_ATTR_MODIFYTIME : 0) |
+ ((creationTime != null) ? SSH_FILEXFER_ATTR_CREATETIME : 0) |
+ ((lastAccessTime != null) ? SSH_FILEXFER_ATTR_ACCESSTIME : 0);
buffer.putInt(flags);
buffer.putByte((byte) (isReg ? SSH_FILEXFER_TYPE_REGULAR :
isDir ? SSH_FILEXFER_TYPE_DIRECTORY :
isLnk ? SSH_FILEXFER_TYPE_SYMLINK :
SSH_FILEXFER_TYPE_UNKNOWN));
if ((flags & SSH_FILEXFER_ATTR_SIZE) != 0) {
- buffer.putLong((Long) attributes.get("size"));
+ buffer.putLong(size.longValue());
}
if ((flags & SSH_FILEXFER_ATTR_OWNERGROUP) != 0) {
buffer.putString(attributes.get("owner").toString(), StandardCharsets.UTF_8);
buffer.putString(attributes.get("group").toString(), StandardCharsets.UTF_8);
}
if ((flags & SSH_FILEXFER_ATTR_PERMISSIONS) != 0) {
- buffer.putInt(attributesToPermissions(attributes));
+ buffer.putInt(attributesToPermissions(isReg, isDir, isLnk, perms));
}
+
if ((flags & SSH_FILEXFER_ATTR_ACCESSTIME) != 0) {
- buffer.putLong(((FileTime) attributes.get("lastAccessTime")).to(TimeUnit.SECONDS));
- if ((flags & SSH_FILEXFER_ATTR_SUBSECOND_TIMES) != 0) {
- long nanos = ((FileTime) attributes.get("lastAccessTime")).to(TimeUnit.NANOSECONDS);
- nanos = nanos % TimeUnit.SECONDS.toNanos(1);
- buffer.putInt((int) nanos);
- }
+ putFileTime(buffer, flags, lastAccessTime);
}
+
if ((flags & SSH_FILEXFER_ATTR_CREATETIME) != 0) {
- buffer.putLong(((FileTime) attributes.get("creationTime")).to(TimeUnit.SECONDS));
- if ((flags & SSH_FILEXFER_ATTR_SUBSECOND_TIMES) != 0) {
- long nanos = ((FileTime) attributes.get("creationTime")).to(TimeUnit.NANOSECONDS);
- nanos = nanos % TimeUnit.SECONDS.toNanos(1);
- buffer.putInt((int) nanos);
- }
+ putFileTime(buffer, flags, lastAccessTime);
}
if ((flags & SSH_FILEXFER_ATTR_MODIFYTIME) != 0) {
- buffer.putLong(((FileTime) attributes.get("lastModifiedTime")).to(TimeUnit.SECONDS));
- if ((flags & SSH_FILEXFER_ATTR_SUBSECOND_TIMES) != 0) {
- long nanos = ((FileTime) attributes.get("lastModifiedTime")).to(TimeUnit.NANOSECONDS);
- nanos = nanos % TimeUnit.SECONDS.toNanos(1);
- buffer.putInt((int) nanos);
- }
+ putFileTime(buffer, flags, lastModifiedTime);
}
// TODO: acls
// TODO: bits
@@ -1724,6 +1712,15 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste
}
}
+ protected void putFileTime(Buffer buffer, int flags, FileTime time) {
+ buffer.putLong(time.to(TimeUnit.SECONDS));
+ if ((flags & SSH_FILEXFER_ATTR_SUBSECOND_TIMES) != 0) {
+ long nanos = time.to(TimeUnit.NANOSECONDS);
+ nanos = nanos % TimeUnit.SECONDS.toNanos(1);
+ buffer.putInt((int) nanos);
+ }
+ }
+
protected boolean getBool(Boolean bool) {
return bool != null && bool;
}
@@ -1733,17 +1730,22 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste
}
protected Map<String, Object> getAttributes(Path file, int flags, boolean followLinks) throws IOException {
- Set<String> views = file.getFileSystem().supportedFileAttributeViews();
- LinkOption[] opts = followLinks ? new LinkOption[0] : new LinkOption[] { LinkOption.NOFOLLOW_LINKS };
+ FileSystem fs = file.getFileSystem();
+ Collection<String> views = fs.supportedFileAttributeViews();
+ LinkOption[] opts = IoUtils.getLinkOptions(followLinks);
// TODO: support flags
if (views.contains("unix")) {
return Files.readAttributes(file, "unix:*", opts);
} else {
Map<String, Object> a = new HashMap<>();
- for (String view : file.getFileSystem().supportedFileAttributeViews()) {
+ for (String view : views) {
Map<String, Object> ta = Files.readAttributes(file, view + ":*", opts);
a.putAll(ta);
}
+ if (OsUtils.isWin32() && (!a.containsKey("permissions"))) {
+ Set<PosixFilePermission> perms = IoUtils.getPermissionsFromFile(file.toFile());
+ a.put("permissions", perms);
+ }
return a;
}
}
@@ -1765,7 +1767,16 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste
case "gid": view = "unix"; break;
case "owner": view = "posix"; value = toUser(file, (UserPrincipal) value); break;
case "group": view = "posix"; value = toGroup(file, (GroupPrincipal) value); break;
- case "permissions": view = "posix"; break;
+ case "permissions":
+ if (OsUtils.isWin32()) {
+ @SuppressWarnings("unchecked")
+ Collection<PosixFilePermission> perms = (Collection<PosixFilePermission>) value;
+ IoUtils.setPermissionsToFile(file.toFile(), perms);
+ continue;
+ }
+ view = "posix";
+ break;
+
case "creationTime": view = "basic"; break;
case "lastModifiedTime": view = "basic"; break;
case "lastAccessTime": view = "basic"; break;
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/ef86ae54/sshd-core/src/test/java/org/apache/sshd/SftpTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/SftpTest.java b/sshd-core/src/test/java/org/apache/sshd/SftpTest.java
index 495e94e..71d6f20 100644
--- a/sshd-core/src/test/java/org/apache/sshd/SftpTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/SftpTest.java
@@ -184,69 +184,72 @@ public class SftpTest extends BaseTest {
public void testClient() throws Exception {
SshClient client = SshClient.setUpDefaultClient();
client.start();
- ClientSession session = client.connect("x", "localhost", port).await().getSession();
- session.addPasswordIdentity("x");
- session.auth().verify();
-
- Utils.deleteRecursive(new File("target/sftp"));
- new File("target/sftp").mkdirs();
- new File("target/sftp/client/test.txt").delete();
- new File("target/sftp/client").delete();
-
- try(SftpClient sftp = session.createSftpClient()) {
- sftp.mkdir("target/sftp/client");
-
- SftpClient.Handle h = sftp.open("target/sftp/client/test.txt", EnumSet.of(SftpClient.OpenMode.Write, SftpClient.OpenMode.Create));
- byte[] d = "0123456789\n".getBytes();
- sftp.write(h, 0, d, 0, d.length);
- sftp.write(h, d.length, d, 0, d.length);
-
- SftpClient.Attributes attrs = sftp.stat(h);
- assertNotNull("No handle attributes", attrs);
-
- sftp.close(h);
-
- h = sftp.openDir("target/sftp/client");
- SftpClient.DirEntry[] dir = sftp.readDir(h);
- assertNotNull("No dir entries", dir);
- assertEquals("Mismatced number of dir entries", 1, dir.length);
- assertNull("Unexpected entry read", sftp.readDir(h));
- sftp.close(h);
-
- sftp.remove("target/sftp/client/test.txt");
-
- byte[] workBuf=new byte[1024 * 128];
- try(OutputStream os = sftp.write("target/sftp/client/test.txt")) {
- os.write(workBuf);
- }
-
- try(InputStream is = sftp.read("target/sftp/client/test.txt")) {
- int readLen=is.read(workBuf);
- assertEquals("Mismatched read data length", workBuf.length, readLen);
-
- int i = is.read();
- assertEquals("Unexpected read past EOF", -1, i);
- }
-
- SftpClient.Attributes attributes = sftp.stat("target/sftp/client/test.txt");
- assertTrue("Test file not detected as regular", attributes.isRegularFile());
-
- attributes = sftp.stat("target/sftp/client");
- assertTrue("Test directory not reported as such", attributes.isDirectory());
-
- int nb = 0;
- for (SftpClient.DirEntry entry : sftp.readDir("target/sftp/client")) {
- assertNotNull("Unexpected null entry", entry);
- nb++;
+ try {
+ try (ClientSession session = client.connect("x", "localhost", port).await().getSession()) {
+ session.addPasswordIdentity("x");
+ session.auth().verify();
+
+ Utils.deleteRecursive(new File("target/sftp"));
+ new File("target/sftp").mkdirs();
+ new File("target/sftp/client/test.txt").delete();
+ new File("target/sftp/client").delete();
+
+ try (SftpClient sftp = session.createSftpClient()) {
+ sftp.mkdir("target/sftp/client");
+
+ SftpClient.Handle h = sftp.open("target/sftp/client/test.txt", EnumSet.of(SftpClient.OpenMode.Write, SftpClient.OpenMode.Create));
+ byte[] d = "0123456789\n".getBytes();
+ sftp.write(h, 0, d, 0, d.length);
+ sftp.write(h, d.length, d, 0, d.length);
+
+ SftpClient.Attributes attrs = sftp.stat(h);
+ assertNotNull("No handle attributes", attrs);
+
+ sftp.close(h);
+
+ h = sftp.openDir("target/sftp/client");
+ SftpClient.DirEntry[] dir = sftp.readDir(h);
+ assertNotNull("No dir entries", dir);
+ assertEquals("Mismatced number of dir entries", 1, dir.length);
+ assertNull("Unexpected entry read", sftp.readDir(h));
+ sftp.close(h);
+
+ sftp.remove("target/sftp/client/test.txt");
+
+ byte[] workBuf = new byte[1024 * 128];
+ try (OutputStream os = sftp.write("target/sftp/client/test.txt")) {
+ os.write(workBuf);
+ }
+
+ try (InputStream is = sftp.read("target/sftp/client/test.txt")) {
+ int readLen = is.read(workBuf);
+ assertEquals("Mismatched read data length", workBuf.length, readLen);
+
+ int i = is.read();
+ assertEquals("Unexpected read past EOF", -1, i);
+ }
+
+ SftpClient.Attributes attributes = sftp.stat("target/sftp/client/test.txt");
+ assertTrue("Test file not detected as regular", attributes.isRegularFile());
+
+ attributes = sftp.stat("target/sftp/client");
+ assertTrue("Test directory not reported as such", attributes.isDirectory());
+
+ int nb = 0;
+ for (SftpClient.DirEntry entry : sftp.readDir("target/sftp/client")) {
+ assertNotNull("Unexpected null entry", entry);
+ nb++;
+ }
+ assertEquals("Mismatched read dir entries", 1, nb);
+
+ sftp.remove("target/sftp/client/test.txt");
+
+ sftp.rmdir("target/sftp/client/");
+ }
}
- assertEquals("Mismatched read dir entries", 1, nb);
-
- sftp.remove("target/sftp/client/test.txt");
-
- sftp.rmdir("target/sftp/client/");
+ } finally {
+ client.stop();
}
-
- client.stop();
}
/**