sftp reformat

This commit is contained in:
Shikhar Bhushan
2010-03-01 23:41:19 +01:00
parent 8ec5055615
commit 5335c282dc
17 changed files with 341 additions and 180 deletions

View File

@@ -27,7 +27,11 @@ public final class FileAttributes {
public static enum Flag { public static enum Flag {
SIZE(0x00000001), UIDGID(0x00000002), MODE(0x00000004), ACMODTIME(0x00000008), EXTENDED(0x80000000); SIZE(0x00000001),
UIDGID(0x00000002),
MODE(0x00000004),
ACMODTIME(0x00000008),
EXTENDED(0x80000000);
private final int flag; private final int flag;

View File

@@ -24,7 +24,8 @@ import java.io.InputStream;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
public class PacketReader extends Thread { public class PacketReader
extends Thread {
/** Logger */ /** Logger */
private final Logger log = LoggerFactory.getLogger(getClass()); private final Logger log = LoggerFactory.getLogger(getClass());
@@ -39,7 +40,8 @@ public class PacketReader extends Thread {
setName("sftp reader"); setName("sftp reader");
} }
private void readIntoBuffer(byte[] buf, int off, int len) throws IOException { private void readIntoBuffer(byte[] buf, int off, int len)
throws IOException {
int count = 0; int count = 0;
int read = 0; int read = 0;
while (count < len && ((read = in.read(buf, off + count, len - count)) != -1)) while (count < len && ((read = in.read(buf, off + count, len - count)) != -1))
@@ -48,17 +50,18 @@ public class PacketReader extends Thread {
throw new SFTPException("EOF while reading packet"); throw new SFTPException("EOF while reading packet");
} }
private int getPacketLength() throws IOException { private int getPacketLength()
throws IOException {
readIntoBuffer(lenBuf, 0, lenBuf.length); readIntoBuffer(lenBuf, 0, lenBuf.length);
return (int) (lenBuf[0] << 24 & 0xff000000L return (int) (lenBuf[0] << 24 & 0xff000000L
| lenBuf[1] << 16 & 0x00ff0000L | lenBuf[1] << 16 & 0x00ff0000L
| lenBuf[2] << 8 & 0x0000ff00L | lenBuf[2] << 8 & 0x0000ff00L
| lenBuf[3] & 0x000000ffL | lenBuf[3] & 0x000000ffL);
);
} }
public SFTPPacket<Response> readPacket() throws IOException { public SFTPPacket<Response> readPacket()
throws IOException {
int len = getPacketLength(); int len = getPacketLength();
packet.rpos(0); packet.rpos(0);
@@ -85,7 +88,8 @@ public class PacketReader extends Thread {
} }
} }
public void handle() throws SFTPException { public void handle()
throws SFTPException {
Response resp = new Response(packet); Response resp = new Response(packet);
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());

View File

@@ -26,7 +26,8 @@ class PathHelper {
this.sftp = sftp; this.sftp = sftp;
} }
public PathComponents getComponents(String path) throws IOException { public PathComponents getComponents(String path)
throws IOException {
if (path.isEmpty() || path.equals(".")) if (path.isEmpty() || path.equals("."))
return getComponents(getDotDir()); return getComponents(getDotDir());
@@ -48,11 +49,13 @@ class PathHelper {
} }
} }
private String getDotDir() throws IOException { private String getDotDir()
throws IOException {
return (dotDir != null) ? dotDir : (dotDir = canon(".")); return (dotDir != null) ? dotDir : (dotDir = canon("."));
} }
private String canon(String path) throws IOException { private String canon(String path)
throws IOException {
return sftp.canonicalize(path); return sftp.canonicalize(path);
} }

View File

@@ -22,7 +22,8 @@ import java.io.DataOutputStream;
import java.io.EOFException; import java.io.EOFException;
import java.io.IOException; import java.io.IOException;
public class RandomAccessRemoteFile implements DataInput, DataOutput { public class RandomAccessRemoteFile
implements DataInput, DataOutput {
private final byte[] singleByte = new byte[1]; private final byte[] singleByte = new byte[1];
@@ -43,35 +44,41 @@ public class RandomAccessRemoteFile implements DataInput, DataOutput {
this.fp = fp; this.fp = fp;
} }
public int read() throws IOException { public int read()
throws IOException {
return read(singleByte, 0, 1) == -1 ? -1 : singleByte[0]; return read(singleByte, 0, 1) == -1 ? -1 : singleByte[0];
} }
public int read(byte[] b) throws IOException { public int read(byte[] b)
throws IOException {
return read(b, 0, b.length); return read(b, 0, b.length);
} }
public int read(byte[] b, int off, int len) throws IOException { public int read(byte[] b, int off, int len)
throws IOException {
final int count = rf.read(fp, b, off, len); final int count = rf.read(fp, b, off, len);
fp += count; fp += count;
return count; return count;
} }
public boolean readBoolean() throws IOException { public boolean readBoolean()
throws IOException {
final int ch = read(); final int ch = read();
if (ch < 0) if (ch < 0)
throw new EOFException(); throw new EOFException();
return (ch != 0); return (ch != 0);
} }
public byte readByte() throws IOException { public byte readByte()
throws IOException {
final int ch = this.read(); final int ch = this.read();
if (ch < 0) if (ch < 0)
throw new EOFException(); throw new EOFException();
return (byte) (ch); return (byte) (ch);
} }
public char readChar() throws IOException { public char readChar()
throws IOException {
final int ch1 = this.read(); final int ch1 = this.read();
final int ch2 = this.read(); final int ch2 = this.read();
if ((ch1 | ch2) < 0) if ((ch1 | ch2) < 0)
@@ -79,19 +86,23 @@ public class RandomAccessRemoteFile implements DataInput, DataOutput {
return (char) ((ch1 << 8) + ch2); return (char) ((ch1 << 8) + ch2);
} }
public double readDouble() throws IOException { public double readDouble()
throws IOException {
return Double.longBitsToDouble(readLong()); return Double.longBitsToDouble(readLong());
} }
public float readFloat() throws IOException { public float readFloat()
throws IOException {
return Float.intBitsToFloat(readInt()); return Float.intBitsToFloat(readInt());
} }
public void readFully(byte[] b) throws IOException { public void readFully(byte[] b)
throws IOException {
readFully(b, 0, b.length); readFully(b, 0, b.length);
} }
public void readFully(byte[] b, int off, int len) throws IOException { public void readFully(byte[] b, int off, int len)
throws IOException {
int n = 0; int n = 0;
do { do {
int count = read(b, off + n, len - n); int count = read(b, off + n, len - n);
@@ -101,7 +112,8 @@ public class RandomAccessRemoteFile implements DataInput, DataOutput {
} while (n < len); } while (n < len);
} }
public int readInt() throws IOException { public int readInt()
throws IOException {
final int ch1 = read(); final int ch1 = read();
final int ch2 = read(); final int ch2 = read();
final int ch3 = read(); final int ch3 = read();
@@ -111,7 +123,8 @@ public class RandomAccessRemoteFile implements DataInput, DataOutput {
return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + ch4); return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + ch4);
} }
public String readLine() throws IOException { public String readLine()
throws IOException {
StringBuffer input = new StringBuffer(); StringBuffer input = new StringBuffer();
int c = -1; int c = -1;
boolean eol = false; boolean eol = false;
@@ -138,11 +151,13 @@ public class RandomAccessRemoteFile implements DataInput, DataOutput {
return input.toString(); return input.toString();
} }
public long readLong() throws IOException { public long readLong()
throws IOException {
return ((long) (readInt()) << 32) + (readInt() & 0xFFFFFFFFL); return ((long) (readInt()) << 32) + (readInt() & 0xFFFFFFFFL);
} }
public short readShort() throws IOException { public short readShort()
throws IOException {
final int ch1 = this.read(); final int ch1 = this.read();
final int ch2 = this.read(); final int ch2 = this.read();
if ((ch1 | ch2) < 0) if ((ch1 | ch2) < 0)
@@ -150,18 +165,21 @@ public class RandomAccessRemoteFile implements DataInput, DataOutput {
return (short) ((ch1 << 8) + ch2); return (short) ((ch1 << 8) + ch2);
} }
public String readUTF() throws IOException { public String readUTF()
throws IOException {
return DataInputStream.readUTF(this); return DataInputStream.readUTF(this);
} }
public int readUnsignedByte() throws IOException { public int readUnsignedByte()
throws IOException {
final int ch = this.read(); final int ch = this.read();
if (ch < 0) if (ch < 0)
throw new EOFException(); throw new EOFException();
return ch; return ch;
} }
public int readUnsignedShort() throws IOException { public int readUnsignedShort()
throws IOException {
final int ch1 = this.read(); final int ch1 = this.read();
final int ch2 = this.read(); final int ch2 = this.read();
if ((ch1 | ch2) < 0) if ((ch1 | ch2) < 0)
@@ -169,7 +187,8 @@ public class RandomAccessRemoteFile implements DataInput, DataOutput {
return (ch1 << 8) + ch2; return (ch1 << 8) + ch2;
} }
public int skipBytes(int n) throws IOException { public int skipBytes(int n)
throws IOException {
if (n <= 0) if (n <= 0)
return 0; return 0;
final long pos = getFilePointer(); final long pos = getFilePointer();
@@ -183,39 +202,47 @@ public class RandomAccessRemoteFile implements DataInput, DataOutput {
return (int) (newpos - pos); return (int) (newpos - pos);
} }
public void write(int i) throws IOException { public void write(int i)
throws IOException {
singleByte[0] = (byte) i; singleByte[0] = (byte) i;
write(singleByte); write(singleByte);
} }
public void write(byte[] b) throws IOException { public void write(byte[] b)
throws IOException {
write(b, 0, b.length); write(b, 0, b.length);
} }
public void write(byte[] b, int off, int len) throws IOException { public void write(byte[] b, int off, int len)
throws IOException {
rf.write(fp, b, off, len); rf.write(fp, b, off, len);
fp += (len - off); fp += (len - off);
} }
public void writeBoolean(boolean v) throws IOException { public void writeBoolean(boolean v)
throws IOException {
write(v ? 1 : 0); write(v ? 1 : 0);
} }
public void writeByte(int v) throws IOException { public void writeByte(int v)
throws IOException {
write(v); write(v);
} }
public void writeBytes(String s) throws IOException { public void writeBytes(String s)
throws IOException {
final byte[] b = s.getBytes(); final byte[] b = s.getBytes();
write(b, 0, b.length); write(b, 0, b.length);
} }
public void writeChar(int v) throws IOException { public void writeChar(int v)
throws IOException {
write((v >>> 8) & 0xFF); write((v >>> 8) & 0xFF);
write(v & 0xFF); write(v & 0xFF);
} }
public void writeChars(String s) throws IOException { public void writeChars(String s)
throws IOException {
final int clen = s.length(); final int clen = s.length();
final int blen = 2 * clen; final int blen = 2 * clen;
final byte[] b = new byte[blen]; final byte[] b = new byte[blen];
@@ -228,22 +255,26 @@ public class RandomAccessRemoteFile implements DataInput, DataOutput {
write(b, 0, blen); write(b, 0, blen);
} }
public void writeDouble(double v) throws IOException { public void writeDouble(double v)
throws IOException {
writeLong(Double.doubleToLongBits(v)); writeLong(Double.doubleToLongBits(v));
} }
public void writeFloat(float v) throws IOException { public void writeFloat(float v)
throws IOException {
writeInt(Float.floatToIntBits(v)); writeInt(Float.floatToIntBits(v));
} }
public void writeInt(int v) throws IOException { public void writeInt(int v)
throws IOException {
write((v >>> 24) & 0xFF); write((v >>> 24) & 0xFF);
write((v >>> 16) & 0xFF); write((v >>> 16) & 0xFF);
write((v >>> 8) & 0xFF); write((v >>> 8) & 0xFF);
write(v & 0xFF); write(v & 0xFF);
} }
public void writeLong(long v) throws IOException { public void writeLong(long v)
throws IOException {
write((int) (v >>> 56) & 0xFF); write((int) (v >>> 56) & 0xFF);
write((int) (v >>> 48) & 0xFF); write((int) (v >>> 48) & 0xFF);
write((int) (v >>> 40) & 0xFF); write((int) (v >>> 40) & 0xFF);
@@ -254,12 +285,14 @@ public class RandomAccessRemoteFile implements DataInput, DataOutput {
write((int) v & 0xFF); write((int) v & 0xFF);
} }
public void writeShort(int v) throws IOException { public void writeShort(int v)
throws IOException {
write((v >>> 8) & 0xFF); write((v >>> 8) & 0xFF);
write(v & 0xFF); write(v & 0xFF);
} }
public void writeUTF(String str) throws IOException { public void writeUTF(String str)
throws IOException {
final DataOutputStream dos = new DataOutputStream(rf.new RemoteFileOutputStream(fp)); final DataOutputStream dos = new DataOutputStream(rf.new RemoteFileOutputStream(fp));
try { try {
dos.writeUTF(str); dos.writeUTF(str);

View File

@@ -21,13 +21,15 @@ import java.io.IOException;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
public class RemoteDirectory extends RemoteResource { public class RemoteDirectory
extends RemoteResource {
public RemoteDirectory(Requester requester, String path, String handle) { public RemoteDirectory(Requester requester, String path, String handle) {
super(requester, path, handle); super(requester, path, handle);
} }
public List<RemoteResourceInfo> scan(RemoteResourceFilter filter) throws IOException { public List<RemoteResourceInfo> scan(RemoteResourceFilter filter)
throws IOException {
List<RemoteResourceInfo> rri = new LinkedList<RemoteResourceInfo>(); List<RemoteResourceInfo> rri = new LinkedList<RemoteResourceInfo>();
loop: loop:
for (; ;) { for (; ;) {

View File

@@ -21,7 +21,8 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
public class RemoteFile extends RemoteResource { public class RemoteFile
extends RemoteResource {
public RemoteFile(Requester requester, String path, String handle) { public RemoteFile(Requester requester, String path, String handle) {
super(requester, path, handle); super(requester, path, handle);
@@ -35,21 +36,25 @@ public class RemoteFile extends RemoteResource {
return new RemoteFileOutputStream(); return new RemoteFileOutputStream();
} }
public FileAttributes fetchAttributes() throws IOException { public FileAttributes fetchAttributes()
throws IOException {
return requester.doRequest(newRequest(PacketType.FSTAT)) // return requester.doRequest(newRequest(PacketType.FSTAT)) //
.ensurePacketTypeIs(PacketType.ATTRS) // .ensurePacketTypeIs(PacketType.ATTRS) //
.readFileAttributes(); .readFileAttributes();
} }
public long length() throws IOException { public long length()
throws IOException {
return fetchAttributes().getSize(); return fetchAttributes().getSize();
} }
public void setLength(long len) throws IOException { public void setLength(long len)
throws IOException {
setAttributes(new FileAttributes.Builder().withSize(len).build()); setAttributes(new FileAttributes.Builder().withSize(len).build());
} }
public int read(long fileOffset, byte[] to, int offset, int len) throws IOException { public int read(long fileOffset, byte[] to, int offset, int len)
throws IOException {
Response res = requester.doRequest(newRequest(PacketType.READ).putUINT64(fileOffset).putInt(len)); Response res = requester.doRequest(newRequest(PacketType.READ).putUINT64(fileOffset).putInt(len));
switch (res.getType()) { switch (res.getType()) {
case DATA: case DATA:
@@ -66,7 +71,8 @@ public class RemoteFile extends RemoteResource {
} }
} }
public void write(long fileOffset, byte[] data, int off, int len) throws IOException { public void write(long fileOffset, byte[] data, int off, int len)
throws IOException {
requester.doRequest( // requester.doRequest( //
newRequest(PacketType.WRITE) // newRequest(PacketType.WRITE) //
.putUINT64(fileOffset) // .putUINT64(fileOffset) //
@@ -75,7 +81,8 @@ public class RemoteFile extends RemoteResource {
).ensureStatusPacketIsOK(); ).ensureStatusPacketIsOK();
} }
public void setAttributes(FileAttributes attrs) throws IOException { public void setAttributes(FileAttributes attrs)
throws IOException {
requester.doRequest(newRequest(PacketType.FSETSTAT).putFileAttributes(attrs)).ensureStatusPacketIsOK(); requester.doRequest(newRequest(PacketType.FSETSTAT).putFileAttributes(attrs)).ensureStatusPacketIsOK();
} }
@@ -89,7 +96,8 @@ public class RemoteFile extends RemoteResource {
4; // packet length 4; // packet length
} }
public class RemoteFileOutputStream extends OutputStream { public class RemoteFileOutputStream
extends OutputStream {
private final byte[] b = new byte[1]; private final byte[] b = new byte[1];
@@ -105,20 +113,23 @@ public class RemoteFile extends RemoteResource {
} }
@Override @Override
public void write(int w) throws IOException { public void write(int w)
throws IOException {
b[0] = (byte) w; b[0] = (byte) w;
write(b, 0, 1); write(b, 0, 1);
} }
@Override @Override
public void write(byte[] buf, int off, int len) throws IOException { public void write(byte[] buf, int off, int len)
throws IOException {
RemoteFile.this.write(fileOffset, buf, off, len); RemoteFile.this.write(fileOffset, buf, off, len);
fileOffset += len; fileOffset += len;
} }
} }
public class RemoteFileInputStream extends InputStream { public class RemoteFileInputStream
extends InputStream {
private final byte[] b = new byte[1]; private final byte[] b = new byte[1];
@@ -146,22 +157,26 @@ public class RemoteFile extends RemoteResource {
} }
@Override @Override
public void reset() throws IOException { public void reset()
throws IOException {
fileOffset = markPos; fileOffset = markPos;
} }
@Override @Override
public long skip(long n) throws IOException { public long skip(long n)
throws IOException {
return (this.fileOffset = Math.min(fileOffset + n, length())); return (this.fileOffset = Math.min(fileOffset + n, length()));
} }
@Override @Override
public int read() throws IOException { public int read()
throws IOException {
return read(b, 0, 1) == -1 ? -1 : b[0]; return read(b, 0, 1) == -1 ? -1 : b[0];
} }
@Override @Override
public int read(byte[] into, int off, int len) throws IOException { public int read(byte[] into, int off, int len)
throws IOException {
int read = RemoteFile.this.read(fileOffset, into, off, len); int read = RemoteFile.this.read(fileOffset, into, off, len);
if (read != -1) { if (read != -1) {
fileOffset += read; fileOffset += read;

View File

@@ -21,7 +21,8 @@ import org.slf4j.LoggerFactory;
import java.io.Closeable; import java.io.Closeable;
import java.io.IOException; import java.io.IOException;
abstract class RemoteResource implements Closeable { abstract class RemoteResource
implements Closeable {
/** Logger */ /** Logger */
protected final Logger log = LoggerFactory.getLogger(getClass()); protected final Logger log = LoggerFactory.getLogger(getClass());
@@ -44,7 +45,8 @@ abstract class RemoteResource implements Closeable {
return requester.newRequest(type).putString(handle); return requester.newRequest(type).putString(handle);
} }
public void close() throws IOException { public void close()
throws IOException {
log.info("Closing `{}`", this); log.info("Closing `{}`", this);
requester.doRequest(newRequest(PacketType.CLOSE)).ensureStatusPacketIsOK(); requester.doRequest(newRequest(PacketType.CLOSE)).ensureStatusPacketIsOK();
} }

View File

@@ -17,7 +17,8 @@ package net.schmizz.sshj.sftp;
import net.schmizz.concurrent.Future; import net.schmizz.concurrent.Future;
public class Request extends SFTPPacket<Request> { public class Request
extends SFTPPacket<Request> {
private final PacketType type; private final PacketType type;
private final long reqID; private final long reqID;

View File

@@ -21,6 +21,7 @@ public interface Requester {
Request newRequest(PacketType type); Request newRequest(PacketType type);
Response doRequest(Request req) throws IOException; Response doRequest(Request req)
throws IOException;
} }

View File

@@ -17,7 +17,8 @@ package net.schmizz.sshj.sftp;
import net.schmizz.sshj.common.Buffer; import net.schmizz.sshj.common.Buffer;
public class Response extends SFTPPacket<Response> { public class Response
extends SFTPPacket<Response> {
public static enum StatusCode { public static enum StatusCode {
UNKNOWN(-1), UNKNOWN(-1),
@@ -67,7 +68,8 @@ public class Response extends SFTPPacket<Response> {
return StatusCode.fromInt(readInt()); return StatusCode.fromInt(readInt());
} }
public Response ensurePacketTypeIs(PacketType pt) throws SFTPException { public Response ensurePacketTypeIs(PacketType pt)
throws SFTPException {
if (getType() != pt) if (getType() != pt)
if (getType() == PacketType.STATUS) if (getType() == PacketType.STATUS)
throw new SFTPException(readStatusCode(), readString()); throw new SFTPException(readStatusCode(), readString());
@@ -76,11 +78,13 @@ public class Response extends SFTPPacket<Response> {
return this; return this;
} }
public Response ensureStatusPacketIsOK() throws SFTPException { public Response ensureStatusPacketIsOK()
throws SFTPException {
return ensurePacketTypeIs(PacketType.STATUS).ensureStatusIs(StatusCode.OK); return ensurePacketTypeIs(PacketType.STATUS).ensureStatusIs(StatusCode.OK);
} }
public Response ensureStatusIs(StatusCode acceptable) throws SFTPException { public Response ensureStatusIs(StatusCode acceptable)
throws SFTPException {
StatusCode sc = readStatusCode(); StatusCode sc = readStatusCode();
if (sc != acceptable) if (sc != acceptable)
throw new SFTPException(sc, readString()); throw new SFTPException(sc, readString());

View File

@@ -33,7 +33,8 @@ public class SFTPClient {
private final SFTPEngine sftp; private final SFTPEngine sftp;
private final SFTPFileTransfer xfer; private final SFTPFileTransfer xfer;
public SFTPClient(SessionFactory ssh) throws IOException { public SFTPClient(SessionFactory ssh)
throws IOException {
this.sftp = new SFTPEngine(ssh).init(); this.sftp = new SFTPEngine(ssh).init();
this.xfer = new SFTPFileTransfer(sftp); this.xfer = new SFTPFileTransfer(sftp);
} }
@@ -46,11 +47,13 @@ public class SFTPClient {
return xfer; return xfer;
} }
public List<RemoteResourceInfo> ls(String path) throws IOException { public List<RemoteResourceInfo> ls(String path)
throws IOException {
return ls(path, null); return ls(path, null);
} }
public List<RemoteResourceInfo> ls(String path, RemoteResourceFilter filter) throws IOException { public List<RemoteResourceInfo> ls(String path, RemoteResourceFilter filter)
throws IOException {
final RemoteDirectory dir = sftp.openDir(path); final RemoteDirectory dir = sftp.openDir(path);
try { try {
return dir.scan(filter); return dir.scan(filter);
@@ -59,36 +62,44 @@ public class SFTPClient {
} }
} }
public RemoteFile open(String filename, Set<OpenMode> mode, FileAttributes attrs) throws IOException { public RemoteFile open(String filename, Set<OpenMode> mode, FileAttributes attrs)
throws IOException {
log.debug("Opening `{}`", filename); log.debug("Opening `{}`", filename);
return sftp.open(filename, mode, attrs); return sftp.open(filename, mode, attrs);
} }
public RemoteFile open(String filename, Set<OpenMode> mode) throws IOException { public RemoteFile open(String filename, Set<OpenMode> mode)
throws IOException {
return open(filename, mode, new FileAttributes()); return open(filename, mode, new FileAttributes());
} }
public RemoteFile open(String filename) throws IOException { public RemoteFile open(String filename)
throws IOException {
return open(filename, EnumSet.of(OpenMode.READ)); return open(filename, EnumSet.of(OpenMode.READ));
} }
public void mkdir(String dirname) throws IOException { public void mkdir(String dirname)
throws IOException {
sftp.makeDir(dirname); sftp.makeDir(dirname);
} }
public void rename(String oldpath, String newpath) throws IOException { public void rename(String oldpath, String newpath)
throws IOException {
sftp.rename(oldpath, newpath); sftp.rename(oldpath, newpath);
} }
public void rm(String filename) throws IOException { public void rm(String filename)
throws IOException {
sftp.remove(filename); sftp.remove(filename);
} }
public void rmdir(String dirname) throws IOException { public void rmdir(String dirname)
throws IOException {
sftp.removeDir(dirname); sftp.removeDir(dirname);
} }
public void symlink(String linkpath, String targetpath) throws IOException { public void symlink(String linkpath, String targetpath)
throws IOException {
sftp.symlink(linkpath, targetpath); sftp.symlink(linkpath, targetpath);
} }
@@ -96,79 +107,98 @@ public class SFTPClient {
return sftp.getOperativeProtocolVersion(); return sftp.getOperativeProtocolVersion();
} }
public void setattr(String path, FileAttributes attrs) throws IOException { public void setattr(String path, FileAttributes attrs)
throws IOException {
sftp.setAttributes(path, attrs); sftp.setAttributes(path, attrs);
} }
public int uid(String path) throws IOException { public int uid(String path)
throws IOException {
return stat(path).getUID(); return stat(path).getUID();
} }
public int gid(String path) throws IOException { public int gid(String path)
throws IOException {
return stat(path).getGID(); return stat(path).getGID();
} }
public long atime(String path) throws IOException { public long atime(String path)
throws IOException {
return stat(path).getAtime(); return stat(path).getAtime();
} }
public long mtime(String path) throws IOException { public long mtime(String path)
throws IOException {
return stat(path).getMtime(); return stat(path).getMtime();
} }
public Set<FilePermission> perms(String path) throws IOException { public Set<FilePermission> perms(String path)
throws IOException {
return stat(path).getPermissions(); return stat(path).getPermissions();
} }
public FileMode mode(String path) throws IOException { public FileMode mode(String path)
throws IOException {
return stat(path).getMode(); return stat(path).getMode();
} }
public FileMode.Type type(String path) throws IOException { public FileMode.Type type(String path)
throws IOException {
return stat(path).getType(); return stat(path).getType();
} }
public String readlink(String path) throws IOException { public String readlink(String path)
throws IOException {
return sftp.readLink(path); return sftp.readLink(path);
} }
public FileAttributes stat(String path) throws IOException { public FileAttributes stat(String path)
throws IOException {
return sftp.stat(path); return sftp.stat(path);
} }
public FileAttributes lstat(String path) throws IOException { public FileAttributes lstat(String path)
throws IOException {
return sftp.lstat(path); return sftp.lstat(path);
} }
public void chown(String path, int uid) throws IOException { public void chown(String path, int uid)
throws IOException {
setattr(path, new FileAttributes.Builder().withUIDGID(uid, gid(path)).build()); setattr(path, new FileAttributes.Builder().withUIDGID(uid, gid(path)).build());
} }
public void chmod(String path, int perms) throws IOException { public void chmod(String path, int perms)
throws IOException {
setattr(path, new FileAttributes.Builder().withPermissions(perms).build()); setattr(path, new FileAttributes.Builder().withPermissions(perms).build());
} }
public void chgrp(String path, int gid) throws IOException { public void chgrp(String path, int gid)
throws IOException {
setattr(path, new FileAttributes.Builder().withUIDGID(uid(path), gid).build()); setattr(path, new FileAttributes.Builder().withUIDGID(uid(path), gid).build());
} }
public void truncate(String path, long size) throws IOException { public void truncate(String path, long size)
throws IOException {
setattr(path, new FileAttributes.Builder().withSize(size).build()); setattr(path, new FileAttributes.Builder().withSize(size).build());
} }
public String canonicalize(String path) throws IOException { public String canonicalize(String path)
throws IOException {
return sftp.canonicalize(path); return sftp.canonicalize(path);
} }
public long size(String path) throws IOException { public long size(String path)
throws IOException {
return stat(path).getSize(); return stat(path).getSize();
} }
public void get(String source, String dest) throws IOException { public void get(String source, String dest)
throws IOException {
xfer.download(source, dest); xfer.download(source, dest);
} }
public void put(String source, String dest) throws IOException { public void put(String source, String dest)
throws IOException {
xfer.upload(source, dest); xfer.upload(source, dest);
} }

View File

@@ -29,7 +29,8 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
public class SFTPEngine implements Requester { public class SFTPEngine
implements Requester {
/** Logger */ /** Logger */
private final Logger log = LoggerFactory.getLogger(getClass()); private final Logger log = LoggerFactory.getLogger(getClass());
@@ -48,7 +49,8 @@ public class SFTPEngine implements Requester {
private int negotiatedVersion; private int negotiatedVersion;
private final Map<String, String> serverExtensions = new HashMap<String, String>(); private final Map<String, String> serverExtensions = new HashMap<String, String>();
public SFTPEngine(SessionFactory ssh) throws SSHException { public SFTPEngine(SessionFactory ssh)
throws SSHException {
sub = ssh.startSession().startSubsystem("sftp"); sub = ssh.startSession().startSubsystem("sftp");
out = sub.getOutputStream(); out = sub.getOutputStream();
reader = new PacketReader(sub.getInputStream()); reader = new PacketReader(sub.getInputStream());
@@ -58,7 +60,8 @@ public class SFTPEngine implements Requester {
return sub; return sub;
} }
public SFTPEngine init() throws IOException { public SFTPEngine init()
throws IOException {
transmit(new SFTPPacket<Request>(PacketType.INIT).putInt(PROTOCOL_VERSION)); transmit(new SFTPPacket<Request>(PacketType.INIT).putInt(PROTOCOL_VERSION));
final SFTPPacket<Response> response = reader.readPacket(); final SFTPPacket<Response> response = reader.readPacket();
@@ -88,14 +91,16 @@ public class SFTPEngine implements Requester {
return new Request(type, reqID = reqID + 1 & 0xffffffffL); return new Request(type, reqID = reqID + 1 & 0xffffffffL);
} }
public Response doRequest(Request req) throws IOException { public Response doRequest(Request req)
throws IOException {
reader.expectResponseTo(req); reader.expectResponseTo(req);
log.debug("Sending {}", req); log.debug("Sending {}", req);
transmit(req); transmit(req);
return req.getResponseFuture().get(timeout, TimeUnit.SECONDS); return req.getResponseFuture().get(timeout, TimeUnit.SECONDS);
} }
private synchronized void transmit(SFTPPacket<Request> payload) throws IOException { private synchronized void transmit(SFTPPacket<Request> payload)
throws IOException {
final int len = payload.available(); final int len = payload.available();
out.write((len >>> 24) & 0xff); out.write((len >>> 24) & 0xff);
out.write((len >>> 16) & 0xff); out.write((len >>> 16) & 0xff);
@@ -105,7 +110,8 @@ public class SFTPEngine implements Requester {
out.flush(); out.flush();
} }
public RemoteFile open(String path, Set<OpenMode> modes, FileAttributes fa) throws IOException { public RemoteFile open(String path, Set<OpenMode> modes, FileAttributes fa)
throws IOException {
final String handle = doRequest( final String handle = doRequest(
newRequest(PacketType.OPEN).putString(path).putInt(OpenMode.toMask(modes)).putFileAttributes(fa) newRequest(PacketType.OPEN).putString(path).putInt(OpenMode.toMask(modes)).putFileAttributes(fa)
@@ -113,90 +119,106 @@ public class SFTPEngine implements Requester {
return new RemoteFile(this, path, handle); return new RemoteFile(this, path, handle);
} }
public RemoteFile open(String filename, Set<OpenMode> modes) throws IOException { public RemoteFile open(String filename, Set<OpenMode> modes)
throws IOException {
return open(filename, modes, new FileAttributes()); return open(filename, modes, new FileAttributes());
} }
public RemoteFile open(String filename) throws IOException { public RemoteFile open(String filename)
throws IOException {
return open(filename, EnumSet.of(OpenMode.READ)); return open(filename, EnumSet.of(OpenMode.READ));
} }
public RemoteDirectory openDir(String path) throws IOException { public RemoteDirectory openDir(String path)
throws IOException {
final String handle = doRequest( final String handle = doRequest(
newRequest(PacketType.OPENDIR).putString(path) newRequest(PacketType.OPENDIR).putString(path)
).ensurePacketTypeIs(PacketType.HANDLE).readString(); ).ensurePacketTypeIs(PacketType.HANDLE).readString();
return new RemoteDirectory(this, path, handle); return new RemoteDirectory(this, path, handle);
} }
public void setAttributes(String path, FileAttributes attrs) throws IOException { public void setAttributes(String path, FileAttributes attrs)
throws IOException {
doRequest( doRequest(
newRequest(PacketType.SETSTAT).putString(path).putFileAttributes(attrs) newRequest(PacketType.SETSTAT).putString(path).putFileAttributes(attrs)
).ensureStatusPacketIsOK(); ).ensureStatusPacketIsOK();
} }
public String readLink(String path) throws IOException { public String readLink(String path)
throws IOException {
return readSingleName( return readSingleName(
doRequest( doRequest(
newRequest(PacketType.READLINK).putString(path) newRequest(PacketType.READLINK).putString(path)
)); ));
} }
public void makeDir(String path, FileAttributes attrs) throws IOException { public void makeDir(String path, FileAttributes attrs)
throws IOException {
doRequest( doRequest(
newRequest(PacketType.MKDIR).putString(path).putFileAttributes(attrs) newRequest(PacketType.MKDIR).putString(path).putFileAttributes(attrs)
).ensureStatusPacketIsOK(); ).ensureStatusPacketIsOK();
} }
public void makeDir(String path) throws IOException { public void makeDir(String path)
throws IOException {
makeDir(path, new FileAttributes()); makeDir(path, new FileAttributes());
} }
public void symlink(String linkpath, String targetpath) throws IOException { public void symlink(String linkpath, String targetpath)
throws IOException {
doRequest( doRequest(
newRequest(PacketType.SYMLINK).putString(linkpath).putString(targetpath) newRequest(PacketType.SYMLINK).putString(linkpath).putString(targetpath)
).ensureStatusPacketIsOK(); ).ensureStatusPacketIsOK();
} }
public void remove(String filename) throws IOException { public void remove(String filename)
throws IOException {
doRequest( doRequest(
newRequest(PacketType.REMOVE).putString(filename) newRequest(PacketType.REMOVE).putString(filename)
).ensureStatusPacketIsOK(); ).ensureStatusPacketIsOK();
} }
public void removeDir(String path) throws IOException { public void removeDir(String path)
throws IOException {
doRequest( doRequest(
newRequest(PacketType.RMDIR).putString(path) newRequest(PacketType.RMDIR).putString(path)
).ensureStatusIs(Response.StatusCode.OK); ).ensureStatusIs(Response.StatusCode.OK);
} }
private FileAttributes stat(PacketType pt, String path) throws IOException { private FileAttributes stat(PacketType pt, String path)
throws IOException {
return doRequest(newRequest(pt).putString(path)) return doRequest(newRequest(pt).putString(path))
.ensurePacketTypeIs(PacketType.ATTRS) .ensurePacketTypeIs(PacketType.ATTRS)
.readFileAttributes(); .readFileAttributes();
} }
public FileAttributes stat(String path) throws IOException { public FileAttributes stat(String path)
throws IOException {
return stat(PacketType.STAT, path); return stat(PacketType.STAT, path);
} }
public FileAttributes lstat(String path) throws IOException { public FileAttributes lstat(String path)
throws IOException {
return stat(PacketType.LSTAT, path); return stat(PacketType.LSTAT, path);
} }
public void rename(String oldPath, String newPath) throws IOException { public void rename(String oldPath, String newPath)
throws IOException {
doRequest( doRequest(
newRequest(PacketType.RENAME).putString(oldPath).putString(newPath) newRequest(PacketType.RENAME).putString(oldPath).putString(newPath)
).ensureStatusPacketIsOK(); ).ensureStatusPacketIsOK();
} }
public String canonicalize(String path) throws IOException { public String canonicalize(String path)
throws IOException {
return readSingleName( return readSingleName(
doRequest( doRequest(
newRequest(PacketType.REALPATH).putString(path) newRequest(PacketType.REALPATH).putString(path)
)); ));
} }
private static String readSingleName(Response res) throws IOException { private static String readSingleName(Response res)
throws IOException {
res.ensurePacketTypeIs(PacketType.NAME); res.ensurePacketTypeIs(PacketType.NAME);
if (res.readInt() == 1) if (res.readInt() == 1)
return res.readString(); return res.readString();

View File

@@ -20,7 +20,8 @@ import net.schmizz.sshj.common.DisconnectReason;
import net.schmizz.sshj.common.SSHException; import net.schmizz.sshj.common.SSHException;
import net.schmizz.sshj.sftp.Response.StatusCode; import net.schmizz.sshj.sftp.Response.StatusCode;
public class SFTPException extends SSHException { public class SFTPException
extends SSHException {
public static final ExceptionChainer<SFTPException> chainer = new ExceptionChainer<SFTPException>() { public static final ExceptionChainer<SFTPException> chainer = new ExceptionChainer<SFTPException>() {

View File

@@ -30,7 +30,9 @@ import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.util.EnumSet; import java.util.EnumSet;
public class SFTPFileTransfer extends AbstractFileTransfer implements FileTransfer { public class SFTPFileTransfer
extends AbstractFileTransfer
implements FileTransfer {
private final SFTPEngine sftp; private final SFTPEngine sftp;
private final PathHelper pathHelper; private final PathHelper pathHelper;
@@ -55,11 +57,13 @@ public class SFTPFileTransfer extends AbstractFileTransfer implements FileTransf
this.pathHelper = new PathHelper(sftp); this.pathHelper = new PathHelper(sftp);
} }
public void upload(String source, String dest) throws IOException { public void upload(String source, String dest)
throws IOException {
new Uploader(getModeGetter(), getUploadFilter()).upload(new File(source), dest); new Uploader(getModeGetter(), getUploadFilter()).upload(new File(source), dest);
} }
public void download(String source, String dest) throws IOException { public void download(String source, String dest)
throws IOException {
PathComponents src = pathHelper.getComponents(source); PathComponents src = pathHelper.getComponents(source);
new Downloader(getModeSetter(), getDownloadFilter()).download(new RemoteResourceInfo(src.getParent(), src new Downloader(getModeSetter(), getDownloadFilter()).download(new RemoteResourceInfo(src.getParent(), src
.getName(), sftp.stat(source)), new File(dest)); .getName(), sftp.stat(source)), new File(dest));
@@ -91,7 +95,8 @@ public class SFTPFileTransfer extends AbstractFileTransfer implements FileTransf
this.filter = filter; this.filter = filter;
} }
private void setAttributes(RemoteResourceInfo remote, File local) throws IOException { private void setAttributes(RemoteResourceInfo remote, File local)
throws IOException {
final FileAttributes attrs = remote.getAttributes(); final FileAttributes attrs = remote.getAttributes();
modeSetter.setPermissions(local, attrs.getMode().getPermissionsMask()); modeSetter.setPermissions(local, attrs.getMode().getPermissionsMask());
if (modeSetter.preservesTimes() && attrs.has(FileAttributes.Flag.ACMODTIME)) { if (modeSetter.preservesTimes() && attrs.has(FileAttributes.Flag.ACMODTIME)) {
@@ -100,7 +105,8 @@ public class SFTPFileTransfer extends AbstractFileTransfer implements FileTransf
} }
} }
private void downloadFile(RemoteResourceInfo remote, File local) throws IOException { private void downloadFile(RemoteResourceInfo remote, File local)
throws IOException {
local = FileTransferUtil.getTargetFile(local, remote.getName()); local = FileTransferUtil.getTargetFile(local, remote.getName());
setAttributes(remote, local); setAttributes(remote, local);
RemoteFile rf = sftp.open(remote.getPath()); RemoteFile rf = sftp.open(remote.getPath());
@@ -117,7 +123,8 @@ public class SFTPFileTransfer extends AbstractFileTransfer implements FileTransf
} }
} }
private void downloadDir(RemoteResourceInfo remote, File local) throws IOException { private void downloadDir(RemoteResourceInfo remote, File local)
throws IOException {
local = FileTransferUtil.getTargetDirectory(local, remote.getName()); local = FileTransferUtil.getTargetDirectory(local, remote.getName());
setAttributes(remote, local); setAttributes(remote, local);
final RemoteDirectory rd = sftp.openDir(remote.getPath()); final RemoteDirectory rd = sftp.openDir(remote.getPath());
@@ -126,7 +133,8 @@ public class SFTPFileTransfer extends AbstractFileTransfer implements FileTransf
rd.close(); rd.close();
} }
void download(RemoteResourceInfo remote, File local) throws IOException { void download(RemoteResourceInfo remote, File local)
throws IOException {
log.info("Downloading [{}] to [{}]", remote, local); log.info("Downloading [{}] to [{}]", remote, local);
if (remote.isDirectory()) if (remote.isDirectory())
downloadDir(remote, local); downloadDir(remote, local);
@@ -147,7 +155,8 @@ public class SFTPFileTransfer extends AbstractFileTransfer implements FileTransf
this.filter = filter; this.filter = filter;
} }
public FileAttributes getAttributes(File local) throws IOException { public FileAttributes getAttributes(File local)
throws IOException {
FileAttributes.Builder builder = new FileAttributes.Builder().withPermissions(modeGetter FileAttributes.Builder builder = new FileAttributes.Builder().withPermissions(modeGetter
.getPermissions(local)); .getPermissions(local));
if (modeGetter.preservesTimes()) if (modeGetter.preservesTimes())
@@ -156,17 +165,19 @@ public class SFTPFileTransfer extends AbstractFileTransfer implements FileTransf
} }
// tread carefully // tread carefully
private void setAttributes(FileAttributes current, File local, String remote) throws IOException { private void setAttributes(FileAttributes current, File local, String remote)
throws IOException {
final FileAttributes attrs = getAttributes(local); final FileAttributes attrs = getAttributes(local);
// TODO whoaaa.. simplify? // TODO whoaaa.. simplify?
if (!(current != null if (!(current != null
&& current.getMode().getPermissionsMask() == attrs.getMode().getPermissionsMask() && current.getMode().getPermissionsMask() == attrs.getMode().getPermissionsMask()
&& (!modeGetter.preservesTimes() || (attrs.getAtime() == current.getAtime() && attrs.getMtime() == current && (!modeGetter.preservesTimes()
.getMtime())))) || (attrs.getAtime() == current.getAtime() && attrs.getMtime() == current.getMtime()))))
sftp.setAttributes(remote, attrs); sftp.setAttributes(remote, attrs);
} }
private String prepareDir(File local, String remote) throws IOException { private String prepareDir(File local, String remote)
throws IOException {
FileAttributes attrs; FileAttributes attrs;
try { try {
attrs = sftp.stat(remote); attrs = sftp.stat(remote);
@@ -192,7 +203,8 @@ public class SFTPFileTransfer extends AbstractFileTransfer implements FileTransf
throw new IOException(attrs.getMode().getType() + " file already exists at " + remote); throw new IOException(attrs.getMode().getType() + " file already exists at " + remote);
} }
private String prepareFile(File local, String remote) throws IOException { private String prepareFile(File local, String remote)
throws IOException {
FileAttributes attrs; FileAttributes attrs;
try { try {
attrs = sftp.stat(remote); attrs = sftp.stat(remote);
@@ -213,13 +225,15 @@ public class SFTPFileTransfer extends AbstractFileTransfer implements FileTransf
} }
} }
private void uploadDir(File local, String remote) throws IOException { private void uploadDir(File local, String remote)
throws IOException {
final String adjusted = prepareDir(local, remote); final String adjusted = prepareDir(local, remote);
for (File f : local.listFiles(filter)) for (File f : local.listFiles(filter))
upload(f, adjusted); upload(f, adjusted);
} }
private void uploadFile(File local, String remote) throws IOException { private void uploadFile(File local, String remote)
throws IOException {
final String adjusted = prepareFile(local, remote); final String adjusted = prepareFile(local, remote);
final RemoteFile rf = sftp.open(adjusted, EnumSet.of(OpenMode.WRITE, OpenMode.CREAT, OpenMode.TRUNC), final RemoteFile rf = sftp.open(adjusted, EnumSet.of(OpenMode.WRITE, OpenMode.CREAT, OpenMode.TRUNC),
getAttributes(local)); getAttributes(local));
@@ -237,7 +251,8 @@ public class SFTPFileTransfer extends AbstractFileTransfer implements FileTransf
} }
} }
void upload(File local, String remote) throws IOException { void upload(File local, String remote)
throws IOException {
log.info("Uploading [{}] to [{}]", local, remote); log.info("Uploading [{}] to [{}]", local, remote);
if (local.isDirectory()) if (local.isDirectory())
uploadDir(local, remote); uploadDir(local, remote);

View File

@@ -17,7 +17,8 @@ package net.schmizz.sshj.sftp;
import net.schmizz.sshj.common.Buffer; import net.schmizz.sshj.common.Buffer;
public class SFTPPacket<T extends SFTPPacket<T>> extends Buffer<T> { public class SFTPPacket<T extends SFTPPacket<T>>
extends Buffer<T> {
public SFTPPacket() { public SFTPPacket() {
super(); super();

View File

@@ -21,11 +21,13 @@ import java.io.IOException;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
public class StatefulSFTPClient extends SFTPClient { public class StatefulSFTPClient
extends SFTPClient {
private String cwd; private String cwd;
public StatefulSFTPClient(SessionFactory ssh) throws IOException { public StatefulSFTPClient(SessionFactory ssh)
throws IOException {
super(ssh); super(ssh);
this.cwd = getSFTPEngine().canonicalize("."); this.cwd = getSFTPEngine().canonicalize(".");
log.info("Start dir = " + cwd); log.info("Start dir = " + cwd);
@@ -40,25 +42,30 @@ public class StatefulSFTPClient extends SFTPClient {
log.info("CWD = " + cwd); log.info("CWD = " + cwd);
} }
public synchronized List<RemoteResourceInfo> ls() throws IOException { public synchronized List<RemoteResourceInfo> ls()
throws IOException {
return ls(cwd, null); return ls(cwd, null);
} }
public synchronized List<RemoteResourceInfo> ls(RemoteResourceFilter filter) throws IOException { public synchronized List<RemoteResourceInfo> ls(RemoteResourceFilter filter)
throws IOException {
return ls(cwd, filter); return ls(cwd, filter);
} }
public synchronized String pwd() throws IOException { public synchronized String pwd()
throws IOException {
return super.canonicalize(cwd); return super.canonicalize(cwd);
} }
@Override @Override
public List<RemoteResourceInfo> ls(String path) throws IOException { public List<RemoteResourceInfo> ls(String path)
throws IOException {
return ls(path, null); return ls(path, null);
} }
@Override @Override
public List<RemoteResourceInfo> ls(String path, RemoteResourceFilter filter) throws IOException { public List<RemoteResourceInfo> ls(String path, RemoteResourceFilter filter)
throws IOException {
final RemoteDirectory dir = getSFTPEngine().openDir(cwdify(path)); final RemoteDirectory dir = getSFTPEngine().openDir(cwdify(path));
try { try {
return dir.scan(filter); return dir.scan(filter);
@@ -68,82 +75,98 @@ public class StatefulSFTPClient extends SFTPClient {
} }
@Override @Override
public RemoteFile open(String filename, Set<OpenMode> mode, FileAttributes attrs) throws IOException { public RemoteFile open(String filename, Set<OpenMode> mode, FileAttributes attrs)
throws IOException {
return super.open(cwdify(filename), mode, attrs); return super.open(cwdify(filename), mode, attrs);
} }
@Override @Override
public RemoteFile open(String filename, Set<OpenMode> mode) throws IOException { public RemoteFile open(String filename, Set<OpenMode> mode)
throws IOException {
return super.open(cwdify(filename), mode); return super.open(cwdify(filename), mode);
} }
@Override @Override
public RemoteFile open(String filename) throws IOException { public RemoteFile open(String filename)
throws IOException {
return super.open(cwdify(filename)); return super.open(cwdify(filename));
} }
@Override @Override
public void mkdir(String dirname) throws IOException { public void mkdir(String dirname)
throws IOException {
super.mkdir(cwdify(dirname)); super.mkdir(cwdify(dirname));
} }
@Override @Override
public void rename(String oldpath, String newpath) throws IOException { public void rename(String oldpath, String newpath)
throws IOException {
super.rename(cwdify(oldpath), cwdify(newpath)); super.rename(cwdify(oldpath), cwdify(newpath));
} }
@Override @Override
public void rm(String filename) throws IOException { public void rm(String filename)
throws IOException {
super.rm(cwdify(filename)); super.rm(cwdify(filename));
} }
@Override @Override
public void rmdir(String dirname) throws IOException { public void rmdir(String dirname)
throws IOException {
super.rmdir(cwdify(dirname)); super.rmdir(cwdify(dirname));
} }
@Override @Override
public void symlink(String linkpath, String targetpath) throws IOException { public void symlink(String linkpath, String targetpath)
throws IOException {
super.symlink(cwdify(linkpath), cwdify(targetpath)); super.symlink(cwdify(linkpath), cwdify(targetpath));
} }
@Override @Override
public void setattr(String path, FileAttributes attrs) throws IOException { public void setattr(String path, FileAttributes attrs)
throws IOException {
super.setattr(cwdify(path), attrs); super.setattr(cwdify(path), attrs);
} }
@Override @Override
public String readlink(String path) throws IOException { public String readlink(String path)
throws IOException {
return super.readlink(cwdify(path)); return super.readlink(cwdify(path));
} }
@Override @Override
public FileAttributes stat(String path) throws IOException { public FileAttributes stat(String path)
throws IOException {
return super.stat(cwdify(path)); return super.stat(cwdify(path));
} }
@Override @Override
public FileAttributes lstat(String path) throws IOException { public FileAttributes lstat(String path)
throws IOException {
return super.lstat(cwdify(path)); return super.lstat(cwdify(path));
} }
@Override @Override
public void truncate(String path, long size) throws IOException { public void truncate(String path, long size)
throws IOException {
super.truncate(cwdify(path), size); super.truncate(cwdify(path), size);
} }
@Override @Override
public String canonicalize(String path) throws IOException { public String canonicalize(String path)
throws IOException {
return super.canonicalize(cwdify(path)); return super.canonicalize(cwdify(path));
} }
@Override @Override
public void get(String source, String dest) throws IOException { public void get(String source, String dest)
throws IOException {
super.get(cwdify(source), dest); super.get(cwdify(source), dest);
} }
@Override @Override
public void put(String source, String dest) throws IOException { public void put(String source, String dest)
throws IOException {
super.get(source, cwdify(dest)); super.get(source, cwdify(dest));
} }