Return-Path: X-Original-To: apmail-mina-commits-archive@minotaur.apache.org Delivered-To: apmail-mina-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id E8587172D1 for ; Mon, 2 Nov 2015 05:25:51 +0000 (UTC) Received: (qmail 11671 invoked by uid 500); 2 Nov 2015 05:25:51 -0000 Delivered-To: apmail-mina-commits-archive@mina.apache.org Received: (qmail 11559 invoked by uid 500); 2 Nov 2015 05:25:51 -0000 Mailing-List: contact commits-help@mina.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@mina.apache.org Delivered-To: mailing list commits@mina.apache.org Received: (qmail 11532 invoked by uid 99); 2 Nov 2015 05:25:51 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 02 Nov 2015 05:25:51 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 4516EDFDEF; Mon, 2 Nov 2015 05:25:51 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: lgoldstein@apache.org To: commits@mina.apache.org Date: Mon, 02 Nov 2015 05:25:53 -0000 Message-Id: In-Reply-To: <5855a767078e4d8182f8b4d7391a8cc6@git.apache.org> References: <5855a767078e4d8182f8b4d7391a8cc6@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [3/3] mina-sshd git commit: [SSDH-573] Canonicalize the permissions field of SFTP v3 into a matching type of v4+ [SSDH-573] Canonicalize the permissions field of SFTP v3 into a matching type of v4+ Project: http://git-wip-us.apache.org/repos/asf/mina-sshd/repo Commit: http://git-wip-us.apache.org/repos/asf/mina-sshd/commit/e2187987 Tree: http://git-wip-us.apache.org/repos/asf/mina-sshd/tree/e2187987 Diff: http://git-wip-us.apache.org/repos/asf/mina-sshd/diff/e2187987 Branch: refs/heads/master Commit: e218798715f9b59fb085c8c86c388a37eecc714b Parents: beffd2a Author: Lyor Goldstein Authored: Mon Nov 2 07:25:36 2015 +0200 Committer: Lyor Goldstein Committed: Mon Nov 2 07:25:36 2015 +0200 ---------------------------------------------------------------------- .../subsystem/sftp/AbstractSftpClient.java | 312 +++++++------------ .../sshd/client/subsystem/sftp/SftpClient.java | 89 ++++-- .../sshd/client/subsystem/sftp/SftpCommand.java | 5 +- .../client/subsystem/sftp/SftpPathIterator.java | 4 +- .../sshd/common/subsystem/sftp/SftpHelper.java | 53 ++++ .../client/simple/SimpleSftpClientTest.java | 2 +- .../sshd/client/subsystem/sftp/SftpTest.java | 4 +- .../client/subsystem/sftp/SftpVersionsTest.java | 58 ++++ 8 files changed, 304 insertions(+), 223 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e2187987/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/AbstractSftpClient.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/AbstractSftpClient.java b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/AbstractSftpClient.java index bb72962..8e59971 100644 --- a/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/AbstractSftpClient.java +++ b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/AbstractSftpClient.java @@ -43,71 +43,6 @@ import org.apache.sshd.common.util.buffer.Buffer; import org.apache.sshd.common.util.buffer.ByteArrayBuffer; import org.apache.sshd.common.util.logging.AbstractLoggingBean; -import static org.apache.sshd.common.subsystem.sftp.SftpConstants.ACE4_APPEND_DATA; -import static org.apache.sshd.common.subsystem.sftp.SftpConstants.ACE4_READ_ATTRIBUTES; -import static org.apache.sshd.common.subsystem.sftp.SftpConstants.ACE4_READ_DATA; -import static org.apache.sshd.common.subsystem.sftp.SftpConstants.ACE4_WRITE_ATTRIBUTES; -import static org.apache.sshd.common.subsystem.sftp.SftpConstants.ACE4_WRITE_DATA; -import static org.apache.sshd.common.subsystem.sftp.SftpConstants.SFTP_V3; -import static org.apache.sshd.common.subsystem.sftp.SftpConstants.SFTP_V4; -import static org.apache.sshd.common.subsystem.sftp.SftpConstants.SFTP_V5; -import static org.apache.sshd.common.subsystem.sftp.SftpConstants.SFTP_V6; -import static org.apache.sshd.common.subsystem.sftp.SftpConstants.SSH_FILEXFER_ATTR_ACCESSTIME; -import static org.apache.sshd.common.subsystem.sftp.SftpConstants.SSH_FILEXFER_ATTR_ACMODTIME; -import static org.apache.sshd.common.subsystem.sftp.SftpConstants.SSH_FILEXFER_ATTR_ALL; -import static org.apache.sshd.common.subsystem.sftp.SftpConstants.SSH_FILEXFER_ATTR_CREATETIME; -import static org.apache.sshd.common.subsystem.sftp.SftpConstants.SSH_FILEXFER_ATTR_MODIFYTIME; -import static org.apache.sshd.common.subsystem.sftp.SftpConstants.SSH_FILEXFER_ATTR_OWNERGROUP; -import static org.apache.sshd.common.subsystem.sftp.SftpConstants.SSH_FILEXFER_ATTR_PERMISSIONS; -import static org.apache.sshd.common.subsystem.sftp.SftpConstants.SSH_FILEXFER_ATTR_SIZE; -import static org.apache.sshd.common.subsystem.sftp.SftpConstants.SSH_FILEXFER_ATTR_UIDGID; -import static org.apache.sshd.common.subsystem.sftp.SftpConstants.SSH_FILEXFER_TYPE_DIRECTORY; -import static org.apache.sshd.common.subsystem.sftp.SftpConstants.SSH_FILEXFER_TYPE_REGULAR; -import static org.apache.sshd.common.subsystem.sftp.SftpConstants.SSH_FILEXFER_TYPE_SYMLINK; -import static org.apache.sshd.common.subsystem.sftp.SftpConstants.SSH_FXF_APPEND; -import static org.apache.sshd.common.subsystem.sftp.SftpConstants.SSH_FXF_CREAT; -import static org.apache.sshd.common.subsystem.sftp.SftpConstants.SSH_FXF_CREATE_NEW; -import static org.apache.sshd.common.subsystem.sftp.SftpConstants.SSH_FXF_CREATE_TRUNCATE; -import static org.apache.sshd.common.subsystem.sftp.SftpConstants.SSH_FXF_EXCL; -import static org.apache.sshd.common.subsystem.sftp.SftpConstants.SSH_FXF_OPEN_EXISTING; -import static org.apache.sshd.common.subsystem.sftp.SftpConstants.SSH_FXF_OPEN_OR_CREATE; -import static org.apache.sshd.common.subsystem.sftp.SftpConstants.SSH_FXF_READ; -import static org.apache.sshd.common.subsystem.sftp.SftpConstants.SSH_FXF_TRUNC; -import static org.apache.sshd.common.subsystem.sftp.SftpConstants.SSH_FXF_TRUNCATE_EXISTING; -import static org.apache.sshd.common.subsystem.sftp.SftpConstants.SSH_FXF_WRITE; -import static org.apache.sshd.common.subsystem.sftp.SftpConstants.SSH_FXP_ATTRS; -import static org.apache.sshd.common.subsystem.sftp.SftpConstants.SSH_FXP_BLOCK; -import static org.apache.sshd.common.subsystem.sftp.SftpConstants.SSH_FXP_CLOSE; -import static org.apache.sshd.common.subsystem.sftp.SftpConstants.SSH_FXP_DATA; -import static org.apache.sshd.common.subsystem.sftp.SftpConstants.SSH_FXP_FSETSTAT; -import static org.apache.sshd.common.subsystem.sftp.SftpConstants.SSH_FXP_FSTAT; -import static org.apache.sshd.common.subsystem.sftp.SftpConstants.SSH_FXP_HANDLE; -import static org.apache.sshd.common.subsystem.sftp.SftpConstants.SSH_FXP_LINK; -import static org.apache.sshd.common.subsystem.sftp.SftpConstants.SSH_FXP_LSTAT; -import static org.apache.sshd.common.subsystem.sftp.SftpConstants.SSH_FXP_MKDIR; -import static org.apache.sshd.common.subsystem.sftp.SftpConstants.SSH_FXP_NAME; -import static org.apache.sshd.common.subsystem.sftp.SftpConstants.SSH_FXP_OPEN; -import static org.apache.sshd.common.subsystem.sftp.SftpConstants.SSH_FXP_OPENDIR; -import static org.apache.sshd.common.subsystem.sftp.SftpConstants.SSH_FXP_READ; -import static org.apache.sshd.common.subsystem.sftp.SftpConstants.SSH_FXP_READDIR; -import static org.apache.sshd.common.subsystem.sftp.SftpConstants.SSH_FXP_READLINK; -import static org.apache.sshd.common.subsystem.sftp.SftpConstants.SSH_FXP_REALPATH; -import static org.apache.sshd.common.subsystem.sftp.SftpConstants.SSH_FXP_REMOVE; -import static org.apache.sshd.common.subsystem.sftp.SftpConstants.SSH_FXP_RENAME; -import static org.apache.sshd.common.subsystem.sftp.SftpConstants.SSH_FXP_RENAME_ATOMIC; -import static org.apache.sshd.common.subsystem.sftp.SftpConstants.SSH_FXP_RENAME_OVERWRITE; -import static org.apache.sshd.common.subsystem.sftp.SftpConstants.SSH_FXP_RMDIR; -import static org.apache.sshd.common.subsystem.sftp.SftpConstants.SSH_FXP_SETSTAT; -import static org.apache.sshd.common.subsystem.sftp.SftpConstants.SSH_FXP_STAT; -import static org.apache.sshd.common.subsystem.sftp.SftpConstants.SSH_FXP_STATUS; -import static org.apache.sshd.common.subsystem.sftp.SftpConstants.SSH_FXP_SYMLINK; -import static org.apache.sshd.common.subsystem.sftp.SftpConstants.SSH_FXP_UNBLOCK; -import static org.apache.sshd.common.subsystem.sftp.SftpConstants.SSH_FXP_WRITE; -import static org.apache.sshd.common.subsystem.sftp.SftpConstants.SSH_FX_EOF; -import static org.apache.sshd.common.subsystem.sftp.SftpConstants.SSH_FX_OK; -import static org.apache.sshd.common.subsystem.sftp.SftpConstants.S_IFDIR; -import static org.apache.sshd.common.subsystem.sftp.SftpConstants.S_IFLNK; -import static org.apache.sshd.common.subsystem.sftp.SftpConstants.S_IFREG; /** * @author Apache MINA SSHD Project @@ -279,7 +214,7 @@ public abstract class AbstractSftpClient extends AbstractLoggingBean implements int length = buffer.getInt(); int type = buffer.getUByte(); int id = buffer.getInt(); - if (type == SSH_FXP_STATUS) { + if (type == SftpConstants.SSH_FXP_STATUS) { int substatus = buffer.getInt(); String msg = buffer.getString(); String lang = buffer.getString(); @@ -302,7 +237,7 @@ public abstract class AbstractSftpClient extends AbstractLoggingBean implements log.trace("checkStatus(id=" + id + ") status: " + substatus + " [" + lang + "]" + msg); } - if (substatus != SSH_FX_OK) { + if (substatus != SftpConstants.SSH_FX_OK) { throwStatusException(id, substatus, msg, lang); } } @@ -330,11 +265,11 @@ public abstract class AbstractSftpClient extends AbstractLoggingBean implements int length = buffer.getInt(); int type = buffer.getUByte(); int id = buffer.getInt(); - if (type == SSH_FXP_HANDLE) { + if (type == SftpConstants.SSH_FXP_HANDLE) { return ValidateUtils.checkNotNullAndNotEmpty(buffer.getBytes(), "Null/empty handle in buffer", GenericUtils.EMPTY_OBJECT_ARRAY); } - if (type == SSH_FXP_STATUS) { + if (type == SftpConstants.SSH_FXP_STATUS) { int substatus = buffer.getInt(); String msg = buffer.getString(); String lang = buffer.getString(); @@ -366,11 +301,11 @@ public abstract class AbstractSftpClient extends AbstractLoggingBean implements int length = buffer.getInt(); int type = buffer.getUByte(); int id = buffer.getInt(); - if (type == SSH_FXP_ATTRS) { + if (type == SftpConstants.SSH_FXP_ATTRS) { return readAttributes(buffer); } - if (type == SSH_FXP_STATUS) { + if (type == SftpConstants.SSH_FXP_STATUS) { int substatus = buffer.getInt(); String msg = buffer.getString(); String lang = buffer.getString(); @@ -402,7 +337,7 @@ public abstract class AbstractSftpClient extends AbstractLoggingBean implements int length = buffer.getInt(); int type = buffer.getUByte(); int id = buffer.getInt(); - if (type == SSH_FXP_NAME) { + if (type == SftpConstants.SSH_FXP_NAME) { int len = buffer.getInt(); if (len != 1) { throw new SshException("SFTP error: received " + len + " names instead of 1"); @@ -410,7 +345,7 @@ public abstract class AbstractSftpClient extends AbstractLoggingBean implements String name = buffer.getString(); String longName = null; int version = getVersion(); - if (version == SFTP_V3) { + if (version == SftpConstants.SFTP_V3) { longName = buffer.getString(); } Attributes attrs = readAttributes(buffer); @@ -420,7 +355,7 @@ public abstract class AbstractSftpClient extends AbstractLoggingBean implements return name; } - if (type == SSH_FXP_STATUS) { + if (type == SftpConstants.SSH_FXP_STATUS) { int substatus = buffer.getInt(); String msg = buffer.getString(); String lang = buffer.getString(); @@ -438,56 +373,48 @@ public abstract class AbstractSftpClient extends AbstractLoggingBean implements Attributes attrs = new Attributes(); int flags = buffer.getInt(); int version = getVersion(); - if (version == SFTP_V3) { - if ((flags & SSH_FILEXFER_ATTR_SIZE) != 0) { + if (version == SftpConstants.SFTP_V3) { + if ((flags & SftpConstants.SSH_FILEXFER_ATTR_SIZE) != 0) { attrs.setSize(buffer.getLong()); } - if ((flags & SSH_FILEXFER_ATTR_UIDGID) != 0) { + if ((flags & SftpConstants.SSH_FILEXFER_ATTR_UIDGID) != 0) { attrs.owner(buffer.getInt(), buffer.getInt()); } - if ((flags & SSH_FILEXFER_ATTR_PERMISSIONS) != 0) { - attrs.setPermissions(buffer.getInt()); + if ((flags & SftpConstants.SSH_FILEXFER_ATTR_PERMISSIONS) != 0) { + int perms = buffer.getInt(); + attrs.setPermissions(perms); + attrs.setType(SftpHelper.permissionsToFileType(perms)); } - if ((flags & SSH_FILEXFER_ATTR_ACMODTIME) != 0) { + + if ((flags & SftpConstants.SSH_FILEXFER_ATTR_ACMODTIME) != 0) { attrs.setAccessTime(readTime(buffer, flags)); attrs.setModifyTime(readTime(buffer, flags)); } - } else if (version >= SFTP_V4) { - attrs.type = buffer.getUByte(); - if ((flags & SSH_FILEXFER_ATTR_SIZE) != 0) { + } else if (version >= SftpConstants.SFTP_V4) { + attrs.setType(buffer.getUByte()); + if ((flags & SftpConstants.SSH_FILEXFER_ATTR_SIZE) != 0) { attrs.setSize(buffer.getLong()); } - if ((flags & SSH_FILEXFER_ATTR_OWNERGROUP) != 0) { + if ((flags & SftpConstants.SSH_FILEXFER_ATTR_OWNERGROUP) != 0) { attrs.setOwner(buffer.getString()); attrs.setGroup(buffer.getString()); } - if ((flags & SSH_FILEXFER_ATTR_PERMISSIONS) != 0) { + if ((flags & SftpConstants.SSH_FILEXFER_ATTR_PERMISSIONS) != 0) { attrs.setPermissions(buffer.getInt()); } // update the permissions according to the type int perms = attrs.getPermissions(); - switch (attrs.type) { - case SSH_FILEXFER_TYPE_REGULAR: - perms |= S_IFREG; - break; - case SSH_FILEXFER_TYPE_DIRECTORY: - perms |= S_IFDIR; - break; - case SSH_FILEXFER_TYPE_SYMLINK: - perms |= S_IFLNK; - break; - default: // do nothing - } + perms |= SftpHelper.fileTypeToPermission(attrs.getType()); attrs.setPermissions(perms); - if ((flags & SSH_FILEXFER_ATTR_ACCESSTIME) != 0) { + if ((flags & SftpConstants.SSH_FILEXFER_ATTR_ACCESSTIME) != 0) { attrs.setAccessTime(readTime(buffer, flags)); } - if ((flags & SSH_FILEXFER_ATTR_CREATETIME) != 0) { + if ((flags & SftpConstants.SSH_FILEXFER_ATTR_CREATETIME) != 0) { attrs.setCreateTime(readTime(buffer, flags)); } - if ((flags & SSH_FILEXFER_ATTR_MODIFYTIME) != 0) { + if ((flags & SftpConstants.SSH_FILEXFER_ATTR_MODIFYTIME) != 0) { attrs.setModifyTime(readTime(buffer, flags)); } // TODO: acl @@ -503,96 +430,97 @@ public abstract class AbstractSftpClient extends AbstractLoggingBean implements protected void writeAttributes(Buffer buffer, Attributes attributes) throws IOException { int version = getVersion(); - if (version == SFTP_V3) { - int flags = 0; - for (Attribute a : attributes.flags) { + Collection flags = ValidateUtils.checkNotNull(attributes, "No attributes").getFlags(); + if (version == SftpConstants.SFTP_V3) { + int flagsMask = 0; + for (Attribute a : flags) { switch (a) { case Size: - flags |= SSH_FILEXFER_ATTR_SIZE; + flagsMask |= SftpConstants.SSH_FILEXFER_ATTR_SIZE; break; case UidGid: - flags |= SSH_FILEXFER_ATTR_UIDGID; + flagsMask |= SftpConstants.SSH_FILEXFER_ATTR_UIDGID; break; case Perms: - flags |= SSH_FILEXFER_ATTR_PERMISSIONS; + flagsMask |= SftpConstants.SSH_FILEXFER_ATTR_PERMISSIONS; break; case AccessTime: - if (attributes.flags.contains(Attribute.ModifyTime)) { - flags |= SSH_FILEXFER_ATTR_ACMODTIME; + if (flags.contains(Attribute.ModifyTime)) { + flagsMask |= SftpConstants.SSH_FILEXFER_ATTR_ACMODTIME; } break; case ModifyTime: - if (attributes.flags.contains(Attribute.AccessTime)) { - flags |= SSH_FILEXFER_ATTR_ACMODTIME; + if (flags.contains(Attribute.AccessTime)) { + flagsMask |= SftpConstants.SSH_FILEXFER_ATTR_ACMODTIME; } break; default: // do nothing } } - buffer.putInt(flags); - if ((flags & SSH_FILEXFER_ATTR_SIZE) != 0) { + buffer.putInt(flagsMask); + if ((flagsMask & SftpConstants.SSH_FILEXFER_ATTR_SIZE) != 0) { buffer.putLong(attributes.getSize()); } - if ((flags & SSH_FILEXFER_ATTR_UIDGID) != 0) { + if ((flagsMask & SftpConstants.SSH_FILEXFER_ATTR_UIDGID) != 0) { buffer.putInt(attributes.getUserId()); buffer.putInt(attributes.getGroupId()); } - if ((flags & SSH_FILEXFER_ATTR_PERMISSIONS) != 0) { + if ((flagsMask & SftpConstants.SSH_FILEXFER_ATTR_PERMISSIONS) != 0) { buffer.putInt(attributes.getPermissions()); } - if ((flags & SSH_FILEXFER_ATTR_ACMODTIME) != 0) { - SftpHelper.writeTime(buffer, version, flags, attributes.getAccessTime()); - SftpHelper.writeTime(buffer, version, flags, attributes.getModifyTime()); + if ((flagsMask & SftpConstants.SSH_FILEXFER_ATTR_ACMODTIME) != 0) { + SftpHelper.writeTime(buffer, version, flagsMask, attributes.getAccessTime()); + SftpHelper.writeTime(buffer, version, flagsMask, attributes.getModifyTime()); } - } else if (version >= SFTP_V4) { - int flags = 0; - for (Attribute a : attributes.flags) { + } else if (version >= SftpConstants.SFTP_V4) { + int flagsMask = 0; + for (Attribute a : flags) { switch (a) { case Size: - flags |= SSH_FILEXFER_ATTR_SIZE; + flagsMask |= SftpConstants.SSH_FILEXFER_ATTR_SIZE; break; case OwnerGroup: - flags |= SSH_FILEXFER_ATTR_OWNERGROUP; + flagsMask |= SftpConstants.SSH_FILEXFER_ATTR_OWNERGROUP; break; case Perms: - flags |= SSH_FILEXFER_ATTR_PERMISSIONS; + flagsMask |= SftpConstants.SSH_FILEXFER_ATTR_PERMISSIONS; break; case AccessTime: - flags |= SSH_FILEXFER_ATTR_ACCESSTIME; + flagsMask |= SftpConstants.SSH_FILEXFER_ATTR_ACCESSTIME; break; case ModifyTime: - flags |= SSH_FILEXFER_ATTR_MODIFYTIME; + flagsMask |= SftpConstants.SSH_FILEXFER_ATTR_MODIFYTIME; break; case CreateTime: - flags |= SSH_FILEXFER_ATTR_CREATETIME; + flagsMask |= SftpConstants.SSH_FILEXFER_ATTR_CREATETIME; break; default: // do nothing } } - buffer.putInt(flags); - buffer.putByte((byte) attributes.type); - if ((flags & SSH_FILEXFER_ATTR_SIZE) != 0) { + buffer.putInt(flagsMask); + buffer.putByte((byte) attributes.getType()); + if ((flagsMask & SftpConstants.SSH_FILEXFER_ATTR_SIZE) != 0) { buffer.putLong(attributes.getSize()); } - if ((flags & SSH_FILEXFER_ATTR_OWNERGROUP) != 0) { + if ((flagsMask & SftpConstants.SSH_FILEXFER_ATTR_OWNERGROUP) != 0) { String owner = attributes.getOwner(); buffer.putString(GenericUtils.isEmpty(owner) ? "OWNER@" : owner); String group = attributes.getGroup(); buffer.putString(GenericUtils.isEmpty(group) ? "GROUP@" : group); } - if ((flags & SSH_FILEXFER_ATTR_PERMISSIONS) != 0) { + if ((flagsMask & SftpConstants.SSH_FILEXFER_ATTR_PERMISSIONS) != 0) { buffer.putInt(attributes.getPermissions()); } - if ((flags & SSH_FILEXFER_ATTR_ACCESSTIME) != 0) { - SftpHelper.writeTime(buffer, version, flags, attributes.getAccessTime()); + if ((flagsMask & SftpConstants.SSH_FILEXFER_ATTR_ACCESSTIME) != 0) { + SftpHelper.writeTime(buffer, version, flagsMask, attributes.getAccessTime()); } - if ((flags & SSH_FILEXFER_ATTR_CREATETIME) != 0) { - SftpHelper.writeTime(buffer, version, flags, attributes.getCreateTime()); + if ((flagsMask & SftpConstants.SSH_FILEXFER_ATTR_CREATETIME) != 0) { + SftpHelper.writeTime(buffer, version, flagsMask, attributes.getCreateTime()); } - if ((flags & SSH_FILEXFER_ATTR_MODIFYTIME) != 0) { - SftpHelper.writeTime(buffer, version, flags, attributes.getModifyTime()); + if ((flagsMask & SftpConstants.SSH_FILEXFER_ATTR_MODIFYTIME) != 0) { + SftpHelper.writeTime(buffer, version, flagsMask, attributes.getModifyTime()); } // TODO: for v6+ add CTIME (see https://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#page-21) // TODO: acl @@ -618,61 +546,61 @@ public abstract class AbstractSftpClient extends AbstractLoggingBean implements buffer.putString(path); int version = getVersion(); int mode = 0; - if (version == SFTP_V3) { + if (version == SftpConstants.SFTP_V3) { for (OpenMode m : options) { switch (m) { case Read: - mode |= SSH_FXF_READ; + mode |= SftpConstants.SSH_FXF_READ; break; case Write: - mode |= SSH_FXF_WRITE; + mode |= SftpConstants.SSH_FXF_WRITE; break; case Append: - mode |= SSH_FXF_APPEND; + mode |= SftpConstants.SSH_FXF_APPEND; break; case Create: - mode |= SSH_FXF_CREAT; + mode |= SftpConstants.SSH_FXF_CREAT; break; case Truncate: - mode |= SSH_FXF_TRUNC; + mode |= SftpConstants.SSH_FXF_TRUNC; break; case Exclusive: - mode |= SSH_FXF_EXCL; + mode |= SftpConstants.SSH_FXF_EXCL; break; default: // do nothing } } } else { - if (version >= SFTP_V5) { + if (version >= SftpConstants.SFTP_V5) { int access = 0; if (options.contains(OpenMode.Read)) { - access |= ACE4_READ_DATA | ACE4_READ_ATTRIBUTES; + access |= SftpConstants.ACE4_READ_DATA | SftpConstants.ACE4_READ_ATTRIBUTES; } if (options.contains(OpenMode.Write)) { - access |= ACE4_WRITE_DATA | ACE4_WRITE_ATTRIBUTES; + access |= SftpConstants.ACE4_WRITE_DATA | SftpConstants.ACE4_WRITE_ATTRIBUTES; } if (options.contains(OpenMode.Append)) { - access |= ACE4_APPEND_DATA; + access |= SftpConstants.ACE4_APPEND_DATA; } buffer.putInt(access); } if (options.contains(OpenMode.Create) && options.contains(OpenMode.Exclusive)) { - mode |= SSH_FXF_CREATE_NEW; + mode |= SftpConstants.SSH_FXF_CREATE_NEW; } else if (options.contains(OpenMode.Create) && options.contains(OpenMode.Truncate)) { - mode |= SSH_FXF_CREATE_TRUNCATE; + mode |= SftpConstants.SSH_FXF_CREATE_TRUNCATE; } else if (options.contains(OpenMode.Create)) { - mode |= SSH_FXF_OPEN_OR_CREATE; + mode |= SftpConstants.SSH_FXF_OPEN_OR_CREATE; } else if (options.contains(OpenMode.Truncate)) { - mode |= SSH_FXF_TRUNCATE_EXISTING; + mode |= SftpConstants.SSH_FXF_TRUNCATE_EXISTING; } else { - mode |= SSH_FXF_OPEN_EXISTING; + mode |= SftpConstants.SSH_FXF_OPEN_EXISTING; } } buffer.putInt(mode); writeAttributes(buffer, new Attributes()); - CloseableHandle handle = new DefaultCloseableHandle(this, checkHandle(SSH_FXP_OPEN, buffer)); + CloseableHandle handle = new DefaultCloseableHandle(this, checkHandle(SftpConstants.SSH_FXP_OPEN, buffer)); if (log.isTraceEnabled()) { log.trace("open({})[{}] options={}: {}", getClientSession(), path, options, handle); } @@ -692,7 +620,7 @@ public abstract class AbstractSftpClient extends AbstractLoggingBean implements byte[] id = ValidateUtils.checkNotNull(handle, "No handle").getIdentifier(); Buffer buffer = new ByteArrayBuffer(id.length + Long.SIZE /* some extra fields */); buffer.putBytes(id); - checkStatus(SSH_FXP_CLOSE, buffer); + checkStatus(SftpConstants.SSH_FXP_CLOSE, buffer); } @Override @@ -707,7 +635,7 @@ public abstract class AbstractSftpClient extends AbstractLoggingBean implements Buffer buffer = new ByteArrayBuffer(path.length() + Long.SIZE /* some extra fields */); buffer.putString(path); - checkStatus(SSH_FXP_REMOVE, buffer); + checkStatus(SftpConstants.SSH_FXP_REMOVE, buffer); } @Override @@ -726,16 +654,16 @@ public abstract class AbstractSftpClient extends AbstractLoggingBean implements int numOptions = GenericUtils.size(options); int version = getVersion(); - if (version >= SFTP_V5) { + if (version >= SftpConstants.SFTP_V5) { int opts = 0; if (numOptions > 0) { for (CopyMode opt : options) { switch (opt) { case Atomic: - opts |= SSH_FXP_RENAME_ATOMIC; + opts |= SftpConstants.SSH_FXP_RENAME_ATOMIC; break; case Overwrite: - opts |= SSH_FXP_RENAME_OVERWRITE; + opts |= SftpConstants.SSH_FXP_RENAME_OVERWRITE; break; default: // do nothing } @@ -746,7 +674,7 @@ public abstract class AbstractSftpClient extends AbstractLoggingBean implements throw new UnsupportedOperationException("rename(" + oldPath + " => " + newPath + ")" + " - copy options can not be used with this SFTP version: " + options); } - checkStatus(SSH_FXP_RENAME, buffer); + checkStatus(SftpConstants.SSH_FXP_RENAME, buffer); } @Override @@ -760,7 +688,7 @@ public abstract class AbstractSftpClient extends AbstractLoggingBean implements buffer.putBytes(id); buffer.putLong(fileOffset); buffer.putInt(len); - return checkData(SSH_FXP_READ, buffer, dstOffset, dst); + return checkData(SftpConstants.SSH_FXP_READ, buffer, dstOffset, dst); } protected int checkData(int cmd, Buffer request, int dstOffset, byte[] dst) throws IOException { @@ -773,13 +701,13 @@ public abstract class AbstractSftpClient extends AbstractLoggingBean implements int length = buffer.getInt(); int type = buffer.getUByte(); int id = buffer.getInt(); - if (type == SSH_FXP_DATA) { + if (type == SftpConstants.SSH_FXP_DATA) { int len = buffer.getInt(); buffer.getRawBytes(dst, dstoff, len); return len; } - if (type == SSH_FXP_STATUS) { + if (type == SftpConstants.SSH_FXP_STATUS) { int substatus = buffer.getInt(); String msg = buffer.getString(); String lang = buffer.getString(); @@ -787,7 +715,7 @@ public abstract class AbstractSftpClient extends AbstractLoggingBean implements log.trace("checkData(id={}) - status: {} [{}] {}", Integer.valueOf(id), Integer.valueOf(substatus), lang, msg); } - if (substatus == SSH_FX_EOF) { + if (substatus == SftpConstants.SSH_FX_EOF) { return -1; } @@ -819,7 +747,7 @@ public abstract class AbstractSftpClient extends AbstractLoggingBean implements buffer.putBytes(id); buffer.putLong(fileOffset); buffer.putBytes(src, srcOffset, len); - checkStatus(SSH_FXP_WRITE, buffer); + checkStatus(SftpConstants.SSH_FXP_WRITE, buffer); } @Override @@ -837,11 +765,11 @@ public abstract class AbstractSftpClient extends AbstractLoggingBean implements buffer.putInt(0); int version = getVersion(); - if (version != SFTP_V3) { + if (version != SftpConstants.SFTP_V3) { buffer.putByte((byte) 0); } - checkStatus(SSH_FXP_MKDIR, buffer); + checkStatus(SftpConstants.SSH_FXP_MKDIR, buffer); } @Override @@ -856,7 +784,7 @@ public abstract class AbstractSftpClient extends AbstractLoggingBean implements Buffer buffer = new ByteArrayBuffer(path.length() + Long.SIZE /* some extra fields */); buffer.putString(path); - checkStatus(SSH_FXP_RMDIR, buffer); + checkStatus(SftpConstants.SSH_FXP_RMDIR, buffer); } @Override @@ -868,7 +796,7 @@ public abstract class AbstractSftpClient extends AbstractLoggingBean implements Buffer buffer = new ByteArrayBuffer(path.length() + Long.SIZE /* some extra fields */); buffer.putString(path); - CloseableHandle handle = new DefaultCloseableHandle(this, checkHandle(SSH_FXP_OPENDIR, buffer)); + CloseableHandle handle = new DefaultCloseableHandle(this, checkHandle(SftpConstants.SSH_FXP_OPENDIR, buffer)); if (log.isTraceEnabled()) { log.trace("openDir({})[{}}: {}", getClientSession(), path, handle); } @@ -885,20 +813,20 @@ public abstract class AbstractSftpClient extends AbstractLoggingBean implements byte[] id = handle.getIdentifier(); Buffer buffer = new ByteArrayBuffer(id.length + Byte.SIZE /* some extra fields */); buffer.putBytes(id); - return checkDir(receive(send(SSH_FXP_READDIR, buffer))); + return checkDir(receive(send(SftpConstants.SSH_FXP_READDIR, buffer))); } protected List checkDir(Buffer buffer) throws IOException { int length = buffer.getInt(); int type = buffer.getUByte(); int id = buffer.getInt(); - if (type == SSH_FXP_NAME) { + if (type == SftpConstants.SSH_FXP_NAME) { int len = buffer.getInt(); List entries = new ArrayList(len); for (int i = 0; i < len; i++) { String name = buffer.getString(); int version = getVersion(); - String longName = (version == SFTP_V3) ? buffer.getString() : null; + String longName = (version == SftpConstants.SFTP_V3) ? buffer.getString() : null; Attributes attrs = readAttributes(buffer); if (log.isTraceEnabled()) { log.trace("checkDir(id={})[{}] ({})[{}]: {}", Integer.valueOf(id), Integer.valueOf(i), name, longName, attrs); @@ -909,7 +837,7 @@ public abstract class AbstractSftpClient extends AbstractLoggingBean implements return entries; } - if (type == SSH_FXP_STATUS) { + if (type == SftpConstants.SSH_FXP_STATUS) { int substatus = buffer.getInt(); String msg = buffer.getString(); String lang = buffer.getString(); @@ -917,7 +845,7 @@ public abstract class AbstractSftpClient extends AbstractLoggingBean implements log.trace("checkDir(id={}) - status: {} [{}] {}", Integer.valueOf(id), Integer.valueOf(substatus), lang, msg); } - if (substatus == SSH_FX_EOF) { + if (substatus == SftpConstants.SSH_FX_EOF) { return null; } @@ -935,7 +863,7 @@ public abstract class AbstractSftpClient extends AbstractLoggingBean implements Buffer buffer = new ByteArrayBuffer(); buffer.putString(path); - return checkOneName(SSH_FXP_REALPATH, buffer); + return checkOneName(SftpConstants.SSH_FXP_REALPATH, buffer); } @Override @@ -948,11 +876,11 @@ public abstract class AbstractSftpClient extends AbstractLoggingBean implements buffer.putString(path); int version = getVersion(); - if (version >= SFTP_V4) { - buffer.putInt(SSH_FILEXFER_ATTR_ALL); + if (version >= SftpConstants.SFTP_V4) { + buffer.putInt(SftpConstants.SSH_FILEXFER_ATTR_ALL); } - return checkAttributes(SSH_FXP_STAT, buffer); + return checkAttributes(SftpConstants.SSH_FXP_STAT, buffer); } @Override @@ -965,11 +893,11 @@ public abstract class AbstractSftpClient extends AbstractLoggingBean implements buffer.putString(path); int version = getVersion(); - if (version >= SFTP_V4) { - buffer.putInt(SSH_FILEXFER_ATTR_ALL); + if (version >= SftpConstants.SFTP_V4) { + buffer.putInt(SftpConstants.SSH_FILEXFER_ATTR_ALL); } - return checkAttributes(SSH_FXP_LSTAT, buffer); + return checkAttributes(SftpConstants.SSH_FXP_LSTAT, buffer); } @Override @@ -983,11 +911,11 @@ public abstract class AbstractSftpClient extends AbstractLoggingBean implements buffer.putBytes(id); int version = getVersion(); - if (version >= SFTP_V4) { - buffer.putInt(SSH_FILEXFER_ATTR_ALL); + if (version >= SftpConstants.SFTP_V4) { + buffer.putInt(SftpConstants.SSH_FILEXFER_ATTR_ALL); } - return checkAttributes(SSH_FXP_FSTAT, buffer); + return checkAttributes(SftpConstants.SSH_FXP_FSTAT, buffer); } @Override @@ -1003,7 +931,7 @@ public abstract class AbstractSftpClient extends AbstractLoggingBean implements Buffer buffer = new ByteArrayBuffer(); buffer.putString(path); writeAttributes(buffer, attributes); - checkStatus(SSH_FXP_SETSTAT, buffer); + checkStatus(SftpConstants.SSH_FXP_SETSTAT, buffer); } @Override @@ -1019,7 +947,7 @@ public abstract class AbstractSftpClient extends AbstractLoggingBean implements Buffer buffer = new ByteArrayBuffer(id.length + (2 * Long.SIZE) /* some extras */); buffer.putBytes(id); writeAttributes(buffer, attributes); - checkStatus(SSH_FXP_FSETSTAT, buffer); + checkStatus(SftpConstants.SSH_FXP_FSETSTAT, buffer); } @Override @@ -1030,7 +958,7 @@ public abstract class AbstractSftpClient extends AbstractLoggingBean implements Buffer buffer = new ByteArrayBuffer(path.length() + Long.SIZE /* some extra fields */); buffer.putString(path); - return checkOneName(SSH_FXP_READLINK, buffer); + return checkOneName(SftpConstants.SSH_FXP_READLINK, buffer); } @Override @@ -1045,18 +973,18 @@ public abstract class AbstractSftpClient extends AbstractLoggingBean implements Buffer buffer = new ByteArrayBuffer(linkPath.length() + targetPath.length() + Long.SIZE /* some extra fields */); int version = getVersion(); - if (version < SFTP_V6) { + if (version < SftpConstants.SFTP_V6) { if (!symbolic) { throw new UnsupportedOperationException("Hard links are not supported in sftp v" + version); } buffer.putString(targetPath); buffer.putString(linkPath); - checkStatus(SSH_FXP_SYMLINK, buffer); + checkStatus(SftpConstants.SSH_FXP_SYMLINK, buffer); } else { buffer.putString(targetPath); buffer.putString(linkPath); buffer.putBoolean(symbolic); - checkStatus(SSH_FXP_LINK, buffer); + checkStatus(SftpConstants.SSH_FXP_LINK, buffer); } } @@ -1077,7 +1005,7 @@ public abstract class AbstractSftpClient extends AbstractLoggingBean implements buffer.putLong(offset); buffer.putLong(length); buffer.putInt(mask); - checkStatus(SSH_FXP_BLOCK, buffer); + checkStatus(SftpConstants.SSH_FXP_BLOCK, buffer); } @Override @@ -1095,7 +1023,7 @@ public abstract class AbstractSftpClient extends AbstractLoggingBean implements buffer.putBytes(id); buffer.putLong(offset); buffer.putLong(length); - checkStatus(SSH_FXP_UNBLOCK, buffer); + checkStatus(SftpConstants.SSH_FXP_UNBLOCK, buffer); } @Override http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e2187987/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpClient.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpClient.java b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpClient.java index 652b3d7..6acd599 100644 --- a/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpClient.java +++ b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpClient.java @@ -33,6 +33,7 @@ import java.util.concurrent.TimeUnit; import org.apache.sshd.client.subsystem.SubsystemClient; import org.apache.sshd.client.subsystem.sftp.extensions.SftpClientExtension; +import org.apache.sshd.common.subsystem.sftp.SftpConstants; import org.apache.sshd.common.util.GenericUtils; import org.apache.sshd.common.util.ValidateUtils; import org.apache.sshd.common.util.buffer.BufferUtils; @@ -129,12 +130,9 @@ public interface SftpClient extends SubsystemClient { } // CHECKSTYLE:ON - class Attributes { - // CHECKSTYLE:OFF - public final Set flags = EnumSet.noneOf(Attribute.class); - public int type; - // CHECKSTYLE:ON - + class Attributes implements Cloneable { + private Set flags = EnumSet.noneOf(Attribute.class); + private int type = SftpConstants.SSH_FILEXFER_TYPE_UNKNOWN; private int perms; private int uid; private int gid; @@ -149,19 +147,21 @@ public interface SftpClient extends SubsystemClient { super(); } - @Override - public String toString() { - return "type=" + type - + ";size=" + getSize() - + ";uid=" + getUserId() - + ";gid=" + getGroupId() - + ";perms=0x" + Integer.toHexString(getPermissions()) - + ";flags=" + flags - + ";owner=" + getOwner() - + ";group=" + getGroup() - + ";aTime=" + getAccessTime() - + ";cTime=" + getCreateTime() - + ";mTime=" + getModifyTime(); + public Set getFlags() { + return flags; + } + + public Attributes addFlag(Attribute flag) { + flags.add(flag); + return this; + } + + public int getType() { + return type; + } + + public void setType(int type) { + this.type = type; } public long getSize() { @@ -322,20 +322,61 @@ public interface SftpClient extends SubsystemClient { public boolean isOther() { return !isRegularFile() && !isDirectory() && !isSymbolicLink(); } + + @Override + public Attributes clone() { + try { + Attributes cloned = getClass().cast(super.clone()); + cloned.flags = EnumSet.copyOf(getFlags()); + return cloned; + } catch (CloneNotSupportedException e) { + throw new RuntimeException("Failed to clone " + toString() + ": " + e.getMessage(), e); + } + } + + @Override + public String toString() { + return "type=" + getType() + + ";size=" + getSize() + + ";uid=" + getUserId() + + ";gid=" + getGroupId() + + ";perms=0x" + Integer.toHexString(getPermissions()) + + ";flags=" + flags + + ";owner=" + getOwner() + + ";group=" + getGroup() + + ";aTime=" + getAccessTime() + + ";cTime=" + getCreateTime() + + ";mTime=" + getModifyTime(); + } } class DirEntry { - // CHECKSTYLE:OFF - public String filename; - public String longFilename; - public Attributes attributes; - // CHECKSTYLE:ON + private final String filename; + private final String longFilename; + private final Attributes attributes; DirEntry(String filename, String longFilename, Attributes attributes) { this.filename = filename; this.longFilename = longFilename; this.attributes = attributes; } + + public String getFilename() { + return filename; + } + + public String getLongFilename() { + return longFilename; + } + + public Attributes getAttributes() { + return attributes; + } + + @Override + public String toString() { + return getFilename() + "[" + getLongFilename() + "]: " + getAttributes(); + } } // default values used if none specified http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e2187987/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpCommand.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpCommand.java b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpCommand.java index e07e3ed..eaf6f46 100644 --- a/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpCommand.java +++ b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpCommand.java @@ -329,8 +329,9 @@ public class SftpCommand implements Channel { String path = resolveRemotePath(pathArg); SftpClient sftp = getClient(); for (SftpClient.DirEntry entry : sftp.readDir(path)) { - SftpClient.Attributes attrs = entry.attributes; - appendFileAttributes(stdout.append('\t').append(entry.filename), sftp, path + "/" + entry.filename, attrs).println(); + String fileName = entry.getFilename(); + SftpClient.Attributes attrs = entry.getAttributes(); + appendFileAttributes(stdout.append('\t').append(fileName), sftp, path + "/" + fileName, attrs).println(); } return false; http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e2187987/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpPathIterator.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpPathIterator.java b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpPathIterator.java index 4a01ca5..49b4b48 100644 --- a/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpPathIterator.java +++ b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpPathIterator.java @@ -56,13 +56,13 @@ public class SftpPathIterator implements Iterator { SftpClient.DirEntry entry = curEntry; curEntry = nextEntry(); - return p.resolve(entry.filename); + return p.resolve(entry.getFilename()); } private SftpClient.DirEntry nextEntry() { while ((it != null) && it.hasNext()) { SftpClient.DirEntry entry = it.next(); - String name = entry.filename; + String name = entry.getFilename(); if (".".equals(name) && (!dotIgnored)) { dotIgnored = true; } else if ("..".equals(name) && (!dotdotIgnored)) { http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e2187987/sshd-core/src/main/java/org/apache/sshd/common/subsystem/sftp/SftpHelper.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/subsystem/sftp/SftpHelper.java b/sshd-core/src/main/java/org/apache/sshd/common/subsystem/sftp/SftpHelper.java index f62274a..80951ef 100644 --- a/sshd-core/src/main/java/org/apache/sshd/common/subsystem/sftp/SftpHelper.java +++ b/sshd-core/src/main/java/org/apache/sshd/common/subsystem/sftp/SftpHelper.java @@ -234,6 +234,59 @@ public final class SftpHelper { } /** + * Converts a POSIX permissions mask to a file type value + * + * @param perms The POSIX permissions mask + * @return The file type - see {@code SSH_FILEXFER_TYPE_xxx} values + */ + public static int permissionsToFileType(int perms) { + if ((SftpConstants.S_IFLNK & perms) == SftpConstants.S_IFLNK) { + return SftpConstants.SSH_FILEXFER_TYPE_SYMLINK; + } else if ((SftpConstants.S_IFREG & perms) == SftpConstants.S_IFREG) { + return SftpConstants.SSH_FILEXFER_TYPE_REGULAR; + } else if ((SftpConstants.S_IFDIR & perms) == SftpConstants.S_IFDIR) { + return SftpConstants.SSH_FILEXFER_TYPE_DIRECTORY; + } else if ((SftpConstants.S_IFSOCK & perms) == SftpConstants.S_IFSOCK) { + return SftpConstants.SSH_FILEXFER_TYPE_SOCKET; + } else if ((SftpConstants.S_IFBLK & perms) == SftpConstants.S_IFBLK) { + return SftpConstants.SSH_FILEXFER_TYPE_BLOCK_DEVICE; + } else if ((SftpConstants.S_IFCHR & perms) == SftpConstants.S_IFCHR) { + return SftpConstants.SSH_FILEXFER_TYPE_CHAR_DEVICE; + } else if ((SftpConstants.S_IFIFO & perms) == SftpConstants.S_IFIFO) { + return SftpConstants.SSH_FILEXFER_TYPE_FIFO; + } else { + return SftpConstants.SSH_FILEXFER_TYPE_UNKNOWN; + } + } + + /** + * Converts a file type into a POSIX permission mask value + + * @param type File type - see {@code SSH_FILEXFER_TYPE_xxx} values + * @return The matching POSIX permission mask value + */ + public static int fileTypeToPermission(int type) { + switch (type) { + case SftpConstants.SSH_FILEXFER_TYPE_REGULAR: + return SftpConstants.S_IFREG; + case SftpConstants.SSH_FILEXFER_TYPE_DIRECTORY: + return SftpConstants.S_IFDIR; + case SftpConstants.SSH_FILEXFER_TYPE_SYMLINK: + return SftpConstants.S_IFLNK; + case SftpConstants.SSH_FILEXFER_TYPE_SOCKET: + return SftpConstants.S_IFSOCK; + case SftpConstants.SSH_FILEXFER_TYPE_BLOCK_DEVICE: + return SftpConstants.S_IFBLK; + case SftpConstants.SSH_FILEXFER_TYPE_CHAR_DEVICE: + return SftpConstants.S_IFCHR; + case SftpConstants.SSH_FILEXFER_TYPE_FIFO: + return SftpConstants.S_IFIFO; + default: + return 0; + } + } + + /** * Translates a mask of permissions into its enumeration values equivalents * * @param perms The permissions mask http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e2187987/sshd-core/src/test/java/org/apache/sshd/client/simple/SimpleSftpClientTest.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/test/java/org/apache/sshd/client/simple/SimpleSftpClientTest.java b/sshd-core/src/test/java/org/apache/sshd/client/simple/SimpleSftpClientTest.java index 9351a98..6482442 100644 --- a/sshd-core/src/test/java/org/apache/sshd/client/simple/SimpleSftpClientTest.java +++ b/sshd-core/src/test/java/org/apache/sshd/client/simple/SimpleSftpClientTest.java @@ -122,7 +122,7 @@ public class SimpleSftpClientTest extends BaseSimpleClientTestSupport { boolean matchFound = false; for (Iterator it = dirEntries.iterator(); it.hasNext(); ) { SftpClient.DirEntry entry = it.next(); - String name = entry.filename; + String name = entry.getFilename(); if (clientFileName.equals(name)) { matchFound = true; break; http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e2187987/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/SftpTest.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/SftpTest.java b/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/SftpTest.java index e2b4f71..feaf9fc 100644 --- a/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/SftpTest.java +++ b/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/SftpTest.java @@ -1071,7 +1071,7 @@ public class SftpTest extends AbstractSftpClientTestSupport { boolean dotFiltered = false, dotdotFiltered = false; for (Iterator it = dirEntries.iterator(); it.hasNext(); ) { SftpClient.DirEntry entry = it.next(); - String name = entry.filename; + String name = entry.getFilename(); if (".".equals(name) && (!dotFiltered)) { it.remove(); dotFiltered = true; @@ -1118,7 +1118,7 @@ public class SftpTest extends AbstractSftpClientTestSupport { boolean dotFiltered = false, dotdotFiltered = false; for (SftpClient.DirEntry entry : sftp.readDir(dir)) { assertNotNull("Unexpected null entry", entry); - String name = entry.filename; + String name = entry.getFilename(); if (".".equals(name) && (!dotFiltered)) { dotFiltered = true; } else if ("..".equals(name) && (!dotdotFiltered)) { http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/e2187987/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/SftpVersionsTest.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/SftpVersionsTest.java b/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/SftpVersionsTest.java index 338ede3..52acf0e 100644 --- a/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/SftpVersionsTest.java +++ b/sshd-core/src/test/java/org/apache/sshd/client/subsystem/sftp/SftpVersionsTest.java @@ -33,7 +33,9 @@ import java.util.concurrent.TimeUnit; import org.apache.sshd.client.SshClient; import org.apache.sshd.client.session.ClientSession; import org.apache.sshd.client.subsystem.sftp.SftpClient.Attributes; +import org.apache.sshd.client.subsystem.sftp.SftpClient.DirEntry; import org.apache.sshd.common.subsystem.sftp.SftpConstants; +import org.apache.sshd.common.subsystem.sftp.SftpHelper; import org.apache.sshd.server.subsystem.sftp.SftpSubsystem; import org.apache.sshd.util.test.Utils; import org.junit.After; @@ -100,6 +102,7 @@ public class SftpVersionsTest extends AbstractSftpClientTestSupport { } } } + @Test // see SSHD-572 public void testSftpFileTimesUpdate() throws Exception { Path targetPath = detectTargetFolder(); @@ -140,4 +143,59 @@ public class SftpVersionsTest extends AbstractSftpClientTestSupport { } } + @Test // see SSHD-573 + public void testSftpFileTypeAndPermissionsUpdate() throws Exception { + Path targetPath = detectTargetFolder(); + Path lclSftp = Utils.resolve(targetPath, SftpConstants.SFTP_SUBSYSTEM_NAME, getClass().getSimpleName()); + Path subFolder = Files.createDirectories(lclSftp.resolve("sub-folder")); + String subFolderName = subFolder.getFileName().toString(); + Path lclFile = assertHierarchyTargetFolderExists(lclSftp).resolve(getCurrentTestName() + "-" + version + ".txt"); + String lclFileName = lclFile.getFileName().toString(); + Files.write(lclFile, getClass().getName().getBytes(StandardCharsets.UTF_8)); + + Path parentPath = targetPath.getParent(); + String remotePath = Utils.resolveRelativeRemotePath(parentPath, lclSftp); + try (SshClient client = setupTestClient()) { + client.start(); + + try (ClientSession session = client.connect(getCurrentTestName(), TEST_LOCALHOST, port).verify(7L, TimeUnit.SECONDS).getSession()) { + session.addPasswordIdentity(getCurrentTestName()); + session.auth().verify(5L, TimeUnit.SECONDS); + + try (SftpClient sftp = session.createSftpClient(version)) { + for (DirEntry entry : sftp.readDir(remotePath)) { + String fileName = entry.getFilename(); + if (".".equals(fileName) || "..".equals(fileName)) { + continue; + } + + Attributes attrs = validateSftpFileTypeAndPermissions(fileName, version, entry.getAttributes()); + if (subFolderName.equals(fileName)) { + assertEquals("Mismatched sub-folder type", SftpConstants.SSH_FILEXFER_TYPE_DIRECTORY, attrs.getType()); + assertTrue("Sub-folder not marked as directory", attrs.isDirectory()); + } else if (lclFileName.equals(fileName)) { + assertEquals("Mismatched sub-file type", SftpConstants.SSH_FILEXFER_TYPE_REGULAR, attrs.getType()); + assertTrue("Sub-folder not marked as directory", attrs.isRegularFile()); + } + } + } + } finally { + client.stop(); + } + } + } + + private static Attributes validateSftpFileTypeAndPermissions(String fileName, int version, Attributes attrs) { + int actualPerms = attrs.getPermissions(); + if (version == SftpConstants.SFTP_V3) { + int expected = SftpHelper.permissionsToFileType(actualPerms); + assertEquals(fileName + ": Mismatched file type", expected, attrs.getType()); + } else { + int expected = SftpHelper.fileTypeToPermission(attrs.getType()); + assertTrue(fileName + ": Missing permision=0x" + Integer.toHexString(expected) + " in 0x" + Integer.toHexString(actualPerms), + (actualPerms & expected) == expected); + } + + return attrs; + } }