http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/a6e2bf9e/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpFileSystem.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpFileSystem.java b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpFileSystem.java new file mode 100644 index 0000000..edbf82b --- /dev/null +++ b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpFileSystem.java @@ -0,0 +1,465 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.sshd.client.subsystem.sftp; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.file.attribute.GroupPrincipal; +import java.nio.file.attribute.UserPrincipal; +import java.nio.file.attribute.UserPrincipalLookupService; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.Queue; +import java.util.Set; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.atomic.AtomicInteger; + +import org.apache.sshd.client.session.ClientSession; +import org.apache.sshd.common.file.util.BaseFileSystem; +import org.apache.sshd.common.file.util.ImmutableList; + +public class SftpFileSystem extends BaseFileSystem<SftpPath> { + + private final ClientSession session; + private final Queue<SftpClient> pool; + private final ThreadLocal<Wrapper> wrappers = new ThreadLocal<>(); + private SftpPath defaultDir; + private int readBufferSize = SftpClient.DEFAULT_READ_BUFFER_SIZE; + private int writeBufferSize = SftpClient.DEFAULT_WRITE_BUFFER_SIZE; + + public SftpFileSystem(SftpFileSystemProvider provider, ClientSession session) throws IOException { + super(provider); + this.session = session; + this.pool = new LinkedBlockingQueue<>(8); + try (SftpClient client = getClient()) { + defaultDir = getPath(client.canonicalPath(".")); + } + } + + public int getReadBufferSize() { + return readBufferSize; + } + + public void setReadBufferSize(int size) { + if (size < SftpClient.MIN_READ_BUFFER_SIZE) { + throw new IllegalArgumentException("Insufficient read buffer size: " + size + ", min.=" + SftpClient.MIN_READ_BUFFER_SIZE); + } + + readBufferSize = size; + } + + public int getWriteBufferSize() { + return writeBufferSize; + } + + public void setWriteBufferSize(int size) { + if (size < SftpClient.MIN_WRITE_BUFFER_SIZE) { + throw new IllegalArgumentException("Insufficient write buffer size: " + size + ", min.=" + SftpClient.MIN_WRITE_BUFFER_SIZE); + } + + writeBufferSize = size; + } + + @Override + protected SftpPath create(String root, ImmutableList<String> names) { + return new SftpPath(this, root, names); + } + + public ClientSession getSession() { + return session; + } + + @SuppressWarnings("synthetic-access") + public SftpClient getClient() throws IOException { + Wrapper wrapper = wrappers.get(); + if (wrapper == null) { + while (wrapper == null) { + SftpClient client = pool.poll(); + if (client == null) { + client = session.createSftpClient(); + } + if (!client.isClosing()) { + wrapper = new Wrapper(client, getReadBufferSize(), getWriteBufferSize()); + } + } + wrappers.set(wrapper); + } else { + wrapper.increment(); + } + return wrapper; + } + + @Override + public void close() throws IOException { + if (isOpen()) { + session.close(true); + } + } + + @Override + public boolean isOpen() { + return !session.isClosing(); + } + + @Override + public Set<String> supportedFileAttributeViews() { + Set<String> set = new HashSet<>(); + set.addAll(Arrays.asList("basic", "posix", "owner")); + return Collections.unmodifiableSet(set); + } + + @Override + public UserPrincipalLookupService getUserPrincipalLookupService() { + return new DefaultUserPrincipalLookupService(); + } + + @Override + public SftpPath getDefaultDir() { + return defaultDir; + } + + private class Wrapper extends AbstractSftpClient { + + private final SftpClient delegate; + private final AtomicInteger count = new AtomicInteger(1); + private final int readSize, writeSize; + + private Wrapper(SftpClient delegate, int readSize, int writeSize) { + this.delegate = delegate; + this.readSize = readSize; + this.writeSize = writeSize; + } + + @Override + public int getVersion() { + return delegate.getVersion(); + } + + @Override + public boolean isClosing() { + return false; + } + + @Override + public boolean isOpen() { + if (count.get() > 0) { + return true; + } else { + return false; // debug breakpoint + } + } + + @SuppressWarnings("synthetic-access") + @Override + public void close() throws IOException { + if (count.decrementAndGet() <= 0) { + if (!pool.offer(delegate)) { + delegate.close(); + } + wrappers.set(null); + } + } + + public void increment() { + count.incrementAndGet(); + } + + @Override + public CloseableHandle open(String path, Collection<OpenMode> options) throws IOException { + if (!isOpen()) { + throw new IOException("open(" + path + ")[" + options + "] client is closed"); + } + return delegate.open(path, options); + } + + @Override + public void close(Handle handle) throws IOException { + if (!isOpen()) { + throw new IOException("close(" + handle + ") client is closed"); + } + delegate.close(handle); + } + + @Override + public void remove(String path) throws IOException { + if (!isOpen()) { + throw new IOException("remove(" + path + ") client is closed"); + } + delegate.remove(path); + } + + @Override + public void rename(String oldPath, String newPath, Collection<CopyMode> options) throws IOException { + if (!isOpen()) { + throw new IOException("rename(" + oldPath + " => " + newPath + ")[" + options + "] client is closed"); + } + delegate.rename(oldPath, newPath, options); + } + + @Override + public int read(Handle handle, long fileOffset, byte[] dst, int dstOffset, int len) throws IOException { + if (!isOpen()) { + throw new IOException("read(" + handle + "/" + fileOffset + ")[" + dstOffset + "/" + len + "] client is closed"); + } + return delegate.read(handle, fileOffset, dst, dstOffset, len); + } + + @Override + public void write(Handle handle, long fileOffset, byte[] src, int srcOffset, int len) throws IOException { + if (!isOpen()) { + throw new IOException("write(" + handle + "/" + fileOffset + ")[" + srcOffset + "/" + len + "] client is closed"); + } + delegate.write(handle, fileOffset, src, srcOffset, len); + } + + @Override + public void mkdir(String path) throws IOException { + if (!isOpen()) { + throw new IOException("mkdir(" + path + ") client is closed"); + } + delegate.mkdir(path); + } + + @Override + public void rmdir(String path) throws IOException { + if (!isOpen()) { + throw new IOException("rmdir(" + path + ") client is closed"); + } + delegate.rmdir(path); + } + + @Override + public CloseableHandle openDir(String path) throws IOException { + if (!isOpen()) { + throw new IOException("openDir(" + path + ") client is closed"); + } + return delegate.openDir(path); + } + + @Override + public DirEntry[] readDir(Handle handle) throws IOException { + if (!isOpen()) { + throw new IOException("readDir(" + handle + ") client is closed"); + } + return delegate.readDir(handle); + } + + @Override + public String canonicalPath(String path) throws IOException { + if (!isOpen()) { + throw new IOException("canonicalPath(" + path + ") client is closed"); + } + return delegate.canonicalPath(path); + } + + @Override + public Attributes stat(String path) throws IOException { + if (!isOpen()) { + throw new IOException("stat(" + path + ") client is closed"); + } + return delegate.stat(path); + } + + @Override + public Attributes lstat(String path) throws IOException { + if (!isOpen()) { + throw new IOException("lstat(" + path + ") client is closed"); + } + return delegate.lstat(path); + } + + @Override + public Attributes stat(Handle handle) throws IOException { + if (!isOpen()) { + throw new IOException("stat(" + handle + ") client is closed"); + } + return delegate.stat(handle); + } + + @Override + public void setStat(String path, Attributes attributes) throws IOException { + if (!isOpen()) { + throw new IOException("setStat(" + path + ")[" + attributes + "] client is closed"); + } + delegate.setStat(path, attributes); + } + + @Override + public void setStat(Handle handle, Attributes attributes) throws IOException { + if (!isOpen()) { + throw new IOException("setStat(" + handle + ")[" + attributes + "] client is closed"); + } + delegate.setStat(handle, attributes); + } + + @Override + public String readLink(String path) throws IOException { + if (!isOpen()) { + throw new IOException("readLink(" + path + ") client is closed"); + } + return delegate.readLink(path); + } + + @Override + public void symLink(String linkPath, String targetPath) throws IOException { + if (!isOpen()) { + throw new IOException("symLink(" + linkPath + " => " + targetPath + ") client is closed"); + } + delegate.symLink(linkPath, targetPath); + } + + @Override + public Iterable<DirEntry> readDir(String path) throws IOException { + if (!isOpen()) { + throw new IOException("readDir(" + path + ") client is closed"); + } + return delegate.readDir(path); + } + + @Override + public InputStream read(String path) throws IOException { + return read(path, readSize); + } + + @Override + public InputStream read(String path, OpenMode... mode) throws IOException { + return read(path, readSize, mode); + } + + @Override + public InputStream read(String path, Collection<OpenMode> mode) throws IOException { + return read(path, readSize, mode); + } + + @Override + public InputStream read(String path, int bufferSize, Collection<OpenMode> mode) throws IOException { + if (!isOpen()) { + throw new IOException("read(" + path + ")[" + mode + "] size=" + bufferSize + ": client is closed"); + } + return delegate.read(path, bufferSize, mode); + } + + @Override + public OutputStream write(String path) throws IOException { + return write(path, writeSize); + } + + @Override + public OutputStream write(String path, OpenMode... mode) throws IOException { + return write(path, writeSize, mode); + } + + @Override + public OutputStream write(String path, Collection<OpenMode> mode) throws IOException { + return write(path, writeSize, mode); + } + + @Override + public OutputStream write(String path, int bufferSize, Collection<OpenMode> mode) throws IOException { + if (!isOpen()) { + throw new IOException("write(" + path + ")[" + mode + "] size=" + bufferSize + ": client is closed"); + } + return delegate.write(path, bufferSize, mode); + } + + @Override + public void link(String linkPath, String targetPath, boolean symbolic) throws IOException { + if (!isOpen()) { + throw new IOException("link(" + linkPath + " => " + targetPath + "] symbolic=" + symbolic + ": client is closed"); + } + delegate.link(linkPath, targetPath, symbolic); + } + + @Override + public void lock(Handle handle, long offset, long length, int mask) throws IOException { + if (!isOpen()) { + throw new IOException("lock(" + handle + ")[offset=" + offset + ", length=" + length + ", mask=0x" + Integer.toHexString(mask) + "] client is closed"); + } + delegate.lock(handle, offset, length, mask); + } + + @Override + public void unlock(Handle handle, long offset, long length) throws IOException { + if (!isOpen()) { + throw new IOException("unlock" + handle + ")[offset=" + offset + ", length=" + length + "] client is closed"); + } + delegate.unlock(handle, offset, length); + } + } + + protected static class DefaultUserPrincipalLookupService extends UserPrincipalLookupService { + + @Override + public UserPrincipal lookupPrincipalByName(String name) throws IOException { + return new DefaultUserPrincipal(name); + } + + @Override + public GroupPrincipal lookupPrincipalByGroupName(String group) throws IOException { + return new DefaultGroupPrincipal(group); + } + } + + protected static class DefaultUserPrincipal implements UserPrincipal { + + private final String name; + + public DefaultUserPrincipal(String name) { + if (name == null) { + throw new IllegalArgumentException("name is null"); + } + this.name = name; + } + + @Override + public String getName() { + return name; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + DefaultUserPrincipal that = (DefaultUserPrincipal) o; + return name.equals(that.name); + } + + @Override + public int hashCode() { + return name.hashCode(); + } + + @Override + public String toString() { + return name; + } + } + + protected static class DefaultGroupPrincipal extends DefaultUserPrincipal implements GroupPrincipal { + + public DefaultGroupPrincipal(String name) { + super(name); + } + + } + +}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/a6e2bf9e/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpFileSystemProvider.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpFileSystemProvider.java b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpFileSystemProvider.java new file mode 100644 index 0000000..0e5169c --- /dev/null +++ b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpFileSystemProvider.java @@ -0,0 +1,892 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.sshd.client.subsystem.sftp; + +import static org.apache.sshd.common.subsystem.sftp.SftpConstants.SFTP_V3; +import static org.apache.sshd.common.subsystem.sftp.SftpConstants.S_IRGRP; +import static org.apache.sshd.common.subsystem.sftp.SftpConstants.S_IROTH; +import static org.apache.sshd.common.subsystem.sftp.SftpConstants.S_IRUSR; +import static org.apache.sshd.common.subsystem.sftp.SftpConstants.S_IWGRP; +import static org.apache.sshd.common.subsystem.sftp.SftpConstants.S_IWOTH; +import static org.apache.sshd.common.subsystem.sftp.SftpConstants.S_IWUSR; +import static org.apache.sshd.common.subsystem.sftp.SftpConstants.S_IXGRP; +import static org.apache.sshd.common.subsystem.sftp.SftpConstants.S_IXOTH; +import static org.apache.sshd.common.subsystem.sftp.SftpConstants.S_IXUSR; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URI; +import java.nio.channels.FileChannel; +import java.nio.channels.SeekableByteChannel; +import java.nio.file.AccessDeniedException; +import java.nio.file.AccessMode; +import java.nio.file.CopyOption; +import java.nio.file.DirectoryStream; +import java.nio.file.FileAlreadyExistsException; +import java.nio.file.FileStore; +import java.nio.file.FileSystem; +import java.nio.file.FileSystemAlreadyExistsException; +import java.nio.file.FileSystemException; +import java.nio.file.FileSystemNotFoundException; +import java.nio.file.LinkOption; +import java.nio.file.NoSuchFileException; +import java.nio.file.OpenOption; +import java.nio.file.Path; +import java.nio.file.ProviderMismatchException; +import java.nio.file.StandardCopyOption; +import java.nio.file.StandardOpenOption; +import java.nio.file.attribute.BasicFileAttributeView; +import java.nio.file.attribute.BasicFileAttributes; +import java.nio.file.attribute.FileAttribute; +import java.nio.file.attribute.FileAttributeView; +import java.nio.file.attribute.FileTime; +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.nio.file.spi.FileSystemProvider; +import java.util.Collection; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.TimeUnit; + +import org.apache.sshd.client.ClientBuilder; +import org.apache.sshd.client.SftpException; +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.common.FactoryManagerUtils; +import org.apache.sshd.common.SshException; +import org.apache.sshd.common.config.SshConfigFileReader; +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.io.IoUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class SftpFileSystemProvider extends FileSystemProvider { + public static final String READ_BUFFER_PROP_NAME = "sftp-fs-read-buffer-size"; + public static final int DEFAULT_READ_BUFFER_SIZE = SftpClient.DEFAULT_READ_BUFFER_SIZE; + public static final String WRITE_BUFFER_PROP_NAME = "sftp-fs-write-buffer-size"; + public static final int DEFAULT_WRITE_BUFFER_SIZE = SftpClient.DEFAULT_WRITE_BUFFER_SIZE; + public static final String CONNECT_TIME_PROP_NAME = "sftp-fs-connect-time"; + public static final long DEFAULT_CONNECT_TIME = SftpClient.DEFAULT_WAIT_TIMEOUT; + + private final SshClient client; + private final Map<String, SftpFileSystem> fileSystems = new HashMap<String, SftpFileSystem>(); + protected final Logger log; + + public SftpFileSystemProvider() { + this(null); + } + + public SftpFileSystemProvider(SshClient client) { + this.log = LoggerFactory.getLogger(getClass()); + if (client == null) { + // TODO: make this configurable using system properties + client = ClientBuilder.builder().build(); + } + this.client = client; + this.client.start(); + } + + @Override + public String getScheme() { + return SftpConstants.SFTP_SUBSYSTEM_NAME; + } + + @Override + public FileSystem newFileSystem(URI uri, Map<String, ?> env) throws IOException { + synchronized (fileSystems) { + String authority = uri.getAuthority(); + SftpFileSystem fileSystem = fileSystems.get(authority); + if (fileSystem != null) { + throw new FileSystemAlreadyExistsException(authority); + } + String host = ValidateUtils.checkNotNullAndNotEmpty(uri.getHost(), "Host not provided", GenericUtils.EMPTY_OBJECT_ARRAY); + String userInfo = ValidateUtils.checkNotNullAndNotEmpty(uri.getUserInfo(), "UserInfo not provided", GenericUtils.EMPTY_OBJECT_ARRAY); + String[] ui = GenericUtils.split(userInfo, ':'); + int port = uri.getPort(); + if (port <= 0) { + port = SshConfigFileReader.DEFAULT_PORT; + } + + ClientSession session=null; + try { + session = client.connect(ui[0], host, port) + .verify(FactoryManagerUtils.getLongProperty(env, CONNECT_TIME_PROP_NAME, DEFAULT_CONNECT_TIME)) + .getSession() + ; + session.addPasswordIdentity(ui[1]); + session.auth().verify(); + fileSystem = new SftpFileSystem(this, session); + fileSystem.setReadBufferSize(FactoryManagerUtils.getIntProperty(env, READ_BUFFER_PROP_NAME, DEFAULT_READ_BUFFER_SIZE)); + fileSystem.setWriteBufferSize(FactoryManagerUtils.getIntProperty(env, WRITE_BUFFER_PROP_NAME, DEFAULT_WRITE_BUFFER_SIZE)); + fileSystems.put(authority, fileSystem); + return fileSystem; + } catch(Exception e) { + if (session != null) { + try { + session.close(); + } catch(IOException t) { + if (log.isDebugEnabled()) { + log.debug("Failed (" + t.getClass().getSimpleName() + ")" + + " to close session for new file system on " + host + ":" + port + + " due to " + e.getClass().getSimpleName() + "[" + e.getMessage() + "]" + + ": " + t.getMessage()); + } + } + } + + if (e instanceof IOException) { + throw (IOException) e; + } else if (e instanceof RuntimeException) { + throw (RuntimeException) e; + } else { + throw new IOException(e); + } + } + } + } + + @Override + public FileSystem getFileSystem(URI uri) { + synchronized (fileSystems) { + String authority = uri.getAuthority(); + SftpFileSystem fileSystem = fileSystems.get(authority); + if (fileSystem == null) { + throw new FileSystemNotFoundException(authority); + } + return fileSystem; + } + } + + @Override + public Path getPath(URI uri) { + FileSystem fs = getFileSystem(uri); + return fs.getPath(uri.getPath()); + } + + @Override + public SeekableByteChannel newByteChannel(Path path, Set<? extends OpenOption> options, FileAttribute<?>... attrs) throws IOException { + return newFileChannel(path, options, attrs); + } + + @Override + public FileChannel newFileChannel(Path path, Set<? extends OpenOption> options, FileAttribute<?>... attrs) throws IOException { + Collection<SftpClient.OpenMode> modes = EnumSet.noneOf(SftpClient.OpenMode.class); + for (OpenOption option : options) { + if (option == StandardOpenOption.READ) { + modes.add(SftpClient.OpenMode.Read); + } else if (option == StandardOpenOption.APPEND) { + modes.add(SftpClient.OpenMode.Append); + } else if (option == StandardOpenOption.CREATE) { + modes.add(SftpClient.OpenMode.Create); + } else if (option == StandardOpenOption.TRUNCATE_EXISTING) { + modes.add(SftpClient.OpenMode.Truncate); + } else if (option == StandardOpenOption.WRITE) { + modes.add(SftpClient.OpenMode.Write); + } else if (option == StandardOpenOption.CREATE_NEW) { + modes.add(SftpClient.OpenMode.Create); + modes.add(SftpClient.OpenMode.Exclusive); + } else if (option == StandardOpenOption.SPARSE) { + /* + * As per the Javadoc: + * + * The option is ignored when the file system does not + * support the creation of sparse files + */ + continue; + } else { + throw new IllegalArgumentException("newFileChannel(" + path + ") unsupported open option: " + option); + } + } + if (modes.isEmpty()) { + modes.add(SftpClient.OpenMode.Read); + modes.add(SftpClient.OpenMode.Write); + } + // TODO: attrs + return new SftpFileChannel(toSftpPath(path), modes); + } + + @Override + public DirectoryStream<Path> newDirectoryStream(Path dir, DirectoryStream.Filter<? super Path> filter) throws IOException { + final SftpPath p = toSftpPath(dir); + return new DirectoryStream<Path>() { + private final SftpFileSystem fs = p.getFileSystem(); + private final SftpClient sftp = fs.getClient(); + private final Iterable<SftpClient.DirEntry> iter = sftp.readDir(p.toString()); + + @Override + public Iterator<Path> iterator() { + return new Iterator<Path>() { + @SuppressWarnings("synthetic-access") + private final Iterator<SftpClient.DirEntry> it = iter.iterator(); + + @Override + public boolean hasNext() { + return it.hasNext(); + } + + @Override + public Path next() { + SftpClient.DirEntry entry = it.next(); + return p.resolve(entry.filename); + } + + @Override + public void remove() { + throw new UnsupportedOperationException("newDirectoryStream(" + p + ") Iterator#remove() N/A"); + } + }; + } + + @Override + public void close() throws IOException { + sftp.close(); + } + }; + } + + @Override + public void createDirectory(Path dir, FileAttribute<?>... attrs) throws IOException { + SftpPath p = toSftpPath(dir); + SftpFileSystem fs = p.getFileSystem(); + try (SftpClient sftp = fs.getClient()) { + try { + sftp.mkdir(dir.toString()); + } catch (SftpException e) { + int sftpStatus=e.getStatus(); + if ((sftp.getVersion() == SFTP_V3) && (sftpStatus == SftpConstants.SSH_FX_FAILURE)) { + try { + Attributes attributes = sftp.stat(dir.toString()); + if (attributes != null) { + throw new FileAlreadyExistsException(p.toString()); + } + } catch (SshException e2) { + e.addSuppressed(e2); + } + } + if (sftpStatus == SftpConstants.SSH_FX_FILE_ALREADY_EXISTS) { + throw new FileAlreadyExistsException(p.toString()); + } + throw e; + } + for (FileAttribute<?> attr : attrs) { + setAttribute(p, attr.name(), attr.value()); + } + } + } + + @Override + public void delete(Path path) throws IOException { + SftpPath p = toSftpPath(path); + checkAccess(p, AccessMode.WRITE); + + SftpFileSystem fs = p.getFileSystem(); + try (SftpClient sftp = fs.getClient()) { + BasicFileAttributes attributes = readAttributes(path, BasicFileAttributes.class); + if (attributes.isDirectory()) { + sftp.rmdir(path.toString()); + } else { + sftp.remove(path.toString()); + } + } + } + + @Override + public void copy(Path source, Path target, CopyOption... options) throws IOException { + SftpPath src = toSftpPath(source); + SftpPath dst = toSftpPath(target); + if (src.getFileSystem() != dst.getFileSystem()) { + throw new ProviderMismatchException("Mismatched file system providers for " + src + " vs. " + dst); + } + checkAccess(src); + + boolean replaceExisting = false; + boolean copyAttributes = false; + boolean noFollowLinks = false; + for (CopyOption opt : options) { + replaceExisting |= opt == StandardCopyOption.REPLACE_EXISTING; + copyAttributes |= opt == StandardCopyOption.COPY_ATTRIBUTES; + noFollowLinks |= opt == LinkOption.NOFOLLOW_LINKS; + } + LinkOption[] linkOptions = IoUtils.getLinkOptions(!noFollowLinks); + + // attributes of source file + BasicFileAttributes attrs = readAttributes(source, BasicFileAttributes.class, linkOptions); + if (attrs.isSymbolicLink()) + throw new IOException("Copying of symbolic links not supported"); + + // delete target if it exists and REPLACE_EXISTING is specified + Boolean status=IoUtils.checkFileExists(target, linkOptions); + if (status == null) { + throw new AccessDeniedException("Existence cannot be determined for copy target: " + target); + } + + if (replaceExisting) { + deleteIfExists(target); + } else { + if (status.booleanValue()) { + throw new FileAlreadyExistsException(target.toString()); + } + } + + // create directory or copy file + if (attrs.isDirectory()) { + createDirectory(target); + } else { + try (InputStream in = newInputStream(source); + OutputStream os = newOutputStream(target)) { + IoUtils.copy(in, os); + } + } + + // copy basic attributes to target + if (copyAttributes) { + BasicFileAttributeView view = getFileAttributeView(target, BasicFileAttributeView.class, linkOptions); + try { + view.setTimes(attrs.lastModifiedTime(), attrs.lastAccessTime(), attrs.creationTime()); + } catch (Throwable x) { + // rollback + try { + delete(target); + } catch (Throwable suppressed) { + x.addSuppressed(suppressed); + } + throw x; + } + } + } + + @Override + public void move(Path source, Path target, CopyOption... options) throws IOException { + SftpPath src = toSftpPath(source); + SftpFileSystem fsSrc = src.getFileSystem(); + SftpPath dst = toSftpPath(target); + + if (src.getFileSystem() != dst.getFileSystem()) { + throw new ProviderMismatchException("Mismatched file system providers for " + src + " vs. " + dst); + } + checkAccess(src); + + boolean replaceExisting = false; + boolean copyAttributes = false; + boolean noFollowLinks = false; + for (CopyOption opt : options) { + replaceExisting |= opt == StandardCopyOption.REPLACE_EXISTING; + copyAttributes |= opt == StandardCopyOption.COPY_ATTRIBUTES; + noFollowLinks |= opt == LinkOption.NOFOLLOW_LINKS; + } + LinkOption[] linkOptions = IoUtils.getLinkOptions(noFollowLinks); + + // attributes of source file + BasicFileAttributes attrs = readAttributes(source, BasicFileAttributes.class, linkOptions); + if (attrs.isSymbolicLink()) { + throw new IOException("Copying of symbolic links not supported"); + } + + // delete target if it exists and REPLACE_EXISTING is specified + Boolean status=IoUtils.checkFileExists(target, linkOptions); + if (status == null) { + throw new AccessDeniedException("Existence cannot be determined for move target " + target); + } + + if (replaceExisting) { + deleteIfExists(target); + } else if (status.booleanValue()) { + throw new FileAlreadyExistsException(target.toString()); + } + + try (SftpClient sftp = fsSrc.getClient()) { + sftp.rename(src.toString(), dst.toString()); + } + + // copy basic attributes to target + if (copyAttributes) { + BasicFileAttributeView view = getFileAttributeView(target, BasicFileAttributeView.class, linkOptions); + try { + view.setTimes(attrs.lastModifiedTime(), attrs.lastAccessTime(), attrs.creationTime()); + } catch (Throwable x) { + // rollback + try { + delete(target); + } catch (Throwable suppressed) { + x.addSuppressed(suppressed); + } + throw x; + } + } + } + + @Override + public boolean isSameFile(Path path1, Path path2) throws IOException { + SftpPath p1 = toSftpPath(path1); + SftpPath p2 = toSftpPath(path2); + if (p1.getFileSystem() != p2.getFileSystem()) { + throw new ProviderMismatchException("Mismatched file system providers for " + p1 + " vs. " + p2); + } + checkAccess(p1); + checkAccess(p2); + return p1.equals(p2); + } + + @Override + public boolean isHidden(Path path) throws IOException { + return false; + } + + @Override + public FileStore getFileStore(Path path) throws IOException { + throw new FileSystemException(path.toString(), path.toString(), "getFileStore(" + path + ") N/A"); + } + + @Override + public void createSymbolicLink(Path link, Path target, FileAttribute<?>... attrs) throws IOException { + SftpPath l = toSftpPath(link); + SftpFileSystem fsLink = l.getFileSystem(); + SftpPath t = toSftpPath(target); + if (fsLink != t.getFileSystem()) { + throw new ProviderMismatchException("Mismatched file system providers for " + l + " vs. " + t); + } + try (SftpClient client = fsLink.getClient()) { + client.symLink(l.toString(), t.toString()); + } + } + + @Override + public Path readSymbolicLink(Path link) throws IOException { + SftpPath l = toSftpPath(link); + SftpFileSystem fsLink = l.getFileSystem(); + try (SftpClient client = fsLink.getClient()) { + return fsLink.getPath(client.readLink(l.toString())); + } + } + + @Override + public void checkAccess(Path path, AccessMode... modes) throws IOException { + SftpPath p = toSftpPath(path); + boolean w = false; + boolean x = false; + if (GenericUtils.length(modes) > 0) { + for (AccessMode mode : modes) { + switch (mode) { + case READ: + break; + case WRITE: + w = true; + break; + case EXECUTE: + x = true; + break; + default: + throw new UnsupportedOperationException("Unsupported mode: " + mode); + } + } + } + + BasicFileAttributes attrs = getFileAttributeView(p, BasicFileAttributeView.class).readAttributes(); + if ((attrs == null) && !(p.isAbsolute() && p.getNameCount() == 0)) { + throw new NoSuchFileException(path.toString()); + } + + SftpFileSystem fs = p.getFileSystem(); + if (x || (w && fs.isReadOnly())) { + throw new AccessDeniedException(path.toString()); + } + } + + @SuppressWarnings("unchecked") + @Override + public <V extends FileAttributeView> V getFileAttributeView(final Path path, Class<V> type, final LinkOption... options) { + if (type.isAssignableFrom(PosixFileAttributeView.class)) { + return (V) new PosixFileAttributeView() { + @Override + public String name() { + return "view"; + } + + @SuppressWarnings("synthetic-access") + @Override + public PosixFileAttributes readAttributes() throws IOException { + SftpPath p = toSftpPath(path); + SftpFileSystem fs = p.getFileSystem(); + final SftpClient.Attributes attributes; + try (SftpClient client =fs.getClient()) { + try { + if (followLinks(options)) { + attributes = client.stat(p.toString()); + } else { + attributes = client.lstat(p.toString()); + } + } catch (SftpException e) { + if (e.getStatus() == SftpConstants.SSH_FX_NO_SUCH_FILE) { + throw new NoSuchFileException(p.toString()); + } + throw e; + } + } + return new PosixFileAttributes() { + @Override + public UserPrincipal owner() { + return attributes.owner != null ? new SftpFileSystem.DefaultGroupPrincipal(attributes.owner) : null; + } + + @Override + public GroupPrincipal group() { + return attributes.group != null ? new SftpFileSystem.DefaultGroupPrincipal(attributes.group) : null; + } + + @Override + public Set<PosixFilePermission> permissions() { + return permissionsToAttributes(attributes.perms); + } + + @Override + public FileTime lastModifiedTime() { + return FileTime.from(attributes.mtime, TimeUnit.SECONDS); + } + + @Override + public FileTime lastAccessTime() { + return FileTime.from(attributes.atime, TimeUnit.SECONDS); + } + + @Override + public FileTime creationTime() { + return FileTime.from(attributes.ctime, TimeUnit.SECONDS); + } + + @Override + public boolean isRegularFile() { + return attributes.isRegularFile(); + } + + @Override + public boolean isDirectory() { + return attributes.isDirectory(); + } + + @Override + public boolean isSymbolicLink() { + return attributes.isSymbolicLink(); + } + + @Override + public boolean isOther() { + return attributes.isOther(); + } + + @Override + public long size() { + return attributes.size; + } + + @Override + public Object fileKey() { + // TODO + return null; + } + }; + } + + @Override + public void setTimes(FileTime lastModifiedTime, FileTime lastAccessTime, FileTime createTime) throws IOException { + if (lastModifiedTime != null) { + setAttribute(path, "lastModifiedTime", lastModifiedTime, options); + } + if (lastAccessTime != null) { + setAttribute(path, "lastAccessTime", lastAccessTime, options); + } + if (createTime != null) { + setAttribute(path, "createTime", createTime, options); + } + } + + @Override + public void setPermissions(Set<PosixFilePermission> perms) throws IOException { + setAttribute(path, "permissions", perms, options); + } + + @Override + public void setGroup(GroupPrincipal group) throws IOException { + setAttribute(path, "group", group, options); + } + + @Override + public UserPrincipal getOwner() throws IOException { + return readAttributes().owner(); + } + + @Override + public void setOwner(UserPrincipal owner) throws IOException { + setAttribute(path, "owner", owner, options); + } + }; + } else { + throw new UnsupportedOperationException("getFileAttributeView(" + path + ") view not supported: " + type.getSimpleName()); + } + } + + @Override + public <A extends BasicFileAttributes> A readAttributes(Path path, Class<A> type, LinkOption... options) throws IOException { + if (type.isAssignableFrom(PosixFileAttributes.class)) { + return type.cast(getFileAttributeView(path, PosixFileAttributeView.class, options).readAttributes()); + } + + throw new UnsupportedOperationException("readAttributes(" + path + ")[" + type.getSimpleName() + "] N/A"); + } + + @Override + public Map<String, Object> readAttributes(Path path, String attributes, LinkOption... options) throws IOException { + String view; + String attrs; + int i = attributes.indexOf(':'); + if (i == -1) { + view = "basic"; + attrs = attributes; + } else { + view = attributes.substring(0, i++); + attrs = attributes.substring(i); + } + SftpPath p = toSftpPath(path); + SftpFileSystem fs = p.getFileSystem(); + Collection<String> views = fs.supportedFileAttributeViews(); + if (GenericUtils.isEmpty(views) || (!views.contains(view))) { + throw new UnsupportedOperationException("readAttributes(" + path + ")[" + attributes + "] view " + view + " not supported: " + views); + } + + PosixFileAttributes v = readAttributes(path, PosixFileAttributes.class, options); + if ("*".equals(attrs)) { + attrs = "lastModifiedTime,lastAccessTime,creationTime,size,isRegularFile,isDirectory,isSymbolicLink,isOther,fileKey,owner,permissions,group"; + } + Map<String, Object> map = new HashMap<>(); + for (String attr : attrs.split(",")) { + switch (attr) { + case "lastModifiedTime": + map.put(attr, v.lastModifiedTime()); + break; + case "lastAccessTime": + map.put(attr, v.lastAccessTime()); + break; + case "creationTime": + map.put(attr, v.creationTime()); + break; + case "size": + map.put(attr, Long.valueOf(v.size())); + break; + case "isRegularFile": + map.put(attr, Boolean.valueOf(v.isRegularFile())); + break; + case "isDirectory": + map.put(attr, Boolean.valueOf(v.isDirectory())); + break; + case "isSymbolicLink": + map.put(attr, Boolean.valueOf(v.isSymbolicLink())); + break; + case "isOther": + map.put(attr, Boolean.valueOf(v.isOther())); + break; + case "fileKey": + map.put(attr, v.fileKey()); + break; + case "owner": + map.put(attr, v.owner()); + break; + case "permissions": + map.put(attr, v.permissions()); + break; + case "group": + map.put(attr, v.group()); + break; + default: + if (log.isTraceEnabled()) { + log.trace("readAttributes({})[{}] ignored {}={}", path, attributes, attr, v); + } + } + } + return map; + } + + @Override + public void setAttribute(Path path, String attribute, Object value, LinkOption... options) throws IOException { + String view; + String attr; + int i = attribute.indexOf(':'); + if (i == -1) { + view = "basic"; + attr = attribute; + } else { + view = attribute.substring(0, i++); + attr = attribute.substring(i); + } + SftpPath p = toSftpPath(path); + SftpFileSystem fs = p.getFileSystem(); + Collection<String> views = fs.supportedFileAttributeViews(); + if (GenericUtils.isEmpty(views) || (!view.contains(view))) { + throw new UnsupportedOperationException("setAttribute(" + path + ")[" + attribute + "=" + value + "] view " + view + " not supported: " + views); + } + + SftpClient.Attributes attributes = new SftpClient.Attributes(); + switch (attr) { + case "lastModifiedTime": + attributes.mtime((int) ((FileTime) value).to(TimeUnit.SECONDS)); + break; + case "lastAccessTime": + attributes.atime((int) ((FileTime) value).to(TimeUnit.SECONDS)); + break; + case "creationTime": + attributes.ctime((int) ((FileTime) value).to(TimeUnit.SECONDS)); + break; + case "size": + attributes.size(((Number) value).longValue()); + break; + case "permissions": { + @SuppressWarnings("unchecked") + Set<PosixFilePermission> attrSet = (Set<PosixFilePermission>) value; + attributes.perms(attributesToPermissions(path, attrSet)); + } + break; + case "owner": + attributes.owner(((UserPrincipal) value).getName()); + break; + case "group": + attributes.group(((GroupPrincipal) value).getName()); + break; + case "isRegularFile": + case "isDirectory": + case "isSymbolicLink": + case "isOther": + case "fileKey": + throw new UnsupportedOperationException("setAttribute(" + path + ")[" + attribute + "=" + value + "]" + + " unknown view=" + view + " attribute: " + attr); + default: + if (log.isTraceEnabled()) { + log.trace("setAttribute({})[{}] ignore {}={}", path, attribute, attr, value); + } + } + + try (SftpClient client = fs.getClient()) { + client.setStat(p.toString(), attributes); + } + } + + private SftpPath toSftpPath(Path path) { + ValidateUtils.checkNotNull(path, "No path provided", GenericUtils.EMPTY_OBJECT_ARRAY); + if (!(path instanceof SftpPath)) { + throw new ProviderMismatchException("Path is not SFTP: " + path); + } + return (SftpPath) path; + } + + static boolean followLinks(LinkOption... paramVarArgs) { + boolean bool = true; + for (LinkOption localLinkOption : paramVarArgs) { + if (localLinkOption == LinkOption.NOFOLLOW_LINKS) { + bool = false; + } + } + return bool; + } + + private Set<PosixFilePermission> permissionsToAttributes(int perms) { + Set<PosixFilePermission> p = new HashSet<>(); + if ((perms & S_IRUSR) != 0) { + p.add(PosixFilePermission.OWNER_READ); + } + if ((perms & S_IWUSR) != 0) { + p.add(PosixFilePermission.OWNER_WRITE); + } + if ((perms & S_IXUSR) != 0) { + p.add(PosixFilePermission.OWNER_EXECUTE); + } + if ((perms & S_IRGRP) != 0) { + p.add(PosixFilePermission.GROUP_READ); + } + if ((perms & S_IWGRP) != 0) { + p.add(PosixFilePermission.GROUP_WRITE); + } + if ((perms & S_IXGRP) != 0) { + p.add(PosixFilePermission.GROUP_EXECUTE); + } + if ((perms & S_IROTH) != 0) { + p.add(PosixFilePermission.OTHERS_READ); + } + if ((perms & S_IWOTH) != 0) { + p.add(PosixFilePermission.OTHERS_WRITE); + } + if ((perms & S_IXOTH) != 0) { + p.add(PosixFilePermission.OTHERS_EXECUTE); + } + return p; + } + + protected int attributesToPermissions(Path path, Collection<PosixFilePermission> perms) { + if (GenericUtils.isEmpty(perms)) { + return 0; + } + + int pf = 0; + for (PosixFilePermission p : perms) { + switch (p) { + case OWNER_READ: + pf |= S_IRUSR; + break; + case OWNER_WRITE: + pf |= S_IWUSR; + break; + case OWNER_EXECUTE: + pf |= S_IXUSR; + break; + case GROUP_READ: + pf |= S_IRGRP; + break; + case GROUP_WRITE: + pf |= S_IWGRP; + break; + case GROUP_EXECUTE: + pf |= S_IXGRP; + break; + case OTHERS_READ: + pf |= S_IROTH; + break; + case OTHERS_WRITE: + pf |= S_IWOTH; + break; + case OTHERS_EXECUTE: + pf |= S_IXOTH; + break; + default: + if (log.isTraceEnabled()) { + log.trace("attributesToPermissions(" + path + ") ignored " + p); + } + } + } + + return pf; + } + +} http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/a6e2bf9e/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpPath.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpPath.java b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpPath.java new file mode 100644 index 0000000..f130d1a --- /dev/null +++ b/sshd-core/src/main/java/org/apache/sshd/client/subsystem/sftp/SftpPath.java @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.sshd.client.subsystem.sftp; + +import java.io.IOException; +import java.nio.file.FileSystem; +import java.nio.file.LinkOption; +import java.nio.file.spi.FileSystemProvider; + +import org.apache.sshd.common.file.util.BasePath; +import org.apache.sshd.common.file.util.ImmutableList; + +public class SftpPath extends BasePath<SftpPath, SftpFileSystem> { + public SftpPath(SftpFileSystem fileSystem, String root, ImmutableList<String> names) { + super(fileSystem, root, names); + } + + @Override + public SftpPath toRealPath(LinkOption... options) throws IOException { +// try (SftpClient client = fileSystem.getClient()) { +// client.realP +// } + // TODO: handle links + SftpPath absolute = toAbsolutePath(); + FileSystem fs = getFileSystem(); + FileSystemProvider provider = fs.provider(); + provider.checkAccess(absolute); + return absolute; + } +} http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/a6e2bf9e/sshd-core/src/main/java/org/apache/sshd/common/file/root/RootedFileSystemProvider.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/file/root/RootedFileSystemProvider.java b/sshd-core/src/main/java/org/apache/sshd/common/file/root/RootedFileSystemProvider.java index bad235f..ef67e34 100644 --- a/sshd-core/src/main/java/org/apache/sshd/common/file/root/RootedFileSystemProvider.java +++ b/sshd-core/src/main/java/org/apache/sshd/common/file/root/RootedFileSystemProvider.java @@ -33,7 +33,6 @@ import java.nio.file.FileStore; import java.nio.file.FileSystem; import java.nio.file.FileSystemAlreadyExistsException; import java.nio.file.FileSystemNotFoundException; -import java.nio.file.Files; import java.nio.file.LinkOption; import java.nio.file.OpenOption; import java.nio.file.Path; @@ -73,42 +72,52 @@ public class RootedFileSystemProvider extends FileSystemProvider { @Override public FileSystem newFileSystem(URI uri, Map<String, ?> env) throws IOException { Path path = uriToPath(uri); - synchronized (fileSystems) - { - Path localPath2 = null; - if (ensureDirectory(path)) - { - localPath2 = path.toRealPath(); - if (this.fileSystems.containsKey(localPath2)) { - throw new FileSystemAlreadyExistsException(); - } + Path localPath2 = ensureDirectory(path).toRealPath(); + + RootedFileSystem rootedFs=null; + synchronized (fileSystems) { + if (!this.fileSystems.containsKey(localPath2)) { + rootedFs = new RootedFileSystem(this, path, env); + this.fileSystems.put(localPath2, rootedFs); } - RootedFileSystem rootedFs = new RootedFileSystem(this, path, env); - this.fileSystems.put(localPath2, rootedFs); - return rootedFs; } + + // do all the throwing outside the synchronized block to minimize its lock time + if (rootedFs == null) { + throw new FileSystemAlreadyExistsException("newFileSystem(" + uri + ") already mapped " + localPath2); + } + + return rootedFs; } @Override public FileSystem getFileSystem(URI uri) { + Path path = uriToPath(uri); + Path real; + try { + real = path.toRealPath(); + } catch (IOException e) { + FileSystemNotFoundException err = new FileSystemNotFoundException(uri.toString()); + err.initCause(e); + throw err; + } + + RootedFileSystem fileSystem = null; synchronized (fileSystems) { - RootedFileSystem fileSystem = null; - try { - fileSystem = fileSystems.get(uriToPath(uri).toRealPath()); - } catch (IOException ignore) { - // ignored - } - if (fileSystem == null) { - throw new FileSystemNotFoundException(uri.toString()); - } - return fileSystem; + fileSystem = fileSystems.get(real); } + + // do all the throwing outside the synchronized block to minimize its lock time + if (fileSystem == null) { + throw new FileSystemNotFoundException(uri.toString()); + } + + return fileSystem; } @Override public FileSystem newFileSystem(Path path, Map<String, ?> env) throws IOException { - ensureDirectory(path); - return new RootedFileSystem(this, path, env); + return new RootedFileSystem(this, ensureDirectory(path), env); } protected Path uriToPath(URI uri) { @@ -130,11 +139,8 @@ public class RootedFileSystemProvider extends FileSystemProvider { } } - private boolean ensureDirectory(Path path) { - if (!Files.isDirectory(path, IoUtils.getLinkOptions(false))) { - throw new UnsupportedOperationException("Not a directory: " + path); - } - return true; + private static Path ensureDirectory(Path path) { + return IoUtils.ensureDirectory(path, IoUtils.getLinkOptions(false)); } @Override http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/a6e2bf9e/sshd-core/src/main/java/org/apache/sshd/common/sftp/SftpConstants.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/sftp/SftpConstants.java b/sshd-core/src/main/java/org/apache/sshd/common/sftp/SftpConstants.java deleted file mode 100644 index dd54bf3..0000000 --- a/sshd-core/src/main/java/org/apache/sshd/common/sftp/SftpConstants.java +++ /dev/null @@ -1,223 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.sshd.common.sftp; - -/** - * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> - */ -public class SftpConstants { - public static String SFTP_SUBSYSTEM_NAME = "sftp"; - - 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; // v3 -> v5 - public static final int SSH_FXP_LINK = 21; // v6 - public static final int SSH_FXP_BLOCK = 22; // v6 - public static final int SSH_FXP_UNBLOCK = 23; // v6 - 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_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_PRINCIPLE = 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_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; // v4 - public static final int SSH_FILEXFER_ATTR_CREATETIME = 0x00000010; // v4 - public static final int SSH_FILEXFER_ATTR_MODIFYTIME = 0x00000020; // v4 - public static final int SSH_FILEXFER_ATTR_ACL = 0x00000040; // v4 - public static final int SSH_FILEXFER_ATTR_OWNERGROUP = 0x00000080; // v4 - public static final int SSH_FILEXFER_ATTR_SUBSECOND_TIMES = 0x00000100; // v5 - public static final int SSH_FILEXFER_ATTR_BITS = 0x00000200; // v5 - public static final int SSH_FILEXFER_ATTR_ALLOCATION_SIZE = 0x00000400; // v6 - public static final int SSH_FILEXFER_ATTR_TEXT_HINT = 0x00000800; // v6 - public static final int SSH_FILEXFER_ATTR_MIME_TYPE = 0x00001000; // v6 - public static final int SSH_FILEXFER_ATTR_LINK_COUNT = 0x00002000; // v6 - public static final int SSH_FILEXFER_ATTR_UNTRANSLATED_NAME = 0x00004000; // v6 - public static final int SSH_FILEXFER_ATTR_CTIME = 0x00008000; // v6 - public static final int SSH_FILEXFER_ATTR_EXTENDED = 0x80000000; - - public static final int SSH_FILEXFER_ATTR_ALL = 0x0000FFFF; // All attributes - - public static final int SSH_FILEXFER_ATTR_FLAGS_READONLY = 0x00000001; - public static final int SSH_FILEXFER_ATTR_FLAGS_SYSTEM = 0x00000002; - public static final int SSH_FILEXFER_ATTR_FLAGS_HIDDEN = 0x00000004; - public static final int SSH_FILEXFER_ATTR_FLAGS_CASE_INSENSITIVE = 0x00000008; - public static final int SSH_FILEXFER_ATTR_FLAGS_ARCHIVE = 0x00000010; - public static final int SSH_FILEXFER_ATTR_FLAGS_ENCRYPTED = 0x00000020; - public static final int SSH_FILEXFER_ATTR_FLAGS_COMPRESSED = 0x00000040; - public static final int SSH_FILEXFER_ATTR_FLAGS_SPARSE = 0x00000080; - public static final int SSH_FILEXFER_ATTR_FLAGS_APPEND_ONLY = 0x00000100; - public static final int SSH_FILEXFER_ATTR_FLAGS_IMMUTABLE = 0x00000200; - public static final int SSH_FILEXFER_ATTR_FLAGS_SYNC = 0x00000400; - - public static final int SSH_FILEXFER_TYPE_REGULAR = 1; - public static final int SSH_FILEXFER_TYPE_DIRECTORY = 2; - public static final int SSH_FILEXFER_TYPE_SYMLINK = 3; - public static final int SSH_FILEXFER_TYPE_SPECIAL = 4; - public static final int SSH_FILEXFER_TYPE_UNKNOWN = 5; - public static final int SSH_FILEXFER_TYPE_SOCKET = 6; // v5 - public static final int SSH_FILEXFER_TYPE_CHAR_DEVICE = 7; // v5 - public static final int SSH_FILEXFER_TYPE_BLOCK_DEVICE = 8; // v5 - public static final int SSH_FILEXFER_TYPE_FIFO = 9; // v5 - - public static final int SSH_FXF_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_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_READ_LOCK = 0x00000040; - public static final int SSH_FXF_WRITE_LOCK = 0x00000080; - public static final int SSH_FXF_DELETE_LOCK = 0x00000100; - - public static final int SSH_FXP_RENAME_OVERWRITE = 0x00000001; - public static final int SSH_FXP_RENAME_ATOMIC = 0x00000002; - public static final int SSH_FXP_RENAME_NATIVE = 0x00000004; - - 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 SSH_FXF_RENAME_OVERWRITE = 0x00000001; - public static final int SSH_FXF_RENAME_ATOMIC = 0x00000002; - public static final int SSH_FXF_RENAME_NATIVE = 0x00000004; - - public static final int ACE4_ACCESS_ALLOWED_ACE_TYPE = 0x00000000; - public static final int ACE4_ACCESS_DENIED_ACE_TYPE = 0x00000001; - public static final int ACE4_SYSTEM_AUDIT_ACE_TYPE = 0x00000002; - public static final int ACE4_SYSTEM_ALARM_ACE_TYPE = 0x00000003; - - public static final int ACE4_FILE_INHERIT_ACE = 0x00000001; - public static final int ACE4_DIRECTORY_INHERIT_ACE = 0x00000002; - public static final int ACE4_NO_PROPAGATE_INHERIT_ACE = 0x00000004; - public static final int ACE4_INHERIT_ONLY_ACE = 0x00000008; - public static final int ACE4_SUCCESSFUL_ACCESS_ACE_FLAG = 0x00000010; - public static final int ACE4_FAILED_ACCESS_ACE_FLAG = 0x00000020; - public static final int ACE4_IDENTIFIER_GROUP = 0x00000040; - - 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 ACE4_SYNCHRONIZE = 0x00100000; - - 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; - - public static int SFTP_V3 = 3; - public static int SFTP_V4 = 4; - public static int SFTP_V5 = 5; - public static int SFTP_V6 = 6; -} http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/a6e2bf9e/sshd-core/src/main/java/org/apache/sshd/common/subsystem/sftp/SftpConstants.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/subsystem/sftp/SftpConstants.java b/sshd-core/src/main/java/org/apache/sshd/common/subsystem/sftp/SftpConstants.java new file mode 100644 index 0000000..f2f005d --- /dev/null +++ b/sshd-core/src/main/java/org/apache/sshd/common/subsystem/sftp/SftpConstants.java @@ -0,0 +1,223 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.sshd.common.subsystem.sftp; + +/** + * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> + */ +public class SftpConstants { + public static String SFTP_SUBSYSTEM_NAME = "sftp"; + + 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; // v3 -> v5 + public static final int SSH_FXP_LINK = 21; // v6 + public static final int SSH_FXP_BLOCK = 22; // v6 + public static final int SSH_FXP_UNBLOCK = 23; // v6 + 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_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_PRINCIPLE = 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_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; // v4 + public static final int SSH_FILEXFER_ATTR_CREATETIME = 0x00000010; // v4 + public static final int SSH_FILEXFER_ATTR_MODIFYTIME = 0x00000020; // v4 + public static final int SSH_FILEXFER_ATTR_ACL = 0x00000040; // v4 + public static final int SSH_FILEXFER_ATTR_OWNERGROUP = 0x00000080; // v4 + public static final int SSH_FILEXFER_ATTR_SUBSECOND_TIMES = 0x00000100; // v5 + public static final int SSH_FILEXFER_ATTR_BITS = 0x00000200; // v5 + public static final int SSH_FILEXFER_ATTR_ALLOCATION_SIZE = 0x00000400; // v6 + public static final int SSH_FILEXFER_ATTR_TEXT_HINT = 0x00000800; // v6 + public static final int SSH_FILEXFER_ATTR_MIME_TYPE = 0x00001000; // v6 + public static final int SSH_FILEXFER_ATTR_LINK_COUNT = 0x00002000; // v6 + public static final int SSH_FILEXFER_ATTR_UNTRANSLATED_NAME = 0x00004000; // v6 + public static final int SSH_FILEXFER_ATTR_CTIME = 0x00008000; // v6 + public static final int SSH_FILEXFER_ATTR_EXTENDED = 0x80000000; + + public static final int SSH_FILEXFER_ATTR_ALL = 0x0000FFFF; // All attributes + + public static final int SSH_FILEXFER_ATTR_FLAGS_READONLY = 0x00000001; + public static final int SSH_FILEXFER_ATTR_FLAGS_SYSTEM = 0x00000002; + public static final int SSH_FILEXFER_ATTR_FLAGS_HIDDEN = 0x00000004; + public static final int SSH_FILEXFER_ATTR_FLAGS_CASE_INSENSITIVE = 0x00000008; + public static final int SSH_FILEXFER_ATTR_FLAGS_ARCHIVE = 0x00000010; + public static final int SSH_FILEXFER_ATTR_FLAGS_ENCRYPTED = 0x00000020; + public static final int SSH_FILEXFER_ATTR_FLAGS_COMPRESSED = 0x00000040; + public static final int SSH_FILEXFER_ATTR_FLAGS_SPARSE = 0x00000080; + public static final int SSH_FILEXFER_ATTR_FLAGS_APPEND_ONLY = 0x00000100; + public static final int SSH_FILEXFER_ATTR_FLAGS_IMMUTABLE = 0x00000200; + public static final int SSH_FILEXFER_ATTR_FLAGS_SYNC = 0x00000400; + + public static final int SSH_FILEXFER_TYPE_REGULAR = 1; + public static final int SSH_FILEXFER_TYPE_DIRECTORY = 2; + public static final int SSH_FILEXFER_TYPE_SYMLINK = 3; + public static final int SSH_FILEXFER_TYPE_SPECIAL = 4; + public static final int SSH_FILEXFER_TYPE_UNKNOWN = 5; + public static final int SSH_FILEXFER_TYPE_SOCKET = 6; // v5 + public static final int SSH_FILEXFER_TYPE_CHAR_DEVICE = 7; // v5 + public static final int SSH_FILEXFER_TYPE_BLOCK_DEVICE = 8; // v5 + public static final int SSH_FILEXFER_TYPE_FIFO = 9; // v5 + + public static final int SSH_FXF_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_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_READ_LOCK = 0x00000040; + public static final int SSH_FXF_WRITE_LOCK = 0x00000080; + public static final int SSH_FXF_DELETE_LOCK = 0x00000100; + + public static final int SSH_FXP_RENAME_OVERWRITE = 0x00000001; + public static final int SSH_FXP_RENAME_ATOMIC = 0x00000002; + public static final int SSH_FXP_RENAME_NATIVE = 0x00000004; + + 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 SSH_FXF_RENAME_OVERWRITE = 0x00000001; + public static final int SSH_FXF_RENAME_ATOMIC = 0x00000002; + public static final int SSH_FXF_RENAME_NATIVE = 0x00000004; + + public static final int ACE4_ACCESS_ALLOWED_ACE_TYPE = 0x00000000; + public static final int ACE4_ACCESS_DENIED_ACE_TYPE = 0x00000001; + public static final int ACE4_SYSTEM_AUDIT_ACE_TYPE = 0x00000002; + public static final int ACE4_SYSTEM_ALARM_ACE_TYPE = 0x00000003; + + public static final int ACE4_FILE_INHERIT_ACE = 0x00000001; + public static final int ACE4_DIRECTORY_INHERIT_ACE = 0x00000002; + public static final int ACE4_NO_PROPAGATE_INHERIT_ACE = 0x00000004; + public static final int ACE4_INHERIT_ONLY_ACE = 0x00000008; + public static final int ACE4_SUCCESSFUL_ACCESS_ACE_FLAG = 0x00000010; + public static final int ACE4_FAILED_ACCESS_ACE_FLAG = 0x00000020; + public static final int ACE4_IDENTIFIER_GROUP = 0x00000040; + + 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 ACE4_SYNCHRONIZE = 0x00100000; + + 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; + + public static int SFTP_V3 = 3; + public static int SFTP_V4 = 4; + public static int SFTP_V5 = 5; + public static int SFTP_V6 = 6; +} http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/a6e2bf9e/sshd-core/src/main/java/org/apache/sshd/common/util/io/IoUtils.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/io/IoUtils.java b/sshd-core/src/main/java/org/apache/sshd/common/util/io/IoUtils.java index 7afc506..74dd77f 100644 --- a/sshd-core/src/main/java/org/apache/sshd/common/util/io/IoUtils.java +++ b/sshd-core/src/main/java/org/apache/sshd/common/util/io/IoUtils.java @@ -312,4 +312,17 @@ public class IoUtils { return null; } + + /** + * @param path The {@link Path} to check + * @param options The {@link LinkOption}s to use when checking if path is a directory + * @return The same input path if it is a directory + * @throws UnsupportedOperationException if input path not a directory + */ + public static Path ensureDirectory(Path path, LinkOption ... options) { + if (!Files.isDirectory(path, options)) { + throw new UnsupportedOperationException("Not a directory: " + path); + } + return path; + } }
