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 2013/07/22 20:37:03 UTC

[6/9] Provide an SFTP client

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/21c1cee9/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 ef555a1..39f80f9 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
@@ -83,161 +83,77 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste
     public static final String ALL_SFTP_IMPL = "3";
     public static final int  MAX_PACKET_LENGTH = 1024 * 16;
 
-    public static final int SSH_FXP_INIT = 1;
-    public static final int SSH_FXP_VERSION = 2;
-    public static final int SSH_FXP_OPEN = 3;
-    public static final int SSH_FXP_CLOSE = 4;
-    public static final int SSH_FXP_READ = 5;
-    public static final int SSH_FXP_WRITE = 6;
-    public static final int SSH_FXP_LSTAT = 7;
-    public static final int SSH_FXP_FSTAT = 8;
-    public static final int SSH_FXP_SETSTAT = 9;
-    public static final int SSH_FXP_FSETSTAT = 10;
-    public static final int SSH_FXP_OPENDIR = 11;
-    public static final int SSH_FXP_READDIR = 12;
-    public static final int SSH_FXP_REMOVE = 13;
-    public static final int SSH_FXP_MKDIR = 14;
-    public static final int SSH_FXP_RMDIR = 15;
-    public static final int SSH_FXP_REALPATH = 16;
-    public static final int SSH_FXP_STAT = 17;
-    public static final int SSH_FXP_RENAME = 18;
-    public static final int SSH_FXP_READLINK = 19;
-    public static final int SSH_FXP_LINK = 21;
-    public static final int SSH_FXP_BLOCK = 22;
-    public static final int SSH_FXP_UNBLOCK = 23;
-
-    public static final int SSH_FXP_STATUS = 101;
-    public static final int SSH_FXP_HANDLE = 102;
-    public static final int SSH_FXP_DATA = 103;
-    public static final int SSH_FXP_NAME = 104;
-    public static final int SSH_FXP_ATTRS = 105;
-
-    public static final int SSH_FXP_EXTENDED = 200;
+    public static final int SSH_FXP_INIT =             1;
+    public static final int SSH_FXP_VERSION =          2;
+    public static final int SSH_FXP_OPEN =             3;
+    public static final int SSH_FXP_CLOSE =            4;
+    public static final int SSH_FXP_READ =             5;
+    public static final int SSH_FXP_WRITE =            6;
+    public static final int SSH_FXP_LSTAT =            7;
+    public static final int SSH_FXP_FSTAT =            8;
+    public static final int SSH_FXP_SETSTAT =          9;
+    public static final int SSH_FXP_FSETSTAT =        10;
+    public static final int SSH_FXP_OPENDIR =         11;
+    public static final int SSH_FXP_READDIR =         12;
+    public static final int SSH_FXP_REMOVE =          13;
+    public static final int SSH_FXP_MKDIR =           14;
+    public static final int SSH_FXP_RMDIR =           15;
+    public static final int SSH_FXP_REALPATH =        16;
+    public static final int SSH_FXP_STAT =            17;
+    public static final int SSH_FXP_RENAME =          18;
+    public static final int SSH_FXP_READLINK =        19;
+    public static final int SSH_FXP_SYMLINK =         20;
+    public static final int SSH_FXP_STATUS =         101;
+    public static final int SSH_FXP_HANDLE =         102;
+    public static final int SSH_FXP_DATA =           103;
+    public static final int SSH_FXP_NAME =           104;
+    public static final int SSH_FXP_ATTRS =          105;
+    public static final int SSH_FXP_EXTENDED =       200;
     public static final int SSH_FXP_EXTENDED_REPLY = 201;
 
-    public static final int SSH_FX_OK = 0;
-    public static final int SSH_FX_EOF = 1;
-    public static final int SSH_FX_NO_SUCH_FILE = 2;
+    public static final int SSH_FX_OK =                0;
+    public static final int SSH_FX_EOF =               1;
+    public static final int SSH_FX_NO_SUCH_FILE =      2;
     public static final int SSH_FX_PERMISSION_DENIED = 3;
-    public static final int SSH_FX_FAILURE = 4;
-    public static final int SSH_FX_BAD_MESSAGE = 5;
-    public static final int SSH_FX_NO_CONNECTION = 6;
-    public static final int SSH_FX_CONNECTION_LOST = 7;
-    public static final int SSH_FX_OP_UNSUPPORTED = 8;
-    public static final int SSH_FX_INVALID_HANDLE = 9;
-    public static final int SSH_FX_NO_SUCH_PATH = 10;
-    public static final int SSH_FX_FILE_ALREADY_EXISTS = 11;
-    public static final int SSH_FX_WRITE_PROTECT = 12;
-    public static final int SSH_FX_NO_MEDIA = 13;
-    public static final int SSH_FX_NO_SPACE_ON_FILESYSTEM = 14;
-    public static final int SSH_FX_QUOTA_EXCEEDED = 15;
-    public static final int SSH_FX_UNKNOWN_PRINCIPAL = 16;
-    public static final int SSH_FX_LOCK_CONFLICT = 17;
-    public static final int SSH_FX_DIR_NOT_EMPTY = 18;
-    public static final int SSH_FX_NOT_A_DIRECTORY = 19;
-    public static final int SSH_FX_INVALID_FILENAME = 20;
-    public static final int SSH_FX_LINK_LOOP = 21;
-    public static final int SSH_FX_CANNOT_DELETE = 22;
-    public static final int SSH_FX_INVALID_PARAMETER = 23;
-    public static final int SSH_FX_FILE_IS_A_DIRECTORY = 24;
-    public static final int SSH_FX_BYTE_RANGE_LOCK_CONFLICT = 25;
-    public static final int SSH_FX_BYTE_RANGE_LOCK_REFUSED = 26;
-    public static final int SSH_FX_DELETE_PENDING = 27;
-    public static final int SSH_FX_FILE_CORRUPT = 28;
-    public static final int SSH_FX_OWNER_INVALID = 29;
-    public static final int SSH_FX_GROUP_INVALID = 30;
-    public static final int SSH_FX_NO_MATCHING_BYTE_RANGE_LOCK = 31;
-
-    public static final int SSH_FILEXFER_ATTR_SIZE = 0x00000001;
+    public static final int SSH_FX_FAILURE =           4;
+    public static final int SSH_FX_BAD_MESSAGE =       5;
+    public static final int SSH_FX_NO_CONNECTION =     6;
+    public static final int SSH_FX_CONNECTION_LOST =   7;
+    public static final int SSH_FX_OP_UNSUPPORTED =    8;
+
+    public static final int SSH_FILEXFER_ATTR_SIZE =        0x00000001;
+    public static final int SSH_FILEXFER_ATTR_UIDGID =      0x00000002;
     public static final int SSH_FILEXFER_ATTR_PERMISSIONS = 0x00000004;
