mirror of
https://github.com/hierynomus/sshj.git
synced 2025-12-06 15:20:54 +03:00
support sftp versions < 3
This commit is contained in:
@@ -33,6 +33,7 @@ import net.schmizz.sshj.connection.channel.forwarded.RemotePortForwarder.Forward
|
|||||||
import net.schmizz.sshj.connection.channel.forwarded.X11Forwarder;
|
import net.schmizz.sshj.connection.channel.forwarded.X11Forwarder;
|
||||||
import net.schmizz.sshj.connection.channel.forwarded.X11Forwarder.X11Channel;
|
import net.schmizz.sshj.connection.channel.forwarded.X11Forwarder.X11Channel;
|
||||||
import net.schmizz.sshj.sftp.SFTPClient;
|
import net.schmizz.sshj.sftp.SFTPClient;
|
||||||
|
import net.schmizz.sshj.sftp.SFTPEngine;
|
||||||
import net.schmizz.sshj.sftp.StatefulSFTPClient;
|
import net.schmizz.sshj.sftp.StatefulSFTPClient;
|
||||||
import net.schmizz.sshj.transport.Transport;
|
import net.schmizz.sshj.transport.Transport;
|
||||||
import net.schmizz.sshj.transport.TransportException;
|
import net.schmizz.sshj.transport.TransportException;
|
||||||
@@ -592,8 +593,21 @@ public class SSHClient
|
|||||||
*/
|
*/
|
||||||
public SFTPClient newSFTPClient()
|
public SFTPClient newSFTPClient()
|
||||||
throws IOException {
|
throws IOException {
|
||||||
|
return newSFTPClient(SFTPEngine.MAX_SUPPORTED_VERSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param version the protocol version to use
|
||||||
|
*
|
||||||
|
* @return Instantiated {@link SFTPClient} implementation.
|
||||||
|
*
|
||||||
|
* @throws IOException if there is an error starting the {@code sftp} subsystem
|
||||||
|
* @see StatefulSFTPClient
|
||||||
|
*/
|
||||||
|
public SFTPClient newSFTPClient(int version)
|
||||||
|
throws IOException {
|
||||||
assert isConnected() && isAuthenticated();
|
assert isConnected() && isAuthenticated();
|
||||||
return new SFTPClient(this);
|
return new SFTPClient(new SFTPEngine(this, version).init());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -34,9 +34,11 @@ public class PacketReader
|
|||||||
private final Map<Long, Future<Response, SFTPException>> futures = new ConcurrentHashMap<Long, Future<Response, SFTPException>>();
|
private final Map<Long, Future<Response, SFTPException>> futures = new ConcurrentHashMap<Long, Future<Response, SFTPException>>();
|
||||||
private final SFTPPacket<Response> packet = new SFTPPacket<Response>();
|
private final SFTPPacket<Response> packet = new SFTPPacket<Response>();
|
||||||
private final byte[] lenBuf = new byte[4];
|
private final byte[] lenBuf = new byte[4];
|
||||||
|
private final SFTPEngine engine;
|
||||||
|
|
||||||
public PacketReader(InputStream in) {
|
public PacketReader(SFTPEngine engine) {
|
||||||
this.in = in;
|
this.engine = engine;
|
||||||
|
this.in = engine.getSubsystem().getInputStream();
|
||||||
setName("sftp reader");
|
setName("sftp reader");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,7 +80,7 @@ public class PacketReader
|
|||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
while (true) {
|
while (!isInterrupted()) {
|
||||||
readPacket();
|
readPacket();
|
||||||
handle();
|
handle();
|
||||||
}
|
}
|
||||||
@@ -90,7 +92,7 @@ public class PacketReader
|
|||||||
|
|
||||||
public void handle()
|
public void handle()
|
||||||
throws SFTPException {
|
throws SFTPException {
|
||||||
Response resp = new Response(packet);
|
Response resp = new Response(packet, engine.getOperativeProtocolVersion());
|
||||||
Future<Response, SFTPException> future = futures.remove(resp.getRequestID());
|
Future<Response, SFTPException> future = futures.remove(resp.getRequestID());
|
||||||
log.debug("Received {} packet", resp.getType());
|
log.debug("Received {} packet", resp.getType());
|
||||||
if (future == null)
|
if (future == null)
|
||||||
|
|||||||
@@ -19,11 +19,11 @@ import java.io.IOException;
|
|||||||
|
|
||||||
public class PathHelper {
|
public class PathHelper {
|
||||||
|
|
||||||
private final SFTPEngine sftp;
|
private final SFTPEngine engine;
|
||||||
private String dotDir;
|
private String dotDir;
|
||||||
|
|
||||||
public PathHelper(SFTPEngine sftp) {
|
public PathHelper(SFTPEngine engine) {
|
||||||
this.sftp = sftp;
|
this.engine = engine;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PathComponents getComponents(String path)
|
public PathComponents getComponents(String path)
|
||||||
@@ -56,7 +56,7 @@ public class PathHelper {
|
|||||||
|
|
||||||
private String canon(String path)
|
private String canon(String path)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
return sftp.canonicalize(path);
|
return engine.canonicalize(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -21,7 +21,7 @@ import org.slf4j.LoggerFactory;
|
|||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
abstract class RemoteResource
|
public abstract class RemoteResource
|
||||||
implements Closeable {
|
implements Closeable {
|
||||||
|
|
||||||
/** Logger */
|
/** Logger */
|
||||||
|
|||||||
@@ -47,15 +47,21 @@ public class Response
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final int protocolVersion;
|
||||||
private final PacketType type;
|
private final PacketType type;
|
||||||
private final long reqID;
|
private final long reqID;
|
||||||
|
|
||||||
public Response(Buffer<Response> pk) {
|
public Response(Buffer<Response> pk, int protocolVersion) {
|
||||||
super(pk);
|
super(pk);
|
||||||
|
this.protocolVersion = protocolVersion;
|
||||||
this.type = readType();
|
this.type = readType();
|
||||||
this.reqID = readLong();
|
this.reqID = readLong();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getProtocolVersion() {
|
||||||
|
return protocolVersion;
|
||||||
|
}
|
||||||
|
|
||||||
public long getRequestID() {
|
public long getRequestID() {
|
||||||
return reqID;
|
return reqID;
|
||||||
}
|
}
|
||||||
@@ -72,7 +78,7 @@ public class Response
|
|||||||
throws SFTPException {
|
throws SFTPException {
|
||||||
if (getType() != pt)
|
if (getType() != pt)
|
||||||
if (getType() == PacketType.STATUS)
|
if (getType() == PacketType.STATUS)
|
||||||
throw new SFTPException(readStatusCode(), readString());
|
error(readStatusCode());
|
||||||
else
|
else
|
||||||
throw new SFTPException("Unexpected packet " + getType());
|
throw new SFTPException("Unexpected packet " + getType());
|
||||||
return this;
|
return this;
|
||||||
@@ -85,10 +91,15 @@ public class Response
|
|||||||
|
|
||||||
public Response ensureStatusIs(StatusCode acceptable)
|
public Response ensureStatusIs(StatusCode acceptable)
|
||||||
throws SFTPException {
|
throws SFTPException {
|
||||||
StatusCode sc = readStatusCode();
|
final StatusCode sc = readStatusCode();
|
||||||
if (sc != acceptable)
|
if (sc != acceptable)
|
||||||
throw new SFTPException(sc, readString());
|
error(sc);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String error(StatusCode sc)
|
||||||
|
throws SFTPException {
|
||||||
|
throw new SFTPException(sc, protocolVersion < 3 ? sc.toString() : readString());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,6 @@
|
|||||||
*/
|
*/
|
||||||
package net.schmizz.sshj.sftp;
|
package net.schmizz.sshj.sftp;
|
||||||
|
|
||||||
import net.schmizz.sshj.connection.channel.direct.SessionFactory;
|
|
||||||
import net.schmizz.sshj.xfer.FilePermission;
|
import net.schmizz.sshj.xfer.FilePermission;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -34,19 +33,18 @@ public class SFTPClient
|
|||||||
/** Logger */
|
/** Logger */
|
||||||
protected final Logger log = LoggerFactory.getLogger(getClass());
|
protected final Logger log = LoggerFactory.getLogger(getClass());
|
||||||
|
|
||||||
private final SFTPEngine sftp;
|
private final SFTPEngine engine;
|
||||||
private final SFTPFileTransfer xfer;
|
private final SFTPFileTransfer xfer;
|
||||||
private final PathHelper pathHelper;
|
private final PathHelper pathHelper;
|
||||||
|
|
||||||
public SFTPClient(SessionFactory ssh)
|
public SFTPClient(SFTPEngine engine) {
|
||||||
throws IOException {
|
this.engine = engine;
|
||||||
this.sftp = new SFTPEngine(ssh).init();
|
this.pathHelper = new PathHelper(engine);
|
||||||
this.pathHelper = new PathHelper(sftp);
|
this.xfer = new SFTPFileTransfer(engine);
|
||||||
this.xfer = new SFTPFileTransfer(sftp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public SFTPEngine getSFTPEngine() {
|
public SFTPEngine getSFTPEngine() {
|
||||||
return sftp;
|
return engine;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SFTPFileTransfer getFileTansfer() {
|
public SFTPFileTransfer getFileTansfer() {
|
||||||
@@ -60,7 +58,7 @@ public class SFTPClient
|
|||||||
|
|
||||||
public List<RemoteResourceInfo> ls(String path, RemoteResourceFilter filter)
|
public List<RemoteResourceInfo> ls(String path, RemoteResourceFilter filter)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
final RemoteDirectory dir = sftp.openDir(path);
|
final RemoteDirectory dir = engine.openDir(path);
|
||||||
try {
|
try {
|
||||||
return dir.scan(filter);
|
return dir.scan(filter);
|
||||||
} finally {
|
} finally {
|
||||||
@@ -71,7 +69,7 @@ public class SFTPClient
|
|||||||
public RemoteFile open(String filename, Set<OpenMode> mode, FileAttributes attrs)
|
public RemoteFile open(String filename, Set<OpenMode> mode, FileAttributes attrs)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
log.debug("Opening `{}`", filename);
|
log.debug("Opening `{}`", filename);
|
||||||
return sftp.open(filename, mode, attrs);
|
return engine.open(filename, mode, attrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
public RemoteFile open(String filename, Set<OpenMode> mode)
|
public RemoteFile open(String filename, Set<OpenMode> mode)
|
||||||
@@ -86,7 +84,7 @@ public class SFTPClient
|
|||||||
|
|
||||||
public void mkdir(String dirname)
|
public void mkdir(String dirname)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
sftp.makeDir(dirname);
|
engine.makeDir(dirname);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void mkdirs(String path)
|
public void mkdirs(String path)
|
||||||
@@ -111,7 +109,7 @@ public class SFTPClient
|
|||||||
public FileAttributes statExistence(String path)
|
public FileAttributes statExistence(String path)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
try {
|
try {
|
||||||
return sftp.stat(path);
|
return engine.stat(path);
|
||||||
} catch (SFTPException sftpe) {
|
} catch (SFTPException sftpe) {
|
||||||
if (sftpe.getStatusCode() == Response.StatusCode.NO_SUCH_FILE) {
|
if (sftpe.getStatusCode() == Response.StatusCode.NO_SUCH_FILE) {
|
||||||
return null;
|
return null;
|
||||||
@@ -123,31 +121,31 @@ public class SFTPClient
|
|||||||
|
|
||||||
public void rename(String oldpath, String newpath)
|
public void rename(String oldpath, String newpath)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
sftp.rename(oldpath, newpath);
|
engine.rename(oldpath, newpath);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void rm(String filename)
|
public void rm(String filename)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
sftp.remove(filename);
|
engine.remove(filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void rmdir(String dirname)
|
public void rmdir(String dirname)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
sftp.removeDir(dirname);
|
engine.removeDir(dirname);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void symlink(String linkpath, String targetpath)
|
public void symlink(String linkpath, String targetpath)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
sftp.symlink(linkpath, targetpath);
|
engine.symlink(linkpath, targetpath);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int version() {
|
public int version() {
|
||||||
return sftp.getOperativeProtocolVersion();
|
return engine.getOperativeProtocolVersion();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setattr(String path, FileAttributes attrs)
|
public void setattr(String path, FileAttributes attrs)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
sftp.setAttributes(path, attrs);
|
engine.setAttributes(path, attrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int uid(String path)
|
public int uid(String path)
|
||||||
@@ -187,17 +185,17 @@ public class SFTPClient
|
|||||||
|
|
||||||
public String readlink(String path)
|
public String readlink(String path)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
return sftp.readLink(path);
|
return engine.readLink(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
public FileAttributes stat(String path)
|
public FileAttributes stat(String path)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
return sftp.stat(path);
|
return engine.stat(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
public FileAttributes lstat(String path)
|
public FileAttributes lstat(String path)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
return sftp.lstat(path);
|
return engine.lstat(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void chown(String path, int uid)
|
public void chown(String path, int uid)
|
||||||
@@ -222,7 +220,7 @@ public class SFTPClient
|
|||||||
|
|
||||||
public String canonicalize(String path)
|
public String canonicalize(String path)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
return sftp.canonicalize(path);
|
return engine.canonicalize(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
public long size(String path)
|
public long size(String path)
|
||||||
@@ -243,7 +241,7 @@ public class SFTPClient
|
|||||||
@Override
|
@Override
|
||||||
public void close()
|
public void close()
|
||||||
throws IOException {
|
throws IOException {
|
||||||
sftp.close();
|
engine.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,37 +33,41 @@ import java.util.concurrent.TimeUnit;
|
|||||||
public class SFTPEngine
|
public class SFTPEngine
|
||||||
implements Requester, Closeable {
|
implements Requester, Closeable {
|
||||||
|
|
||||||
/** Logger */
|
public static final int MAX_SUPPORTED_VERSION = 3;
|
||||||
private final Logger log = LoggerFactory.getLogger(getClass());
|
|
||||||
|
|
||||||
public static final int PROTOCOL_VERSION = 3;
|
|
||||||
|
|
||||||
public static final int DEFAULT_TIMEOUT = 30;
|
public static final int DEFAULT_TIMEOUT = 30;
|
||||||
|
|
||||||
private volatile int timeout = DEFAULT_TIMEOUT;
|
/** Logger */
|
||||||
|
protected final Logger log = LoggerFactory.getLogger(getClass());
|
||||||
|
|
||||||
private final Subsystem sub;
|
protected volatile int timeout = DEFAULT_TIMEOUT;
|
||||||
private final PacketReader reader;
|
|
||||||
private final OutputStream out;
|
|
||||||
|
|
||||||
private long reqID;
|
protected final int clientVersion;
|
||||||
private int negotiatedVersion;
|
protected final Subsystem sub;
|
||||||
private final Map<String, String> serverExtensions = new HashMap<String, String>();
|
protected final PacketReader reader;
|
||||||
|
protected final OutputStream out;
|
||||||
|
|
||||||
|
protected long reqID;
|
||||||
|
protected int operativeVersion;
|
||||||
|
protected final Map<String, String> serverExtensions = new HashMap<String, String>();
|
||||||
|
|
||||||
public SFTPEngine(SessionFactory ssh)
|
public SFTPEngine(SessionFactory ssh)
|
||||||
throws SSHException {
|
throws SSHException {
|
||||||
sub = ssh.startSession().startSubsystem("sftp");
|
this(ssh, MAX_SUPPORTED_VERSION);
|
||||||
out = sub.getOutputStream();
|
|
||||||
reader = new PacketReader(sub.getInputStream());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Subsystem getSubsystem() {
|
public SFTPEngine(SessionFactory ssh, int clientVersion)
|
||||||
return sub;
|
throws SSHException {
|
||||||
|
if (clientVersion > MAX_SUPPORTED_VERSION)
|
||||||
|
throw new SFTPException("Max. supported protocol version is: " + MAX_SUPPORTED_VERSION);
|
||||||
|
this.clientVersion = clientVersion;
|
||||||
|
sub = ssh.startSession().startSubsystem("sftp");
|
||||||
|
out = sub.getOutputStream();
|
||||||
|
reader = new PacketReader(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SFTPEngine init()
|
public SFTPEngine init()
|
||||||
throws IOException {
|
throws IOException {
|
||||||
transmit(new SFTPPacket<Request>(PacketType.INIT).putInt(PROTOCOL_VERSION));
|
transmit(new SFTPPacket<Request>(PacketType.INIT).putInt(clientVersion));
|
||||||
|
|
||||||
final SFTPPacket<Response> response = reader.readPacket();
|
final SFTPPacket<Response> response = reader.readPacket();
|
||||||
|
|
||||||
@@ -71,10 +75,10 @@ public class SFTPEngine
|
|||||||
if (type != PacketType.VERSION)
|
if (type != PacketType.VERSION)
|
||||||
throw new SFTPException("Expected INIT packet, received: " + type);
|
throw new SFTPException("Expected INIT packet, received: " + type);
|
||||||
|
|
||||||
negotiatedVersion = response.readInt();
|
operativeVersion = response.readInt();
|
||||||
log.info("Client version {}, server version {}", PROTOCOL_VERSION, negotiatedVersion);
|
log.info("Client version {}, server version {}", clientVersion, operativeVersion);
|
||||||
if (negotiatedVersion < PROTOCOL_VERSION)
|
if (operativeVersion < clientVersion)
|
||||||
throw new SFTPException("Server reported protocol version: " + negotiatedVersion);
|
throw new SFTPException("Server reported protocol version: " + operativeVersion);
|
||||||
|
|
||||||
while (response.available() > 0)
|
while (response.available() > 0)
|
||||||
serverExtensions.put(response.readString(), response.readString());
|
serverExtensions.put(response.readString(), response.readString());
|
||||||
@@ -84,8 +88,16 @@ public class SFTPEngine
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Subsystem getSubsystem() {
|
||||||
|
return sub;
|
||||||
|
}
|
||||||
|
|
||||||
public int getOperativeProtocolVersion() {
|
public int getOperativeProtocolVersion() {
|
||||||
return negotiatedVersion;
|
return operativeVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Request newExtendedRequest(String reqName) {
|
||||||
|
return newRequest(PacketType.EXTENDED).putString(reqName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -102,17 +114,6 @@ public class SFTPEngine
|
|||||||
return req.getResponseFuture().get(timeout, TimeUnit.SECONDS);
|
return req.getResponseFuture().get(timeout, TimeUnit.SECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void transmit(SFTPPacket<Request> payload)
|
|
||||||
throws IOException {
|
|
||||||
final int len = payload.available();
|
|
||||||
out.write((len >>> 24) & 0xff);
|
|
||||||
out.write((len >>> 16) & 0xff);
|
|
||||||
out.write((len >>> 8) & 0xff);
|
|
||||||
out.write(len & 0xff);
|
|
||||||
out.write(payload.array(), payload.rpos(), len);
|
|
||||||
out.flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
public RemoteFile open(String path, Set<OpenMode> modes, FileAttributes fa)
|
public RemoteFile open(String path, Set<OpenMode> modes, FileAttributes fa)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
final String handle = doRequest(
|
final String handle = doRequest(
|
||||||
@@ -148,6 +149,8 @@ public class SFTPEngine
|
|||||||
|
|
||||||
public String readLink(String path)
|
public String readLink(String path)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
|
if (operativeVersion < 3)
|
||||||
|
throw new SFTPException("READLINK is not supported in SFTPv" + operativeVersion);
|
||||||
return readSingleName(
|
return readSingleName(
|
||||||
doRequest(
|
doRequest(
|
||||||
newRequest(PacketType.READLINK).putString(path)
|
newRequest(PacketType.READLINK).putString(path)
|
||||||
@@ -166,6 +169,8 @@ public class SFTPEngine
|
|||||||
|
|
||||||
public void symlink(String linkpath, String targetpath)
|
public void symlink(String linkpath, String targetpath)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
|
if (operativeVersion < 3)
|
||||||
|
throw new SFTPException("SYMLINK is not supported in SFTPv" + operativeVersion);
|
||||||
doRequest(
|
doRequest(
|
||||||
newRequest(PacketType.SYMLINK).putString(linkpath).putString(targetpath)
|
newRequest(PacketType.SYMLINK).putString(linkpath).putString(targetpath)
|
||||||
).ensureStatusPacketIsOK();
|
).ensureStatusPacketIsOK();
|
||||||
@@ -185,13 +190,6 @@ public class SFTPEngine
|
|||||||
).ensureStatusIs(Response.StatusCode.OK);
|
).ensureStatusIs(Response.StatusCode.OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
private FileAttributes stat(PacketType pt, String path)
|
|
||||||
throws IOException {
|
|
||||||
return doRequest(newRequest(pt).putString(path))
|
|
||||||
.ensurePacketTypeIs(PacketType.ATTRS)
|
|
||||||
.readFileAttributes();
|
|
||||||
}
|
|
||||||
|
|
||||||
public FileAttributes stat(String path)
|
public FileAttributes stat(String path)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
return stat(PacketType.STAT, path);
|
return stat(PacketType.STAT, path);
|
||||||
@@ -204,6 +202,8 @@ public class SFTPEngine
|
|||||||
|
|
||||||
public void rename(String oldPath, String newPath)
|
public void rename(String oldPath, String newPath)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
|
if (operativeVersion < 1)
|
||||||
|
throw new SFTPException("RENAME is not supported in SFTPv" + operativeVersion);
|
||||||
doRequest(
|
doRequest(
|
||||||
newRequest(PacketType.RENAME).putString(oldPath).putString(newPath)
|
newRequest(PacketType.RENAME).putString(oldPath).putString(newPath)
|
||||||
).ensureStatusPacketIsOK();
|
).ensureStatusPacketIsOK();
|
||||||
@@ -217,15 +217,6 @@ public class SFTPEngine
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String readSingleName(Response res)
|
|
||||||
throws IOException {
|
|
||||||
res.ensurePacketTypeIs(PacketType.NAME);
|
|
||||||
if (res.readInt() == 1)
|
|
||||||
return res.readString();
|
|
||||||
else
|
|
||||||
throw new SFTPException("Unexpected data in " + res.getType() + " packet");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTimeout(int timeout) {
|
public void setTimeout(int timeout) {
|
||||||
this.timeout = timeout;
|
this.timeout = timeout;
|
||||||
}
|
}
|
||||||
@@ -240,4 +231,31 @@ public class SFTPEngine
|
|||||||
sub.close();
|
sub.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected FileAttributes stat(PacketType pt, String path)
|
||||||
|
throws IOException {
|
||||||
|
return doRequest(newRequest(pt).putString(path))
|
||||||
|
.ensurePacketTypeIs(PacketType.ATTRS)
|
||||||
|
.readFileAttributes();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static String readSingleName(Response res)
|
||||||
|
throws IOException {
|
||||||
|
res.ensurePacketTypeIs(PacketType.NAME);
|
||||||
|
if (res.readInt() == 1)
|
||||||
|
return res.readString();
|
||||||
|
else
|
||||||
|
throw new SFTPException("Unexpected data in " + res.getType() + " packet");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected synchronized void transmit(SFTPPacket<Request> payload)
|
||||||
|
throws IOException {
|
||||||
|
final int len = payload.available();
|
||||||
|
out.write((len >>> 24) & 0xff);
|
||||||
|
out.write((len >>> 16) & 0xff);
|
||||||
|
out.write((len >>> 8) & 0xff);
|
||||||
|
out.write(len & 0xff);
|
||||||
|
out.write(payload.array(), payload.rpos(), len);
|
||||||
|
out.flush();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,7 +67,6 @@ public class SFTPException
|
|||||||
|
|
||||||
public StatusCode getStatusCode() {
|
public StatusCode getStatusCode() {
|
||||||
return (sc == null) ? StatusCode.UNKNOWN : sc;
|
return (sc == null) ? StatusCode.UNKNOWN : sc;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public SFTPException(StatusCode sc, String msg) {
|
public SFTPException(StatusCode sc, String msg) {
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ public class SFTPFileTransfer
|
|||||||
extends AbstractFileTransfer
|
extends AbstractFileTransfer
|
||||||
implements FileTransfer {
|
implements FileTransfer {
|
||||||
|
|
||||||
private final SFTPEngine sftp;
|
private final SFTPEngine engine;
|
||||||
private final PathHelper pathHelper;
|
private final PathHelper pathHelper;
|
||||||
|
|
||||||
private volatile FileFilter uploadFilter = defaultLocalFilter;
|
private volatile FileFilter uploadFilter = defaultLocalFilter;
|
||||||
@@ -53,9 +53,9 @@ public class SFTPFileTransfer
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public SFTPFileTransfer(SFTPEngine sftp) {
|
public SFTPFileTransfer(SFTPEngine engine) {
|
||||||
this.sftp = sftp;
|
this.engine = engine;
|
||||||
this.pathHelper = new PathHelper(sftp);
|
this.pathHelper = new PathHelper(engine);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -68,7 +68,7 @@ public class SFTPFileTransfer
|
|||||||
public void download(String source, String dest)
|
public void download(String source, String dest)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
final PathComponents pathComponents = pathHelper.getComponents(source);
|
final PathComponents pathComponents = pathHelper.getComponents(source);
|
||||||
final FileAttributes attributes = sftp.stat(source);
|
final FileAttributes attributes = engine.stat(source);
|
||||||
new Downloader().download(new RemoteResourceInfo(pathComponents, attributes), new File(dest));
|
new Downloader().download(new RemoteResourceInfo(pathComponents, attributes), new File(dest));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,7 +119,7 @@ public class SFTPFileTransfer
|
|||||||
private File downloadDir(final RemoteResourceInfo remote, final File local)
|
private File downloadDir(final RemoteResourceInfo remote, final File local)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
final File adjusted = FileTransferUtil.getTargetDirectory(local, remote.getName());
|
final File adjusted = FileTransferUtil.getTargetDirectory(local, remote.getName());
|
||||||
final RemoteDirectory rd = sftp.openDir(remote.getPath());
|
final RemoteDirectory rd = engine.openDir(remote.getPath());
|
||||||
try {
|
try {
|
||||||
for (RemoteResourceInfo rri : rd.scan(getDownloadFilter()))
|
for (RemoteResourceInfo rri : rd.scan(getDownloadFilter()))
|
||||||
download(rri, new File(adjusted.getPath(), rri.getName()));
|
download(rri, new File(adjusted.getPath(), rri.getName()));
|
||||||
@@ -132,11 +132,11 @@ public class SFTPFileTransfer
|
|||||||
private File downloadFile(final RemoteResourceInfo remote, final File local)
|
private File downloadFile(final RemoteResourceInfo remote, final File local)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
final File adjusted = FileTransferUtil.getTargetFile(local, remote.getName());
|
final File adjusted = FileTransferUtil.getTargetFile(local, remote.getName());
|
||||||
final RemoteFile rf = sftp.open(remote.getPath());
|
final RemoteFile rf = engine.open(remote.getPath());
|
||||||
try {
|
try {
|
||||||
final FileOutputStream fos = new FileOutputStream(adjusted);
|
final FileOutputStream fos = new FileOutputStream(adjusted);
|
||||||
try {
|
try {
|
||||||
StreamCopier.copy(rf.getInputStream(), fos, sftp.getSubsystem()
|
StreamCopier.copy(rf.getInputStream(), fos, engine.getSubsystem()
|
||||||
.getLocalMaxPacketSize(), false, listener);
|
.getLocalMaxPacketSize(), false, listener);
|
||||||
} finally {
|
} finally {
|
||||||
fos.close();
|
fos.close();
|
||||||
@@ -176,7 +176,7 @@ public class SFTPFileTransfer
|
|||||||
listener.finishedFile();
|
listener.finishedFile();
|
||||||
} else
|
} else
|
||||||
throw new IOException(local + " is not a file or directory");
|
throw new IOException(local + " is not a file or directory");
|
||||||
sftp.setAttributes(adjustedPath, getAttributes(local));
|
engine.setAttributes(adjustedPath, getAttributes(local));
|
||||||
}
|
}
|
||||||
|
|
||||||
private String uploadDir(File local, String remote)
|
private String uploadDir(File local, String remote)
|
||||||
@@ -190,13 +190,13 @@ public class SFTPFileTransfer
|
|||||||
private String uploadFile(File local, String remote)
|
private String uploadFile(File local, String remote)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
final String adjusted = prepareFile(local, remote);
|
final String adjusted = prepareFile(local, remote);
|
||||||
final RemoteFile rf = sftp.open(adjusted, EnumSet.of(OpenMode.WRITE,
|
final RemoteFile rf = engine.open(adjusted, EnumSet.of(OpenMode.WRITE,
|
||||||
OpenMode.CREAT,
|
OpenMode.CREAT,
|
||||||
OpenMode.TRUNC));
|
OpenMode.TRUNC));
|
||||||
try {
|
try {
|
||||||
final FileInputStream fis = new FileInputStream(local);
|
final FileInputStream fis = new FileInputStream(local);
|
||||||
try {
|
try {
|
||||||
final int bufSize = sftp.getSubsystem().getRemoteMaxPacketSize() - rf.getOutgoingPacketOverhead();
|
final int bufSize = engine.getSubsystem().getRemoteMaxPacketSize() - rf.getOutgoingPacketOverhead();
|
||||||
StreamCopier.copy(fis, rf.getOutputStream(), bufSize, false, listener);
|
StreamCopier.copy(fis, rf.getOutputStream(), bufSize, false, listener);
|
||||||
} finally {
|
} finally {
|
||||||
fis.close();
|
fis.close();
|
||||||
@@ -211,11 +211,11 @@ public class SFTPFileTransfer
|
|||||||
throws IOException {
|
throws IOException {
|
||||||
final FileAttributes attrs;
|
final FileAttributes attrs;
|
||||||
try {
|
try {
|
||||||
attrs = sftp.stat(remote);
|
attrs = engine.stat(remote);
|
||||||
} catch (SFTPException e) {
|
} catch (SFTPException e) {
|
||||||
if (e.getStatusCode() == StatusCode.NO_SUCH_FILE) {
|
if (e.getStatusCode() == StatusCode.NO_SUCH_FILE) {
|
||||||
log.debug("probeDir: {} does not exist, creating", remote);
|
log.debug("probeDir: {} does not exist, creating", remote);
|
||||||
sftp.makeDir(remote);
|
engine.makeDir(remote);
|
||||||
return remote;
|
return remote;
|
||||||
} else
|
} else
|
||||||
throw e;
|
throw e;
|
||||||
@@ -237,7 +237,7 @@ public class SFTPFileTransfer
|
|||||||
throws IOException {
|
throws IOException {
|
||||||
final FileAttributes attrs;
|
final FileAttributes attrs;
|
||||||
try {
|
try {
|
||||||
attrs = sftp.stat(remote);
|
attrs = engine.stat(remote);
|
||||||
} catch (SFTPException e) {
|
} catch (SFTPException e) {
|
||||||
if (e.getStatusCode() == StatusCode.NO_SUCH_FILE) {
|
if (e.getStatusCode() == StatusCode.NO_SUCH_FILE) {
|
||||||
log.debug("probeFile: {} does not exist", remote);
|
log.debug("probeFile: {} does not exist", remote);
|
||||||
|
|||||||
@@ -15,8 +15,6 @@
|
|||||||
*/
|
*/
|
||||||
package net.schmizz.sshj.sftp;
|
package net.schmizz.sshj.sftp;
|
||||||
|
|
||||||
import net.schmizz.sshj.connection.channel.direct.SessionFactory;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@@ -26,9 +24,9 @@ public class StatefulSFTPClient
|
|||||||
|
|
||||||
private String cwd;
|
private String cwd;
|
||||||
|
|
||||||
public StatefulSFTPClient(SessionFactory ssh)
|
public StatefulSFTPClient(SFTPEngine engine)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
super(ssh);
|
super(engine);
|
||||||
this.cwd = getSFTPEngine().canonicalize(".");
|
this.cwd = getSFTPEngine().canonicalize(".");
|
||||||
log.info("Start dir = " + cwd);
|
log.info("Start dir = " + cwd);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user