00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 package com.jcraft.jsch;
00031
00032 import java.io.*;
00033
00034 import java.util.Vector;
00035
00067 public class ChannelSftp extends ChannelSession{
00068
00069 static private final int LOCAL_MAXIMUM_PACKET_SIZE=32*1024;
00070 static private final int LOCAL_WINDOW_SIZE_MAX=(64*LOCAL_MAXIMUM_PACKET_SIZE);
00071
00072 private static final byte SSH_FXP_INIT= 1;
00073 private static final byte SSH_FXP_VERSION= 2;
00074 private static final byte SSH_FXP_OPEN= 3;
00075 private static final byte SSH_FXP_CLOSE= 4;
00076 private static final byte SSH_FXP_READ= 5;
00077 private static final byte SSH_FXP_WRITE= 6;
00078 private static final byte SSH_FXP_LSTAT= 7;
00079 private static final byte SSH_FXP_FSTAT= 8;
00080 private static final byte SSH_FXP_SETSTAT= 9;
00081 private static final byte SSH_FXP_FSETSTAT= 10;
00082 private static final byte SSH_FXP_OPENDIR= 11;
00083 private static final byte SSH_FXP_READDIR= 12;
00084 private static final byte SSH_FXP_REMOVE= 13;
00085 private static final byte SSH_FXP_MKDIR= 14;
00086 private static final byte SSH_FXP_RMDIR= 15;
00087 private static final byte SSH_FXP_REALPATH= 16;
00088 private static final byte SSH_FXP_STAT= 17;
00089 private static final byte SSH_FXP_RENAME= 18;
00090 private static final byte SSH_FXP_READLINK= 19;
00091 private static final byte SSH_FXP_SYMLINK= 20;
00092 private static final byte SSH_FXP_STATUS= 101;
00093 private static final byte SSH_FXP_HANDLE= 102;
00094 private static final byte SSH_FXP_DATA= 103;
00095 private static final byte SSH_FXP_NAME= 104;
00096 private static final byte SSH_FXP_ATTRS= 105;
00097 private static final byte SSH_FXP_EXTENDED= (byte)200;
00098 private static final byte SSH_FXP_EXTENDED_REPLY= (byte)201;
00099
00100
00101 private static final int SSH_FXF_READ= 0x00000001;
00102 private static final int SSH_FXF_WRITE= 0x00000002;
00103 private static final int SSH_FXF_APPEND= 0x00000004;
00104 private static final int SSH_FXF_CREAT= 0x00000008;
00105 private static final int SSH_FXF_TRUNC= 0x00000010;
00106 private static final int SSH_FXF_EXCL= 0x00000020;
00107
00108 private static final int SSH_FILEXFER_ATTR_SIZE= 0x00000001;
00109 private static final int SSH_FILEXFER_ATTR_UIDGID= 0x00000002;
00110 private static final int SSH_FILEXFER_ATTR_PERMISSIONS= 0x00000004;
00111 private static final int SSH_FILEXFER_ATTR_ACMODTIME= 0x00000008;
00112 private static final int SSH_FILEXFER_ATTR_EXTENDED= 0x80000000;
00113
00114 public static final int SSH_FX_OK= 0;
00115 public static final int SSH_FX_EOF= 1;
00116 public static final int SSH_FX_NO_SUCH_FILE= 2;
00117 public static final int SSH_FX_PERMISSION_DENIED= 3;
00118 public static final int SSH_FX_FAILURE= 4;
00119 public static final int SSH_FX_BAD_MESSAGE= 5;
00120 public static final int SSH_FX_NO_CONNECTION= 6;
00121 public static final int SSH_FX_CONNECTION_LOST= 7;
00122 public static final int SSH_FX_OP_UNSUPPORTED= 8;
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159 private static final int MAX_MSG_LENGTH = 256* 1024;
00160
00164 public static final int OVERWRITE=0;
00170 public static final int RESUME=1;
00174 public static final int APPEND=2;
00175
00176 private boolean interactive=false;
00177 private int seq=1;
00178 private int[] ackid=new int[1];
00179
00180 private Buffer buf;
00181 private Packet packet;
00182
00183
00184 private Buffer obuf;
00185 private Packet opacket;
00186
00187 private int client_version=3;
00188 private int server_version=3;
00189 private String version=String.valueOf(client_version);
00190
00191 private java.util.Hashtable extensions=null;
00192 private InputStream io_in=null;
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210 private static final String file_separator=java.io.File.separator;
00211 private static final char file_separatorc=java.io.File.separatorChar;
00212 private static boolean fs_is_bs=(byte)java.io.File.separatorChar == '\\';
00213
00214 private String cwd;
00215 private String home;
00216 private String lcwd;
00217
00218 private static final String UTF8="UTF-8";
00219 private String fEncoding=UTF8;
00220 private boolean fEncoding_is_utf8=true;
00221
00222 private RequestQueue rq = new RequestQueue(10);
00223 public void setBulkRequests(int bulk_requests) throws JSchException {
00224 if(bulk_requests>0)
00225 rq = new RequestQueue(bulk_requests);
00226 else
00227 throw new JSchException("setBulkRequests: "+
00228 bulk_requests+" must be greater than 0.");
00229 }
00230 public int getBulkRequests(){
00231 return rq.size();
00232 }
00233
00234 ChannelSftp(){
00235 super();
00236 setLocalWindowSizeMax(LOCAL_WINDOW_SIZE_MAX);
00237 setLocalWindowSize(LOCAL_WINDOW_SIZE_MAX);
00238 setLocalPacketSize(LOCAL_MAXIMUM_PACKET_SIZE);
00239 }
00240
00241 void init(){
00242 }
00243
00244
00245 public void start() throws JSchException{
00246 try{
00247
00248 PipedOutputStream pos=new PipedOutputStream();
00249 io.setOutputStream(pos);
00250 PipedInputStream pis=new MyPipedInputStream(pos, rmpsize);
00251 io.setInputStream(pis);
00252
00253 io_in=io.in;
00254
00255 if(io_in==null){
00256 throw new JSchException("channel is down");
00257 }
00258
00259 Request request=new RequestSftp();
00260 request.request(getSession(), this);
00261
00262
00263
00264
00265
00266
00267
00268
00269 buf=new Buffer(lmpsize);
00270 packet=new Packet(buf);
00271
00272 obuf=new Buffer(rmpsize);
00273 opacket=new Packet(obuf);
00274
00275 int i=0;
00276 int length;
00277 int type;
00278 byte[] str;
00279
00280
00281 sendINIT();
00282
00283
00284 Header header=new Header();
00285 header=header(buf, header);
00286 length=header.length;
00287 if(length > MAX_MSG_LENGTH){
00288 throw new SftpException(SSH_FX_FAILURE,
00289 "Received message is too long: " + length);
00290 }
00291 type=header.type;
00292 server_version=header.rid;
00293
00294 if(length>0){
00295 extensions=new java.util.Hashtable();
00296
00297 fill(buf, length);
00298 byte[] extension_name=null;
00299 byte[] extension_data=null;
00300 while(length>0){
00301 extension_name=buf.getString();
00302 length-=(4+extension_name.length);
00303 extension_data=buf.getString();
00304 length-=(4+extension_data.length);
00305 extensions.put(Util.byte2str(extension_name),
00306 Util.byte2str(extension_data));
00307 }
00308 }
00309
00310 lcwd=new File(".").getCanonicalPath();
00311 }
00312 catch(Exception e){
00313
00314 if(e instanceof JSchException) throw (JSchException)e;
00315 if(e instanceof Throwable)
00316 throw new JSchException(e.toString(), (Throwable)e);
00317 throw new JSchException(e.toString());
00318 }
00319 }
00320
00324 public void quit(){ disconnect();}
00325
00329 public void exit(){ disconnect();}
00330
00338 public void lcd(String path) throws SftpException{
00339 path=localAbsolutePath(path);
00340 if((new File(path)).isDirectory()){
00341 try{
00342 path=(new File(path)).getCanonicalPath();
00343 }
00344 catch(Exception e){}
00345 lcwd=path;
00346 return;
00347 }
00348 throw new SftpException(SSH_FX_NO_SUCH_FILE, "No such directory");
00349 }
00350
00362 public void cd(String path) throws SftpException{
00363 try{
00364 ((MyPipedInputStream)io_in).updateReadSide();
00365
00366 path=remoteAbsolutePath(path);
00367 path=isUnique(path);
00368
00369 byte[] str=_realpath(path);
00370 SftpATTRS attr=_stat(str);
00371
00372 if((attr.getFlags()&SftpATTRS.SSH_FILEXFER_ATTR_PERMISSIONS)==0){
00373 throw new SftpException(SSH_FX_FAILURE,
00374 "Can't change directory: "+path);
00375 }
00376 if(!attr.isDir()){
00377 throw new SftpException(SSH_FX_FAILURE,
00378 "Can't change directory: "+path);
00379 }
00380
00381 setCwd(Util.byte2str(str, fEncoding));
00382 }
00383 catch(Exception e){
00384 if(e instanceof SftpException) throw (SftpException)e;
00385 if(e instanceof Throwable)
00386
00387 throw new SftpException(SSH_FX_FAILURE, "", (Throwable)e);
00388 throw new SftpException(SSH_FX_FAILURE, "");
00389 }
00390 }
00391
00392
00393
00394
00404 public void put(String src, String dst) throws SftpException{
00405 put(src, dst, null, OVERWRITE);
00406 }
00407
00419 public void put(String src, String dst, int mode) throws SftpException{
00420 put(src, dst, null, mode);
00421 }
00422
00435 public void put(String src, String dst,
00436 SftpProgressMonitor monitor) throws SftpException{
00437 put(src, dst, monitor, OVERWRITE);
00438 }
00439
00453 public void put(String src, String dst,
00454 SftpProgressMonitor monitor, int mode) throws SftpException{
00455
00456 try{
00457 ((MyPipedInputStream)io_in).updateReadSide();
00458
00459 src=localAbsolutePath(src);
00460 dst=remoteAbsolutePath(dst);
00461
00462 Vector v=glob_remote(dst);
00463 int vsize=v.size();
00464 if(vsize!=1){
00465 if(vsize==0){
00466 if(isPattern(dst))
00467 throw new SftpException(SSH_FX_FAILURE, dst);
00468 else
00469 dst=Util.unquote(dst);
00470 }
00471 throw new SftpException(SSH_FX_FAILURE, v.toString());
00472 }
00473 else{
00474 dst=(String)(v.elementAt(0));
00475 }
00476
00477 boolean isRemoteDir=isRemoteDir(dst);
00478
00479 v=glob_local(src);
00480 vsize=v.size();
00481
00482 StringBuffer dstsb=null;
00483 if(isRemoteDir){
00484 if(!dst.endsWith("/")){
00485 dst+="/";
00486 }
00487 dstsb=new StringBuffer(dst);
00488 }
00489 else if(vsize>1){
00490 throw new SftpException(SSH_FX_FAILURE,
00491 "Copying multiple files, but the destination is missing or a file.");
00492 }
00493
00494 for(int j=0; j<vsize; j++){
00495 String _src=(String)(v.elementAt(j));
00496 String _dst=null;
00497 if(isRemoteDir){
00498 int i=_src.lastIndexOf(file_separatorc);
00499 if(fs_is_bs){
00500 int ii=_src.lastIndexOf('/');
00501 if(ii!=-1 && ii>i)
00502 i=ii;
00503 }
00504 if(i==-1) dstsb.append(_src);
00505 else dstsb.append(_src.substring(i + 1));
00506 _dst=dstsb.toString();
00507 dstsb.delete(dst.length(), _dst.length());
00508 }
00509 else{
00510 _dst=dst;
00511 }
00512
00513
00514 long size_of_dst=0;
00515 if(mode==RESUME){
00516 try{
00517 SftpATTRS attr=_stat(_dst);
00518 size_of_dst=attr.getSize();
00519 }
00520 catch(Exception eee){
00521
00522 }
00523 long size_of_src=new File(_src).length();
00524 if(size_of_src<size_of_dst){
00525 throw new SftpException(SSH_FX_FAILURE,
00526 "failed to resume for "+_dst);
00527 }
00528 if(size_of_src==size_of_dst){
00529 return;
00530 }
00531 }
00532
00533 if(monitor!=null){
00534 monitor.init(SftpProgressMonitor.PUT, _src, _dst,
00535 (new File(_src)).length());
00536 if(mode==RESUME){
00537 monitor.count(size_of_dst);
00538 }
00539 }
00540 FileInputStream fis=null;
00541 try{
00542 fis=new FileInputStream(_src);
00543 _put(fis, _dst, monitor, mode);
00544 }
00545 finally{
00546 if(fis!=null) {
00547 fis.close();
00548 }
00549 }
00550 }
00551 }
00552 catch(Exception e){
00553 if(e instanceof SftpException) throw (SftpException)e;
00554 if(e instanceof Throwable)
00555 throw new SftpException(SSH_FX_FAILURE, e.toString(), (Throwable)e);
00556 throw new SftpException(SSH_FX_FAILURE, e.toString());
00557 }
00558 }
00559
00569 public void put(InputStream src, String dst) throws SftpException{
00570 put(src, dst, null, OVERWRITE);
00571 }
00572
00584 public void put(InputStream src, String dst, int mode) throws SftpException{
00585 put(src, dst, null, mode);
00586 }
00587
00600 public void put(InputStream src, String dst,
00601 SftpProgressMonitor monitor) throws SftpException{
00602 put(src, dst, monitor, OVERWRITE);
00603 }
00604
00617 public void put(InputStream src, String dst,
00618 SftpProgressMonitor monitor, int mode) throws SftpException{
00619 try{
00620 ((MyPipedInputStream)io_in).updateReadSide();
00621
00622 dst=remoteAbsolutePath(dst);
00623
00624 Vector v=glob_remote(dst);
00625 int vsize=v.size();
00626 if(vsize!=1){
00627 if(vsize==0){
00628 if(isPattern(dst))
00629 throw new SftpException(SSH_FX_FAILURE, dst);
00630 else
00631 dst=Util.unquote(dst);
00632 }
00633 throw new SftpException(SSH_FX_FAILURE, v.toString());
00634 }
00635 else{
00636 dst=(String)(v.elementAt(0));
00637 }
00638
00639 if(isRemoteDir(dst)){
00640 throw new SftpException(SSH_FX_FAILURE, dst+" is a directory");
00641 }
00642
00643 if(monitor!=null){
00644 monitor.init(SftpProgressMonitor.PUT,
00645 "-", dst,
00646 SftpProgressMonitor.UNKNOWN_SIZE);
00647 }
00648
00649 _put(src, dst, monitor, mode);
00650 }
00651 catch(Exception e){
00652 if(e instanceof SftpException) throw (SftpException)e;
00653 if(e instanceof Throwable)
00654 throw new SftpException(SSH_FX_FAILURE, e.toString(), (Throwable)e);
00655 throw new SftpException(SSH_FX_FAILURE, e.toString());
00656 }
00657 }
00658
00666 public void _put(InputStream src, String dst,
00667 SftpProgressMonitor monitor, int mode) throws SftpException{
00668 try{
00669 ((MyPipedInputStream)io_in).updateReadSide();
00670
00671 byte[] dstb=Util.str2byte(dst, fEncoding);
00672 long skip=0;
00673 if(mode==RESUME || mode==APPEND){
00674 try{
00675 SftpATTRS attr=_stat(dstb);
00676 skip=attr.getSize();
00677 }
00678 catch(Exception eee){
00679
00680 }
00681 }
00682 if(mode==RESUME && skip>0){
00683 long skipped=src.skip(skip);
00684 if(skipped<skip){
00685 throw new SftpException(SSH_FX_FAILURE, "failed to resume for "+dst);
00686 }
00687 }
00688
00689 if(mode==OVERWRITE){ sendOPENW(dstb); }
00690 else{ sendOPENA(dstb); }
00691
00692 Header header=new Header();
00693 header=header(buf, header);
00694 int length=header.length;
00695 int type=header.type;
00696
00697 fill(buf, length);
00698
00699 if(type!=SSH_FXP_STATUS && type!=SSH_FXP_HANDLE){
00700 throw new SftpException(SSH_FX_FAILURE, "invalid type="+type);
00701 }
00702 if(type==SSH_FXP_STATUS){
00703 int i=buf.getInt();
00704 throwStatusError(buf, i);
00705 }
00706 byte[] handle=buf.getString();
00707 byte[] data=null;
00708
00709 boolean dontcopy=true;
00710
00711 if(!dontcopy){
00712 data=new byte[obuf.buffer.length
00713 -(5+13+21+handle.length+Session.buffer_margin
00714 )
00715 ];
00716 }
00717
00718 long offset=0;
00719 if(mode==RESUME || mode==APPEND){
00720 offset+=skip;
00721 }
00722
00723 int startid=seq;
00724 int ackcount=0;
00725 int _s=0;
00726 int _datalen=0;
00727
00728 if(!dontcopy){
00729 _datalen=data.length;
00730 }
00731 else{
00732 data=obuf.buffer;
00733 _s=5+13+21+handle.length;
00734 _datalen=obuf.buffer.length-_s-Session.buffer_margin;
00735 }
00736
00737 int bulk_requests = rq.size();
00738
00739 while(true){
00740 int nread=0;
00741 int count=0;
00742 int s=_s;
00743 int datalen=_datalen;
00744
00745 do{
00746 nread=src.read(data, s, datalen);
00747 if(nread>0){
00748 s+=nread;
00749 datalen-=nread;
00750 count+=nread;
00751 }
00752 }
00753 while(datalen>0 && nread>0);
00754 if(count<=0)break;
00755
00756 int foo=count;
00757 while(foo>0){
00758 if((seq-1)==startid ||
00759 ((seq-startid)-ackcount)>=bulk_requests){
00760 while(((seq-startid)-ackcount)>=bulk_requests){
00761 if(this.rwsize>=foo) break;
00762 if(checkStatus(ackid, header)){
00763 int _ackid = ackid[0];
00764 if(startid>_ackid || _ackid>seq-1){
00765 if(_ackid==seq){
00766 System.err.println("ack error: startid="+startid+" seq="+seq+" _ackid="+_ackid);
00767 }
00768 else{
00769 throw new SftpException(SSH_FX_FAILURE, "ack error: startid="+startid+" seq="+seq+" _ackid="+_ackid);
00770 }
00771 }
00772 ackcount++;
00773 }
00774 else{
00775 break;
00776 }
00777 }
00778 }
00779 foo-=sendWRITE(handle, offset, data, 0, foo);
00780 }
00781 offset+=count;
00782 if(monitor!=null && !monitor.count(count)){
00783 break;
00784 }
00785 }
00786 int _ackcount=seq-startid;
00787 while(_ackcount>ackcount){
00788 if(!checkStatus(null, header)){
00789 break;
00790 }
00791 ackcount++;
00792 }
00793 if(monitor!=null)monitor.end();
00794 _sendCLOSE(handle, header);
00795 }
00796 catch(Exception e){
00797 if(e instanceof SftpException) throw (SftpException)e;
00798 if(e instanceof Throwable)
00799 throw new SftpException(SSH_FX_FAILURE, e.toString(), (Throwable)e);
00800 throw new SftpException(SSH_FX_FAILURE, e.toString());
00801 }
00802 }
00803
00815 public OutputStream put(String dst) throws SftpException{
00816 return put(dst, (SftpProgressMonitor)null, OVERWRITE);
00817 }
00818
00831 public OutputStream put(String dst, final int mode) throws SftpException{
00832 return put(dst, (SftpProgressMonitor)null, mode);
00833 }
00834
00850 public OutputStream put(String dst, final SftpProgressMonitor monitor, final int mode) throws SftpException{
00851 return put(dst, monitor, mode, 0);
00852 }
00853
00878 public OutputStream put(String dst, final SftpProgressMonitor monitor, final int mode, long offset) throws SftpException{
00879 try{
00880 ((MyPipedInputStream)io_in).updateReadSide();
00881
00882 dst=remoteAbsolutePath(dst);
00883 dst=isUnique(dst);
00884
00885 if(isRemoteDir(dst)){
00886 throw new SftpException(SSH_FX_FAILURE, dst+" is a directory");
00887 }
00888
00889 byte[] dstb=Util.str2byte(dst, fEncoding);
00890
00891 long skip=0;
00892 if(mode==RESUME || mode==APPEND){
00893 try{
00894 SftpATTRS attr=_stat(dstb);
00895 skip=attr.getSize();
00896 }
00897 catch(Exception eee){
00898
00899 }
00900 }
00901
00902 if(mode==OVERWRITE){ sendOPENW(dstb); }
00903 else{ sendOPENA(dstb); }
00904
00905 Header header=new Header();
00906 header=header(buf, header);
00907 int length=header.length;
00908 int type=header.type;
00909
00910 fill(buf, length);
00911
00912 if(type!=SSH_FXP_STATUS && type!=SSH_FXP_HANDLE){
00913 throw new SftpException(SSH_FX_FAILURE, "");
00914 }
00915 if(type==SSH_FXP_STATUS){
00916 int i=buf.getInt();
00917 throwStatusError(buf, i);
00918 }
00919 final byte[] handle=buf.getString();
00920
00921 if(mode==RESUME || mode==APPEND){
00922 offset+=skip;
00923 }
00924
00925 final long[] _offset=new long[1];
00926 _offset[0]=offset;
00927 OutputStream out = new OutputStream(){
00928 private boolean init=true;
00929 private boolean isClosed=false;
00930 private int[] ackid=new int[1];
00931 private int startid=0;
00932 private int _ackid=0;
00933 private int ackcount=0;
00934 private int writecount=0;
00935 private Header header=new Header();
00936
00937 public void write(byte[] d) throws java.io.IOException{
00938 write(d, 0, d.length);
00939 }
00940
00941 public void write(byte[] d, int s, int len) throws java.io.IOException{
00942 if(init){
00943 startid=seq;
00944 _ackid=seq;
00945 init=false;
00946 }
00947
00948 if(isClosed){
00949 throw new IOException("stream already closed");
00950 }
00951
00952 try{
00953 int _len=len;
00954 while(_len>0){
00955 int sent=sendWRITE(handle, _offset[0], d, s, _len);
00956 writecount++;
00957 _offset[0]+=sent;
00958 s+=sent;
00959 _len-=sent;
00960 if((seq-1)==startid ||
00961 io_in.available()>=1024){
00962 while(io_in.available()>0){
00963 if(checkStatus(ackid, header)){
00964 _ackid=ackid[0];
00965 if(startid>_ackid || _ackid>seq-1){
00966 throw new SftpException(SSH_FX_FAILURE, "");
00967 }
00968 ackcount++;
00969 }
00970 else{
00971 break;
00972 }
00973 }
00974 }
00975 }
00976 if(monitor!=null && !monitor.count(len)){
00977 close();
00978 throw new IOException("canceled");
00979 }
00980 }
00981 catch(IOException e){ throw e; }
00982 catch(Exception e){ throw new IOException(e.toString()); }
00983 }
00984
00985 byte[] _data=new byte[1];
00986 public void write(int foo) throws java.io.IOException{
00987 _data[0]=(byte)foo;
00988 write(_data, 0, 1);
00989 }
00990
00991 public void flush() throws java.io.IOException{
00992
00993 if(isClosed){
00994 throw new IOException("stream already closed");
00995 }
00996
00997 if(!init){
00998 try{
00999 while(writecount>ackcount){
01000 if(!checkStatus(null, header)){
01001 break;
01002 }
01003 ackcount++;
01004 }
01005 }
01006 catch(SftpException e){
01007 throw new IOException(e.toString());
01008 }
01009 }
01010 }
01011
01012 public void close() throws java.io.IOException{
01013 if(isClosed){
01014 return;
01015 }
01016 flush();
01017 if(monitor!=null)monitor.end();
01018 try{ _sendCLOSE(handle, header); }
01019 catch(IOException e){ throw e; }
01020 catch(Exception e){
01021 throw new IOException(e.toString());
01022 }
01023 isClosed=true;
01024 }
01025 };
01026 return out;
01027 }
01028 catch(Exception e){
01029 if(e instanceof SftpException) throw (SftpException)e;
01030 if(e instanceof Throwable)
01031 throw new SftpException(SSH_FX_FAILURE, "", (Throwable)e);
01032 throw new SftpException(SSH_FX_FAILURE, "");
01033 }
01034 }
01035
01036
01037
01038
01044 public void get(String src, String dst) throws SftpException{
01045 get(src, dst, null, OVERWRITE);
01046 }
01047
01053 public void get(String src, String dst,
01054 SftpProgressMonitor monitor) throws SftpException{
01055 get(src, dst, monitor, OVERWRITE);
01056 }
01057
01071 public void get(String src, String dst,
01072 SftpProgressMonitor monitor, int mode) throws SftpException{
01073
01074
01075 boolean _dstExist = false;
01076 String _dst=null;
01077 try{
01078 ((MyPipedInputStream)io_in).updateReadSide();
01079
01080 src=remoteAbsolutePath(src);
01081 dst=localAbsolutePath(dst);
01082
01083 Vector v=glob_remote(src);
01084 int vsize=v.size();
01085 if(vsize==0){
01086 throw new SftpException(SSH_FX_NO_SUCH_FILE, "No such file");
01087 }
01088
01089 File dstFile=new File(dst);
01090 boolean isDstDir=dstFile.isDirectory();
01091 StringBuffer dstsb=null;
01092 if(isDstDir){
01093 if(!dst.endsWith(file_separator)){
01094 dst+=file_separator;
01095 }
01096 dstsb=new StringBuffer(dst);
01097 }
01098 else if(vsize>1){
01099 throw new SftpException(SSH_FX_FAILURE,
01100 "Copying multiple files, but destination is missing or a file.");
01101 }
01102
01103 for(int j=0; j<vsize; j++){
01104 String _src=(String)(v.elementAt(j));
01105 SftpATTRS attr=_stat(_src);
01106 if(attr.isDir()){
01107 throw new SftpException(SSH_FX_FAILURE,
01108 "not supported to get directory "+_src);
01109 }
01110
01111 _dst=null;
01112 if(isDstDir){
01113 int i=_src.lastIndexOf('/');
01114 if(i==-1) dstsb.append(_src);
01115 else dstsb.append(_src.substring(i + 1));
01116 _dst=dstsb.toString();
01117 dstsb.delete(dst.length(), _dst.length());
01118 }
01119 else{
01120 _dst=dst;
01121 }
01122
01123 File _dstFile=new File(_dst);
01124 if(mode==RESUME){
01125 long size_of_src=attr.getSize();
01126 long size_of_dst=_dstFile.length();
01127 if(size_of_dst>size_of_src){
01128 throw new SftpException(SSH_FX_FAILURE,
01129 "failed to resume for "+_dst);
01130 }
01131 if(size_of_dst==size_of_src){
01132 return;
01133 }
01134 }
01135
01136 if(monitor!=null){
01137 monitor.init(SftpProgressMonitor.GET, _src, _dst, attr.getSize());
01138 if(mode==RESUME){
01139 monitor.count(_dstFile.length());
01140 }
01141 }
01142
01143 FileOutputStream fos=null;
01144 _dstExist = _dstFile.exists();
01145 try{
01146 if(mode==OVERWRITE){
01147 fos=new FileOutputStream(_dst);
01148 }
01149 else{
01150 fos=new FileOutputStream(_dst, true);
01151 }
01152
01153 _get(_src, fos, monitor, mode, new File(_dst).length());
01154 }
01155 finally{
01156 if(fos!=null){
01157 fos.close();
01158 }
01159 }
01160 }
01161 }
01162 catch(Exception e){
01163 if(!_dstExist && _dst!=null){
01164 File _dstFile = new File(_dst);
01165 if(_dstFile.exists() && _dstFile.length()==0){
01166 _dstFile.delete();
01167 }
01168 }
01169 if(e instanceof SftpException) throw (SftpException)e;
01170 if(e instanceof Throwable)
01171 throw new SftpException(SSH_FX_FAILURE, "", (Throwable)e);
01172 throw new SftpException(SSH_FX_FAILURE, "");
01173 }
01174 }
01175
01181 public void get(String src, OutputStream dst) throws SftpException{
01182 get(src, dst, null, OVERWRITE, 0);
01183 }
01184
01190 public void get(String src, OutputStream dst,
01191 SftpProgressMonitor monitor) throws SftpException{
01192 get(src, dst, monitor, OVERWRITE, 0);
01193 }
01194
01211 public void get(String src, OutputStream dst,
01212 SftpProgressMonitor monitor, int mode, long skip) throws SftpException{
01213
01214 try{
01215 ((MyPipedInputStream)io_in).updateReadSide();
01216
01217 src=remoteAbsolutePath(src);
01218 src=isUnique(src);
01219
01220 if(monitor!=null){
01221 SftpATTRS attr=_stat(src);
01222 monitor.init(SftpProgressMonitor.GET, src, "??", attr.getSize());
01223 if(mode==RESUME){
01224 monitor.count(skip);
01225 }
01226 }
01227 _get(src, dst, monitor, mode, skip);
01228 }
01229 catch(Exception e){
01230 if(e instanceof SftpException) throw (SftpException)e;
01231 if(e instanceof Throwable)
01232 throw new SftpException(SSH_FX_FAILURE, "", (Throwable)e);
01233 throw new SftpException(SSH_FX_FAILURE, "");
01234 }
01235 }
01236
01240 private void _get(String src, OutputStream dst,
01241 SftpProgressMonitor monitor, int mode, long skip) throws SftpException{
01242
01243
01244 byte[] srcb=Util.str2byte(src, fEncoding);
01245 try{
01246 sendOPENR(srcb);
01247
01248 Header header=new Header();
01249 header=header(buf, header);
01250 int length=header.length;
01251 int type=header.type;
01252
01253 fill(buf, length);
01254
01255 if(type!=SSH_FXP_STATUS && type!=SSH_FXP_HANDLE){
01256 throw new SftpException(SSH_FX_FAILURE, "");
01257 }
01258
01259 if(type==SSH_FXP_STATUS){
01260 int i=buf.getInt();
01261 throwStatusError(buf, i);
01262 }
01263
01264 byte[] handle=buf.getString();
01265
01266 long offset=0;
01267 if(mode==RESUME){
01268 offset+=skip;
01269 }
01270
01271 int request_max=1;
01272 rq.init();
01273 long request_offset=offset;
01274
01275 int request_len = buf.buffer.length-13;
01276 if(server_version==0){ request_len=1024; }
01277
01278 loop:
01279 while(true){
01280
01281 while(rq.count() < request_max){
01282 sendREAD(handle, request_offset, request_len, rq);
01283 request_offset += request_len;
01284 }
01285
01286 header=header(buf, header);
01287 length=header.length;
01288 type=header.type;
01289
01290 RequestQueue.Request rr = rq.get(header.rid);
01291
01292 if(type==SSH_FXP_STATUS){
01293 fill(buf, length);
01294 int i=buf.getInt();
01295 if(i==SSH_FX_EOF){
01296 break loop;
01297 }
01298 throwStatusError(buf, i);
01299 }
01300
01301 if(type!=SSH_FXP_DATA){
01302 break loop;
01303 }
01304
01305 buf.rewind();
01306 fill(buf.buffer, 0, 4); length-=4;
01307 int length_of_data = buf.getInt();
01308
01319 int optional_data = length - length_of_data;
01320
01321 int foo = length_of_data;
01322 while(foo>0){
01323 int bar=foo;
01324 if(bar>buf.buffer.length){
01325 bar=buf.buffer.length;
01326 }
01327 int data_len = io_in.read(buf.buffer, 0, bar);
01328 if(data_len<0){
01329 break loop;
01330 }
01331
01332 dst.write(buf.buffer, 0, data_len);
01333
01334 offset+=data_len;
01335 foo-=data_len;
01336
01337 if(monitor!=null){
01338 if(!monitor.count(data_len)){
01339 skip(foo);
01340 if(optional_data>0){
01341 skip(optional_data);
01342 }
01343 break loop;
01344 }
01345 }
01346
01347 }
01348
01349
01350 if(optional_data>0){
01351 skip(optional_data);
01352 }
01353
01354 if(length_of_data<rr.length){
01355 rq.cancel(header, buf);
01356 sendREAD(handle, rr.offset+length_of_data, (int)(rr.length-length_of_data), rq);
01357 request_offset=rr.offset+rr.length;
01358 }
01359
01360 if(request_max < rq.size()){
01361 request_max++;
01362 }
01363 }
01364 dst.flush();
01365
01366 if(monitor!=null)monitor.end();
01367
01368 rq.cancel(header, buf);
01369
01370 _sendCLOSE(handle, header);
01371 }
01372 catch(Exception e){
01373 if(e instanceof SftpException) throw (SftpException)e;
01374 if(e instanceof Throwable)
01375 throw new SftpException(SSH_FX_FAILURE, "", (Throwable)e);
01376 throw new SftpException(SSH_FX_FAILURE, "");
01377 }
01378 }
01379
01380
01381 private class RequestQueue {
01382 class Request {
01383 int id;
01384 long offset;
01385 long length;
01386 }
01387
01388 Request[] rrq=null;
01389 int head, count;
01390 RequestQueue(int size){
01391 rrq = new Request[size];
01392 for(int i=0; i<rrq.length; i++){
01393 rrq[i]=new Request();
01394 }
01395 init();
01396 }
01397
01398 void init(){
01399 head=count=0;
01400 }
01401
01402 void add(int id, long offset, int length){
01403 if(count == 0) head = 0;
01404 int tail = head + count;
01405 if(tail>=rrq.length) tail -= rrq.length;
01406 rrq[tail].id=id;
01407 rrq[tail].offset=offset;
01408 rrq[tail].length=length;
01409 count++;
01410 }
01411
01412 Request get(int id){
01413 count -= 1;
01414 int i=head;
01415 head++;
01416 if(head==rrq.length) head=0;
01417 if(rrq[i].id!=id){
01418 System.err.println("The request is not in order.");
01419 }
01420 rrq[i].id=0;
01421 return rrq[i];
01422 }
01423
01424 int count() {
01425 return count;
01426 }
01427
01428 int size() {
01429 return rrq.length;
01430 }
01431
01432 void cancel(Header header, Buffer buf) throws IOException {
01433 int _count = count;
01434 for(int i=0; i<_count; i++){
01435 header=header(buf, header);
01436 int length=header.length;
01437 get(header.rid);
01438 skip(length);
01439 }
01440 }
01441 }
01442
01448 public InputStream get(String src) throws SftpException{
01449 return get(src, null, 0L);
01450 }
01456 public InputStream get(String src, SftpProgressMonitor monitor) throws SftpException{
01457 return get(src, monitor, 0L);
01458 }
01459
01467 public InputStream get(String src, int mode) throws SftpException{
01468 return get(src, null, 0L);
01469 }
01477 public InputStream get(String src, final SftpProgressMonitor monitor, final int mode) throws SftpException{
01478 return get(src, monitor, 0L);
01479 }
01480
01494 public InputStream get(String src, final SftpProgressMonitor monitor, final long skip) throws SftpException{
01495
01496 try{
01497 ((MyPipedInputStream)io_in).updateReadSide();
01498
01499 src=remoteAbsolutePath(src);
01500 src=isUnique(src);
01501
01502 byte[] srcb=Util.str2byte(src, fEncoding);
01503
01504 SftpATTRS attr=_stat(srcb);
01505 if(monitor!=null){
01506 monitor.init(SftpProgressMonitor.GET, src, "??", attr.getSize());
01507 }
01508
01509 sendOPENR(srcb);
01510
01511 Header header=new Header();
01512 header=header(buf, header);
01513 int length=header.length;
01514 int type=header.type;
01515
01516 fill(buf, length);
01517
01518 if(type!=SSH_FXP_STATUS && type!=SSH_FXP_HANDLE){
01519 throw new SftpException(SSH_FX_FAILURE, "");
01520 }
01521 if(type==SSH_FXP_STATUS){
01522 int i=buf.getInt();
01523 throwStatusError(buf, i);
01524 }
01525
01526 final byte[] handle=buf.getString();
01527
01528 java.io.InputStream in=new java.io.InputStream(){
01529 long offset=skip;
01530 boolean closed=false;
01531 int rest_length=0;
01532 byte[] _data=new byte[1];
01533 byte[] rest_byte=new byte[1024];
01534 Header header=new Header();
01535
01536 public int read() throws java.io.IOException{
01537 if(closed)return -1;
01538 int i=read(_data, 0, 1);
01539 if (i==-1) { return -1; }
01540 else {
01541 return _data[0]&0xff;
01542 }
01543 }
01544 public int read(byte[] d) throws java.io.IOException{
01545 if(closed)return -1;
01546 return read(d, 0, d.length);
01547 }
01548 public int read(byte[] d, int s, int len) throws java.io.IOException{
01549 if(closed)return -1;
01550 if(d==null){throw new NullPointerException();}
01551 if(s<0 || len <0 || s+len>d.length){
01552 throw new IndexOutOfBoundsException();
01553 }
01554 if(len==0){ return 0; }
01555
01556 if(rest_length>0){
01557 int foo=rest_length;
01558 if(foo>len) foo=len;
01559 System.arraycopy(rest_byte, 0, d, s, foo);
01560 if(foo!=rest_length){
01561 System.arraycopy(rest_byte, foo,
01562 rest_byte, 0, rest_length-foo);
01563 }
01564
01565 if(monitor!=null){
01566 if(!monitor.count(foo)){
01567 close();
01568 return -1;
01569 }
01570 }
01571
01572 rest_length-=foo;
01573 return foo;
01574 }
01575
01576 if(buf.buffer.length-13<len){
01577 len=buf.buffer.length-13;
01578 }
01579 if(server_version==0 && len>1024){
01580 len=1024;
01581 }
01582
01583 try{sendREAD(handle, offset, len);}
01584 catch(Exception e){ throw new IOException("error"); }
01585
01586 header=header(buf, header);
01587 rest_length=header.length;
01588 int type=header.type;
01589 int id=header.rid;
01590
01591 if(type!=SSH_FXP_STATUS && type!=SSH_FXP_DATA){
01592 throw new IOException("error");
01593 }
01594 if(type==SSH_FXP_STATUS){
01595 fill(buf, rest_length);
01596 int i=buf.getInt();
01597 rest_length=0;
01598 if(i==SSH_FX_EOF){
01599 close();
01600 return -1;
01601 }
01602
01603 throw new IOException("error");
01604 }
01605 buf.rewind();
01606 fill(buf.buffer, 0, 4);
01607 int length_of_data = buf.getInt(); rest_length-=4;
01608
01619 int optional_data = rest_length - length_of_data;
01620
01621 offset += length_of_data;
01622 int foo = length_of_data;
01623 if(foo>0){
01624 int bar=foo;
01625 if(bar>len){
01626 bar=len;
01627 }
01628 int i=io_in.read(d, s, bar);
01629 if(i<0){
01630 return -1;
01631 }
01632 foo-=i;
01633 rest_length=foo;
01634
01635 if(foo>0){
01636 if(rest_byte.length<foo){
01637 rest_byte=new byte[foo];
01638 }
01639 int _s=0;
01640 int _len=foo;
01641 int j;
01642 while(_len>0){
01643 j=io_in.read(rest_byte, _s, _len);
01644 if(j<=0)break;
01645 _s+=j;
01646 _len-=j;
01647 }
01648 }
01649
01650 if(optional_data>0){
01651 io_in.skip(optional_data);
01652 }
01653
01654 if(monitor!=null){
01655 if(!monitor.count(i)){
01656 close();
01657 return -1;
01658 }
01659 }
01660
01661 return i;
01662 }
01663 return 0;
01664 }
01665 public void close() throws IOException{
01666 if(closed)return;
01667 closed=true;
01668 if(monitor!=null)monitor.end();
01669 try{_sendCLOSE(handle, header);}
01670 catch(Exception e){throw new IOException("error");}
01671 }
01672 };
01673 return in;
01674 }
01675 catch(Exception e){
01676 if(e instanceof SftpException) throw (SftpException)e;
01677 if(e instanceof Throwable)
01678 throw new SftpException(SSH_FX_FAILURE, "", (Throwable)e);
01679 throw new SftpException(SSH_FX_FAILURE, "");
01680 }
01681 }
01682
01691 public java.util.Vector ls(String path) throws SftpException{
01692
01693 try{
01694 ((MyPipedInputStream)io_in).updateReadSide();
01695
01696 path=remoteAbsolutePath(path);
01697 byte[] pattern=null;
01698 java.util.Vector v=new java.util.Vector();
01699
01700 int foo=path.lastIndexOf('/');
01701 String dir=path.substring(0, ((foo==0)?1:foo));
01702 String _pattern=path.substring(foo+1);
01703 dir=Util.unquote(dir);
01704
01705
01706
01707 byte[][] _pattern_utf8=new byte[1][];
01708 boolean pattern_has_wildcard=isPattern(_pattern, _pattern_utf8);
01709
01710 if(pattern_has_wildcard){
01711 pattern=_pattern_utf8[0];
01712 }
01713 else{
01714 String upath=Util.unquote(path);
01715
01716 SftpATTRS attr=_stat(upath);
01717 if(attr.isDir()){
01718 pattern=null;
01719 dir=upath;
01720 }
01721 else{
01722
01723
01724
01725
01726
01727
01728
01729
01730
01731 if(fEncoding_is_utf8){
01732 pattern=_pattern_utf8[0];
01733 pattern=Util.unquote(pattern);
01734 }
01735 else{
01736 _pattern=Util.unquote(_pattern);
01737 pattern=Util.str2byte(_pattern, fEncoding);
01738 }
01739
01740 }
01741 }
01742
01743 sendOPENDIR(Util.str2byte(dir, fEncoding));
01744
01745 Header header=new Header();
01746 header=header(buf, header);
01747 int length=header.length;
01748 int type=header.type;
01749
01750 fill(buf, length);
01751
01752 if(type!=SSH_FXP_STATUS && type!=SSH_FXP_HANDLE){
01753 throw new SftpException(SSH_FX_FAILURE, "");
01754 }
01755 if(type==SSH_FXP_STATUS){
01756 int i=buf.getInt();
01757 throwStatusError(buf, i);
01758 }
01759
01760 byte[] handle=buf.getString();
01761
01762 while(true){
01763 sendREADDIR(handle);
01764
01765 header=header(buf, header);
01766 length=header.length;
01767 type=header.type;
01768 if(type!=SSH_FXP_STATUS && type!=SSH_FXP_NAME){
01769 throw new SftpException(SSH_FX_FAILURE, "");
01770 }
01771 if(type==SSH_FXP_STATUS){
01772 fill(buf, length);
01773 int i=buf.getInt();
01774 if(i==SSH_FX_EOF)
01775 break;
01776 throwStatusError(buf, i);
01777 }
01778
01779 buf.rewind();
01780 fill(buf.buffer, 0, 4); length-=4;
01781 int count=buf.getInt();
01782
01783 byte[] str;
01784 int flags;
01785
01786 buf.reset();
01787 while(count>0){
01788 if(length>0){
01789 buf.shift();
01790 int j=(buf.buffer.length>(buf.index+length)) ?
01791 length :
01792 (buf.buffer.length-buf.index);
01793 int i=fill(buf.buffer, buf.index, j);
01794 buf.index+=i;
01795 length-=i;
01796 }
01797 byte[] filename=buf.getString();
01798 byte[] longname=null;
01799 if(server_version<=3){
01800 longname=buf.getString();
01801 }
01802 SftpATTRS attrs=SftpATTRS.getATTR(buf);
01803
01804 boolean find=false;
01805 String f=null;
01806 if(pattern==null){
01807 find=true;
01808 }
01809 else if(!pattern_has_wildcard){
01810 find=Util.array_equals(pattern, filename);
01811 }
01812 else{
01813 byte[] _filename=filename;
01814 if(!fEncoding_is_utf8){
01815 f=Util.byte2str(_filename, fEncoding);
01816 _filename=Util.str2byte(f, UTF8);
01817 }
01818 find=Util.glob(pattern, _filename);
01819 }
01820
01821 if(find){
01822 if(f==null){
01823 f=Util.byte2str(filename, fEncoding);
01824 }
01825 String l=null;
01826 if(longname==null){
01827
01828
01829 l=attrs.toString()+" "+f;
01830 }
01831 else{
01832 l=Util.byte2str(longname, fEncoding);
01833 }
01834 v.addElement(new LsEntry(f, l, attrs));
01835 }
01836
01837 count--;
01838 }
01839 }
01840 _sendCLOSE(handle, header);
01841
01842
01843
01844
01845
01846
01847
01848
01849
01850
01851
01852
01853
01854
01855
01856
01857
01858
01859 return v;
01860 }
01861 catch(Exception e){
01862 if(e instanceof SftpException) throw (SftpException)e;
01863 if(e instanceof Throwable)
01864 throw new SftpException(SSH_FX_FAILURE, "", (Throwable)e);
01865 throw new SftpException(SSH_FX_FAILURE, "");
01866 }
01867 }
01868
01878 public String readlink(String path) throws SftpException{
01879 try{
01880 if(server_version<3){
01881 throw new SftpException(SSH_FX_OP_UNSUPPORTED,
01882 "The remote sshd is too old to support symlink operation.");
01883 }
01884
01885 ((MyPipedInputStream)io_in).updateReadSide();
01886
01887 path=remoteAbsolutePath(path);
01888
01889 path=isUnique(path);
01890
01891 sendREADLINK(Util.str2byte(path, fEncoding));
01892
01893 Header header=new Header();
01894 header=header(buf, header);
01895 int length=header.length;
01896 int type=header.type;
01897
01898 fill(buf, length);
01899
01900 if(type!=SSH_FXP_STATUS && type!=SSH_FXP_NAME){
01901 throw new SftpException(SSH_FX_FAILURE, "");
01902 }
01903 if(type==SSH_FXP_NAME){
01904 int count=buf.getInt();
01905 byte[] filename=null;
01906 for(int i=0; i<count; i++){
01907 filename=buf.getString();
01908 if(server_version<=3){
01909 byte[] longname=buf.getString();
01910 }
01911 SftpATTRS.getATTR(buf);
01912 }
01913 return Util.byte2str(filename, fEncoding);
01914 }
01915
01916 int i=buf.getInt();
01917 throwStatusError(buf, i);
01918 }
01919 catch(Exception e){
01920 if(e instanceof SftpException) throw (SftpException)e;
01921 if(e instanceof Throwable)
01922 throw new SftpException(SSH_FX_FAILURE, "", (Throwable)e);
01923 throw new SftpException(SSH_FX_FAILURE, "");
01924 }
01925 return null;
01926 }
01927
01948 public void symlink(String oldpath, String newpath) throws SftpException{
01949 if(server_version<3){
01950 throw new SftpException(SSH_FX_OP_UNSUPPORTED,
01951 "The remote sshd is too old to support symlink operation.");
01952 }
01953
01954 try{
01955 ((MyPipedInputStream)io_in).updateReadSide();
01956
01957 oldpath=remoteAbsolutePath(oldpath);
01958 newpath=remoteAbsolutePath(newpath);
01959
01960 oldpath=isUnique(oldpath);
01961
01962 if(isPattern(newpath)){
01963 throw new SftpException(SSH_FX_FAILURE, newpath);
01964 }
01965 newpath=Util.unquote(newpath);
01966
01967 sendSYMLINK(Util.str2byte(oldpath, fEncoding),
01968 Util.str2byte(newpath, fEncoding));
01969
01970 Header header=new Header();
01971 header=header(buf, header);
01972 int length=header.length;
01973 int type=header.type;
01974
01975 fill(buf, length);
01976
01977 if(type!=SSH_FXP_STATUS){
01978 throw new SftpException(SSH_FX_FAILURE, "");
01979 }
01980
01981 int i=buf.getInt();
01982 if(i==SSH_FX_OK) return;
01983 throwStatusError(buf, i);
01984 }
01985 catch(Exception e){
01986 if(e instanceof SftpException) throw (SftpException)e;
01987 if(e instanceof Throwable)
01988 throw new SftpException(SSH_FX_FAILURE, "", (Throwable)e);
01989 throw new SftpException(SSH_FX_FAILURE, "");
01990 }
01991 }
01992
02001 public void rename(String oldpath, String newpath) throws SftpException{
02002 if(server_version<2){
02003 throw new SftpException(SSH_FX_OP_UNSUPPORTED,
02004 "The remote sshd is too old to support rename operation.");
02005 }
02006
02007 try{
02008 ((MyPipedInputStream)io_in).updateReadSide();
02009
02010 oldpath=remoteAbsolutePath(oldpath);
02011 newpath=remoteAbsolutePath(newpath);
02012
02013 oldpath=isUnique(oldpath);
02014
02015 Vector v=glob_remote(newpath);
02016 int vsize=v.size();
02017 if(vsize>=2){
02018 throw new SftpException(SSH_FX_FAILURE, v.toString());
02019 }
02020 if(vsize==1){
02021 newpath=(String)(v.elementAt(0));
02022 }
02023 else{
02024 if(isPattern(newpath))
02025 throw new SftpException(SSH_FX_FAILURE, newpath);
02026 newpath=Util.unquote(newpath);
02027 }
02028
02029 sendRENAME(Util.str2byte(oldpath, fEncoding),
02030 Util.str2byte(newpath, fEncoding));
02031
02032 Header header=new Header();
02033 header=header(buf, header);
02034 int length=header.length;
02035 int type=header.type;
02036
02037 fill(buf, length);
02038
02039 if(type!=SSH_FXP_STATUS){
02040 throw new SftpException(SSH_FX_FAILURE, "");
02041 }
02042
02043 int i=buf.getInt();
02044 if(i==SSH_FX_OK) return;
02045 throwStatusError(buf, i);
02046 }
02047 catch(Exception e){
02048 if(e instanceof SftpException) throw (SftpException)e;
02049 if(e instanceof Throwable)
02050 throw new SftpException(SSH_FX_FAILURE, "", (Throwable)e);
02051 throw new SftpException(SSH_FX_FAILURE, "");
02052 }
02053 }
02054
02061 public void rm(String path) throws SftpException{
02062 try{
02063 ((MyPipedInputStream)io_in).updateReadSide();
02064
02065 path=remoteAbsolutePath(path);
02066
02067 Vector v=glob_remote(path);
02068 int vsize=v.size();
02069
02070 Header header=new Header();
02071
02072 for(int j=0; j<vsize; j++){
02073 path=(String)(v.elementAt(j));
02074 sendREMOVE(Util.str2byte(path, fEncoding));
02075
02076 header=header(buf, header);
02077 int length=header.length;
02078 int type=header.type;
02079
02080 fill(buf, length);
02081
02082 if(type!=SSH_FXP_STATUS){
02083 throw new SftpException(SSH_FX_FAILURE, "");
02084 }
02085 int i=buf.getInt();
02086 if(i!=SSH_FX_OK){
02087 throwStatusError(buf, i);
02088 }
02089 }
02090 }
02091 catch(Exception e){
02092 if(e instanceof SftpException) throw (SftpException)e;
02093 if(e instanceof Throwable)
02094 throw new SftpException(SSH_FX_FAILURE, "", (Throwable)e);
02095 throw new SftpException(SSH_FX_FAILURE, "");
02096 }
02097 }
02098
02099 private boolean isRemoteDir(String path){
02100 try{
02101 sendSTAT(Util.str2byte(path, fEncoding));
02102
02103 Header header=new Header();
02104 header=header(buf, header);
02105 int length=header.length;
02106 int type=header.type;
02107
02108 fill(buf, length);
02109
02110 if(type!=SSH_FXP_ATTRS){
02111 return false;
02112 }
02113 SftpATTRS attr=SftpATTRS.getATTR(buf);
02114 return attr.isDir();
02115 }
02116 catch(Exception e){}
02117 return false;
02118 }
02119
02126 public void chgrp(int gid, String path) throws SftpException{
02127 try{
02128 ((MyPipedInputStream)io_in).updateReadSide();
02129
02130 path=remoteAbsolutePath(path);
02131
02132 Vector v=glob_remote(path);
02133 int vsize=v.size();
02134 for(int j=0; j<vsize; j++){
02135 path=(String)(v.elementAt(j));
02136
02137 SftpATTRS attr=_stat(path);
02138
02139 attr.setFLAGS(0);
02140 attr.setUIDGID(attr.uid, gid);
02141 _setStat(path, attr);
02142 }
02143 }
02144 catch(Exception e){
02145 if(e instanceof SftpException) throw (SftpException)e;
02146 if(e instanceof Throwable)
02147 throw new SftpException(SSH_FX_FAILURE, "", (Throwable)e);
02148 throw new SftpException(SSH_FX_FAILURE, "");
02149 }
02150 }
02151
02158 public void chown(int uid, String path) throws SftpException{
02159 try{
02160 ((MyPipedInputStream)io_in).updateReadSide();
02161
02162 path=remoteAbsolutePath(path);
02163
02164 Vector v=glob_remote(path);
02165 int vsize=v.size();
02166 for(int j=0; j<vsize; j++){
02167 path=(String)(v.elementAt(j));
02168
02169 SftpATTRS attr=_stat(path);
02170
02171 attr.setFLAGS(0);
02172 attr.setUIDGID(uid, attr.gid);
02173 _setStat(path, attr);
02174 }
02175 }
02176 catch(Exception e){
02177 if(e instanceof SftpException) throw (SftpException)e;
02178 if(e instanceof Throwable)
02179 throw new SftpException(SSH_FX_FAILURE, "", (Throwable)e);
02180 throw new SftpException(SSH_FX_FAILURE, "");
02181 }
02182 }
02183
02191 public void chmod(int permissions, String path) throws SftpException{
02192 try{
02193 ((MyPipedInputStream)io_in).updateReadSide();
02194
02195 path=remoteAbsolutePath(path);
02196
02197 Vector v=glob_remote(path);
02198 int vsize=v.size();
02199 for(int j=0; j<vsize; j++){
02200 path=(String)(v.elementAt(j));
02201
02202 SftpATTRS attr=_stat(path);
02203
02204 attr.setFLAGS(0);
02205 attr.setPERMISSIONS(permissions);
02206 _setStat(path, attr);
02207 }
02208 }
02209 catch(Exception e){
02210 if(e instanceof SftpException) throw (SftpException)e;
02211 if(e instanceof Throwable)
02212 throw new SftpException(SSH_FX_FAILURE, "", (Throwable)e);
02213 throw new SftpException(SSH_FX_FAILURE, "");
02214 }
02215 }
02216
02224 public void setMtime(String path, int mtime) throws SftpException{
02225 try{
02226 ((MyPipedInputStream)io_in).updateReadSide();
02227
02228 path=remoteAbsolutePath(path);
02229
02230 Vector v=glob_remote(path);
02231 int vsize=v.size();
02232 for(int j=0; j<vsize; j++){
02233 path=(String)(v.elementAt(j));
02234
02235 SftpATTRS attr=_stat(path);
02236
02237 attr.setFLAGS(0);
02238 attr.setACMODTIME(attr.getATime(), mtime);
02239 _setStat(path, attr);
02240 }
02241 }
02242 catch(Exception e){
02243 if(e instanceof SftpException) throw (SftpException)e;
02244 if(e instanceof Throwable)
02245 throw new SftpException(SSH_FX_FAILURE, "", (Throwable)e);
02246 throw new SftpException(SSH_FX_FAILURE, "");
02247 }
02248 }
02249
02250
02256 public void rmdir(String path) throws SftpException{
02257 try{
02258 ((MyPipedInputStream)io_in).updateReadSide();
02259
02260 path=remoteAbsolutePath(path);
02261
02262 Vector v=glob_remote(path);
02263 int vsize=v.size();
02264
02265 Header header=new Header();
02266
02267 for(int j=0; j<vsize; j++){
02268 path=(String)(v.elementAt(j));
02269 sendRMDIR(Util.str2byte(path, fEncoding));
02270
02271 header=header(buf, header);
02272 int length=header.length;
02273 int type=header.type;
02274
02275 fill(buf, length);
02276
02277 if(type!=SSH_FXP_STATUS){
02278 throw new SftpException(SSH_FX_FAILURE, "");
02279 }
02280
02281 int i=buf.getInt();
02282 if(i!=SSH_FX_OK){
02283 throwStatusError(buf, i);
02284 }
02285 }
02286 }
02287 catch(Exception e){
02288 if(e instanceof SftpException) throw (SftpException)e;
02289 if(e instanceof Throwable)
02290 throw new SftpException(SSH_FX_FAILURE, "", (Throwable)e);
02291 throw new SftpException(SSH_FX_FAILURE, "");
02292 }
02293 }
02294
02295
02301 public void mkdir(String path) throws SftpException{
02302 try{
02303 ((MyPipedInputStream)io_in).updateReadSide();
02304
02305 path=remoteAbsolutePath(path);
02306
02307 sendMKDIR(Util.str2byte(path, fEncoding), null);
02308
02309 Header header=new Header();
02310 header=header(buf, header);
02311 int length=header.length;
02312 int type=header.type;
02313
02314 fill(buf, length);
02315
02316 if(type!=SSH_FXP_STATUS){
02317 throw new SftpException(SSH_FX_FAILURE, "");
02318 }
02319
02320 int i=buf.getInt();
02321 if(i==SSH_FX_OK) return;
02322 throwStatusError(buf, i);
02323 }
02324 catch(Exception e){
02325 if(e instanceof SftpException) throw (SftpException)e;
02326 if(e instanceof Throwable)
02327 throw new SftpException(SSH_FX_FAILURE, "", (Throwable)e);
02328 throw new SftpException(SSH_FX_FAILURE, "");
02329 }
02330 }
02331
02342 public SftpATTRS stat(String path) throws SftpException{
02343 try{
02344 ((MyPipedInputStream)io_in).updateReadSide();
02345
02346 path=remoteAbsolutePath(path);
02347 path=isUnique(path);
02348
02349 return _stat(path);
02350 }
02351 catch(Exception e){
02352 if(e instanceof SftpException) throw (SftpException)e;
02353 if(e instanceof Throwable)
02354 throw new SftpException(SSH_FX_FAILURE, "", (Throwable)e);
02355 throw new SftpException(SSH_FX_FAILURE, "");
02356 }
02357
02358 }
02359
02360 private SftpATTRS _stat(byte[] path) throws SftpException{
02361 try{
02362
02363 sendSTAT(path);
02364
02365 Header header=new Header();
02366 header=header(buf, header);
02367 int length=header.length;
02368 int type=header.type;
02369
02370 fill(buf, length);
02371
02372 if(type!=SSH_FXP_ATTRS){
02373 if(type==SSH_FXP_STATUS){
02374 int i=buf.getInt();
02375 throwStatusError(buf, i);
02376 }
02377 throw new SftpException(SSH_FX_FAILURE, "");
02378 }
02379 SftpATTRS attr=SftpATTRS.getATTR(buf);
02380 return attr;
02381 }
02382 catch(Exception e){
02383 if(e instanceof SftpException) throw (SftpException)e;
02384 if(e instanceof Throwable)
02385 throw new SftpException(SSH_FX_FAILURE, "", (Throwable)e);
02386 throw new SftpException(SSH_FX_FAILURE, "");
02387 }
02388
02389 }
02390
02391 private SftpATTRS _stat(String path) throws SftpException{
02392 return _stat(Util.str2byte(path, fEncoding));
02393 }
02394
02405 public SftpATTRS lstat(String path) throws SftpException{
02406 try{
02407 ((MyPipedInputStream)io_in).updateReadSide();
02408
02409 path=remoteAbsolutePath(path);
02410 path=isUnique(path);
02411
02412 return _lstat(path);
02413 }
02414 catch(Exception e){
02415 if(e instanceof SftpException) throw (SftpException)e;
02416 if(e instanceof Throwable)
02417 throw new SftpException(SSH_FX_FAILURE, "", (Throwable)e);
02418 throw new SftpException(SSH_FX_FAILURE, "");
02419 }
02420 }
02421
02422 private SftpATTRS _lstat(String path) throws SftpException{
02423 try{
02424 sendLSTAT(Util.str2byte(path, fEncoding));
02425
02426 Header header=new Header();
02427 header=header(buf, header);
02428 int length=header.length;
02429 int type=header.type;
02430
02431 fill(buf, length);
02432
02433 if(type!=SSH_FXP_ATTRS){
02434 if(type==SSH_FXP_STATUS){
02435 int i=buf.getInt();
02436 throwStatusError(buf, i);
02437 }
02438 throw new SftpException(SSH_FX_FAILURE, "");
02439 }
02440 SftpATTRS attr=SftpATTRS.getATTR(buf);
02441 return attr;
02442 }
02443 catch(Exception e){
02444 if(e instanceof SftpException) throw (SftpException)e;
02445 if(e instanceof Throwable)
02446 throw new SftpException(SSH_FX_FAILURE, "", (Throwable)e);
02447 throw new SftpException(SSH_FX_FAILURE, "");
02448 }
02449 }
02450
02451 private byte[] _realpath(String path) throws SftpException, IOException, Exception{
02452 sendREALPATH(Util.str2byte(path, fEncoding));
02453
02454 Header header=new Header();
02455 header=header(buf, header);
02456 int length=header.length;
02457 int type=header.type;
02458
02459 fill(buf, length);
02460
02461 if(type!=SSH_FXP_STATUS && type!=SSH_FXP_NAME){
02462 throw new SftpException(SSH_FX_FAILURE, "");
02463 }
02464 int i;
02465 if(type==SSH_FXP_STATUS){
02466 i=buf.getInt();
02467 throwStatusError(buf, i);
02468 }
02469 i=buf.getInt();
02470
02471 byte[] str=null;
02472 while(i-->0){
02473 str=buf.getString();
02474 if(server_version<=3){
02475 byte[] lname=buf.getString();
02476 }
02477 SftpATTRS attr=SftpATTRS.getATTR(buf);
02478 }
02479 return str;
02480 }
02481
02488 public void setStat(String path, SftpATTRS attr) throws SftpException{
02489 try{
02490 ((MyPipedInputStream)io_in).updateReadSide();
02491
02492 path=remoteAbsolutePath(path);
02493
02494 Vector v=glob_remote(path);
02495 int vsize=v.size();
02496 for(int j=0; j<vsize; j++){
02497 path=(String)(v.elementAt(j));
02498 _setStat(path, attr);
02499 }
02500 }
02501 catch(Exception e){
02502 if(e instanceof SftpException) throw (SftpException)e;
02503 if(e instanceof Throwable)
02504 throw new SftpException(SSH_FX_FAILURE, "", (Throwable)e);
02505 throw new SftpException(SSH_FX_FAILURE, "");
02506 }
02507 }
02508 private void _setStat(String path, SftpATTRS attr) throws SftpException{
02509 try{
02510 sendSETSTAT(Util.str2byte(path, fEncoding), attr);
02511
02512 Header header=new Header();
02513 header=header(buf, header);
02514 int length=header.length;
02515 int type=header.type;
02516
02517 fill(buf, length);
02518
02519 if(type!=SSH_FXP_STATUS){
02520 throw new SftpException(SSH_FX_FAILURE, "");
02521 }
02522 int i=buf.getInt();
02523 if(i!=SSH_FX_OK){
02524 throwStatusError(buf, i);
02525 }
02526 }
02527 catch(Exception e){
02528 if(e instanceof SftpException) throw (SftpException)e;
02529 if(e instanceof Throwable)
02530 throw new SftpException(SSH_FX_FAILURE, "", (Throwable)e);
02531 throw new SftpException(SSH_FX_FAILURE, "");
02532 }
02533 }
02534
02540 public String pwd() throws SftpException{ return getCwd(); }
02546 public String lpwd(){ return lcwd; }
02550 public String version(){ return version; }
02551
02555 public String getHome() throws SftpException {
02556 if(home==null){
02557 try{
02558 ((MyPipedInputStream)io_in).updateReadSide();
02559
02560 byte[] _home=_realpath("");
02561 home=Util.byte2str(_home, fEncoding);
02562 }
02563 catch(Exception e){
02564 if(e instanceof SftpException) throw (SftpException)e;
02565 if(e instanceof Throwable)
02566 throw new SftpException(SSH_FX_FAILURE, "", (Throwable)e);
02567 throw new SftpException(SSH_FX_FAILURE, "");
02568 }
02569 }
02570 return home;
02571 }
02572
02573 private String getCwd() throws SftpException{
02574 if(cwd==null)
02575 cwd=getHome();
02576 return cwd;
02577 }
02578
02579 private void setCwd(String cwd){
02580 this.cwd=cwd;
02581 }
02582
02583 private void read(byte[] buf, int s, int l) throws IOException, SftpException{
02584 int i=0;
02585 while(l>0){
02586 i=io_in.read(buf, s, l);
02587 if(i<=0){
02588 throw new SftpException(SSH_FX_FAILURE, "");
02589 }
02590 s+=i;
02591 l-=i;
02592 }
02593 }
02594
02595 private boolean checkStatus(int[] ackid, Header header) throws IOException, SftpException{
02596 header=header(buf, header);
02597 int length=header.length;
02598 int type=header.type;
02599 if(ackid!=null)
02600 ackid[0]=header.rid;
02601
02602 fill(buf, length);
02603
02604 if(type!=SSH_FXP_STATUS){
02605 throw new SftpException(SSH_FX_FAILURE, "");
02606 }
02607 int i=buf.getInt();
02608 if(i!=SSH_FX_OK){
02609 throwStatusError(buf, i);
02610 }
02611 return true;
02612 }
02613 private boolean _sendCLOSE(byte[] handle, Header header) throws Exception{
02614 sendCLOSE(handle);
02615 return checkStatus(null, header);
02616 }
02617
02618 private void sendINIT() throws Exception{
02619 packet.reset();
02620 putHEAD(SSH_FXP_INIT, 5);
02621 buf.putInt(3);
02622 getSession().write(packet, this, 5+4);
02623 }
02624
02625 private void sendREALPATH(byte[] path) throws Exception{
02626 sendPacketPath(SSH_FXP_REALPATH, path);
02627 }
02628 private void sendSTAT(byte[] path) throws Exception{
02629 sendPacketPath(SSH_FXP_STAT, path);
02630 }
02631 private void sendLSTAT(byte[] path) throws Exception{
02632 sendPacketPath(SSH_FXP_LSTAT, path);
02633 }
02634 private void sendFSTAT(byte[] handle) throws Exception{
02635 sendPacketPath(SSH_FXP_FSTAT, handle);
02636 }
02637 private void sendSETSTAT(byte[] path, SftpATTRS attr) throws Exception{
02638 packet.reset();
02639 putHEAD(SSH_FXP_SETSTAT, 9+path.length+attr.length());
02640 buf.putInt(seq++);
02641 buf.putString(path);
02642 attr.dump(buf);
02643 getSession().write(packet, this, 9+path.length+attr.length()+4);
02644 }
02645 private void sendREMOVE(byte[] path) throws Exception{
02646 sendPacketPath(SSH_FXP_REMOVE, path);
02647 }
02648 private void sendMKDIR(byte[] path, SftpATTRS attr) throws Exception{
02649 packet.reset();
02650 putHEAD(SSH_FXP_MKDIR, 9+path.length+(attr!=null?attr.length():4));
02651 buf.putInt(seq++);
02652 buf.putString(path);
02653 if(attr!=null) attr.dump(buf);
02654 else buf.putInt(0);
02655 getSession().write(packet, this, 9+path.length+(attr!=null?attr.length():4)+4);
02656 }
02657 private void sendRMDIR(byte[] path) throws Exception{
02658 sendPacketPath(SSH_FXP_RMDIR, path);
02659 }
02660 private void sendSYMLINK(byte[] p1, byte[] p2) throws Exception{
02661 sendPacketPath(SSH_FXP_SYMLINK, p1, p2);
02662 }
02663 private void sendREADLINK(byte[] path) throws Exception{
02664 sendPacketPath(SSH_FXP_READLINK, path);
02665 }
02666 private void sendOPENDIR(byte[] path) throws Exception{
02667 sendPacketPath(SSH_FXP_OPENDIR, path);
02668 }
02669 private void sendREADDIR(byte[] path) throws Exception{
02670 sendPacketPath(SSH_FXP_READDIR, path);
02671 }
02672 private void sendRENAME(byte[] p1, byte[] p2) throws Exception{
02673 sendPacketPath(SSH_FXP_RENAME, p1, p2);
02674 }
02675 private void sendCLOSE(byte[] path) throws Exception{
02676 sendPacketPath(SSH_FXP_CLOSE, path);
02677 }
02678 private void sendOPENR(byte[] path) throws Exception{
02679 sendOPEN(path, SSH_FXF_READ);
02680 }
02681 private void sendOPENW(byte[] path) throws Exception{
02682 sendOPEN(path, SSH_FXF_WRITE|SSH_FXF_CREAT|SSH_FXF_TRUNC);
02683 }
02684 private void sendOPENA(byte[] path) throws Exception{
02685 sendOPEN(path, SSH_FXF_WRITE|SSH_FXF_CREAT);
02686 }
02687 private void sendOPEN(byte[] path, int mode) throws Exception{
02688 packet.reset();
02689 putHEAD(SSH_FXP_OPEN, 17+path.length);
02690 buf.putInt(seq++);
02691 buf.putString(path);
02692 buf.putInt(mode);
02693 buf.putInt(0);
02694 getSession().write(packet, this, 17+path.length+4);
02695 }
02696 private void sendPacketPath(byte fxp, byte[] path) throws Exception{
02697 packet.reset();
02698 putHEAD(fxp, 9+path.length);
02699 buf.putInt(seq++);
02700 buf.putString(path);
02701 getSession().write(packet, this, 9+path.length+4);
02702 }
02703 private void sendPacketPath(byte fxp, byte[] p1, byte[] p2) throws Exception{
02704 packet.reset();
02705 putHEAD(fxp, 13+p1.length+p2.length);
02706 buf.putInt(seq++);
02707 buf.putString(p1);
02708 buf.putString(p2);
02709 getSession().write(packet, this, 13+p1.length+p2.length+4);
02710 }
02711
02712 private int sendWRITE(byte[] handle, long offset,
02713 byte[] data, int start, int length) throws Exception{
02714 int _length=length;
02715 opacket.reset();
02716 if(obuf.buffer.length<obuf.index+13+21+handle.length+length+Session.buffer_margin){
02717 _length=obuf.buffer.length-(obuf.index+13+21+handle.length+Session.buffer_margin);
02718
02719 }
02720
02721 putHEAD(obuf, SSH_FXP_WRITE, 21+handle.length+_length);
02722 obuf.putInt(seq++);
02723 obuf.putString(handle);
02724 obuf.putLong(offset);
02725 if(obuf.buffer!=data){
02726 obuf.putString(data, start, _length);
02727 }
02728 else{
02729 obuf.putInt(_length);
02730 obuf.skip(_length);
02731 }
02732 getSession().write(opacket, this, 21+handle.length+_length+4);
02733 return _length;
02734 }
02735 private void sendREAD(byte[] handle, long offset, int length) throws Exception{
02736 sendREAD(handle, offset, length, null);
02737 }
02738 private void sendREAD(byte[] handle, long offset, int length,
02739 RequestQueue rrq) throws Exception{
02740 packet.reset();
02741 putHEAD(SSH_FXP_READ, 21+handle.length);
02742 buf.putInt(seq++);
02743 buf.putString(handle);
02744 buf.putLong(offset);
02745 buf.putInt(length);
02746 getSession().write(packet, this, 21+handle.length+4);
02747 if(rrq!=null){
02748 rrq.add(seq-1, offset, length);
02749 }
02750 }
02751
02752 private void putHEAD(Buffer buf, byte type, int length) throws Exception{
02753 buf.putByte((byte)Session.SSH_MSG_CHANNEL_DATA);
02754 buf.putInt(recipient);
02755 buf.putInt(length+4);
02756 buf.putInt(length);
02757 buf.putByte(type);
02758 }
02759
02760 private void putHEAD(byte type, int length) throws Exception{
02761 putHEAD(buf, type, length);
02762 }
02763
02764 private Vector glob_remote(String _path) throws Exception{
02765 Vector v=new Vector();
02766 int i=0;
02767
02768 int foo=_path.lastIndexOf('/');
02769 if(foo<0){
02770 v.addElement(Util.unquote(_path));
02771 return v;
02772 }
02773
02774 String dir=_path.substring(0, ((foo==0)?1:foo));
02775 String _pattern=_path.substring(foo+1);
02776
02777 dir=Util.unquote(dir);
02778
02779 byte[] pattern=null;
02780 byte[][] _pattern_utf8=new byte[1][];
02781 boolean pattern_has_wildcard=isPattern(_pattern, _pattern_utf8);
02782
02783 if(!pattern_has_wildcard){
02784 if(!dir.equals("/"))
02785 dir+="/";
02786 v.addElement(dir+Util.unquote(_pattern));
02787 return v;
02788 }
02789
02790 pattern=_pattern_utf8[0];
02791
02792 sendOPENDIR(Util.str2byte(dir, fEncoding));
02793
02794 Header header=new Header();
02795 header=header(buf, header);
02796 int length=header.length;
02797 int type=header.type;
02798
02799 fill(buf, length);
02800
02801 if(type!=SSH_FXP_STATUS && type!=SSH_FXP_HANDLE){
02802 throw new SftpException(SSH_FX_FAILURE, "");
02803 }
02804 if(type==SSH_FXP_STATUS){
02805 i=buf.getInt();
02806 throwStatusError(buf, i);
02807 }
02808
02809 byte[] handle=buf.getString();
02810 String pdir=null;
02811
02812 while(true){
02813 sendREADDIR(handle);
02814 header=header(buf, header);
02815 length=header.length;
02816 type=header.type;
02817
02818 if(type!=SSH_FXP_STATUS && type!=SSH_FXP_NAME){
02819 throw new SftpException(SSH_FX_FAILURE, "");
02820 }
02821 if(type==SSH_FXP_STATUS){
02822 fill(buf, length);
02823 break;
02824 }
02825
02826 buf.rewind();
02827 fill(buf.buffer, 0, 4); length-=4;
02828 int count=buf.getInt();
02829
02830 byte[] str;
02831 int flags;
02832
02833 buf.reset();
02834 while(count>0){
02835 if(length>0){
02836 buf.shift();
02837 int j=(buf.buffer.length>(buf.index+length)) ? length : (buf.buffer.length-buf.index);
02838 i=io_in.read(buf.buffer, buf.index, j);
02839 if(i<=0)break;
02840 buf.index+=i;
02841 length-=i;
02842 }
02843
02844 byte[] filename=buf.getString();
02845
02846 if(server_version<=3){
02847 str=buf.getString();
02848 }
02849 SftpATTRS attrs=SftpATTRS.getATTR(buf);
02850
02851 byte[] _filename=filename;
02852 String f=null;
02853 boolean found=false;
02854
02855 if(!fEncoding_is_utf8){
02856 f=Util.byte2str(filename, fEncoding);
02857 _filename=Util.str2byte(f, UTF8);
02858 }
02859 found=Util.glob(pattern, _filename);
02860
02861 if(found){
02862 if(f==null){
02863 f=Util.byte2str(filename, fEncoding);
02864 }
02865 if(pdir==null){
02866 pdir=dir;
02867 if(!pdir.endsWith("/")){
02868 pdir+="/";
02869 }
02870 }
02871 v.addElement(pdir+f);
02872 }
02873 count--;
02874 }
02875 }
02876 if(_sendCLOSE(handle, header))
02877 return v;
02878 return null;
02879 }
02880
02881 private boolean isPattern(byte[] path){
02882 int length=path.length;
02883 int i=0;
02884 while(i<length){
02885 if(path[i]=='*' || path[i]=='?')
02886 return true;
02887 if(path[i]=='\\' && (i+1)<length)
02888 i++;
02889 i++;
02890 }
02891 return false;
02892 }
02893
02894 private Vector glob_local(String _path) throws Exception{
02895
02896 Vector v=new Vector();
02897 byte[] path=Util.str2byte(_path, UTF8);
02898 int i=path.length-1;
02899 while(i>=0){
02900 if(path[i]!='*' && path[i]!='?'){
02901 i--;
02902 continue;
02903 }
02904 if(!fs_is_bs &&
02905 i>0 && path[i-1]=='\\'){
02906 i--;
02907 if(i>0 && path[i-1]=='\\'){
02908 i--;
02909 i--;
02910 continue;
02911 }
02912 }
02913 break;
02914 }
02915
02916 if(i<0){ v.addElement(fs_is_bs ? _path : Util.unquote(_path)); return v;}
02917
02918 while(i>=0){
02919 if(path[i]==file_separatorc ||
02920 (fs_is_bs && path[i]=='/')){
02921 break;
02922 }
02923 i--;
02924 }
02925
02926 if(i<0){ v.addElement(fs_is_bs ? _path : Util.unquote(_path)); return v;}
02927
02928 byte[] dir;
02929 if(i==0){dir=new byte[]{(byte)file_separatorc};}
02930 else{
02931 dir=new byte[i];
02932 System.arraycopy(path, 0, dir, 0, i);
02933 }
02934
02935 byte[] pattern=new byte[path.length-i-1];
02936 System.arraycopy(path, i+1, pattern, 0, pattern.length);
02937
02938
02939 try{
02940 String[] children=(new File(Util.byte2str(dir, UTF8))).list();
02941 String pdir=Util.byte2str(dir)+file_separator;
02942 for(int j=0; j<children.length; j++){
02943
02944 if(Util.glob(pattern, Util.str2byte(children[j], UTF8))){
02945 v.addElement(pdir+children[j]);
02946 }
02947 }
02948 }
02949 catch(Exception e){
02950 }
02951 return v;
02952 }
02953
02954 private void throwStatusError(Buffer buf, int i) throws SftpException{
02955 if(server_version>=3 &&
02956 buf.getLength()>=4){
02957 byte[] str=buf.getString();
02958
02959 throw new SftpException(i, Util.byte2str(str, UTF8));
02960 }
02961 else{
02962 throw new SftpException(i, "Failure");
02963 }
02964 }
02965
02966 private static boolean isLocalAbsolutePath(String path){
02967 return (new File(path)).isAbsolute();
02968 }
02969
02973 public void disconnect(){
02974 super.disconnect();
02975 }
02976
02977 private boolean isPattern(String path, byte[][] utf8){
02978 byte[] _path=Util.str2byte(path, UTF8);
02979 if(utf8!=null)
02980 utf8[0]=_path;
02981 return isPattern(_path);
02982 }
02983
02984 private boolean isPattern(String path){
02985 return isPattern(path, null);
02986 }
02987
02988 private void fill(Buffer buf, int len) throws IOException{
02989 buf.reset();
02990 fill(buf.buffer, 0, len);
02991 buf.skip(len);
02992 }
02993
02994 private int fill(byte[] buf, int s, int len) throws IOException{
02995 int i=0;
02996 int foo=s;
02997 while(len>0){
02998 i=io_in.read(buf, s, len);
02999 if(i<=0){
03000 throw new IOException("inputstream is closed");
03001
03002 }
03003 s+=i;
03004 len-=i;
03005 }
03006 return s-foo;
03007 }
03008 private void skip(long foo) throws IOException{
03009 while(foo>0){
03010 long bar=io_in.skip(foo);
03011 if(bar<=0)
03012 break;
03013 foo-=bar;
03014 }
03015 }
03016
03017 class Header{
03018 int length;
03019 int type;
03020 int rid;
03021 }
03022 private Header header(Buffer buf, Header header) throws IOException{
03023 buf.rewind();
03024 int i=fill(buf.buffer, 0, 9);
03025 header.length=buf.getInt()-5;
03026 header.type=buf.getByte()&0xff;
03027 header.rid=buf.getInt();
03028 return header;
03029 }
03030
03031 private String remoteAbsolutePath(String path) throws SftpException{
03032 if(path.charAt(0)=='/') return path;
03033 String cwd=getCwd();
03034
03035 if(cwd.endsWith("/")) return cwd+path;
03036 return cwd+"/"+path;
03037 }
03038
03039 private String localAbsolutePath(String path){
03040 if(isLocalAbsolutePath(path)) return path;
03041 if(lcwd.endsWith(file_separator)) return lcwd+path;
03042 return lcwd+file_separator+path;
03043 }
03044
03051 private String isUnique(String path) throws SftpException, Exception{
03052 Vector v=glob_remote(path);
03053 if(v.size()!=1){
03054 throw new SftpException(SSH_FX_FAILURE, path+" is not unique: "+v.toString());
03055 }
03056 return (String)(v.elementAt(0));
03057 }
03058
03062 public int getServerVersion() throws SftpException{
03063 if(!isConnected()){
03064 throw new SftpException(SSH_FX_FAILURE, "The channel is not connected.");
03065 }
03066 return server_version;
03067 }
03068
03079 public void setFilenameEncoding(String encoding) throws SftpException{
03080 int sversion=getServerVersion();
03081 if(3 <= sversion && sversion <= 5 &&
03082 !encoding.equals(UTF8)){
03083 throw new SftpException(SSH_FX_FAILURE,
03084 "The encoding can not be changed for this sftp server.");
03085 }
03086 if(encoding.equals(UTF8)){
03087 encoding=UTF8;
03088 }
03089 fEncoding=encoding;
03090 fEncoding_is_utf8=fEncoding.equals(UTF8);
03091 }
03092
03099 public String getExtension(String key){
03100 if(extensions==null)
03101 return null;
03102 return (String)extensions.get(key);
03103 }
03104
03113 public String realpath(String path) throws SftpException{
03114 try{
03115 byte[] _path=_realpath(remoteAbsolutePath(path));
03116 return Util.byte2str(_path, fEncoding);
03117 }
03118 catch(Exception e){
03119 if(e instanceof SftpException) throw (SftpException)e;
03120 if(e instanceof Throwable)
03121 throw new SftpException(SSH_FX_FAILURE, "", (Throwable)e);
03122 throw new SftpException(SSH_FX_FAILURE, "");
03123 }
03124 }
03125
03132 public class LsEntry implements Comparable{
03133 private String filename;
03134 private String longname;
03135 private SftpATTRS attrs;
03136 LsEntry(String filename, String longname, SftpATTRS attrs){
03137 setFilename(filename);
03138 setLongname(longname);
03139 setAttrs(attrs);
03140 }
03144 public String getFilename(){return filename;};
03145 void setFilename(String filename){this.filename = filename;};
03151 public String getLongname(){return longname;};
03152 void setLongname(String longname){this.longname = longname;};
03156 public SftpATTRS getAttrs(){return attrs;};
03157 void setAttrs(SftpATTRS attrs) {this.attrs = attrs;};
03161 public String toString(){ return longname; }
03166 public int compareTo(Object o) throws ClassCastException{
03167 if(o instanceof LsEntry){
03168 return filename.compareTo(((LsEntry)o).getFilename());
03169 }
03170 throw new ClassCastException("a decendent of LsEntry must be given.");
03171 }
03172 }
03173 }