-    public static final int SSH_FILEXFER_ATTR_ACMODTIME = 0x00000008; //v3 naming convention
-    public static final int SSH_FILEXFER_ATTR_ACCESSTIME = 0x00000008;
-    public static final int SSH_FILEXFER_ATTR_CREATETIME = 0x00000010;
-    public static final int SSH_FILEXFER_ATTR_MODIFYTIME = 0x00000020;
-    public static final int SSH_FILEXFER_ATTR_ACL = 0x00000040;
-    public static final int SSH_FILEXFER_ATTR_OWNERGROUP = 0x00000080;
-    public static final int SSH_FILEXFER_ATTR_SUBSECOND_TIMES = 0x00000100;
-    public static final int SSH_FILEXFER_ATTR_BITS = 0x00000200;
-    public static final int SSH_FILEXFER_ATTR_ALLOCATION_SIZE = 0x00000400;
-    public static final int SSH_FILEXFER_ATTR_TEXT_HINT = 0x00000800;
-    public static final int SSH_FILEXFER_ATTR_MIME_TYPE = 0x00001000;
-    public static final int SSH_FILEXFER_ATTR_LINK_COUNT = 0x00002000;
-    public static final int SSH_FILEXFER_ATTR_UNTRANSLATED_NAME = 0x00004000;
-    public static final int SSH_FILEXFER_ATTR_CTIME = 0x00008000;
-    public static final int SSH_FILEXFER_ATTR_EXTENDED = 0x80000000;
-
-    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;
-    public static final int SSH_FILEXFER_TYPE_CHAR_DEVICE = 7;
-    public static final int SSH_FILEXFER_TYPE_BLOCK_DEVICE = 8;
-    public static final int SSH_FILEXFER_TYPE_FIFO = 9;
-
-
-    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;
-    public static final int SSH_FXF_OPEN_EXISTING = 0x00000002;
-    public static final int SSH_FXF_OPEN_OR_CREATE = 0x00000003;
-    public static final int SSH_FXF_TRUNCATE_EXISTING = 0x00000004;
-    public static final int SSH_FXF_APPEND_DATA = 0x00000008;
-    public static final int SSH_FXF_APPEND_DATA_ATOMIC = 0x00000010;
-    public static final int SSH_FXF_TEXT_MODE = 0x00000020;
-    public static final int SSH_FXF_BLOCK_READ = 0x00000040;
-    public static final int SSH_FXF_BLOCK_WRITE = 0x00000080;
-    public static final int SSH_FXF_BLOCK_DELETE = 0x00000100;
-    public static final int SSH_FXF_BLOCK_ADVISORY = 0x00000200;
-    public static final int SSH_FXF_NOFOLLOW = 0x00000400;
-    public static final int SSH_FXF_DELETE_ON_CLOSE = 0x00000800;
-    public static final int SSH_FXF_ACCESS_AUDIT_ALARM_INFO = 0x00001000;
-    public static final int SSH_FXF_ACCESS_BACKUP = 0x00002000;
-    public static final int SSH_FXF_BACKUP_STREAM = 0x00004000;
-    public static final int SSH_FXF_OVERRIDE_OWNER = 0x00008000;
-
-    public static final int SSH_FXF_READ = 0x00000001;
-    public static final int SSH_FXF_WRITE = 0x00000002;
+    public static final int SSH_FILEXFER_ATTR_ACMODTIME =   0x00000008; //v3 naming convention
+    public static final int SSH_FILEXFER_ATTR_EXTENDED =    0x80000000;
+
+    public static final int SSH_FXF_READ =   0x00000001;
+    public static final int SSH_FXF_WRITE =  0x00000002;
     public static final int SSH_FXF_APPEND = 0x00000004;
-    public static final int SSH_FXF_CREAT = 0x00000008;
-    public static final int SSH_FXF_TRUNC = 0x00000010;
-    public static final int SSH_FXF_EXCL = 0x00000020;
-    public static final int SSH_FXF_TEXT = 0x00000040;
-
-    public static final int SSH_FXP_REALPATH_NO_CHECK =    0x00000001;
-    public static final int SSH_FXP_REALPATH_STAT_IF =     0x00000002;
-    public static final int SSH_FXP_REALPATH_STAT_ALWAYS = 0x00000003;
-
-    public static final int ACE4_READ_DATA = 0x00000001;
-    public static final int ACE4_LIST_DIRECTORY = 0x00000001;
-    public static final int ACE4_WRITE_DATA = 0x00000002;
-    public static final int ACE4_ADD_FILE = 0x00000002;
-    public static final int ACE4_APPEND_DATA = 0x00000004;
-    public static final int ACE4_ADD_SUBDIRECTORY = 0x00000004;
-    public static final int ACE4_READ_NAMED_ATTRS = 0x00000008;
-    public static final int ACE4_WRITE_NAMED_ATTRS = 0x00000010;
-    public static final int ACE4_EXECUTE = 0x00000020;
-    public static final int ACE4_DELETE_CHILD = 0x00000040;
-    public static final int ACE4_READ_ATTRIBUTES = 0x00000080;
-    public static final int ACE4_WRITE_ATTRIBUTES = 0x00000100;
-    public static final int ACE4_DELETE = 0x00010000;
-    public static final int ACE4_READ_ACL = 0x00020000;
-    public static final int ACE4_WRITE_ACL = 0x00040000;
-    public static final int ACE4_WRITE_OWNER = 0x00080000;
-
-    public static final int S_IRUSR = 0000400;
-    public static final int S_IWUSR = 0000200;
-    public static final int S_IXUSR = 0000100;
-    public static final int S_IRGRP = 0000040;
-    public static final int S_IWGRP = 0000020;
-    public static final int S_IXGRP = 0000010;
-    public static final int S_IROTH = 0000004;
-    public static final int S_IWOTH = 0000002;
-    public static final int S_IXOTH = 0000001;
-    public static final int S_ISUID = 0004000;
-    public static final int S_ISGID = 0002000;
-    public static final int S_ISVTX = 0001000;
+    public static final int SSH_FXF_CREAT =  0x00000008;
+    public static final int SSH_FXF_TRUNC =  0x00000010;
+    public static final int SSH_FXF_EXCL =   0x00000020;
+
+    public static final int S_IFMT =   0170000;  // bitmask for the file type bitfields
+    public static final int S_IFSOCK = 0140000;  // socket
+    public static final int S_IFLNK =  0120000;  // symbolic link
+    public static final int S_IFREG =  0100000;  // regular file
+    public static final int S_IFBLK =  0060000;  // block device
+    public static final int S_IFDIR =  0040000;  // directory
+    public static final int S_IFCHR =  0020000;  // character device
+    public static final int S_IFIFO =  0010000;  // fifo
+    public static final int S_ISUID =  0004000;  // set UID bit
+    public static final int S_ISGID =  0002000;  // set GID bit
+    public static final int S_ISVTX =  0001000;  // sticky bit
+    public static final int S_IRUSR =  0000400;
+    public static final int S_IWUSR =  0000200;
+    public static final int S_IXUSR =  0000100;
+    public static final int S_IRGRP =  0000040;
+    public static final int S_IWGRP =  0000020;
+    public static final int S_IXGRP =  0000010;
+    public static final int S_IROTH =  0000004;
+    public static final int S_IWOTH =  0000002;
+    public static final int S_IXOTH =  0000001;
 
 
     private ExitCallback callback;
