1 2 29 30 package com.jcraft.jsch; 31 32 import java.io.*; 33 34 import java.util.Vector ; 35 36 public class ChannelSftp extends ChannelSession{ 37 38 private static final byte SSH_FXP_INIT= 1; 39 private static final byte SSH_FXP_VERSION= 2; 40 private static final byte SSH_FXP_OPEN= 3; 41 private static final byte SSH_FXP_CLOSE= 4; 42 private static final byte SSH_FXP_READ= 5; 43 private static final byte SSH_FXP_WRITE= 6; 44 private static final byte SSH_FXP_LSTAT= 7; 45 private static final byte SSH_FXP_FSTAT= 8; 46 private static final byte SSH_FXP_SETSTAT= 9; 47 private static final byte SSH_FXP_FSETSTAT= 10; 48 private static final byte SSH_FXP_OPENDIR= 11; 49 private static final byte SSH_FXP_READDIR= 12; 50 private static final byte SSH_FXP_REMOVE= 13; 51 private static final byte SSH_FXP_MKDIR= 14; 52 private static final byte SSH_FXP_RMDIR= 15; 53 private static final byte SSH_FXP_REALPATH= 16; 54 private static final byte SSH_FXP_STAT= 17; 55 private static final byte SSH_FXP_RENAME= 18; 56 private static final byte SSH_FXP_READLINK= 19; 57 private static final byte SSH_FXP_SYMLINK= 20; 58 private static final byte SSH_FXP_STATUS= 101; 59 private static final byte SSH_FXP_HANDLE= 102; 60 private static final byte SSH_FXP_DATA= 103; 61 private static final byte SSH_FXP_NAME= 104; 62 private static final byte SSH_FXP_ATTRS= 105; 63 private static final byte SSH_FXP_EXTENDED= (byte)200; 64 private static final byte SSH_FXP_EXTENDED_REPLY= (byte)201; 65 66 private static final int SSH_FXF_READ= 0x00000001; 68 private static final int SSH_FXF_WRITE= 0x00000002; 69 private static final int SSH_FXF_APPEND= 0x00000004; 70 private static final int SSH_FXF_CREAT= 0x00000008; 71 private static final int SSH_FXF_TRUNC= 0x00000010; 72 private static final int SSH_FXF_EXCL= 0x00000020; 73 74 private static final int SSH_FILEXFER_ATTR_SIZE= 0x00000001; 75 private static final int SSH_FILEXFER_ATTR_UIDGID= 0x00000002; 76 private static final int SSH_FILEXFER_ATTR_PERMISSIONS= 0x00000004; 77 private static final int SSH_FILEXFER_ATTR_ACMODTIME= 0x00000008; 78 private static final int SSH_FILEXFER_ATTR_EXTENDED= 0x80000000; 79 80 public static final int SSH_FX_OK= 0; 81 public static final int SSH_FX_EOF= 1; 82 public static final int SSH_FX_NO_SUCH_FILE= 2; 83 public static final int SSH_FX_PERMISSION_DENIED= 3; 84 public static final int SSH_FX_FAILURE= 4; 85 public static final int SSH_FX_BAD_MESSAGE= 5; 86 public static final int SSH_FX_NO_CONNECTION= 6; 87 public static final int SSH_FX_CONNECTION_LOST= 7; 88 public static final int SSH_FX_OP_UNSUPPORTED= 8; 89 125 private static final int MAX_MSG_LENGTH = 256* 1024; 126 127 public static final int OVERWRITE=0; 128 public static final int RESUME=1; 129 public static final int APPEND=2; 130 131 private boolean interactive=false; 133 private int seq=1; 134 private int[] ackid=new int[1]; 135 private Buffer buf; 136 private Packet packet=new Packet(buf); 137 138 private String version="3"; 139 private int server_version=3; 140 141 156 157 private static final String file_separator=java.io.File.separator; 158 private static final char file_separatorc=java.io.File.separatorChar; 159 160 private String cwd; 161 private String home; 162 private String lcwd; 163 164 public void init(){ 165 } 166 167 public void start() throws JSchException{ 168 try{ 169 170 PipedOutputStream pos=new PipedOutputStream(); 171 io.setOutputStream(pos); 172 PipedInputStream pis=new MyPipedInputStream(pos, 32*1024); 173 io.setInputStream(pis); 174 175 Request request=new RequestSftp(); 176 request.request(session, this); 177 178 184 185 buf=new Buffer(rmpsize); 186 packet=new Packet(buf); 187 int i=0; 188 int length; 189 int type; 190 byte[] str; 191 192 sendINIT(); 194 195 Header header=new Header(); 197 header=header(buf, header); 198 length=header.length; 199 if(length > MAX_MSG_LENGTH){ 200 throw new SftpException(SSH_FX_FAILURE, "Received message is too long: " + length); 201 } 202 type=header.type; server_version=header.rid; 204 skip(length); 205 207 sendREALPATH(".".getBytes()); 209 210 header=header(buf, header); 212 length=header.length; 213 type=header.type; buf.rewind(); 215 fill(buf.buffer, 0, length); 216 i=buf.getInt(); str=buf.getString(); home=cwd=new String (str); 219 str=buf.getString(); 222 lcwd=new File(".").getCanonicalPath(); 223 } 224 catch(Exception e){ 225 if(e instanceof JSchException) throw (JSchException)e; 227 if(e instanceof Throwable ) 228 throw new JSchException(e.toString(), (Throwable )e); 229 throw new JSchException(e.toString()); 230 } 231 } 232 233 public void quit(){ disconnect();} 234 public void exit(){ disconnect();} 235 public void lcd(String path) throws SftpException{ 236 path=localAbsolutePath(path); 237 if((new File(path)).isDirectory()){ 238 try{ 239 path=(new File(path)).getCanonicalPath(); 240 } 241 catch(Exception e){} 242 lcwd=path; 243 return; 244 } 245 throw new SftpException(SSH_FX_NO_SUCH_FILE, "No such directory"); 246 } 247 248 255 public void cd(String path) throws SftpException{ 256 try{ 257 path=remoteAbsolutePath(path); 258 259 Vector v=glob_remote(path); 260 if(v.size()!=1){ 261 throw new SftpException(SSH_FX_FAILURE, v.toString()); 262 } 263 path=(String )(v.elementAt(0)); 264 sendREALPATH(path.getBytes()); 265 266 Header header=new Header(); 267 header=header(buf, header); 268 int length=header.length; 269 int type=header.type; 270 buf.rewind(); 271 fill(buf.buffer, 0, length); 272 273 if(type!=101 && type!=104){ 274 throw new SftpException(SSH_FX_FAILURE, ""); 275 } 276 int i; 277 if(type==101){ 278 i=buf.getInt(); 279 throwStatusError(buf, i); 280 } 281 i=buf.getInt(); 282 byte[] str=buf.getString(); 283 if(str!=null && str[0]!='/'){ 284 str=(cwd+"/"+new String (str)).getBytes(); 285 } 286 str=buf.getString(); i=buf.getInt(); 289 String newpwd=new String (str); 290 SftpATTRS attr=_stat(newpwd); 291 if((attr.getFlags()&SftpATTRS.SSH_FILEXFER_ATTR_PERMISSIONS)==0){ 292 throw new SftpException(SSH_FX_FAILURE, 293 "Can't change directory: "+path); 294 } 295 if(!attr.isDir()){ 296 throw new SftpException(SSH_FX_FAILURE, 297 "Can't change directory: "+path); 298 } 299 cwd=newpwd; 300 } 301 catch(Exception e){ 302 if(e instanceof SftpException) throw (SftpException)e; 303 if(e instanceof Throwable ) 304 throw new SftpException(SSH_FX_FAILURE, "", (Throwable )e); 305 throw new SftpException(SSH_FX_FAILURE, ""); 306 } 307 } 308 309 318 public void put(String src, String dst) throws SftpException{ 319 put(src, dst, null, OVERWRITE); 320 } 321 public void put(String src, String dst, int mode) throws SftpException{ 322 put(src, dst, null, mode); 323 } 324 public void put(String src, String dst, 325 SftpProgressMonitor monitor) throws SftpException{ 326 put(src, dst, monitor, OVERWRITE); 327 } 328 public void put(String src, String dst, 329 SftpProgressMonitor monitor, int mode) throws SftpException{ 330 src=localAbsolutePath(src); 331 dst=remoteAbsolutePath(dst); 332 333 try{ 335 Vector v=glob_remote(dst); 336 int vsize=v.size(); 337 if(vsize!=1){ 338 if(vsize==0){ 339 if(isPattern(dst)) 340 throw new SftpException(SSH_FX_FAILURE, dst); 341 else 342 dst=Util.unquote(dst); 343 } 344 throw new SftpException(SSH_FX_FAILURE, v.toString()); 345 } 346 else{ 347 dst=(String )(v.elementAt(0)); 348 } 349 350 352 boolean isRemoteDir=isRemoteDir(dst); 353 354 v=glob_local(src); 355 vsize=v.size(); 357 358 StringBuffer dstsb=null; 359 if(isRemoteDir){ 360 if(!dst.endsWith("/")){ 361 dst+="/"; 362 } 363 dstsb=new StringBuffer (dst); 364 } 365 else if(vsize>1){ 366 throw new SftpException(SSH_FX_FAILURE, "Copying multiple files, but destination is missing or a file."); 367 } 368 369 for(int j=0; j<vsize; j++){ 370 String _src=(String )(v.elementAt(j)); 371 String _dst=null; 372 if(isRemoteDir){ 373 int i=_src.lastIndexOf(file_separatorc); 374 if(i==-1) dstsb.append(_src); 375 else dstsb.append(_src.substring(i + 1)); 376 _dst=dstsb.toString(); 377 dstsb.delete(dst.length(), _dst.length()); 378 } 379 else{ 380 _dst=dst; 381 } 382 384 long size_of_dst=0; 385 if(mode==RESUME){ 386 try{ 387 SftpATTRS attr=_stat(_dst); 388 size_of_dst=attr.getSize(); 389 } 390 catch(Exception eee){ 391 } 393 long size_of_src=new File(_src).length(); 394 if(size_of_src<size_of_dst){ 395 throw new SftpException(SSH_FX_FAILURE, "failed to resume for "+_dst); 396 } 397 if(size_of_src==size_of_dst){ 398 return; 399 } 400 } 401 402 if(monitor!=null){ 403 monitor.init(SftpProgressMonitor.PUT, _src, _dst, 404 (new File(_src)).length()); 405 if(mode==RESUME){ 406 monitor.count(size_of_dst); 407 } 408 } 409 FileInputStream fis=null; 410 try{ 411 fis=new FileInputStream(_src); 412 _put(fis, _dst, monitor, mode); 413 } 414 finally{ 415 if(fis!=null) { 416 fis.close(); 418 } 420 } 421 } 422 } 423 catch(Exception e){ 424 if(e instanceof SftpException) throw (SftpException)e; 425 if(e instanceof Throwable ) 426 throw new SftpException(SSH_FX_FAILURE, e.toString(), (Throwable )e); 427 throw new SftpException(SSH_FX_FAILURE, e.toString()); 428 } 429 } 430 public void put(InputStream src, String dst) throws SftpException{ 431 put(src, dst, null, OVERWRITE); 432 } 433 public void put(InputStream src, String dst, int mode) throws SftpException{ 434 put(src, dst, null, mode); 435 } 436 public void put(InputStream src, String dst, 437 SftpProgressMonitor monitor) throws SftpException{ 438 put(src, dst, monitor, OVERWRITE); 439 } 440 public void put(InputStream src, String dst, 441 SftpProgressMonitor monitor, int mode) throws SftpException{ 442 try{ 443 dst=remoteAbsolutePath(dst); 444 Vector v=glob_remote(dst); 445 int vsize=v.size(); 446 if(vsize!=1){ 447 if(vsize==0){ 448 if(isPattern(dst)) 449 throw new SftpException(SSH_FX_FAILURE, dst); 450 else 451 dst=Util.unquote(dst); 452 } 453 throw new SftpException(SSH_FX_FAILURE, v.toString()); 454 } 455 else{ 456 dst=(String )(v.elementAt(0)); 457 } 458 if(isRemoteDir(dst)){ 459 throw new SftpException(SSH_FX_FAILURE, dst+" is a directory"); 460 } 461 _put(src, dst, monitor, mode); 462 } 463 catch(Exception e){ 464 if(e instanceof SftpException) throw (SftpException)e; 465 if(e instanceof Throwable ) 466 throw new SftpException(SSH_FX_FAILURE, e.toString(), (Throwable )e); 467 throw new SftpException(SSH_FX_FAILURE, e.toString()); 468 } 469 } 470 public void _put(InputStream src, String dst, 471 SftpProgressMonitor monitor, int mode) throws SftpException{ 472 473 try{ 474 long skip=0; 475 if(mode==RESUME || mode==APPEND){ 476 try{ 477 SftpATTRS attr=_stat(dst); 478 skip=attr.getSize(); 479 } 480 catch(Exception eee){ 481 } 483 } 484 if(mode==RESUME && skip>0){ 485 long skipped=src.skip(skip); 486 if(skipped<skip){ 487 throw new SftpException(SSH_FX_FAILURE, "failed to resume for "+dst); 488 } 489 } 490 if(mode==OVERWRITE){ sendOPENW(dst.getBytes()); } 491 else{ sendOPENA(dst.getBytes()); } 492 493 Header header=new Header(); 494 header=header(buf, header); 495 int length=header.length; 496 int type=header.type; 497 buf.rewind(); 498 fill(buf.buffer, 0, length); 499 500 if(type!=SSH_FXP_STATUS && type!=SSH_FXP_HANDLE){ 501 throw new SftpException(SSH_FX_FAILURE, "invalid type="+type); 502 } 503 if(type==SSH_FXP_STATUS){ 504 int i=buf.getInt(); 505 throwStatusError(buf, i); 506 } 507 byte[] handle=buf.getString(); byte[] data=null; 509 510 boolean dontcopy=true; 511 512 if(!dontcopy){ 513 data=new byte[buf.buffer.length 514 -(5+13+21+handle.length 515 +32 +20 ) 517 ]; 518 } 519 520 long offset=0; 521 if(mode==RESUME || mode==APPEND){ 522 offset+=skip; 523 } 524 525 int startid=seq; 526 int _ackid=seq; 527 int ackcount=0; 528 while(true){ 529 int nread=0; 530 int s=0; 531 int datalen=0; 532 int count=0; 533 534 if(!dontcopy){ 535 datalen=data.length-s; 536 } 537 else{ 538 data=buf.buffer; 539 s=5+13+21+handle.length; 540 datalen=buf.buffer.length -s 541 -32 -20; } 543 544 do{ 545 nread=src.read(data, s, datalen); 546 if(nread>0){ 547 s+=nread; 548 datalen-=nread; 549 count+=nread; 550 } 551 } 552 while(datalen>0 && nread>0); 553 if(count<=0)break; 554 555 int _i=count; 556 while(_i>0){ 557 _i-=sendWRITE(handle, offset, data, 0, _i); 558 if((seq-1)==startid || 559 io.in.available()>=1024){ 560 while(io.in.available()>0){ 561 if(checkStatus(ackid, header)){ 562 _ackid=ackid[0]; 563 if(startid>_ackid || _ackid>seq-1){ 564 if(_ackid==seq){ 565 System.err.println("ack error: startid="+startid+" seq="+seq+" _ackid="+_ackid); 566 } 567 else{ 568 throw new SftpException(SSH_FX_FAILURE, "ack error: startid="+startid+" seq="+seq+" _ackid="+_ackid); 570 } 571 } 572 ackcount++; 573 } 574 else{ 575 break; 576 } 577 } 578 } 579 } 580 offset+=count; 581 if(monitor!=null && !monitor.count(count)){ 582 break; 583 } 584 } 585 int _ackcount=seq-startid; 586 while(_ackcount>ackcount){ 587 if(!checkStatus(null, header)){ 588 break; 589 } 590 ackcount++; 591 } 592 if(monitor!=null)monitor.end(); 593 _sendCLOSE(handle, header); 594 } 596 catch(Exception e){ 597 if(e instanceof SftpException) throw (SftpException)e; 598 if(e instanceof Throwable ) 599 throw new SftpException(SSH_FX_FAILURE, e.toString(), (Throwable )e); 600 throw new SftpException(SSH_FX_FAILURE, e.toString()); 601 } 602 } 603 604 public OutputStream put(String dst) throws SftpException{ 605 return put(dst, (SftpProgressMonitor)null, OVERWRITE); 606 } 607 public OutputStream put(String dst, final int mode) throws SftpException{ 608 return put(dst, (SftpProgressMonitor)null, mode); 609 } 610 public OutputStream put(String dst, final SftpProgressMonitor monitor, final int mode) throws SftpException{ 611 return put(dst, monitor, mode, 0); 612 } 613 public OutputStream put(String dst, final SftpProgressMonitor monitor, final int mode, long offset) throws SftpException{ 614 dst=remoteAbsolutePath(dst); 615 try{ 616 Vector v=glob_remote(dst); 617 if(v.size()!=1){ 618 throw new SftpException(SSH_FX_FAILURE, v.toString()); 619 } 620 dst=(String )(v.elementAt(0)); 621 if(isRemoteDir(dst)){ 622 throw new SftpException(SSH_FX_FAILURE, dst+" is a directory"); 623 } 624 625 long skip=0; 626 if(mode==RESUME || mode==APPEND){ 627 try{ 628 SftpATTRS attr=_stat(dst); 629 skip=attr.getSize(); 630 } 631 catch(Exception eee){ 632 } 634 } 635 636 if(mode==OVERWRITE){ sendOPENW(dst.getBytes()); } 637 else{ sendOPENA(dst.getBytes()); } 638 639 Header header=new Header(); 640 header=header(buf, header); 641 int length=header.length; 642 int type=header.type; 643 buf.rewind(); 644 fill(buf.buffer, 0, length); 645 646 if(type!=SSH_FXP_STATUS && type!=SSH_FXP_HANDLE){ 647 throw new SftpException(SSH_FX_FAILURE, ""); 648 } 649 if(type==SSH_FXP_STATUS){ 650 int i=buf.getInt(); 651 throwStatusError(buf, i); 652 } 653 final byte[] handle=buf.getString(); 655 if(mode==RESUME || mode==APPEND){ 657 offset+=skip; 658 } 659 660 final long[] _offset=new long[1]; 661 _offset[0]=offset; 662 OutputStream out = new OutputStream(){ 663 private boolean init=true; 664 private boolean isClosed=false; 665 private int[] ackid=new int[1]; 666 private int startid=0; 667 private int _ackid=0; 668 private int ackcount=0; 669 private int writecount=0; 670 private Header header=new Header(); 671 672 public void write(byte[] d) throws java.io.IOException { 673 write(d, 0, d.length); 674 } 675 676 public void write(byte[] d, int s, int len) throws java.io.IOException { 677 if(init){ 678 startid=seq; 679 _ackid=seq; 680 init=false; 681 } 682 683 if(isClosed){ 684 throw new IOException("stream already closed"); 685 } 686 687 try{ 688 int _len=len; 689 while(_len>0){ 690 int sent=sendWRITE(handle, _offset[0], d, s, _len); 691 writecount++; 692 _offset[0]+=sent; 693 s+=sent; 694 _len-=sent; 695 if((seq-1)==startid || 696 io.in.available()>=1024){ 697 while(io.in.available()>0){ 698 if(checkStatus(ackid, header)){ 699 _ackid=ackid[0]; 700 if(startid>_ackid || _ackid>seq-1){ 701 throw new SftpException(SSH_FX_FAILURE, ""); 702 } 703 ackcount++; 704 } 705 else{ 706 break; 707 } 708 } 709 } 710 } 711 if(monitor!=null && !monitor.count(len)){ 712 close(); 713 throw new IOException("canceled"); 714 } 715 } 716 catch(IOException e){ throw e; } 717 catch(Exception e){ throw new IOException(e.toString()); } 718 } 719 720 byte[] _data=new byte[1]; 721 public void write(int foo) throws java.io.IOException { 722 _data[0]=(byte)foo; 723 write(_data, 0, 1); 724 } 725 726 public void flush() throws java.io.IOException { 727 728 if(isClosed){ 729 throw new IOException("stream already closed"); 730 } 731 732 if(!init){ 733 try{ 734 while(writecount>ackcount){ 735 if(!checkStatus(null, header)){ 736 break; 737 } 738 ackcount++; 739 } 740 } 741 catch(SftpException e){ 742 throw new IOException(e.toString()); 743 } 744 } 745 } 746 747 public void close() throws java.io.IOException { 748 if(isClosed){ 749 return; 750 } 751 flush(); 752 if(monitor!=null)monitor.end(); 753 try{ _sendCLOSE(handle, header); } 754 catch(IOException e){ throw e; } 755 catch(Exception e){ 756 throw new IOException(e.toString()); 757 } 758 isClosed=true; 759 } 760 }; 761 return out; 762 } 763 catch(Exception e){ 764 if(e instanceof SftpException) throw (SftpException)e; 765 if(e instanceof Throwable ) 766 throw new SftpException(SSH_FX_FAILURE, "", (Throwable )e); 767 throw new SftpException(SSH_FX_FAILURE, ""); 768 } 769 } 770 771 772 public void get(String src, String dst) throws SftpException{ 773 get(src, dst, null, OVERWRITE); 774 } 775 public void get(String src, String dst, 776 SftpProgressMonitor monitor) throws SftpException{ 777 get(src, dst, monitor, OVERWRITE); 778 } 779 public void get(String src, String dst, 780 SftpProgressMonitor monitor, int mode) throws SftpException{ 781 src=remoteAbsolutePath(src); 782 dst=localAbsolutePath(dst); 783 try{ 784 Vector v=glob_remote(src); 785 int vsize=v.size(); 786 if(vsize==0){ 787 throw new SftpException(SSH_FX_NO_SUCH_FILE, "No such file"); 788 } 789 790 File dstFile=new File(dst); 791 boolean isDstDir=dstFile.isDirectory(); 792 StringBuffer dstsb=null; 793 if(isDstDir){ 794 if(!dst.endsWith(file_separator)){ 795 dst+=file_separator; 796 } 797 dstsb=new StringBuffer (dst); 798 } 799 else if(vsize>1){ 800 throw new SftpException(SSH_FX_FAILURE, "Copying multiple files, but destination is missing or a file."); 801 } 802 803 for(int j=0; j<vsize; j++){ 804 String _src=(String )(v.elementAt(j)); 805 806 SftpATTRS attr=_stat(_src); 807 if(attr.isDir()){ 808 throw new SftpException(SSH_FX_FAILURE, "not supported to get directory "+_src); 809 } 810 811 String _dst=null; 812 if(isDstDir){ 813 int i=_src.lastIndexOf('/'); 814 if(i==-1) dstsb.append(_src); 815 else dstsb.append(_src.substring(i + 1)); 816 _dst=dstsb.toString(); 817 dstsb.delete(dst.length(), _dst.length()); 818 } 819 else{ 820 _dst=dst; 821 } 822 823 if(mode==RESUME){ 824 long size_of_src=attr.getSize(); 825 long size_of_dst=new File(_dst).length(); 826 if(size_of_dst>size_of_src){ 827 throw new SftpException(SSH_FX_FAILURE, "failed to resume for "+_dst); 828 } 829 if(size_of_dst==size_of_src){ 830 return; 831 } 832 } 833 834 if(monitor!=null){ 835 monitor.init(SftpProgressMonitor.GET, _src, _dst, attr.getSize()); 836 if(mode==RESUME){ 837 monitor.count(new File(_dst).length()); 838 } 839 } 840 FileOutputStream fos=null; 841 if(mode==OVERWRITE){ 842 fos=new FileOutputStream(_dst); 843 } 844 else{ 845 fos=new FileOutputStream(_dst, true); } 847 848 _get(_src, fos, monitor, mode, new File(_dst).length()); 850 fos.close(); 851 } 852 } 853 catch(Exception e){ 854 if(e instanceof SftpException) throw (SftpException)e; 855 if(e instanceof Throwable ) 856 throw new SftpException(SSH_FX_FAILURE, "", (Throwable )e); 857 throw new SftpException(SSH_FX_FAILURE, ""); 858 } 859 } 860 public void get(String src, OutputStream dst) throws SftpException{ 861 get(src, dst, null, OVERWRITE, 0); 862 } 863 public void get(String src, OutputStream dst, 864 SftpProgressMonitor monitor) throws SftpException{ 865 get(src, dst, monitor, OVERWRITE, 0); 866 } 867 public void get(String src, OutputStream dst, 868 SftpProgressMonitor monitor, int mode, long skip) throws SftpException{ 869 try{ 871 src=remoteAbsolutePath(src); 872 Vector v=glob_remote(src); 873 if(v.size()!=1){ 874 throw new SftpException(SSH_FX_FAILURE, v.toString()); 875 } 876 src=(String )(v.elementAt(0)); 877 878 if(monitor!=null){ 879 SftpATTRS attr=_stat(src); 880 monitor.init(SftpProgressMonitor.GET, src, "??", attr.getSize()); 881 if(mode==RESUME){ 882 monitor.count(skip); 883 } 884 } 885 _get(src, dst, monitor, mode, skip); 886 } 887 catch(Exception e){ 888 if(e instanceof SftpException) throw (SftpException)e; 889 if(e instanceof Throwable ) 890 throw new SftpException(SSH_FX_FAILURE, "", (Throwable )e); 891 throw new SftpException(SSH_FX_FAILURE, ""); 892 } 893 } 894 private void _get(String src, OutputStream dst, 895 SftpProgressMonitor monitor, int mode, long skip) throws SftpException{ 896 try{ 898 sendOPENR(src.getBytes()); 899 900 Header header=new Header(); 901 header=header(buf, header); 902 int length=header.length; 903 int type=header.type; 904 buf.rewind(); 905 fill(buf.buffer, 0, length); 906 907 if(type!=SSH_FXP_STATUS && type!=SSH_FXP_HANDLE){ 908 throw new SftpException(SSH_FX_FAILURE, ""); 909 } 910 if(type==SSH_FXP_STATUS){ 911 int i=buf.getInt(); 912 throwStatusError(buf, i); 913 } 914 915 byte[] handle=buf.getString(); 917 long offset=0; 918 if(mode==RESUME){ 919 offset+=skip; 920 } 921 922 int request_len=0; 923 loop: 924 while(true){ 925 926 request_len=buf.buffer.length-13; 927 if(server_version==0){ request_len=1024; } 928 sendREAD(handle, offset, request_len); 929 930 header=header(buf, header); 931 length=header.length; 932 type=header.type; 933 934 if(type==SSH_FXP_STATUS){ 935 buf.rewind(); 936 fill(buf.buffer, 0, length); 937 int i=buf.getInt(); 938 if(i==SSH_FX_EOF){ 939 break loop; 940 } 941 throwStatusError(buf, i); 942 } 943 944 if(type!=SSH_FXP_DATA){ 945 break loop; 946 } 947 948 buf.rewind(); 949 fill(buf.buffer, 0, 4); length-=4; 950 int i=buf.getInt(); int foo=i; 952 953 while(foo>0){ 954 int bar=foo; 955 if(bar>buf.buffer.length){ 956 bar=buf.buffer.length; 957 } 958 i=io.in.read(buf.buffer, 0, bar); 959 if(i<0){ 960 break loop; 961 } 962 int data_len=i; 963 dst.write(buf.buffer, 0, data_len); 964 965 offset+=data_len; 966 foo-=data_len; 967 968 if(monitor!=null){ 969 if(!monitor.count(data_len)){ 970 while(foo>0){ 971 i=io.in.read(buf.buffer, 972 0, 973 (buf.buffer.length<foo?buf.buffer.length:foo)); 974 if(i<=0) break; 975 foo-=i; 976 } 977 break loop; 978 } 979 } 980 981 } 982 } 984 dst.flush(); 985 986 if(monitor!=null)monitor.end(); 987 _sendCLOSE(handle, header); 988 } 989 catch(Exception e){ 990 if(e instanceof SftpException) throw (SftpException)e; 991 if(e instanceof Throwable ) 992 throw new SftpException(SSH_FX_FAILURE, "", (Throwable )e); 993 throw new SftpException(SSH_FX_FAILURE, ""); 994 } 995 } 996 997 public InputStream get(String src) throws SftpException{ 998 return get(src, null, OVERWRITE); 999 } 1000 public InputStream get(String src, SftpProgressMonitor monitor) throws SftpException{ 1001 return get(src, monitor, OVERWRITE); 1002 } 1003 public InputStream get(String src, int mode) throws SftpException{ 1004 return get(src, null, mode); 1005 } 1006 public InputStream get(String src, final SftpProgressMonitor monitor, final int mode) throws SftpException{ 1007 if(mode==RESUME){ 1008 throw new SftpException(SSH_FX_FAILURE, "faile to resume from "+src); 1009 } 1010 src=remoteAbsolutePath(src); 1011 try{ 1012 Vector v=glob_remote(src); 1013 if(v.size()!=1){ 1014 throw new SftpException(SSH_FX_FAILURE, v.toString()); 1015 } 1016 src=(String )(v.elementAt(0)); 1017 1018 SftpATTRS attr=_stat(src); 1019 if(monitor!=null){ 1020 monitor.init(SftpProgressMonitor.GET, src, "??", attr.getSize()); 1021 } 1022 1023 sendOPENR(src.getBytes()); 1024 1025 Header header=new Header(); 1026 header=header(buf, header); 1027 int length=header.length; 1028 int type=header.type; 1029 buf.rewind(); 1030 fill(buf.buffer, 0, length); 1031 1032 if(type!=SSH_FXP_STATUS && type!=SSH_FXP_HANDLE){ 1033 throw new SftpException(SSH_FX_FAILURE, ""); 1034 } 1035 if(type==SSH_FXP_STATUS){ 1036 int i=buf.getInt(); 1037 throwStatusError(buf, i); 1038 } 1039 1040 final byte[] handle=buf.getString(); 1042 java.io.InputStream in=new java.io.InputStream (){ 1043 long offset=0; 1044 boolean closed=false; 1045 int rest_length=0; 1046 byte[] _data=new byte[1]; 1047 byte[] rest_byte=new byte[1024]; 1048 Header header=new Header(); 1049 1050 public int read() throws java.io.IOException { 1051 if(closed)return -1; 1052 int i=read(_data, 0, 1); 1053 if (i==-1) { return -1; } 1054 else { 1055 return _data[0]&0xff; 1056 } 1057 } 1058 public int read(byte[] d) throws java.io.IOException { 1059 if(closed)return -1; 1060 return read(d, 0, d.length); 1061 } 1062 public int read(byte[] d, int s, int len) throws java.io.IOException { 1063 if(closed)return -1; 1064 if(d==null){throw new NullPointerException ();} 1065 if(s<0 || len <0 || s+len>d.length){ 1066 throw new IndexOutOfBoundsException (); 1067 } 1068 if(len==0){ return 0; } 1069 1070 if(rest_length>0){ 1071 int foo=rest_length; 1072 if(foo>len) foo=len; 1073 System.arraycopy(rest_byte, 0, d, s, foo); 1074 if(foo!=rest_length){ 1075 System.arraycopy(rest_byte, foo, 1076 rest_byte, 0, rest_length-foo); 1077 } 1078 1079 if(monitor!=null){ 1080 if(!monitor.count(foo)){ 1081 close(); 1082 return -1; 1083 } 1084 } 1085 1086 rest_length-=foo; 1087 return foo; 1088 } 1089 1090 if(buf.buffer.length-13<len){ 1091 len=buf.buffer.length-13; 1092 } 1093 if(server_version==0 && len>1024){ 1094 len=1024; 1095 } 1096 1097 try{sendREAD(handle, offset, len);} 1098 catch(Exception e){ throw new IOException("error"); } 1099 1100 header=header(buf, header); 1101 rest_length=header.length; 1102 int type=header.type; 1103 int id=header.rid; 1104 1105 if(type!=SSH_FXP_STATUS && type!=SSH_FXP_DATA){ 1106 throw new IOException("error"); 1107 } 1108 if(type==SSH_FXP_STATUS){ 1109 buf.rewind(); 1110 fill(buf.buffer, 0, rest_length); 1111 int i=buf.getInt(); 1112 rest_length=0; 1113 if(i==SSH_FX_EOF){ 1114 close(); 1115 return -1; 1116 } 1117 throw new IOException("error"); 1119 } 1120 buf.rewind(); 1121 fill(buf.buffer, 0, 4); 1122 int i=buf.getInt(); rest_length-=4; 1123 1124 offset+=rest_length; 1125 int foo=i; 1126 if(foo>0){ 1127 int bar=rest_length; 1128 if(bar>len){ 1129 bar=len; 1130 } 1131 i=io.in.read(d, s, bar); 1132 if(i<0){ 1133 return -1; 1134 } 1135 rest_length-=i; 1136 1137 if(rest_length>0){ 1138 if(rest_byte.length<rest_length){ 1139 rest_byte=new byte[rest_length]; 1140 } 1141 int _s=0; 1142 int _len=rest_length; 1143 int j; 1144 while(_len>0){ 1145 j=io.in.read(rest_byte, _s, _len); 1146 if(j<=0)break; 1147 _s+=j; 1148 _len-=j; 1149 } 1150 } 1151 1152 if(monitor!=null){ 1153 if(!monitor.count(i)){ 1154 close(); 1155 return -1; 1156 } 1157 } 1158 1159 return i; 1160 } 1161 return 0; } 1163 public void close() throws IOException{ 1164 if(closed)return; 1165 closed=true; 1166 1176 if(monitor!=null)monitor.end(); 1177 try{_sendCLOSE(handle, header);} 1178 catch(Exception e){throw new IOException("error");} 1179 } 1180 }; 1181 return in; 1182 } 1183 catch(Exception e){ 1184 if(e instanceof SftpException) throw (SftpException)e; 1185 if(e instanceof Throwable ) 1186 throw new SftpException(SSH_FX_FAILURE, "", (Throwable )e); 1187 throw new SftpException(SSH_FX_FAILURE, ""); 1188 } 1189 } 1190 1191 public java.util.Vector ls(String path) throws SftpException{ 1192 try{ 1193 path=remoteAbsolutePath(path); 1194 1195 String dir=path; 1196 byte[] pattern=null; 1197 SftpATTRS attr=null; 1198 if(isPattern(dir) || 1199 ((attr=stat(dir))!=null && !attr.isDir())){ 1200 int foo=path.lastIndexOf('/'); 1201 dir=path.substring(0, ((foo==0)?1:foo)); 1202 pattern=path.substring(foo+1).getBytes(); 1203 } 1204 1205 sendOPENDIR(dir.getBytes()); 1206 1207 Header header=new Header(); 1208 header=header(buf, header); 1209 int length=header.length; 1210 int type=header.type; 1211 buf.rewind(); 1212 fill(buf.buffer, 0, length); 1213 1214 if(type!=SSH_FXP_STATUS && type!=SSH_FXP_HANDLE){ 1215 throw new SftpException(SSH_FX_FAILURE, ""); 1216 } 1217 if(type==SSH_FXP_STATUS){ 1218 int i=buf.getInt(); 1219 throwStatusError(buf, i); 1220 } 1221 1222 byte[] handle=buf.getString(); 1224 java.util.Vector v=new java.util.Vector (); 1225 while(true){ 1226 sendREADDIR(handle); 1227 1228 header=header(buf, header); 1229 length=header.length; 1230 type=header.type; 1231 if(type!=SSH_FXP_STATUS && type!=SSH_FXP_NAME){ 1232 throw new SftpException(SSH_FX_FAILURE, ""); 1233 } 1234 if(type==SSH_FXP_STATUS){ 1235 buf.rewind(); 1236 fill(buf.buffer, 0, length); 1237 int i=buf.getInt(); 1238 if(i==SSH_FX_EOF) 1239 break; 1240 throwStatusError(buf, i); 1241 } 1242 1243 buf.rewind(); 1244 fill(buf.buffer, 0, 4); length-=4; 1245 int count=buf.getInt(); 1246 1247 byte[] str; 1248 int flags; 1249 1250 buf.reset(); 1251 while(count>0){ 1252 if(length>0){ 1253 buf.shift(); 1254 int j=(buf.buffer.length>(buf.index+length)) ? length : (buf.buffer.length-buf.index); 1255 int i=fill(buf.buffer, buf.index, j); 1256 buf.index+=i; 1257 length-=i; 1258 } 1259 byte[] filename=buf.getString(); 1260 str=buf.getString(); 1261 String longname=new String (str); 1262 1263 SftpATTRS attrs=SftpATTRS.getATTR(buf); 1264 if(pattern==null || Util.glob(pattern, filename)){ 1265 v.addElement(new LsEntry(new String (filename), longname, attrs)); 1266 } 1267 1268 count--; 1269 } 1270 } 1271 _sendCLOSE(handle, header); 1272 return v; 1273 } 1274 catch(Exception e){ 1275 if(e instanceof SftpException) throw (SftpException)e; 1276 if(e instanceof Throwable ) 1277 throw new SftpException(SSH_FX_FAILURE, "", (Throwable )e); 1278 throw new SftpException(SSH_FX_FAILURE, ""); 1279 } 1280 } 1281 public String readlink(String path) throws SftpException{ 1282 try{ 1283 path=remoteAbsolutePath(path); 1284 Vector v=glob_remote(path); 1285 if(v.size()!=1){ 1286 throw new SftpException(SSH_FX_FAILURE, v.toString()); 1287 } 1288 path=(String )(v.elementAt(0)); 1289 1290 sendREADLINK(path.getBytes()); 1291 1292 Header header=new Header(); 1293 header=header(buf, header); 1294 int length=header.length; 1295 int type=header.type; 1296 buf.rewind(); 1297 fill(buf.buffer, 0, length); 1298 1299 if(type!=SSH_FXP_STATUS && type!=SSH_FXP_NAME){ 1300 throw new SftpException(SSH_FX_FAILURE, ""); 1301 } 1302 if(type==SSH_FXP_NAME){ 1303 int count=buf.getInt(); byte[] filename=null; 1305 byte[] longname=null; 1306 for(int i=0; i<count; i++){ 1307 filename=buf.getString(); 1308 longname=buf.getString(); 1309 SftpATTRS.getATTR(buf); 1310 } 1311 return new String (filename); 1312 } 1313 1314 int i=buf.getInt(); 1315 throwStatusError(buf, i); 1316 } 1317 catch(Exception e){ 1318 if(e instanceof SftpException) throw (SftpException)e; 1319 if(e instanceof Throwable ) 1320 throw new SftpException(SSH_FX_FAILURE, "", (Throwable )e); 1321 throw new SftpException(SSH_FX_FAILURE, ""); 1322 } 1323 return null; 1324 } 1325 public void symlink(String oldpath, String newpath) throws SftpException{ 1326 if(server_version<3){ 1327 throw new SftpException(SSH_FX_FAILURE, 1328 "The remote sshd is too old to support symlink operation."); 1329 } 1330 1331 try{ 1332 oldpath=remoteAbsolutePath(oldpath); 1333 newpath=remoteAbsolutePath(newpath); 1334 1335 Vector v=glob_remote(oldpath); 1336 int vsize=v.size(); 1337 if(vsize!=1){ 1338 throw new SftpException(SSH_FX_FAILURE, v.toString()); 1339 } 1340 oldpath=(String )(v.elementAt(0)); 1341 1342 if(isPattern(newpath)){ 1343 throw new SftpException(SSH_FX_FAILURE, v.toString()); 1344 } 1345 1346 newpath=Util.unquote(newpath); 1347 1348 sendSYMLINK(oldpath.getBytes(), newpath.getBytes()); 1349 1350 Header header=new Header(); 1351 header=header(buf, header); 1352 int length=header.length; 1353 int type=header.type; 1354 buf.rewind(); 1355 fill(buf.buffer, 0, length); 1356 1357 if(type!=SSH_FXP_STATUS){ 1358 throw new SftpException(SSH_FX_FAILURE, ""); 1359 } 1360 1361 int i=buf.getInt(); 1362 if(i==SSH_FX_OK) return; 1363 throwStatusError(buf, i); 1364 } 1365 catch(Exception e){ 1366 if(e instanceof SftpException) throw (SftpException)e; 1367 if(e instanceof Throwable ) 1368 throw new SftpException(SSH_FX_FAILURE, "", (Throwable )e); 1369 throw new SftpException(SSH_FX_FAILURE, ""); 1370 } 1371 } 1372 public void rename(String oldpath, String newpath) throws SftpException{ 1373 if(server_version<2){ 1374 throw new SftpException(SSH_FX_FAILURE, 1375 "The remote sshd is too old to support rename operation."); 1376 } 1377 try{ 1378 oldpath=remoteAbsolutePath(oldpath); 1379 newpath=remoteAbsolutePath(newpath); 1380 1381 Vector v=glob_remote(oldpath); 1382 int vsize=v.size(); 1383 if(vsize!=1){ 1384 throw new SftpException(SSH_FX_FAILURE, v.toString()); 1385 } 1386 oldpath=(String )(v.elementAt(0)); 1387 1388 v=glob_remote(newpath); 1389 vsize=v.size(); 1390 if(vsize>=2){ 1391 throw new SftpException(SSH_FX_FAILURE, v.toString()); 1392 } 1393 if(vsize==1){ 1394 newpath=(String )(v.elementAt(0)); 1395 } 1396 else{ if(isPattern(newpath)) 1398 throw new SftpException(SSH_FX_FAILURE, newpath); 1399 newpath=Util.unquote(newpath); 1400 } 1401 1402 sendRENAME(oldpath.getBytes(), newpath.getBytes()); 1403 1404 Header header=new Header(); 1405 header=header(buf, header); 1406 int length=header.length; 1407 int type=header.type; 1408 buf.rewind(); 1409 fill(buf.buffer, 0, length); 1410 1411 if(type!=SSH_FXP_STATUS){ 1412 throw new SftpException(SSH_FX_FAILURE, ""); 1413 } 1414 1415 int i=buf.getInt(); 1416 if(i==SSH_FX_OK) return; 1417 throwStatusError(buf, i); 1418 } 1419 catch(Exception e){ 1420 if(e instanceof SftpException) throw (SftpException)e; 1421 if(e instanceof Throwable ) 1422 throw new SftpException(SSH_FX_FAILURE, "", (Throwable )e); 1423 throw new SftpException(SSH_FX_FAILURE, ""); 1424 } 1425 } 1426 public void rm(String path) throws SftpException{ 1427 try{ 1428 path=remoteAbsolutePath(path); 1429 Vector v=glob_remote(path); 1430 int vsize=v.size(); 1431 Header header=new Header(); 1432 1433 for(int j=0; j<vsize; j++){ 1434 path=(String )(v.elementAt(j)); 1435 sendREMOVE(path.getBytes()); 1436 1437 header=header(buf, header); 1438 int length=header.length; 1439 int type=header.type; 1440 buf.rewind(); 1441 fill(buf.buffer, 0, length); 1442 1443 if(type!=SSH_FXP_STATUS){ 1444 throw new SftpException(SSH_FX_FAILURE, ""); 1445 } 1446 int i=buf.getInt(); 1447 if(i!=SSH_FX_OK){ 1448 throwStatusError(buf, i); 1449 } 1450 } 1451 } 1452 catch(Exception e){ 1453 if(e instanceof SftpException) throw (SftpException)e; 1454 if(e instanceof Throwable ) 1455 throw new SftpException(SSH_FX_FAILURE, "", (Throwable )e); 1456 throw new SftpException(SSH_FX_FAILURE, ""); 1457 } 1458 } 1459 private boolean isRemoteDir(String path){ 1460 try{ 1461 sendSTAT(path.getBytes()); 1462 1463 Header header=new Header(); 1464 header=header(buf, header); 1465 int length=header.length; 1466 int type=header.type; 1467 buf.rewind(); 1468 fill(buf.buffer, 0, length); 1469 1470 if(type!=SSH_FXP_ATTRS){ 1471 return false; 1472 } 1473 SftpATTRS attr=SftpATTRS.getATTR(buf); 1474 return attr.isDir(); 1475 } 1476 catch(Exception e){} 1477 return false; 1478 } 1479 1485 public void chgrp(int gid, String path) throws SftpException{ 1486 try{ 1487 path=remoteAbsolutePath(path); 1488 1489 Vector v=glob_remote(path); 1490 int vsize=v.size(); 1491 for(int j=0; j<vsize; j++){ 1492 path=(String )(v.elementAt(j)); 1493 1494 SftpATTRS attr=_stat(path); 1495 1496 attr.setFLAGS(0); 1497 attr.setUIDGID(attr.uid, gid); 1498 _setStat(path, attr); 1499 } 1500 } 1501 catch(Exception e){ 1502 if(e instanceof SftpException) throw (SftpException)e; 1503 if(e instanceof Throwable ) 1504 throw new SftpException(SSH_FX_FAILURE, "", (Throwable )e); 1505 throw new SftpException(SSH_FX_FAILURE, ""); 1506 } 1507 } 1508 public void chown(int uid, String path) throws SftpException{ 1509 try{ 1510 path=remoteAbsolutePath(path); 1511 1512 Vector v=glob_remote(path); 1513 int vsize=v.size(); 1514 for(int j=0; j<vsize; j++){ 1515 path=(String )(v.elementAt(j)); 1516 1517 SftpATTRS attr=_stat(path); 1518 1519 attr.setFLAGS(0); 1520 attr.setUIDGID(uid, attr.gid); 1521 _setStat(path, attr); 1522 } 1523 } 1524 catch(Exception e){ 1525 if(e instanceof SftpException) throw (SftpException)e; 1526 if(e instanceof Throwable ) 1527 throw new SftpException(SSH_FX_FAILURE, "", (Throwable )e); 1528 throw new SftpException(SSH_FX_FAILURE, ""); 1529 } 1530 } 1531 public void chmod(int permissions, String path) throws SftpException{ 1532 try{ 1533 path=remoteAbsolutePath(path); 1534 1535 Vector v=glob_remote(path); 1536 int vsize=v.size(); 1537 for(int j=0; j<vsize; j++){ 1538 path=(String )(v.elementAt(j)); 1539 1540 SftpATTRS attr=_stat(path); 1541 1542 attr.setFLAGS(0); 1543 attr.setPERMISSIONS(permissions); 1544 _setStat(path, attr); 1545 } 1546 } 1547 catch(Exception e){ 1548 if(e instanceof SftpException) throw (SftpException)e; 1549 if(e instanceof Throwable ) 1550 throw new SftpException(SSH_FX_FAILURE, "", (Throwable )e); 1551 throw new SftpException(SSH_FX_FAILURE, ""); 1552 } 1553 } 1554 public void setMtime(String path, int mtime) throws SftpException{ 1555 try{ 1556 path=remoteAbsolutePath(path); 1557 1558 Vector v=glob_remote(path); 1559 int vsize=v.size(); 1560 for(int j=0; j<vsize; j++){ 1561 path=(String )(v.elementAt(j)); 1562 1563 SftpATTRS attr=_stat(path); 1564 1565 attr.setFLAGS(0); 1566 attr.setACMODTIME(attr.getATime(), mtime); 1567 _setStat(path, attr); 1568 } 1569 } 1570 catch(Exception e){ 1571 if(e instanceof SftpException) throw (SftpException)e; 1572 if(e instanceof Throwable ) 1573 throw new SftpException(SSH_FX_FAILURE, "", (Throwable )e); 1574 throw new SftpException(SSH_FX_FAILURE, ""); 1575 } 1576 } 1577 public void rmdir(String path) throws SftpException{ 1578 try{ 1579 path=remoteAbsolutePath(path); 1580 1581 Vector v=glob_remote(path); 1582 int vsize=v.size(); 1583 Header header=new Header(); 1584 1585 for(int j=0; j<vsize; j++){ 1586 path=(String )(v.elementAt(j)); 1587 sendRMDIR(path.getBytes()); 1588 1589 header=header(buf, header); 1590 int length=header.length; 1591 int type=header.type; 1592 buf.rewind(); 1593 fill(buf.buffer, 0, length); 1594 1595 if(type!=SSH_FXP_STATUS){ 1596 throw new SftpException(SSH_FX_FAILURE, ""); 1597 } 1598 1599 int i=buf.getInt(); 1600 if(i!=SSH_FX_OK){ 1601 throwStatusError(buf, i); 1602 } 1603 } 1604 } 1605 catch(Exception e){ 1606 if(e instanceof SftpException) throw (SftpException)e; 1607 if(e instanceof Throwable ) 1608 throw new SftpException(SSH_FX_FAILURE, "", (Throwable )e); 1609 throw new SftpException(SSH_FX_FAILURE, ""); 1610 } 1611 } 1612 1613 public void mkdir(String path) throws SftpException{ 1614 try{ 1615 path=remoteAbsolutePath(path); 1616 1617 sendMKDIR(path.getBytes(), null); 1618 1619 Header header=new Header(); 1620 header=header(buf, header); 1621 int length=header.length; 1622 int type=header.type; 1623 buf.rewind(); 1624 fill(buf.buffer, 0, length); 1625 1626 if(type!=SSH_FXP_STATUS){ 1627 throw new SftpException(SSH_FX_FAILURE, ""); 1628 } 1629 1630 int i=buf.getInt(); 1631 if(i==SSH_FX_OK) return; 1632 throwStatusError(buf, i); 1633 } 1634 catch(Exception e){ 1635 if(e instanceof SftpException) throw (SftpException)e; 1636 if(e instanceof Throwable ) 1637 throw new SftpException(SSH_FX_FAILURE, "", (Throwable )e); 1638 throw new SftpException(SSH_FX_FAILURE, ""); 1639 } 1640 } 1641 1642 public SftpATTRS stat(String path) throws SftpException{ 1643 try{ 1644 path=remoteAbsolutePath(path); 1645 1646 Vector v=glob_remote(path); 1647 if(v.size()!=1){ 1648 throw new SftpException(SSH_FX_FAILURE, v.toString()); 1649 } 1650 path=(String )(v.elementAt(0)); 1651 return _stat(path); 1652 } 1653 catch(Exception e){ 1654 if(e instanceof SftpException) throw (SftpException)e; 1655 if(e instanceof Throwable ) 1656 throw new SftpException(SSH_FX_FAILURE, "", (Throwable )e); 1657 throw new SftpException(SSH_FX_FAILURE, ""); 1658 } 1659 } 1661 1662 private SftpATTRS _stat(String path) throws SftpException{ 1663 try{ 1664 sendSTAT(path.getBytes()); 1665 1666 Header header=new Header(); 1667 header=header(buf, header); 1668 int length=header.length; 1669 int type=header.type; 1670 buf.rewind(); 1671 fill(buf.buffer, 0, length); 1672 1673 if(type!=SSH_FXP_ATTRS){ 1674 if(type==SSH_FXP_STATUS){ 1675 int i=buf.getInt(); 1676 throwStatusError(buf, i); 1677 } 1678 throw new SftpException(SSH_FX_FAILURE, ""); 1679 } 1680 SftpATTRS attr=SftpATTRS.getATTR(buf); 1681 return attr; 1682 } 1683 catch(Exception e){ 1684 if(e instanceof SftpException) throw (SftpException)e; 1685 if(e instanceof Throwable ) 1686 throw new SftpException(SSH_FX_FAILURE, "", (Throwable )e); 1687 throw new SftpException(SSH_FX_FAILURE, ""); 1688 } 1689 } 1691 1692 public SftpATTRS lstat(String path) throws SftpException{ 1693 try{ 1694 path=remoteAbsolutePath(path); 1695 1696 Vector v=glob_remote(path); 1697 if(v.size()!=1){ 1698 throw new SftpException(SSH_FX_FAILURE, v.toString()); 1699 } 1700 path=(String )(v.elementAt(0)); 1701 1702 return _lstat(path); 1703 } 1704 catch(Exception e){ 1705 if(e instanceof SftpException) throw (SftpException)e; 1706 if(e instanceof Throwable ) 1707 throw new SftpException(SSH_FX_FAILURE, "", (Throwable )e); 1708 throw new SftpException(SSH_FX_FAILURE, ""); 1709 } 1710 } 1711 1712 private SftpATTRS _lstat(String path) throws SftpException{ 1713 try{ 1714 sendLSTAT(path.getBytes()); 1715 1716 Header header=new Header(); 1717 header=header(buf, header); 1718 int length=header.length; 1719 int type=header.type; 1720 buf.rewind(); 1721 fill(buf.buffer, 0, length); 1722 1723 if(type!=SSH_FXP_ATTRS){ 1724 if(type==SSH_FXP_STATUS){ 1725 int i=buf.getInt(); 1726 throwStatusError(buf, i); 1727 } 1728 throw new SftpException(SSH_FX_FAILURE, ""); 1729 } 1730 SftpATTRS attr=SftpATTRS.getATTR(buf); 1731 return attr; 1732 } 1733 catch(Exception e){ 1734 if(e instanceof SftpException) throw (SftpException)e; 1735 if(e instanceof Throwable ) 1736 throw new SftpException(SSH_FX_FAILURE, "", (Throwable )e); 1737 throw new SftpException(SSH_FX_FAILURE, ""); 1738 } 1739 } 1740 1741 public void setStat(String path, SftpATTRS attr) throws SftpException{ 1742 try{ 1743 path=remoteAbsolutePath(path); 1744 1745 Vector v=glob_remote(path); 1746 int vsize=v.size(); 1747 for(int j=0; j<vsize; j++){ 1748 path=(String )(v.elementAt(j)); 1749 _setStat(path, attr); 1750 } 1751 } 1752 catch(Exception e){ 1753 if(e instanceof SftpException) throw (SftpException)e; 1754 if(e instanceof Throwable ) 1755 throw new SftpException(SSH_FX_FAILURE, "", (Throwable )e); 1756 throw new SftpException(SSH_FX_FAILURE, ""); 1757 } 1758 } 1759 private void _setStat(String path, SftpATTRS attr) throws SftpException{ 1760 try{ 1761 sendSETSTAT(path.getBytes(), attr); 1762 1763 Header header=new Header(); 1764 header=header(buf, header); 1765 int length=header.length; 1766 int type=header.type; 1767 buf.rewind(); 1768 fill(buf.buffer, 0, length); 1769 1770 if(type!=SSH_FXP_STATUS){ 1771 throw new SftpException(SSH_FX_FAILURE, ""); 1772 } 1773 int i=buf.getInt(); 1774 if(i!=SSH_FX_OK){ 1775 throwStatusError(buf, i); 1776 } 1777 } 1778 catch(Exception e){ 1779 if(e instanceof SftpException) throw (SftpException)e; 1780 if(e instanceof Throwable ) 1781 throw new SftpException(SSH_FX_FAILURE, "", (Throwable )e); 1782 throw new SftpException(SSH_FX_FAILURE, ""); 1783 } 1784 } 1785 1786 public String pwd(){ return cwd; } 1787 public String lpwd(){ return lcwd; } 1788 public String version(){ return version; } 1789 public String getHome(){ return home; } 1790 1791 private void read(byte[] buf, int s, int l) throws IOException, SftpException{ 1792 int i=0; 1793 while(l>0){ 1794 i=io.in.read(buf, s, l); 1795 if(i<=0){ 1796 throw new SftpException(SSH_FX_FAILURE, ""); 1797 } 1798 s+=i; 1799 l-=i; 1800 } 1801 } 1802 1803 private boolean checkStatus(int[] ackid, Header header) throws IOException, SftpException{ 1804 header=header(buf, header); 1805 int length=header.length; 1806 int type=header.type; 1807 if(ackid!=null) 1808 ackid[0]=header.rid; 1809 buf.rewind(); 1810 fill(buf.buffer, 0, length); 1811 1812 if(type!=SSH_FXP_STATUS){ 1813 throw new SftpException(SSH_FX_FAILURE, ""); 1814 } 1815 int i=buf.getInt(); 1816 if(i!=SSH_FX_OK){ 1817 throwStatusError(buf, i); 1818 } 1819 return true; 1820 } 1821 private boolean _sendCLOSE(byte[] handle, Header header) throws Exception { 1822 sendCLOSE(handle); 1823 return checkStatus(null, header); 1824 } 1825 1826 private void sendINIT() throws Exception { 1827 packet.reset(); 1828 putHEAD(SSH_FXP_INIT, 5); 1829 buf.putInt(3); session.write(packet, this, 5+4); 1831 } 1832 1833 private void sendREALPATH(byte[] path) throws Exception { 1834 sendPacketPath(SSH_FXP_REALPATH, path); 1835 } 1836 private void sendSTAT(byte[] path) throws Exception { 1837 sendPacketPath(SSH_FXP_STAT, path); 1838 } 1839 private void sendLSTAT(byte[] path) throws Exception { 1840 sendPacketPath(SSH_FXP_LSTAT, path); 1841 } 1842 private void sendFSTAT(byte[] handle) throws Exception { 1843 sendPacketPath(SSH_FXP_FSTAT, handle); 1844 } 1845 private void sendSETSTAT(byte[] path, SftpATTRS attr) throws Exception { 1846 packet.reset(); 1847 putHEAD(SSH_FXP_SETSTAT, 9+path.length+attr.length()); 1848 buf.putInt(seq++); 1849 buf.putString(path); attr.dump(buf); 1851 session.write(packet, this, 9+path.length+attr.length()+4); 1852 } 1853 private void sendREMOVE(byte[] path) throws Exception { 1854 sendPacketPath(SSH_FXP_REMOVE, path); 1855 } 1856 private void sendMKDIR(byte[] path, SftpATTRS attr) throws Exception { 1857 packet.reset(); 1858 putHEAD(SSH_FXP_MKDIR, 9+path.length+(attr!=null?attr.length():4)); 1859 buf.putInt(seq++); 1860 buf.putString(path); if(attr!=null) attr.dump(buf); 1862 else buf.putInt(0); 1863 session.write(packet, this, 9+path.length+(attr!=null?attr.length():4)+4); 1864 } 1865 private void sendRMDIR(byte[] path) throws Exception { 1866 sendPacketPath(SSH_FXP_RMDIR, path); 1867 } 1868 private void sendSYMLINK(byte[] p1, byte[] p2) throws Exception { 1869 sendPacketPath(SSH_FXP_SYMLINK, p1, p2); 1870 } 1871 private void sendREADLINK(byte[] path) throws Exception { 1872 sendPacketPath(SSH_FXP_READLINK, path); 1873 } 1874 private void sendOPENDIR(byte[] path) throws Exception { 1875 sendPacketPath(SSH_FXP_OPENDIR, path); 1876 } 1877 private void sendREADDIR(byte[] path) throws Exception { 1878 sendPacketPath(SSH_FXP_READDIR, path); 1879 } 1880 private void sendRENAME(byte[] p1, byte[] p2) throws Exception { 1881 sendPacketPath(SSH_FXP_RENAME, p1, p2); 1882 } 1883 private void sendCLOSE(byte[] path) throws Exception { 1884 sendPacketPath(SSH_FXP_CLOSE, path); 1885 } 1886 private void sendOPENR(byte[] path) throws Exception { 1887 sendOPEN(path, SSH_FXF_READ); 1888 } 1889 private void sendOPENW(byte[] path) throws Exception { 1890 sendOPEN(path, SSH_FXF_WRITE|SSH_FXF_CREAT|SSH_FXF_TRUNC); 1891 } 1892 private void sendOPENA(byte[] path) throws Exception { 1893 sendOPEN(path, SSH_FXF_WRITE|SSH_FXF_CREAT); 1894 } 1895 private void sendOPEN(byte[] path, int mode) throws Exception { 1896 packet.reset(); 1897 putHEAD(SSH_FXP_OPEN, 17+path.length); 1898 buf.putInt(seq++); 1899 buf.putString(path); 1900 buf.putInt(mode); 1901 buf.putInt(0); session.write(packet, this, 17+path.length+4); 1903 } 1904 private void sendPacketPath(byte fxp, byte[] path) throws Exception { 1905 packet.reset(); 1906 putHEAD(fxp, 9+path.length); 1907 buf.putInt(seq++); 1908 buf.putString(path); session.write(packet, this, 9+path.length+4); 1910 } 1911 private void sendPacketPath(byte fxp, byte[] p1, byte[] p2) throws Exception { 1912 packet.reset(); 1913 putHEAD(fxp, 13+p1.length+p2.length); 1914 buf.putInt(seq++); 1915 buf.putString(p1); 1916 buf.putString(p2); 1917 session.write(packet, this, 13+p1.length+p2.length+4); 1918 } 1919 1920 private int sendWRITE(byte[] handle, long offset, 1921 byte[] data, int start, int length) throws Exception { 1922 int _length=length; 1923 packet.reset(); 1924 if(buf.buffer.length<buf.index+13+21+handle.length+length 1925 +32 +20 ){ 1927 _length=buf.buffer.length-(buf.index+13+21+handle.length 1928 +32 +20 ); 1930 } 1932 1933 putHEAD(SSH_FXP_WRITE, 21+handle.length+_length); buf.putInt(seq++); buf.putString(handle); buf.putLong(offset); if(buf.buffer!=data){ 1938 buf.putString(data, start, _length); } 1940 else{ 1941 buf.putInt(_length); 1942 buf.skip(_length); 1943 } 1944 session.write(packet, this, 21+handle.length+_length+4); 1945 return _length; 1946 } 1947 1948 private void sendREAD(byte[] handle, long offset, int length) throws Exception { 1949 packet.reset(); 1950 putHEAD(SSH_FXP_READ, 21+handle.length); 1951 buf.putInt(seq++); 1952 buf.putString(handle); 1953 buf.putLong(offset); 1954 buf.putInt(length); 1955 session.write(packet, this, 21+handle.length+4); 1956 } 1957 1958 private void putHEAD(byte type, int length) throws Exception { 1959 buf.putByte((byte)Session.SSH_MSG_CHANNEL_DATA); 1960 buf.putInt(recipient); 1961 buf.putInt(length+4); 1962 buf.putInt(length); 1963 buf.putByte(type); 1964 } 1965 1966 private Vector glob_remote(String _path) throws Exception { 1967 Vector v=new Vector (); 1969 byte[] path=_path.getBytes(); 1970 if(!isPattern(path)){ 1971 v.addElement(Util.unquote(_path)); return v; 1972 } 1973 int i=path.length-1; 1974 while(i>=0){if(path[i]=='/')break;i--;} 1975 if(i<0){ v.addElement(Util.unquote(_path)); return v;} 1976 byte[] dir; 1977 if(i==0){dir=new byte[]{(byte)'/'};} 1978 else{ 1979 dir=new byte[i]; 1980 System.arraycopy(path, 0, dir, 0, i); 1981 } 1982 byte[] pattern=new byte[path.length-i-1]; 1984 System.arraycopy(path, i+1, pattern, 0, pattern.length); 1985 1987 sendOPENDIR(dir); 1988 1989 Header header=new Header(); 1990 header=header(buf, header); 1991 int length=header.length; 1992 int type=header.type; 1993 buf.rewind(); 1994 fill(buf.buffer, 0, length); 1995 1996 if(type!=SSH_FXP_STATUS && type!=SSH_FXP_HANDLE){ 1997 throw new SftpException(SSH_FX_FAILURE, ""); 1998 } 1999 if(type==SSH_FXP_STATUS){ 2000 i=buf.getInt(); 2001 throwStatusError(buf, i); 2002 } 2003 2004 byte[] handle=buf.getString(); 2006 while(true){ 2007 sendREADDIR(handle); 2008 header=header(buf, header); 2009 length=header.length; 2010 type=header.type; 2011 2012 if(type!=SSH_FXP_STATUS && type!=SSH_FXP_NAME){ 2013 throw new SftpException(SSH_FX_FAILURE, ""); 2014 } 2015 if(type==SSH_FXP_STATUS){ 2016 buf.rewind(); 2017 fill(buf.buffer, 0, length); 2018 break; 2019 } 2020 2021 buf.rewind(); 2022 fill(buf.buffer, 0, 4); length-=4; 2023 int count=buf.getInt(); 2024 2025 byte[] str; 2026 int flags; 2027 2028 buf.reset(); 2029 while(count>0){ 2030 if(length>0){ 2031 buf.shift(); 2032 int j=(buf.buffer.length>(buf.index+length)) ? length : (buf.buffer.length-buf.index); 2033 i=io.in.read(buf.buffer, buf.index, j); 2034 if(i<=0)break; 2035 buf.index+=i; 2036 length-=i; 2037 } 2038 2039 byte[] filename=buf.getString(); 2040 str=buf.getString(); 2042 SftpATTRS attrs=SftpATTRS.getATTR(buf); 2043 2044 if(Util.glob(pattern, filename)){ 2045 v.addElement(new String (dir)+"/"+new String (filename)); 2046 } 2047 count--; 2048 } 2049 } 2050 if(_sendCLOSE(handle, header)) 2051 return v; 2052 return null; 2053 } 2054 2055 private boolean isPattern(byte[] path){ 2056 int i=path.length-1; 2057 while(i>=0){ 2058 if(path[i]=='*' || path[i]=='?'){ 2059 if(i>0 && path[i-1]=='\\'){ 2060 i--; 2061 } 2062 else{ 2063 break; 2064 } 2065 } 2066 i--; 2067 } 2068 return !(i<0); 2070 } 2071 2072 private Vector glob_local(String _path) throws Exception { 2073 Vector v=new Vector (); 2075 byte[] path=_path.getBytes(); 2076 int i=path.length-1; 2077 while(i>=0){if(path[i]=='*' || path[i]=='?')break;i--;} 2078 if(i<0){ v.addElement(_path); return v;} 2079 while(i>=0){if(path[i]==file_separatorc)break;i--;} 2080 if(i<0){ v.addElement(_path); return v;} 2081 byte[] dir; 2082 if(i==0){dir=new byte[]{(byte)file_separatorc};} 2083 else{ 2084 dir=new byte[i]; 2085 System.arraycopy(path, 0, dir, 0, i); 2086 } 2087 byte[] pattern=new byte[path.length-i-1]; 2088 System.arraycopy(path, i+1, pattern, 0, pattern.length); 2089 try{ 2091 String [] children=(new File(new String (dir))).list(); 2092 for(int j=0; j<children.length; j++){ 2093 if(Util.glob(pattern, children[j].getBytes())){ 2095 v.addElement(new String (dir)+file_separator+children[j]); 2096 } 2097 } 2098 } 2099 catch(Exception e){ 2100 } 2101 return v; 2102 } 2103 2104 private void throwStatusError(Buffer buf, int i) throws SftpException{ 2105 if(server_version>=3){ 2106 byte[] str=buf.getString(); 2107 throw new SftpException(i, new String (str)); 2109 } 2110 else{ 2111 throw new SftpException(i, "Failure"); 2112 } 2113 } 2114 2115 private static boolean isLocalAbsolutePath(String path){ 2116 return (new File(path)).isAbsolute(); 2117 } 2118 2119 2124 2125 public void disconnect(){ 2126 clearRunningThreads(); 2128 super.disconnect(); 2129 } 2130 private java.util.Vector threadList=null; 2131 protected synchronized void addRunningThread(Thread thread){ 2132 if(threadList==null)threadList=new java.util.Vector (); 2133 threadList.add(thread); 2134 } 2135 protected synchronized void clearRunningThreads(){ 2136 if(threadList==null)return; 2137 for(int t=0;t<threadList.size();t++){ 2138 Thread thread=(Thread )threadList.get(t); 2139 if(thread!=null) 2140 if(thread.isAlive()) 2141 thread.interrupt(); 2142 } 2143 threadList.clear(); 2144 } 2145 private boolean isPattern(String path){ 2146 return path.indexOf("*")!=-1 || path.indexOf("?")!=-1; 2147 } 2148 2149 private int fill(byte[] buf, int s, int len) throws IOException{ 2150 int i=0; 2151 int foo=s; 2152 while(len>0){ 2153 i=io.in.read(buf, s, len); 2154 if(i<=0){ 2155 throw new IOException("inputstream is closed"); 2156 } 2158 s+=i; 2159 len-=i; 2160 } 2161 return s-foo; 2162 } 2163 private void skip(long foo) throws IOException{ 2164 while(foo>0){ 2165 long bar=io.in.skip(foo); 2166 if(bar<=0) 2167 break; 2168 foo-=bar; 2169 } 2170 } 2171 2172 class Header{ 2173 int length; 2174 int type; 2175 int rid; 2176 } 2177 private Header header(Buffer buf, Header header) throws IOException{ 2178 buf.rewind(); 2179 int i=fill(buf.buffer, 0, 9); 2180 header.length=buf.getInt()-5; 2181 header.type=buf.getByte()&0xff; 2182 header.rid=buf.getInt(); 2183 return header; 2184 } 2185 private String remoteAbsolutePath(String path){ 2186 if(path.charAt(0)=='/') return path; 2187 if(cwd.endsWith("/")) return cwd+path; 2188 return cwd+"/"+path; 2189 } 2190 2191 private String localAbsolutePath(String path){ 2192 if(isLocalAbsolutePath(path)) return path; 2193 if(lcwd.endsWith(file_separator)) return lcwd+path; 2194 return lcwd+file_separator+path; 2195 } 2196 2197 public class LsEntry { 2198 private String filename; 2199 private String longname; 2200 private SftpATTRS attrs; 2201 LsEntry(String filename, String longname, SftpATTRS attrs){ 2202 setFilename(filename); 2203 setLongname(longname); 2204 setAttrs(attrs); 2205 } 2206 public String getFilename(){return filename;}; 2207 void setFilename(String filename){this.filename = filename;}; 2208 public String getLongname(){return longname;}; 2209 void setLongname(String longname){this.longname = longname;}; 2210 public SftpATTRS getAttrs(){return attrs;}; 2211 void setAttrs(SftpATTRS attrs) {this.attrs = attrs;}; 2212 public String toString(){ return longname; } 2213 } 2214} 2215 | Popular Tags |