@@ -254,91 +170,6 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste
     private Map<String, Handle> handles = new HashMap<String, Handle>();
 
     
-    protected static int mapV4ToV3(int code) {
-        switch (code) {
-            case SSH_FX_INVALID_HANDLE:
-                return SSH_FX_FAILURE;
-            case SSH_FX_NO_SUCH_PATH:
-                return SSH_FX_NO_SUCH_FILE;
-            case SSH_FX_FILE_ALREADY_EXISTS:
-                return SSH_FX_FAILURE;
-            case SSH_FX_WRITE_PROTECT:
-                return SSH_FX_PERMISSION_DENIED;
-            case SSH_FX_NO_MEDIA:
-                return SSH_FX_FAILURE;
-            default:
-                return code;
-        }
-    }
-    
-    protected static int mapV5ToV4(int code) {
-        switch (code) {
-            case SSH_FX_NO_SPACE_ON_FILESYSTEM:
-                return SSH_FX_FAILURE;
-            case SSH_FX_QUOTA_EXCEEDED:
-                return SSH_FX_FAILURE;
-            case SSH_FX_UNKNOWN_PRINCIPAL:
-                return SSH_FX_FAILURE;
-            case SSH_FX_LOCK_CONFLICT:
-                return SSH_FX_FAILURE;
-            default:
-                return code;
-        }
-    }
-
-    protected static int mapV6ToV5(int code) {
-        switch (code) {
-            case SSH_FX_DIR_NOT_EMPTY:
-                return SSH_FX_FAILURE;
-            case SSH_FX_NOT_A_DIRECTORY:
-                return SSH_FX_NO_SUCH_FILE;
-            case SSH_FX_INVALID_FILENAME:
-                return SSH_FX_NO_SUCH_FILE;
-            case SSH_FX_LINK_LOOP:
-                return SSH_FX_FAILURE;
-            case SSH_FX_CANNOT_DELETE:
-                return SSH_FX_PERMISSION_DENIED;
-            case SSH_FX_INVALID_PARAMETER:
-                return SSH_FX_FAILURE;
-            case SSH_FX_FILE_IS_A_DIRECTORY:
-                return SSH_FX_NO_SUCH_FILE;
-            case SSH_FX_BYTE_RANGE_LOCK_CONFLICT:
-                return SSH_FX_FAILURE;
-            case SSH_FX_BYTE_RANGE_LOCK_REFUSED:
-                return SSH_FX_FAILURE;
-            case SSH_FX_DELETE_PENDING:
-                return SSH_FX_FAILURE;
-            case SSH_FX_FILE_CORRUPT:
-                return SSH_FX_FAILURE;
-            case SSH_FX_OWNER_INVALID:
-                return SSH_FX_PERMISSION_DENIED;
-            case SSH_FX_GROUP_INVALID:
-                return SSH_FX_PERMISSION_DENIED;
-            case SSH_FX_NO_MATCHING_BYTE_RANGE_LOCK:
-                return SSH_FX_FAILURE;
-            default:
-                return code;
-        }
-    }
-    
-    protected static int mapToVersion(int code, int version) {
-        int mappedCode = code;
-        if (version < 6) {
-            mappedCode = mapV6ToV5(mappedCode);
-        }
-        if (version < 5) {
-            mappedCode = mapV5ToV4(mappedCode);
-        }
-        if (version < 4) {
-            mappedCode = mapV4ToV3(mappedCode);
-        }
-        return mappedCode;
-    }
-    
-    protected int mapToVersion(int code) {
-        return mapToVersion(code, version);
-    }
-
     protected static abstract class Handle {
         SshFile file;
 
@@ -572,103 +403,35 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste
                     }
                 }
 
-                if (version <= 4) {
-                    String path = buffer.getString();
-                    int pflags = buffer.getInt();
-                    // attrs
-                    try {
-                        SshFile file = resolveFile(path);
-                        if (file.doesExist()) {
-                            if (((pflags & SSH_FXF_CREAT) != 0) && ((pflags & SSH_FXF_EXCL) != 0)) {
-                                sendStatus(id, SSH_FX_FILE_ALREADY_EXISTS, path);
+                String path = buffer.getString();
+                int pflags = buffer.getInt();
+                // attrs
+                try {
+                    SshFile file = resolveFile(path);
+                    if (file.doesExist()) {
+                        if (((pflags & SSH_FXF_CREAT) != 0) && ((pflags & SSH_FXF_EXCL) != 0)) {
+                            sendStatus(id, SSH_FX_FAILURE, path);
+                            return;
+                        }
+                    } else {
+                        if (((pflags & SSH_FXF_CREAT) != 0)) {
+                            if (!file.isWritable()) {
+                                sendStatus(id, SSH_FX_PERMISSION_DENIED, "Can not create " + path);
                                 return;
                             }
-                        } else {
-                            if (((pflags & SSH_FXF_CREAT) != 0)) {
-                                if (!file.isWritable()) {
-                                    sendStatus(id, SSH_FX_PERMISSION_DENIED, "Can not create " + path);
-                                    return;
-                                }
-                                file.create();
-                            }
-                        }
-                        String acc = ((pflags & (SSH_FXF_READ | SSH_FXF_WRITE)) != 0 ? "r" : "") +
-                                ((pflags & SSH_FXF_WRITE) != 0 ? "w" : "");
-                        if ((pflags & SSH_FXF_TRUNC) != 0) {
-                            file.truncate();
+                            file.create();
                         }
-                        String handle = UUID.randomUUID().toString();
-                        handles.put(handle, new FileHandle(file, pflags)); // handle flags conversion
-                        sendHandle(id, handle);
-                    } catch (IOException e) {
-                        sendStatus(id, SSH_FX_FAILURE, e.getMessage() == null ? "" : e.getMessage());
                     }
-                } else {
-                    String path = buffer.getString();
-                    int acc = buffer.getInt();
-                    int flags = buffer.getInt();
-                    // attrs
-                    try {
-                        SshFile file = resolveFile(path);
-                        switch (flags & SSH_FXF_ACCESS_DISPOSITION) {
-                            case SSH_FXF_CREATE_NEW: {
-                                if (file.doesExist()) {
-                                    sendStatus(id, SSH_FX_FILE_ALREADY_EXISTS, path);
-                                    return;
-                                } else if (!file.isWritable()) {
-                                    sendStatus(id, SSH_FX_PERMISSION_DENIED, "Can not create " + path);
-                                }
-                                file.create();
-                                break;
-                            }
-                            case SSH_FXF_CREATE_TRUNCATE: {
-                                if (file.doesExist()) {
-                                    sendStatus(id, SSH_FX_FILE_ALREADY_EXISTS, path);
-                                    return;
-                                } else if (!file.isWritable()) {
-                                    sendStatus(id, SSH_FX_PERMISSION_DENIED, "Can not create " + path);
-                                }
-                                file.truncate();
-                                break;
-                            }
-                            case SSH_FXF_OPEN_EXISTING: {
-                                if (!file.doesExist()) {
-                                    if (!file.getParentFile().doesExist()) {
-                                        sendStatus(id, SSH_FX_NO_SUCH_PATH, path);
-                                    } else {
-                                        sendStatus(id, SSH_FX_NO_SUCH_FILE, path);
-                                    }
-                                    return;
-                                }
-                                break;
-                            }
-                            case SSH_FXF_OPEN_OR_CREATE: {
-                                if (!file.doesExist()) {
-                                    file.create();
-                                }
-                                break;
-                            }
-                            case SSH_FXF_TRUNCATE_EXISTING: {
-                                if (!file.doesExist()) {
-                                    if (!file.getParentFile().doesExist()) {
-                                        sendStatus(id, SSH_FX_NO_SUCH_PATH, path);
-                                    } else {
-                                        sendStatus(id, SSH_FX_NO_SUCH_FILE, path);
-                                    }
-                                    return;
-                                }
-                                file.truncate();
-                                break;
-                            }
-                            default:
-                                throw new IllegalArgumentException("Unsupported open mode: " + flags);
-                        }
-                        String handle = UUID.randomUUID().toString();
-                        handles.put(handle, new FileHandle(file, flags));
-                        sendHandle(id, handle);
-                    } catch (IOException e) {
-                        sendStatus(id, SSH_FX_FAILURE, e.getMessage());
+                    String acc = ((pflags & (SSH_FXF_READ | SSH_FXF_WRITE)) != 0 ? "r" : "") +
+                            ((pflags & SSH_FXF_WRITE) != 0 ? "w" : "");
+                    if ((pflags & SSH_FXF_TRUNC) != 0) {
+                        file.truncate();
                     }
+                    String handle = UUID.randomUUID().toString();
+                    handles.put(handle, new FileHandle(file, pflags)); // handle flags conversion
+                    sendHandle(id, handle);
+                } catch (IOException e) {
+                    sendStatus(id, SSH_FX_FAILURE, e.getMessage() == null ? "" : e.getMessage());
                 }
                 break;
             }
@@ -677,7 +440,7 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste
                 try {
                     Handle h = handles.get(handle);
                     if (h == null) {
-                        sendStatus(id, SSH_FX_INVALID_HANDLE, handle, "");
+                        sendStatus(id, SSH_FX_FAILURE, handle, "");
                     } else {
                         handles.remove(handle);
                         h.close();
@@ -695,7 +458,7 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste
                 try {
                     Handle p = handles.get(handle);
                     if (!(p instanceof FileHandle)) {
-                        sendStatus(id, SSH_FX_INVALID_HANDLE, handle);
+                        sendStatus(id, SSH_FX_FAILURE, handle);
                     } else {
                         FileHandle fh = (FileHandle) p;
                         byte[] b = new byte[Math.min(len, 1024 * 32)];
@@ -705,9 +468,6 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste
                             buf.putByte((byte) SSH_FXP_DATA);
                             buf.putInt(id);
                             buf.putBytes(b, 0, len);
-                            if (version >= 6) {
-                                buf.putBoolean(len == 0);
-                            }
                             send(buf);
                         } else {
                             sendStatus(id, SSH_FX_EOF, "");
@@ -725,7 +485,7 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste
                 try {
                     Handle p = handles.get(handle);
                     if (!(p instanceof FileHandle)) {
-                        sendStatus(id, SSH_FX_INVALID_HANDLE, handle);
+                        sendStatus(id, SSH_FX_FAILURE, handle);
                     } else {
                         FileHandle fh = (FileHandle) p;
                         fh.write(data, offset);
@@ -758,7 +518,7 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste
                 try {
                     Handle p = handles.get(handle);
                     if (p == null) {
-                        sendStatus(id, SSH_FX_INVALID_HANDLE, handle);
+                        sendStatus(id, SSH_FX_FAILURE, handle);
                     } else {
                         sendAttrs(id, p.getFile());
                     }
@@ -776,7 +536,7 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste
                     if (!p.doesExist()) {
                         sendStatus(id, SSH_FX_NO_SUCH_FILE, path);
                     } else if (!p.isDirectory()) {
-                        sendStatus(id, SSH_FX_NOT_A_DIRECTORY, path);
+                        sendStatus(id, SSH_FX_NO_SUCH_FILE, path);
                     } else if (!p.isReadable()) {
                         sendStatus(id, SSH_FX_PERMISSION_DENIED, path);
                     } else {
@@ -794,13 +554,13 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste
                 try {
                     Handle p = handles.get(handle);
                     if (!(p instanceof DirectoryHandle)) {
-                        sendStatus(id, SSH_FX_INVALID_HANDLE, handle);
+                        sendStatus(id, SSH_FX_FAILURE, handle);
                     } else if (((DirectoryHandle) p).isDone()) {
                         sendStatus(id, SSH_FX_EOF, "", "");
                     } else if (!p.getFile().doesExist()) {
                         sendStatus(id, SSH_FX_NO_SUCH_FILE, p.getFile().getAbsolutePath());
                     } else if (!p.getFile().isDirectory()) {
-                        sendStatus(id, SSH_FX_NOT_A_DIRECTORY, p.getFile().getAbsolutePath());
+                        sendStatus(id, SSH_FX_NO_SUCH_FILE, p.getFile().getAbsolutePath());
                     } else if (!p.getFile().isReadable()) {
                         sendStatus(id, SSH_FX_PERMISSION_DENIED, p.getFile().getAbsolutePath());
                     } else {
@@ -834,7 +594,7 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste
                     if (!p.doesExist()) {
                         sendStatus(id, SSH_FX_NO_SUCH_FILE, p.getAbsolutePath());
                     } else if (p.isDirectory()) {
-                        sendStatus(id, SSH_FX_FILE_IS_A_DIRECTORY, p.getAbsolutePath());
+                        sendStatus(id, SSH_FX_NO_SUCH_FILE, p.getAbsolutePath());
                     } else if (!p.delete()) {
                         sendStatus(id, SSH_FX_FAILURE, "Failed to delete file");
                     } else {
@@ -852,9 +612,9 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste
                     SshFile p = resolveFile(path);
                     if (p.doesExist()) {
                         if (p.isDirectory()) {
-                            sendStatus(id, SSH_FX_FILE_ALREADY_EXISTS, p.getAbsolutePath());
+                            sendStatus(id, SSH_FX_FAILURE, p.getAbsolutePath());
                         } else {
-                            sendStatus(id, SSH_FX_NOT_A_DIRECTORY, p.getAbsolutePath());
+                            sendStatus(id, SSH_FX_NO_SUCH_FILE, p.getAbsolutePath());
                         }
                     } else if (!p.isWritable()) {
                         sendStatus(id, SSH_FX_PERMISSION_DENIED, p.getAbsolutePath());
@@ -882,13 +642,13 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste
                                     sendStatus(id, SSH_FX_FAILURE, "Unable to delete directory " + path);
                                 }
                             } else {
-                                sendStatus(id, SSH_FX_DIR_NOT_EMPTY, path);
+                                sendStatus(id, SSH_FX_FAILURE, path);
                             }
                         } else {
-                            sendStatus(id, SSH_FX_NO_SUCH_PATH, path);
+                            sendStatus(id, SSH_FX_NO_SUCH_FILE, path);
                         }
                     } else {
-                        sendStatus(id, SSH_FX_NOT_A_DIRECTORY, p.getAbsolutePath());
+                        sendStatus(id, SSH_FX_NO_SUCH_FILE, p.getAbsolutePath());
                     }
                 } catch (IOException e) {
                     sendStatus(id, SSH_FX_FAILURE, e.getMessage());
@@ -900,20 +660,9 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste
                 if (path.trim().length() == 0) {
                     path = ".";
                 }
-                byte options = SSH_FXP_REALPATH_NO_CHECK;
-                List<String> compose = new ArrayList<String>();
-                if (version >= 6 && buffer.available() > 0) {
-                    options = buffer.getByte();
-                }
-                while (version >= 6 && buffer.available() > 0) {
-                    compose.add(buffer.getString());
-                }
                 try {
                     SshFile p = resolveFile(path);
-                    for (String s : compose) {
-                        p = this.root.getFile(p, s);
-                    }
-                    sendPath(id, p, options);
+                    sendPath(id, p);
                 } catch (FileNotFoundException e) {
                     e.printStackTrace();
                     sendStatus(id, SSH_FX_NO_SUCH_FILE, e.getMessage());
@@ -932,7 +681,7 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste
                     if (!o.doesExist()) {
                         sendStatus(id, SSH_FX_NO_SUCH_FILE, o.getAbsolutePath());
                     } else if (n.doesExist()) {
-                        sendStatus(id, SSH_FX_FILE_ALREADY_EXISTS, n.getAbsolutePath());
+                        sendStatus(id, SSH_FX_FAILURE, n.getAbsolutePath());
                     } else if (!o.move(n)) {
                         sendStatus(id, SSH_FX_FAILURE, "Failed to rename file");
                     } else {
@@ -976,16 +725,7 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste
         send(buffer);
     }
 
-    protected void sendAttrs(int id, SshFile file, int flags) throws IOException {
-        Buffer buffer = new Buffer();
-        buffer.putByte((byte) SSH_FXP_ATTRS);
-        buffer.putInt(id);
-        writeAttrs(buffer, file, flags);
-        send(buffer);
-    }
-
-
-    protected void sendPath(int id, SshFile f, byte options) throws IOException {
+    protected void sendPath(int id, SshFile f) throws IOException {
         Buffer buffer = new Buffer();
         buffer.putByte((byte) SSH_FXP_NAME);
         buffer.putInt(id);
@@ -1000,19 +740,8 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste
         if (f.getName().length() == 0) {
             f = resolveFile(".");
         }
-        if (options == SSH_FXP_REALPATH_STAT_IF && f.doesExist() || options == SSH_FXP_REALPATH_STAT_ALWAYS) {
-            buffer.putString(f.getName()); // Supposed to be UTF-8
-            writeAttrs(buffer, f);
-        } else {
-            if (version <= 3) {
-                buffer.putString(getLongName(f)); // Format specified in the specs
-                buffer.putInt(0);
-            } else if (version >= 4 || options == SSH_FXP_REALPATH_NO_CHECK) {
-                buffer.putString(f.getName());
-                buffer.putInt(0);
-                buffer.putByte((byte) 0);
-            }
-        }
+        buffer.putString(getLongName(f)); // Format specified in the specs
+        buffer.putInt(0);
         send(buffer);
     }
 
@@ -1026,11 +755,7 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste
         while (files.hasNext() && buffer.wpos() < MAX_PACKET_LENGTH) {
             SshFile f = files.next();
             buffer.putString(f.getName());
-            if (version <= 3) {
-                buffer.putString(getLongName(f)); // Format specified in the specs
-            } else {
-                buffer.putString(f.getName()); // Supposed to be UTF-8
-            }
+            buffer.putString(getLongName(f)); // Format specified in the specs
             writeAttrs(buffer, f);
             nb++;
         }
@@ -1041,8 +766,9 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste
         send(buffer);
     }
 
-    private String getLongName(SshFile f) {
-        String username = f.getOwner();
+    private String getLongName(SshFile f) throws IOException {
+        Map<SshFile.Attribute, Object> attributes = f.getAttributes();
+        String username = (String) attributes.get(SshFile.Attribute.Owner);
         if (username.length() > 8) {
             username = username.substring(0, 8);
         } else {
@@ -1050,31 +776,43 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste
                 username = username + " ";
             }
         }
+        String group = (String) attributes.get(SshFile.Attribute.Group);
+        if (group.length() > 8) {
+            group = group.substring(0, 8);
+        } else {
+            for (int i = group.length(); i < 8; i++) {
+                group = group + " ";
+            }
+        }
 
-        long length = f.getSize();
+        long length = (Long) attributes.get(SshFile.Attribute.Size);
         String lengthString = String.format("%1$8s", length);
 
+        boolean isDirectory = (Boolean) attributes.get(SshFile.Attribute.IsDirectory);
+        boolean isLink = (Boolean) attributes.get(SshFile.Attribute.IsSymbolicLink);
+        int perms = (Integer) attributes.get(SshFile.Attribute.Permissions);
+
         StringBuilder sb = new StringBuilder();
-        sb.append((f.isDirectory() ? "d" : "-"));
-        sb.append((f.isReadable() ? "r" : "-"));
-        sb.append((f.isWritable() ? "w" : "-"));
-        sb.append((f.isExecutable() ? "x" : "-"));
-        sb.append((f.isReadable() ? "r" : "-"));
-        sb.append((f.isWritable() ? "w" : "-"));
-        sb.append((f.isExecutable() ? "x" : "-"));
-        sb.append((f.isReadable() ? "r" : "-"));
-        sb.append((f.isWritable() ? "w" : "-"));
-        sb.append((f.isExecutable() ? "x" : "-"));
+        sb.append(isDirectory ? "d" : isLink ? "l" : "-");
+        sb.append((perms & 0000400) != 0 ? "r" : "-");
+        sb.append((perms & 0000200) != 0 ? "w" : "-");
+        sb.append((perms & 0000100) != 0 ? "x" : "-");
+        sb.append((perms & 0000040) != 0 ? "r" : "-");
+        sb.append((perms & 0000020) != 0 ? "w" : "-");
+        sb.append((perms & 0000010) != 0 ? "x" : "-");
+        sb.append((perms & 0000004) != 0 ? "r" : "-");
+        sb.append((perms & 0000002) != 0 ? "w" : "-");
+        sb.append((perms & 0000001) != 0 ? "x" : "-");
         sb.append(" ");
         sb.append("  1");
         sb.append(" ");
         sb.append(username);
         sb.append(" ");
-        sb.append(username);
+        sb.append(group);
         sb.append(" ");
         sb.append(lengthString);
         sb.append(" ");
-        sb.append(getUnixDate(f.getLastModified()));
+        sb.append(getUnixDate((Long) attributes.get(SshFile.Attribute.LastModifiedTime)));
         sb.append(" ");
         sb.append(f.getName());
 
@@ -1082,76 +820,39 @@ public class SftpSubsystem implements Command, Runnable, SessionAware, FileSyste
     }
 
     protected void writeAttrs(Buffer buffer, SshFile file) throws IOException {
-        writeAttrs(buffer, file, 0);
-    }
-
-
-    protected void writeAttrs(Buffer buffer, SshFile file, int flags) throws IOException {
         if (!file.doesExist()) {
             throw new FileNotFoundException(file.getAbsolutePath());
         }
-        if (version >= 4) {
-            long size = file.getSize();
-            String username = session.getUsername();
-            long lastModif = file.getLastModified();
-            int p = 0;
-            if (file.isReadable()) {
-                p |= S_IRUSR;
-            }
-            if (file.isWritable()) {
-                p |= S_IWUSR;
-            }
-            if (file.isExecutable()) {
-                p |= S_IXUSR;
-            }
-            if (file.isFile()) {
-                buffer.putInt(SSH_FILEXFER_ATTR_PERMISSIONS);
-                buffer.putByte((byte) SSH_FILEXFER_TYPE_REGULAR);
-                buffer.putInt(p);
-            } else if (file.isDirectory()) {
-                buffer.putInt(SSH_FILEXFER_ATTR_PERMISSIONS);
-                buffer.putByte((byte) SSH_FILEXFER_TYPE_DIRECTORY);
-                buffer.putInt(p);
-            } else {
-                buffer.putInt(0);
-                buffer.putByte((byte) SSH_FILEXFER_TYPE_UNKNOWN);
-            }
+        Map<SshFile.Attribute, Object> attributes = file.getAttributes();
+        boolean isReg = (Boolean) attributes.get(SshFile.Attribute.IsRegularFile);
+        boolean isDir = (Boolean) attributes.get(SshFile.Attribute.IsDirectory);
+        boolean isLnk = (Boolean) attributes.get(SshFile.Attribute.IsSymbolicLink);
+        int p = (Integer) attributes.get(SshFile.Attribute.Permissions);
+        p |= isReg ? S_IFREG : 0;
+        p |= isDir ? S_IFDIR : 0;
+        p |= isLnk ? S_IFLNK : 0;
+        if (isReg) {
+            buffer.putInt(SSH_FILEXFER_ATTR_SIZE | SSH_FILEXFER_ATTR_UIDGID | SSH_FILEXFER_ATTR_PERMISSIONS | SSH_FILEXFER_ATTR_ACMODTIME);
+            buffer.putLong((Long) attributes.get(SshFile.Attribute.Size));
+            buffer.putInt((Integer) attributes.get(SshFile.Attribute.Uid));
+            buffer.putInt((Integer) attributes.get(SshFile.Attribute.Gid));
+            buffer.putInt(p);
+            buffer.putInt(((Long) attributes.get(SshFile.Attribute.LastAccessTime)) / 1000);
+            buffer.putInt(((Long) attributes.get(SshFile.Attribute.LastModifiedTime)) / 1000);
+        } else if (isDir || isLnk) {
+            buffer.putInt(SSH_FILEXFER_ATTR_UIDGID | SSH_FILEXFER_ATTR_PERMISSIONS | SSH_FILEXFER_ATTR_ACMODTIME);
+            buffer.putInt((Integer) attributes.get(SshFile.Attribute.Uid));
+            buffer.putInt((Integer) attributes.get(SshFile.Attribute.Gid));
+            buffer.putInt(p);
+            buffer.putInt(((Long) attributes.get(SshFile.Attribute.LastAccessTime)) / 1000);
+            buffer.putInt(((Long) attributes.get(SshFile.Attribute.LastModifiedTime)) / 1000);
         } else {
-            int p = 0;
-            if (file.isFile()) {
-                p |= 0100000;
-            }
-            if (file.isDirectory()) {
-                p |= 0040000;
-            }
-            if (file.isReadable()) {
-                p |= 0000400;
-            }
-            if (file.isWritable()) {
-                p |= 0000200;
-            }
-            if (file.isExecutable()) {
-                p |= 0000100;
-            }
-            if (file.isFile()) {
-                buffer.putInt(SSH_FILEXFER_ATTR_SIZE| SSH_FILEXFER_ATTR_PERMISSIONS | SSH_FILEXFER_ATTR_ACMODTIME);
-                buffer.putLong(file.getSize());
-                buffer.putInt(p);
-                buffer.putInt(file.getLastModified()/1000);
-                buffer.putInt(file.getLastModified()/1000);
-            } else if (file.isDirectory()) {
-                buffer.putInt(SSH_FILEXFER_ATTR_PERMISSIONS | SSH_FILEXFER_ATTR_ACMODTIME);
-                buffer.putInt(p);
-                buffer.putInt(file.getLastModified()/1000);
-                buffer.putInt(file.getLastModified()/1000);
-            } else {
-                buffer.putInt(0);
-            }
+            buffer.putInt(0);
         }
     }
 
     protected void sendStatus(int id, int substatus, String msg) throws IOException {
-        sendStatus(id, mapToVersion(substatus), msg, "");
+        sendStatus(id, substatus, msg, "");
     }
 
     protected void sendStatus(int id, int substatus, String msg, String lang) throws IOException {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/21c1cee9/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 7259b61..94af9a5 100644
--- a/sshd-core/src/test/java/org/apache/sshd/SftpTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/SftpTest.java
@@ -25,12 +25,14 @@ import java.io.InputStream;
 import java.io.OutputStream;
 import java.net.ServerSocket;
 import java.util.Arrays;
+import java.util.EnumSet;
 import java.util.Vector;
 
 import com.jcraft.jsch.ChannelSftp;
 import com.jcraft.jsch.JSch;
 import com.jcraft.jsch.Logger;
 import com.jcraft.jsch.UserInfo;
+import org.apache.sshd.client.SftpClient;
 import org.apache.sshd.common.NamedFactory;
 import org.apache.sshd.server.Command;
 import org.apache.sshd.server.command.ScpCommandFactory;
@@ -39,10 +41,13 @@ import org.apache.sshd.util.BogusPasswordAuthenticator;
 import org.apache.sshd.util.EchoShellFactory;
 import org.apache.sshd.util.Utils;
 import org.junit.After;
+import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Ignore;
 import org.junit.Test;
 
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertNull;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
@@ -120,6 +125,62 @@ public class SftpTest {
     }
 
     @Test
+    public void testClient() throws Exception {
+        SshClient client = SshClient.setUpDefaultClient();
+        client.start();
+        ClientSession session = client.connect("localhost", port).await().getSession();
+        session.authPassword("x", "x").await();
+
+        new File("target/scp").mkdirs();
+        new File("target/scp/client/test.txt").delete();
+        new File("target/scp/client").delete();
+
+        SftpClient sftp = session.createSftpClient();
+
+        sftp.mkdir("target/scp/client");
+
+        SftpClient.Handle h = sftp.open("target/scp/client/test.txt", EnumSet.of(SftpClient.OpenMode.Write));
+        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);
+        Assert.assertNotNull(attrs);
+
+        sftp.close(h);
+
+        h = sftp.openDir("target/scp/client");
+        SftpClient.DirEntry[] dir = sftp.readDir(h);
+        assertNotNull(dir);
+        assertEquals(1, dir.length);
+        assertNull(sftp.readDir(h));
+        sftp.close(h);
+
+        sftp.remove("target/scp/client/test.txt");
+
+        OutputStream os = sftp.write("target/scp/client/test.txt");
+        os.write(new byte[1024 * 128]);
+        os.close();
+
+        InputStream is = sftp.read("target/scp/client/test.txt");
+        is.read(new byte[1024 * 128]);
+        int i = is.read();
+        is.close();
+
+        int nb = 0;
+        for (SftpClient.DirEntry entry : sftp.readDir("target/scp/client")) {
+            nb++;
+        }
+        assertEquals(1, nb);
+
+        sftp.remove("target/scp/client/test.txt");
+
+        sftp.rmdir("target/scp/client/");
+
+        client.stop();
+    }
+
+    @Test
     public void testSftp() throws Exception {
         String d = "0123456789\n";
 

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/21c1cee9/sshd-sftp/src/main/java/org/apache/sshd/sftp/reply/SshFxpStatusReply.java
----------------------------------------------------------------------
diff --git a/sshd-sftp/src/main/java/org/apache/sshd/sftp/reply/SshFxpStatusReply.java b/sshd-sftp/src/main/java/org/apache/sshd/sftp/reply/SshFxpStatusReply.java
index 8e5cfee..9722480 100644
--- a/sshd-sftp/src/main/java/org/apache/sshd/sftp/reply/SshFxpStatusReply.java
+++ b/sshd-sftp/src/main/java/org/apache/sshd/sftp/reply/SshFxpStatusReply.java
@@ -20,9 +20,10 @@ package org.apache.sshd.sftp.reply;
 
 import java.io.IOException;
 
-import org.apache.sshd.server.sftp.SftpSubsystem;
 import org.apache.sshd.sftp.subsystem.SftpConstants;
 
+import static org.apache.sshd.sftp.subsystem.SftpConstants.*;
+
 /**
  * Data container for 'SSH_FXP_STATUS' reply.
  * 
@@ -67,52 +68,52 @@ public class SshFxpStatusReply extends BaseReply {
 		this.msg = msg;
 
     	switch (substatus) {
-		case SftpSubsystem.SSH_FX_FILE_ALREADY_EXISTS:
+		case SSH_FX_FILE_ALREADY_EXISTS:
 			substatusAsSTR = "SSH_FX_FILE_ALREADY_EXISTS";
 			break;
-		case SftpSubsystem.SSH_FX_DIR_NOT_EMPTY:
+		case SSH_FX_DIR_NOT_EMPTY:
 			substatusAsSTR = "SSH_FX_DIR_NOT_EMPTY";
 			break;
-		case SftpSubsystem.SSH_FX_EOF:
+		case SSH_FX_EOF:
 			substatusAsSTR = "SSH_FX_EOF";
 			break;
-		case SftpSubsystem.SSH_FX_FILE_IS_A_DIRECTORY:
+		case SSH_FX_FILE_IS_A_DIRECTORY:
 			substatusAsSTR = "SSH_FX_FILE_IS_A_DIRECTORY";
 			break;
-		case SftpSubsystem.SSH_FX_INVALID_HANDLE:
+		case SSH_FX_INVALID_HANDLE:
 			substatusAsSTR = "SSH_FX_INVALID_HANDLE";
 			break;
-		case SftpSubsystem.SSH_FX_NO_SUCH_FILE:
+		case SSH_FX_NO_SUCH_FILE:
 			substatusAsSTR = "SSH_FX_NO_SUCH_FILE";
 			break;
-		case SftpSubsystem.SSH_FX_NO_SUCH_PATH:
+		case SSH_FX_NO_SUCH_PATH:
 			substatusAsSTR = "SSH_FX_NO_SUCH_PATH";
 			break;
-		case SftpSubsystem.SSH_FX_NOT_A_DIRECTORY:
+		case SSH_FX_NOT_A_DIRECTORY:
 			substatusAsSTR = "SSH_FX_NOT_A_DIRECTORY";
 			break;
-		case SftpSubsystem.SSH_FX_OK:
+		case SSH_FX_OK:
 			substatusAsSTR = "SSH_FX_OK";
 			break;
-		case SftpSubsystem.SSH_FX_OP_UNSUPPORTED:
+		case SSH_FX_OP_UNSUPPORTED:
 			substatusAsSTR = "SSH_FX_OP_UNSUPPORTED";
 			break;
-		case SftpSubsystem.SSH_FX_FAILURE:
+		case SSH_FX_FAILURE:
 			substatusAsSTR = "SSH_FX_FAILURE";
 			break;
-		case SftpSubsystem.SSH_FX_PERMISSION_DENIED:
+		case SSH_FX_PERMISSION_DENIED:
 			substatusAsSTR = "SSH_FX_PERMISSION_DENIED";
 			break;
-		case SftpSubsystem.SSH_FXP_MKDIR:
+		case SSH_FXP_MKDIR:
 			substatusAsSTR = "SSH_FXP_MKDIR";
 			break;
-		case SftpSubsystem.SSH_FXP_REMOVE:
+		case SSH_FXP_REMOVE:
 			substatusAsSTR = "SSH_FXP_REMOVE";
 			break;
-		case SftpSubsystem.SSH_FXP_RMDIR:
+		case SSH_FXP_RMDIR:
 			substatusAsSTR = "SSH_FXP_RMDIR";
 			break;
-		case SftpSubsystem.SSH_FX_WRITE_PROTECT:
+		case SSH_FX_WRITE_PROTECT:
 			substatusAsSTR = "SSH_FX_WRITE_PROTECT";
 			break;
 		default:

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/21c1cee9/sshd-sftp/src/test/java/org/apache/sshd/sftp/SftpTest.java
----------------------------------------------------------------------
diff --git a/sshd-sftp/src/test/java/org/apache/sshd/sftp/SftpTest.java b/sshd-sftp/src/test/java/org/apache/sshd/sftp/SftpTest.java
index 9652c3b..a1df9e8 100644
--- a/sshd-sftp/src/test/java/org/apache/sshd/sftp/SftpTest.java
+++ b/sshd-sftp/src/test/java/org/apache/sshd/sftp/SftpTest.java
@@ -24,7 +24,18 @@ import java.io.File;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.net.ServerSocket;
+import java.nio.file.Files;
+import java.nio.file.LinkOption;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.attribute.GroupPrincipal;
+import java.nio.file.attribute.PosixFileAttributeView;
+import java.nio.file.attribute.PosixFileAttributes;
+import java.nio.file.attribute.PosixFilePermission;
+import java.nio.file.attribute.UserPrincipal;
 import java.util.Arrays;
+import java.util.Map;
+import java.util.Set;
 import java.util.Vector;
 
 import com.jcraft.jsch.ChannelSftp;