]> Joshua Wise's Git repositories - dumload.git/blame_incremental - src/com/jcraft/jsch/ChannelSftp.java
Add a progress bar.
[dumload.git] / src / com / jcraft / jsch / ChannelSftp.java
... / ...
CommitLineData
1/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
2/*
3Copyright (c) 2002-2010 ymnk, JCraft,Inc. All rights reserved.
4
5Redistribution and use in source and binary forms, with or without
6modification, are permitted provided that the following conditions are met:
7
8 1. Redistributions of source code must retain the above copyright notice,
9 this list of conditions and the following disclaimer.
10
11 2. Redistributions in binary form must reproduce the above copyright
12 notice, this list of conditions and the following disclaimer in
13 the documentation and/or other materials provided with the distribution.
14
15 3. The names of the authors may not be used to endorse or promote products
16 derived from this software without specific prior written permission.
17
18THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
19INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
21INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
22INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
24OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
27EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*/
29
30package com.jcraft.jsch;
31
32import java.io.*;
33
34import java.util.Vector;
35
36public 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 // pflags
67 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/*
90 SSH_FX_OK
91 Indicates successful completion of the operation.
92 SSH_FX_EOF
93 indicates end-of-file condition; for SSH_FX_READ it means that no
94 more data is available in the file, and for SSH_FX_READDIR it
95 indicates that no more files are contained in the directory.
96 SSH_FX_NO_SUCH_FILE
97 is returned when a reference is made to a file which should exist
98 but doesn't.
99 SSH_FX_PERMISSION_DENIED
100 is returned when the authenticated user does not have sufficient
101 permissions to perform the operation.
102 SSH_FX_FAILURE
103 is a generic catch-all error message; it should be returned if an
104 error occurs for which there is no more specific error code
105 defined.
106 SSH_FX_BAD_MESSAGE
107 may be returned if a badly formatted packet or protocol
108 incompatibility is detected.
109 SSH_FX_NO_CONNECTION
110 is a pseudo-error which indicates that the client has no
111 connection to the server (it can only be generated locally by the
112 client, and MUST NOT be returned by servers).
113 SSH_FX_CONNECTION_LOST
114 is a pseudo-error which indicates that the connection to the
115 server has been lost (it can only be generated locally by the
116 client, and MUST NOT be returned by servers).
117 SSH_FX_OP_UNSUPPORTED
118 indicates that an attempt was made to perform an operation which
119 is not supported for the server (it may be generated locally by
120 the client if e.g. the version number exchange indicates that a
121 required feature is not supported by the server, or it may be
122 returned by the server if the server does not implement an
123 operation).
124*/
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;
132 private int seq=1;
133 private int[] ackid=new int[1];
134 private Buffer buf;
135 private Packet packet=new Packet(buf);
136
137 private int client_version=3;
138 private int server_version=3;
139 private String version=String.valueOf(client_version);
140
141 private java.util.Hashtable extensions=null;
142 private InputStream io_in=null;
143
144/*
14510. Changes from previous protocol versions
146 The SSH File Transfer Protocol has changed over time, before it's
147 standardization. The following is a description of the incompatible
148 changes between different versions.
14910.1 Changes between versions 3 and 2
150 o The SSH_FXP_READLINK and SSH_FXP_SYMLINK messages were added.
151 o The SSH_FXP_EXTENDED and SSH_FXP_EXTENDED_REPLY messages were added.
152 o The SSH_FXP_STATUS message was changed to include fields `error
153 message' and `language tag'.
15410.2 Changes between versions 2 and 1
155 o The SSH_FXP_RENAME message was added.
15610.3 Changes between versions 1 and 0
157 o Implementation changes, no actual protocol changes.
158*/
159
160 private static final String file_separator=java.io.File.separator;
161 private static final char file_separatorc=java.io.File.separatorChar;
162 private static boolean fs_is_bs=(byte)java.io.File.separatorChar == '\\';
163
164 private String cwd;
165 private String home;
166 private String lcwd;
167
168 private static final String UTF8="UTF-8";
169 private String fEncoding=UTF8;
170 private boolean fEncoding_is_utf8=true;
171
172 void init(){
173 }
174
175 public void start() throws JSchException{
176 try{
177
178 PipedOutputStream pos=new PipedOutputStream();
179 io.setOutputStream(pos);
180 PipedInputStream pis=new MyPipedInputStream(pos, 32*1024);
181 io.setInputStream(pis);
182
183 io_in=io.in;
184
185 if(io_in==null){
186 throw new JSchException("channel is down");
187 }
188
189 Request request=new RequestSftp();
190 request.request(getSession(), this);
191
192 /*
193 System.err.println("lmpsize: "+lmpsize);
194 System.err.println("lwsize: "+lwsize);
195 System.err.println("rmpsize: "+rmpsize);
196 System.err.println("rwsize: "+rwsize);
197 */
198
199 buf=new Buffer(rmpsize);
200 packet=new Packet(buf);
201 int i=0;
202 int length;
203 int type;
204 byte[] str;
205
206 // send SSH_FXP_INIT
207 sendINIT();
208
209 // receive SSH_FXP_VERSION
210 Header header=new Header();
211 header=header(buf, header);
212 length=header.length;
213 if(length > MAX_MSG_LENGTH){
214 throw new SftpException(SSH_FX_FAILURE,
215 "Received message is too long: " + length);
216 }
217 type=header.type; // 2 -> SSH_FXP_VERSION
218 server_version=header.rid;
219 //System.err.println("SFTP protocol server-version="+server_version);
220 if(length>0){
221 extensions=new java.util.Hashtable();
222 // extension data
223 fill(buf, length);
224 byte[] extension_name=null;
225 byte[] extension_data=null;
226 while(length>0){
227 extension_name=buf.getString();
228 length-=(4+extension_name.length);
229 extension_data=buf.getString();
230 length-=(4+extension_data.length);
231 extensions.put(Util.byte2str(extension_name),
232 Util.byte2str(extension_data));
233 }
234 }
235
236 lcwd=new File(".").getCanonicalPath();
237 }
238 catch(Exception e){
239 //System.err.println(e);
240 if(e instanceof JSchException) throw (JSchException)e;
241 if(e instanceof Throwable)
242 throw new JSchException(e.toString(), (Throwable)e);
243 throw new JSchException(e.toString());
244 }
245 }
246
247 public void quit(){ disconnect();}
248 public void exit(){ disconnect();}
249 public void lcd(String path) throws SftpException{
250 path=localAbsolutePath(path);
251 if((new File(path)).isDirectory()){
252 try{
253 path=(new File(path)).getCanonicalPath();
254 }
255 catch(Exception e){}
256 lcwd=path;
257 return;
258 }
259 throw new SftpException(SSH_FX_NO_SUCH_FILE, "No such directory");
260 }
261
262 public void cd(String path) throws SftpException{
263 try{
264 path=remoteAbsolutePath(path);
265
266 path=isUnique(path);
267
268 byte[] str=_realpath(path);
269 SftpATTRS attr=_stat(str);
270
271 if((attr.getFlags()&SftpATTRS.SSH_FILEXFER_ATTR_PERMISSIONS)==0){
272 throw new SftpException(SSH_FX_FAILURE,
273 "Can't change directory: "+path);
274 }
275 if(!attr.isDir()){
276 throw new SftpException(SSH_FX_FAILURE,
277 "Can't change directory: "+path);
278 }
279
280 setCwd(Util.byte2str(str, fEncoding));
281 }
282 catch(Exception e){
283 if(e instanceof SftpException) throw (SftpException)e;
284 if(e instanceof Throwable)
285 throw new SftpException(SSH_FX_FAILURE, "", (Throwable)e);
286 throw new SftpException(SSH_FX_FAILURE, "");
287 }
288 }
289
290 public void put(String src, String dst) throws SftpException{
291 put(src, dst, null, OVERWRITE);
292 }
293 public void put(String src, String dst, int mode) throws SftpException{
294 put(src, dst, null, mode);
295 }
296 public void put(String src, String dst,
297 SftpProgressMonitor monitor) throws SftpException{
298 put(src, dst, monitor, OVERWRITE);
299 }
300 public void put(String src, String dst,
301 SftpProgressMonitor monitor, int mode) throws SftpException{
302 src=localAbsolutePath(src);
303 dst=remoteAbsolutePath(dst);
304
305 try{
306
307 Vector v=glob_remote(dst);
308 int vsize=v.size();
309 if(vsize!=1){
310 if(vsize==0){
311 if(isPattern(dst))
312 throw new SftpException(SSH_FX_FAILURE, dst);
313 else
314 dst=Util.unquote(dst);
315 }
316 throw new SftpException(SSH_FX_FAILURE, v.toString());
317 }
318 else{
319 dst=(String)(v.elementAt(0));
320 }
321
322 boolean isRemoteDir=isRemoteDir(dst);
323
324 v=glob_local(src);
325 vsize=v.size();
326
327 StringBuffer dstsb=null;
328 if(isRemoteDir){
329 if(!dst.endsWith("/")){
330 dst+="/";
331 }
332 dstsb=new StringBuffer(dst);
333 }
334 else if(vsize>1){
335 throw new SftpException(SSH_FX_FAILURE,
336 "Copying multiple files, but the destination is missing or a file.");
337 }
338
339 for(int j=0; j<vsize; j++){
340 String _src=(String)(v.elementAt(j));
341 String _dst=null;
342 if(isRemoteDir){
343 int i=_src.lastIndexOf(file_separatorc);
344 if(fs_is_bs){
345 int ii=_src.lastIndexOf('/');
346 if(ii!=-1 && ii>i)
347 i=ii;
348 }
349 if(i==-1) dstsb.append(_src);
350 else dstsb.append(_src.substring(i + 1));
351 _dst=dstsb.toString();
352 dstsb.delete(dst.length(), _dst.length());
353 }
354 else{
355 _dst=dst;
356 }
357 //System.err.println("_dst "+_dst);
358
359 long size_of_dst=0;
360 if(mode==RESUME){
361 try{
362 SftpATTRS attr=_stat(_dst);
363 size_of_dst=attr.getSize();
364 }
365 catch(Exception eee){
366 //System.err.println(eee);
367 }
368 long size_of_src=new File(_src).length();
369 if(size_of_src<size_of_dst){
370 throw new SftpException(SSH_FX_FAILURE,
371 "failed to resume for "+_dst);
372 }
373 if(size_of_src==size_of_dst){
374 return;
375 }
376 }
377
378 if(monitor!=null){
379 monitor.init(SftpProgressMonitor.PUT, _src, _dst,
380 (new File(_src)).length());
381 if(mode==RESUME){
382 monitor.count(size_of_dst);
383 }
384 }
385 FileInputStream fis=null;
386 try{
387 fis=new FileInputStream(_src);
388 _put(fis, _dst, monitor, mode);
389 }
390 finally{
391 if(fis!=null) {
392 fis.close();
393 }
394 }
395 }
396 }
397 catch(Exception e){
398 if(e instanceof SftpException) throw (SftpException)e;
399 if(e instanceof Throwable)
400 throw new SftpException(SSH_FX_FAILURE, e.toString(), (Throwable)e);
401 throw new SftpException(SSH_FX_FAILURE, e.toString());
402 }
403 }
404 public void put(InputStream src, String dst) throws SftpException{
405 put(src, dst, null, OVERWRITE);
406 }
407 public void put(InputStream src, String dst, int mode) throws SftpException{
408 put(src, dst, null, mode);
409 }
410 public void put(InputStream src, String dst,
411 SftpProgressMonitor monitor) throws SftpException{
412 put(src, dst, monitor, OVERWRITE);
413 }
414 public void put(InputStream src, String dst,
415 SftpProgressMonitor monitor, int mode) throws SftpException{
416 try{
417 dst=remoteAbsolutePath(dst);
418
419 Vector v=glob_remote(dst);
420 int vsize=v.size();
421 if(vsize!=1){
422 if(vsize==0){
423 if(isPattern(dst))
424 throw new SftpException(SSH_FX_FAILURE, dst);
425 else
426 dst=Util.unquote(dst);
427 }
428 throw new SftpException(SSH_FX_FAILURE, v.toString());
429 }
430 else{
431 dst=(String)(v.elementAt(0));
432 }
433
434 if(isRemoteDir(dst)){
435 throw new SftpException(SSH_FX_FAILURE, dst+" is a directory");
436 }
437
438 _put(src, dst, monitor, mode);
439 }
440 catch(Exception e){
441 if(e instanceof SftpException) throw (SftpException)e;
442 if(e instanceof Throwable)
443 throw new SftpException(SSH_FX_FAILURE, e.toString(), (Throwable)e);
444 throw new SftpException(SSH_FX_FAILURE, e.toString());
445 }
446 }
447
448 public void _put(InputStream src, String dst,
449 SftpProgressMonitor monitor, int mode) throws SftpException{
450 try{
451 byte[] dstb=Util.str2byte(dst, fEncoding);
452 long skip=0;
453 if(mode==RESUME || mode==APPEND){
454 try{
455 SftpATTRS attr=_stat(dstb);
456 skip=attr.getSize();
457 }
458 catch(Exception eee){
459 //System.err.println(eee);
460 }
461 }
462 if(mode==RESUME && skip>0){
463 long skipped=src.skip(skip);
464 if(skipped<skip){
465 throw new SftpException(SSH_FX_FAILURE, "failed to resume for "+dst);
466 }
467 }
468
469 if(mode==OVERWRITE){ sendOPENW(dstb); }
470 else{ sendOPENA(dstb); }
471
472 Header header=new Header();
473 header=header(buf, header);
474 int length=header.length;
475 int type=header.type;
476
477 fill(buf, length);
478
479 if(type!=SSH_FXP_STATUS && type!=SSH_FXP_HANDLE){
480 throw new SftpException(SSH_FX_FAILURE, "invalid type="+type);
481 }
482 if(type==SSH_FXP_STATUS){
483 int i=buf.getInt();
484 throwStatusError(buf, i);
485 }
486 byte[] handle=buf.getString(); // handle
487 byte[] data=null;
488
489 boolean dontcopy=true;
490
491 if(!dontcopy){
492 data=new byte[buf.buffer.length
493 -(5+13+21+handle.length
494 +32 +20 // padding and mac
495 )
496 ];
497 }
498
499 long offset=0;
500 if(mode==RESUME || mode==APPEND){
501 offset+=skip;
502 }
503
504 int startid=seq;
505 int _ackid=seq;
506 int ackcount=0;
507 while(true){
508 int nread=0;
509 int s=0;
510 int datalen=0;
511 int count=0;
512
513 if(!dontcopy){
514 datalen=data.length-s;
515 }
516 else{
517 data=buf.buffer;
518 s=5+13+21+handle.length;
519 datalen=buf.buffer.length -s
520 -32 -20; // padding and mac
521 }
522
523 do{
524 nread=src.read(data, s, datalen);
525 if(nread>0){
526 s+=nread;
527 datalen-=nread;
528 count+=nread;
529 }
530 }
531 while(datalen>0 && nread>0);
532 if(count<=0)break;
533
534 int _i=count;
535 while(_i>0){
536 _i-=sendWRITE(handle, offset, data, 0, _i);
537 if((seq-1)==startid ||
538 io_in.available()>=1024){
539 while(io_in.available()>0){
540 if(checkStatus(ackid, header)){
541 _ackid=ackid[0];
542 if(startid>_ackid || _ackid>seq-1){
543 if(_ackid==seq){
544 System.err.println("ack error: startid="+startid+" seq="+seq+" _ackid="+_ackid);
545 }
546 else{
547 //throw new SftpException(SSH_FX_FAILURE, "ack error:");
548 throw new SftpException(SSH_FX_FAILURE, "ack error: startid="+startid+" seq="+seq+" _ackid="+_ackid);
549 }
550 }
551 ackcount++;
552 }
553 else{
554 break;
555 }
556 }
557 }
558 }
559 offset+=count;
560 if(monitor!=null && !monitor.count(count)){
561 break;
562 }
563 }
564 int _ackcount=seq-startid;
565 while(_ackcount>ackcount){
566 if(!checkStatus(null, header)){
567 break;
568 }
569 ackcount++;
570 }
571 if(monitor!=null)monitor.end();
572 _sendCLOSE(handle, header);
573 }
574 catch(Exception e){
575 if(e instanceof SftpException) throw (SftpException)e;
576 if(e instanceof Throwable)
577 throw new SftpException(SSH_FX_FAILURE, e.toString(), (Throwable)e);
578 throw new SftpException(SSH_FX_FAILURE, e.toString());
579 }
580 }
581
582 public OutputStream put(String dst) throws SftpException{
583 return put(dst, (SftpProgressMonitor)null, OVERWRITE);
584 }
585 public OutputStream put(String dst, final int mode) throws SftpException{
586 return put(dst, (SftpProgressMonitor)null, mode);
587 }
588 public OutputStream put(String dst, final SftpProgressMonitor monitor, final int mode) throws SftpException{
589 return put(dst, monitor, mode, 0);
590 }
591 public OutputStream put(String dst, final SftpProgressMonitor monitor, final int mode, long offset) throws SftpException{
592 dst=remoteAbsolutePath(dst);
593 try{
594
595 dst=isUnique(dst);
596
597 if(isRemoteDir(dst)){
598 throw new SftpException(SSH_FX_FAILURE, dst+" is a directory");
599 }
600
601 byte[] dstb=Util.str2byte(dst, fEncoding);
602
603 long skip=0;
604 if(mode==RESUME || mode==APPEND){
605 try{
606 SftpATTRS attr=_stat(dstb);
607 skip=attr.getSize();
608 }
609 catch(Exception eee){
610 //System.err.println(eee);
611 }
612 }
613
614 if(mode==OVERWRITE){ sendOPENW(dstb); }
615 else{ sendOPENA(dstb); }
616
617 Header header=new Header();
618 header=header(buf, header);
619 int length=header.length;
620 int type=header.type;
621
622 fill(buf, length);
623
624 if(type!=SSH_FXP_STATUS && type!=SSH_FXP_HANDLE){
625 throw new SftpException(SSH_FX_FAILURE, "");
626 }
627 if(type==SSH_FXP_STATUS){
628 int i=buf.getInt();
629 throwStatusError(buf, i);
630 }
631 final byte[] handle=buf.getString(); // handle
632
633 if(mode==RESUME || mode==APPEND){
634 offset+=skip;
635 }
636
637 final long[] _offset=new long[1];
638 _offset[0]=offset;
639 OutputStream out = new OutputStream(){
640 private boolean init=true;
641 private boolean isClosed=false;
642 private int[] ackid=new int[1];
643 private int startid=0;
644 private int _ackid=0;
645 private int ackcount=0;
646 private int writecount=0;
647 private Header header=new Header();
648
649 public void write(byte[] d) throws java.io.IOException{
650 write(d, 0, d.length);
651 }
652
653 public void write(byte[] d, int s, int len) throws java.io.IOException{
654 if(init){
655 startid=seq;
656 _ackid=seq;
657 init=false;
658 }
659
660 if(isClosed){
661 throw new IOException("stream already closed");
662 }
663
664 try{
665 int _len=len;
666 while(_len>0){
667 int sent=sendWRITE(handle, _offset[0], d, s, _len);
668 writecount++;
669 _offset[0]+=sent;
670 s+=sent;
671 _len-=sent;
672 if((seq-1)==startid ||
673 io_in.available()>=1024){
674 while(io_in.available()>0){
675 if(checkStatus(ackid, header)){
676 _ackid=ackid[0];
677 if(startid>_ackid || _ackid>seq-1){
678 throw new SftpException(SSH_FX_FAILURE, "");
679 }
680 ackcount++;
681 }
682 else{
683 break;
684 }
685 }
686 }
687 }
688 if(monitor!=null && !monitor.count(len)){
689 close();
690 throw new IOException("canceled");
691 }
692 }
693 catch(IOException e){ throw e; }
694 catch(Exception e){ throw new IOException(e.toString()); }
695 }
696
697 byte[] _data=new byte[1];
698 public void write(int foo) throws java.io.IOException{
699 _data[0]=(byte)foo;
700 write(_data, 0, 1);
701 }
702
703 public void flush() throws java.io.IOException{
704
705 if(isClosed){
706 throw new IOException("stream already closed");
707 }
708
709 if(!init){
710 try{
711 while(writecount>ackcount){
712 if(!checkStatus(null, header)){
713 break;
714 }
715 ackcount++;
716 }
717 }
718 catch(SftpException e){
719 throw new IOException(e.toString());
720 }
721 }
722 }
723
724 public void close() throws java.io.IOException{
725 if(isClosed){
726 return;
727 }
728 flush();
729 if(monitor!=null)monitor.end();
730 try{ _sendCLOSE(handle, header); }
731 catch(IOException e){ throw e; }
732 catch(Exception e){
733 throw new IOException(e.toString());
734 }
735 isClosed=true;
736 }
737 };
738 return out;
739 }
740 catch(Exception e){
741 if(e instanceof SftpException) throw (SftpException)e;
742 if(e instanceof Throwable)
743 throw new SftpException(SSH_FX_FAILURE, "", (Throwable)e);
744 throw new SftpException(SSH_FX_FAILURE, "");
745 }
746 }
747
748 public void get(String src, String dst) throws SftpException{
749 get(src, dst, null, OVERWRITE);
750 }
751 public void get(String src, String dst,
752 SftpProgressMonitor monitor) throws SftpException{
753 get(src, dst, monitor, OVERWRITE);
754 }
755 public void get(String src, String dst,
756 SftpProgressMonitor monitor, int mode) throws SftpException{
757 // System.out.println("get: "+src+" "+dst);
758
759 src=remoteAbsolutePath(src);
760 dst=localAbsolutePath(dst);
761
762 try{
763 Vector v=glob_remote(src);
764 int vsize=v.size();
765 if(vsize==0){
766 throw new SftpException(SSH_FX_NO_SUCH_FILE, "No such file");
767 }
768
769 File dstFile=new File(dst);
770 boolean isDstDir=dstFile.isDirectory();
771 StringBuffer dstsb=null;
772 if(isDstDir){
773 if(!dst.endsWith(file_separator)){
774 dst+=file_separator;
775 }
776 dstsb=new StringBuffer(dst);
777 }
778 else if(vsize>1){
779 throw new SftpException(SSH_FX_FAILURE,
780 "Copying multiple files, but destination is missing or a file.");
781 }
782
783 for(int j=0; j<vsize; j++){
784 String _src=(String)(v.elementAt(j));
785 SftpATTRS attr=_stat(_src);
786 if(attr.isDir()){
787 throw new SftpException(SSH_FX_FAILURE,
788 "not supported to get directory "+_src);
789 }
790
791 String _dst=null;
792 if(isDstDir){
793 int i=_src.lastIndexOf('/');
794 if(i==-1) dstsb.append(_src);
795 else dstsb.append(_src.substring(i + 1));
796 _dst=dstsb.toString();
797 dstsb.delete(dst.length(), _dst.length());
798 }
799 else{
800 _dst=dst;
801 }
802
803 if(mode==RESUME){
804 long size_of_src=attr.getSize();
805 long size_of_dst=new File(_dst).length();
806 if(size_of_dst>size_of_src){
807 throw new SftpException(SSH_FX_FAILURE,
808 "failed to resume for "+_dst);
809 }
810 if(size_of_dst==size_of_src){
811 return;
812 }
813 }
814
815 if(monitor!=null){
816 monitor.init(SftpProgressMonitor.GET, _src, _dst, attr.getSize());
817 if(mode==RESUME){
818 monitor.count(new File(_dst).length());
819 }
820 }
821
822 FileOutputStream fos=null;
823 try{
824 if(mode==OVERWRITE){
825 fos=new FileOutputStream(_dst);
826 }
827 else{
828 fos=new FileOutputStream(_dst, true); // append
829 }
830 // System.err.println("_get: "+_src+", "+_dst);
831 _get(_src, fos, monitor, mode, new File(_dst).length());
832 }
833 finally{
834 if(fos!=null){
835 fos.close();
836 }
837 }
838 }
839 }
840 catch(Exception e){
841 if(e instanceof SftpException) throw (SftpException)e;
842 if(e instanceof Throwable)
843 throw new SftpException(SSH_FX_FAILURE, "", (Throwable)e);
844 throw new SftpException(SSH_FX_FAILURE, "");
845 }
846 }
847 public void get(String src, OutputStream dst) throws SftpException{
848 get(src, dst, null, OVERWRITE, 0);
849 }
850 public void get(String src, OutputStream dst,
851 SftpProgressMonitor monitor) throws SftpException{
852 get(src, dst, monitor, OVERWRITE, 0);
853 }
854 public void get(String src, OutputStream dst,
855 SftpProgressMonitor monitor, int mode, long skip) throws SftpException{
856//System.err.println("get: "+src+", "+dst);
857 try{
858 src=remoteAbsolutePath(src);
859
860 src=isUnique(src);
861
862 if(monitor!=null){
863 SftpATTRS attr=_stat(src);
864 monitor.init(SftpProgressMonitor.GET, src, "??", attr.getSize());
865 if(mode==RESUME){
866 monitor.count(skip);
867 }
868 }
869 _get(src, dst, monitor, mode, skip);
870 }
871 catch(Exception e){
872 if(e instanceof SftpException) throw (SftpException)e;
873 if(e instanceof Throwable)
874 throw new SftpException(SSH_FX_FAILURE, "", (Throwable)e);
875 throw new SftpException(SSH_FX_FAILURE, "");
876 }
877 }
878
879 private void _get(String src, OutputStream dst,
880 SftpProgressMonitor monitor, int mode, long skip) throws SftpException{
881 //System.err.println("_get: "+src+", "+dst);
882
883 byte[] srcb=Util.str2byte(src, fEncoding);
884 try{
885 sendOPENR(srcb);
886
887 Header header=new Header();
888 header=header(buf, header);
889 int length=header.length;
890 int type=header.type;
891
892 fill(buf, length);
893
894 if(type!=SSH_FXP_STATUS && type!=SSH_FXP_HANDLE){
895 throw new SftpException(SSH_FX_FAILURE, "");
896 }
897
898 if(type==SSH_FXP_STATUS){
899 int i=buf.getInt();
900 throwStatusError(buf, i);
901 }
902
903 byte[] handle=buf.getString(); // filename
904
905 long offset=0;
906 if(mode==RESUME){
907 offset+=skip;
908 }
909
910 int request_len=0;
911 loop:
912 while(true){
913
914 request_len=buf.buffer.length-13;
915 if(server_version==0){ request_len=1024; }
916 sendREAD(handle, offset, request_len);
917
918 header=header(buf, header);
919 length=header.length;
920 type=header.type;
921
922 if(type==SSH_FXP_STATUS){
923 fill(buf, length);
924 int i=buf.getInt();
925 if(i==SSH_FX_EOF){
926 break loop;
927 }
928 throwStatusError(buf, i);
929 }
930
931 if(type!=SSH_FXP_DATA){
932 break loop;
933 }
934
935 buf.rewind();
936 fill(buf.buffer, 0, 4); length-=4;
937 int i=buf.getInt(); // length of data
938 int foo=i;
939
940 while(foo>0){
941 int bar=foo;
942 if(bar>buf.buffer.length){
943 bar=buf.buffer.length;
944 }
945 i=io_in.read(buf.buffer, 0, bar);
946 if(i<0){
947 break loop;
948 }
949 int data_len=i;
950 dst.write(buf.buffer, 0, data_len);
951
952 offset+=data_len;
953 foo-=data_len;
954
955 if(monitor!=null){
956 if(!monitor.count(data_len)){
957 while(foo>0){
958 i=io_in.read(buf.buffer,
959 0,
960 (buf.buffer.length<foo?buf.buffer.length:foo));
961 if(i<=0) break;
962 foo-=i;
963 }
964 break loop;
965 }
966 }
967
968 }
969 //System.err.println("length: "+length); // length should be 0
970 }
971 dst.flush();
972
973 if(monitor!=null)monitor.end();
974 _sendCLOSE(handle, header);
975 }
976 catch(Exception e){
977 if(e instanceof SftpException) throw (SftpException)e;
978 if(e instanceof Throwable)
979 throw new SftpException(SSH_FX_FAILURE, "", (Throwable)e);
980 throw new SftpException(SSH_FX_FAILURE, "");
981 }
982 }
983
984 public InputStream get(String src) throws SftpException{
985 return get(src, null, 0L);
986 }
987 public InputStream get(String src, SftpProgressMonitor monitor) throws SftpException{
988 return get(src, monitor, 0L);
989 }
990
991 /**
992 * @deprecated This method will be deleted in the future.
993 */
994 public InputStream get(String src, int mode) throws SftpException{
995 return get(src, null, 0L);
996 }
997 /**
998 * @deprecated This method will be deleted in the future.
999 */
1000 public InputStream get(String src, final SftpProgressMonitor monitor, final int mode) throws SftpException{
1001 return get(src, monitor, 0L);
1002 }
1003 public InputStream get(String src, final SftpProgressMonitor monitor, final long skip) throws SftpException{
1004 src=remoteAbsolutePath(src);
1005 try{
1006 src=isUnique(src);
1007
1008 byte[] srcb=Util.str2byte(src, fEncoding);
1009
1010 SftpATTRS attr=_stat(srcb);
1011 if(monitor!=null){
1012 monitor.init(SftpProgressMonitor.GET, src, "??", attr.getSize());
1013 }
1014
1015 sendOPENR(srcb);
1016
1017 Header header=new Header();
1018 header=header(buf, header);
1019 int length=header.length;
1020 int type=header.type;
1021
1022 fill(buf, length);
1023
1024 if(type!=SSH_FXP_STATUS && type!=SSH_FXP_HANDLE){
1025 throw new SftpException(SSH_FX_FAILURE, "");
1026 }
1027 if(type==SSH_FXP_STATUS){
1028 int i=buf.getInt();
1029 throwStatusError(buf, i);
1030 }
1031
1032 final byte[] handle=buf.getString(); // handle
1033
1034 java.io.InputStream in=new java.io.InputStream(){
1035 long offset=skip;
1036 boolean closed=false;
1037 int rest_length=0;
1038 byte[] _data=new byte[1];
1039 byte[] rest_byte=new byte[1024];
1040 Header header=new Header();
1041
1042 public int read() throws java.io.IOException{
1043 if(closed)return -1;
1044 int i=read(_data, 0, 1);
1045 if (i==-1) { return -1; }
1046 else {
1047 return _data[0]&0xff;
1048 }
1049 }
1050 public int read(byte[] d) throws java.io.IOException{
1051 if(closed)return -1;
1052 return read(d, 0, d.length);
1053 }
1054 public int read(byte[] d, int s, int len) throws java.io.IOException{
1055 if(closed)return -1;
1056 if(d==null){throw new NullPointerException();}
1057 if(s<0 || len <0 || s+len>d.length){
1058 throw new IndexOutOfBoundsException();
1059 }
1060 if(len==0){ return 0; }
1061
1062 if(rest_length>0){
1063 int foo=rest_length;
1064 if(foo>len) foo=len;
1065 System.arraycopy(rest_byte, 0, d, s, foo);
1066 if(foo!=rest_length){
1067 System.arraycopy(rest_byte, foo,
1068 rest_byte, 0, rest_length-foo);
1069 }
1070
1071 if(monitor!=null){
1072 if(!monitor.count(foo)){
1073 close();
1074 return -1;
1075 }
1076 }
1077
1078 rest_length-=foo;
1079 return foo;
1080 }
1081
1082 if(buf.buffer.length-13<len){
1083 len=buf.buffer.length-13;
1084 }
1085 if(server_version==0 && len>1024){
1086 len=1024;
1087 }
1088
1089 try{sendREAD(handle, offset, len);}
1090 catch(Exception e){ throw new IOException("error"); }
1091
1092 header=header(buf, header);
1093 rest_length=header.length;
1094 int type=header.type;
1095 int id=header.rid;
1096
1097 if(type!=SSH_FXP_STATUS && type!=SSH_FXP_DATA){
1098 throw new IOException("error");
1099 }
1100 if(type==SSH_FXP_STATUS){
1101 fill(buf, rest_length);
1102 int i=buf.getInt();
1103 rest_length=0;
1104 if(i==SSH_FX_EOF){
1105 close();
1106 return -1;
1107 }
1108 //throwStatusError(buf, i);
1109 throw new IOException("error");
1110 }
1111 buf.rewind();
1112 fill(buf.buffer, 0, 4);
1113 int i=buf.getInt(); rest_length-=4;
1114
1115 offset+=rest_length;
1116 int foo=i;
1117 if(foo>0){
1118 int bar=rest_length;
1119 if(bar>len){
1120 bar=len;
1121 }
1122 i=io_in.read(d, s, bar);
1123 if(i<0){
1124 return -1;
1125 }
1126 rest_length-=i;
1127
1128 if(rest_length>0){
1129 if(rest_byte.length<rest_length){
1130 rest_byte=new byte[rest_length];
1131 }
1132 int _s=0;
1133 int _len=rest_length;
1134 int j;
1135 while(_len>0){
1136 j=io_in.read(rest_byte, _s, _len);
1137 if(j<=0)break;
1138 _s+=j;
1139 _len-=j;
1140 }
1141 }
1142
1143 if(monitor!=null){
1144 if(!monitor.count(i)){
1145 close();
1146 return -1;
1147 }
1148 }
1149
1150 return i;
1151 }
1152 return 0; // ??
1153 }
1154 public void close() throws IOException{
1155 if(closed)return;
1156 closed=true;
1157 if(monitor!=null)monitor.end();
1158 try{_sendCLOSE(handle, header);}
1159 catch(Exception e){throw new IOException("error");}
1160 }
1161 };
1162 return in;
1163 }
1164 catch(Exception e){
1165 if(e instanceof SftpException) throw (SftpException)e;
1166 if(e instanceof Throwable)
1167 throw new SftpException(SSH_FX_FAILURE, "", (Throwable)e);
1168 throw new SftpException(SSH_FX_FAILURE, "");
1169 }
1170 }
1171
1172 public java.util.Vector ls(String path) throws SftpException{
1173 //System.out.println("ls: "+path);
1174 try{
1175 path=remoteAbsolutePath(path);
1176 byte[] pattern=null;
1177 java.util.Vector v=new java.util.Vector();
1178
1179 int foo=path.lastIndexOf('/');
1180 String dir=path.substring(0, ((foo==0)?1:foo));
1181 String _pattern=path.substring(foo+1);
1182 dir=Util.unquote(dir);
1183
1184 // If pattern has included '*' or '?', we need to convert
1185 // to UTF-8 string before globbing.
1186 byte[][] _pattern_utf8=new byte[1][];
1187 boolean pattern_has_wildcard=isPattern(_pattern, _pattern_utf8);
1188
1189 if(pattern_has_wildcard){
1190 pattern=_pattern_utf8[0];
1191 }
1192 else{
1193 String upath=Util.unquote(path);
1194 //SftpATTRS attr=_lstat(upath);
1195 SftpATTRS attr=_stat(upath);
1196 if(attr.isDir()){
1197 pattern=null;
1198 dir=upath;
1199 }
1200 else{
1201 /*
1202 // If we can generage longname by ourself,
1203 // we don't have to use openDIR.
1204 String filename=Util.unquote(_pattern);
1205 String longname=...
1206 v.addElement(new LsEntry(filename, longname, attr));
1207 return v;
1208 */
1209
1210 if(fEncoding_is_utf8){
1211 pattern=_pattern_utf8[0];
1212 pattern=Util.unquote(pattern);
1213 }
1214 else{
1215 _pattern=Util.unquote(_pattern);
1216 pattern=Util.str2byte(_pattern, fEncoding);
1217 }
1218
1219 }
1220 }
1221
1222 sendOPENDIR(Util.str2byte(dir, fEncoding));
1223
1224 Header header=new Header();
1225 header=header(buf, header);
1226 int length=header.length;
1227 int type=header.type;
1228
1229 fill(buf, length);
1230
1231 if(type!=SSH_FXP_STATUS && type!=SSH_FXP_HANDLE){
1232 throw new SftpException(SSH_FX_FAILURE, "");
1233 }
1234 if(type==SSH_FXP_STATUS){
1235 int i=buf.getInt();
1236 throwStatusError(buf, i);
1237 }
1238
1239 byte[] handle=buf.getString(); // handle
1240
1241 while(true){
1242 sendREADDIR(handle);
1243
1244 header=header(buf, header);
1245 length=header.length;
1246 type=header.type;
1247 if(type!=SSH_FXP_STATUS && type!=SSH_FXP_NAME){
1248 throw new SftpException(SSH_FX_FAILURE, "");
1249 }
1250 if(type==SSH_FXP_STATUS){
1251 fill(buf, length);
1252 int i=buf.getInt();
1253 if(i==SSH_FX_EOF)
1254 break;
1255 throwStatusError(buf, i);
1256 }
1257
1258 buf.rewind();
1259 fill(buf.buffer, 0, 4); length-=4;
1260 int count=buf.getInt();
1261
1262 byte[] str;
1263 int flags;
1264
1265 buf.reset();
1266 while(count>0){
1267 if(length>0){
1268 buf.shift();
1269 int j=(buf.buffer.length>(buf.index+length)) ?
1270 length :
1271 (buf.buffer.length-buf.index);
1272 int i=fill(buf.buffer, buf.index, j);
1273 buf.index+=i;
1274 length-=i;
1275 }
1276 byte[] filename=buf.getString();
1277 byte[] longname=null;
1278 if(server_version<=3){
1279 longname=buf.getString();
1280 }
1281 SftpATTRS attrs=SftpATTRS.getATTR(buf);
1282
1283 boolean find=false;
1284 String f=null;
1285 if(pattern==null){
1286 find=true;
1287 }
1288 else if(!pattern_has_wildcard){
1289 find=Util.array_equals(pattern, filename);
1290 }
1291 else{
1292 byte[] _filename=filename;
1293 if(!fEncoding_is_utf8){
1294 f=Util.byte2str(_filename, fEncoding);
1295 _filename=Util.str2byte(f, UTF8);
1296 }
1297 find=Util.glob(pattern, _filename);
1298 }
1299
1300 if(find){
1301 if(f==null){
1302 f=Util.byte2str(filename, fEncoding);
1303 }
1304 String l=null;
1305 if(longname==null){
1306 // TODO: we need to generate long name from attrs
1307 // for the sftp protocol 4(and later).
1308 l=attrs.toString()+" "+f;
1309 }
1310 else{
1311 l=Util.byte2str(longname, fEncoding);
1312 }
1313 v.addElement(new LsEntry(f, l, attrs));
1314 }
1315
1316 count--;
1317 }
1318 }
1319 _sendCLOSE(handle, header);
1320
1321 /*
1322 if(v.size()==1 && pattern_has_wildcard){
1323 LsEntry le=(LsEntry)v.elementAt(0);
1324 if(le.getAttrs().isDir()){
1325 String f=le.getFilename();
1326 if(isPattern(f)){
1327 f=Util.quote(f);
1328 }
1329 if(!dir.endsWith("/")){
1330 dir+="/";
1331 }
1332 v=null;
1333 return ls(dir+f);
1334 }
1335 }
1336 */
1337
1338 return v;
1339 }
1340 catch(Exception e){
1341 if(e instanceof SftpException) throw (SftpException)e;
1342 if(e instanceof Throwable)
1343 throw new SftpException(SSH_FX_FAILURE, "", (Throwable)e);
1344 throw new SftpException(SSH_FX_FAILURE, "");
1345 }
1346 }
1347 public String readlink(String path) throws SftpException{
1348 try{
1349
1350 if(server_version<3){
1351 throw new SftpException(SSH_FX_OP_UNSUPPORTED,
1352 "The remote sshd is too old to support symlink operation.");
1353 }
1354
1355 path=remoteAbsolutePath(path);
1356
1357 path=isUnique(path);
1358
1359 sendREADLINK(Util.str2byte(path, fEncoding));
1360
1361 Header header=new Header();
1362 header=header(buf, header);
1363 int length=header.length;
1364 int type=header.type;
1365
1366 fill(buf, length);
1367
1368 if(type!=SSH_FXP_STATUS && type!=SSH_FXP_NAME){
1369 throw new SftpException(SSH_FX_FAILURE, "");
1370 }
1371 if(type==SSH_FXP_NAME){
1372 int count=buf.getInt(); // count
1373 byte[] filename=null;
1374 for(int i=0; i<count; i++){
1375 filename=buf.getString();
1376 if(server_version<=3){
1377 byte[] longname=buf.getString();
1378 }
1379 SftpATTRS.getATTR(buf);
1380 }
1381 return Util.byte2str(filename, fEncoding);
1382 }
1383
1384 int i=buf.getInt();
1385 throwStatusError(buf, i);
1386 }
1387 catch(Exception e){
1388 if(e instanceof SftpException) throw (SftpException)e;
1389 if(e instanceof Throwable)
1390 throw new SftpException(SSH_FX_FAILURE, "", (Throwable)e);
1391 throw new SftpException(SSH_FX_FAILURE, "");
1392 }
1393 return null;
1394 }
1395 public void symlink(String oldpath, String newpath) throws SftpException{
1396 if(server_version<3){
1397 throw new SftpException(SSH_FX_OP_UNSUPPORTED,
1398 "The remote sshd is too old to support symlink operation.");
1399 }
1400
1401 try{
1402 oldpath=remoteAbsolutePath(oldpath);
1403 newpath=remoteAbsolutePath(newpath);
1404
1405 oldpath=isUnique(oldpath);
1406
1407 if(isPattern(newpath)){
1408 throw new SftpException(SSH_FX_FAILURE, newpath);
1409 }
1410 newpath=Util.unquote(newpath);
1411
1412 sendSYMLINK(Util.str2byte(oldpath, fEncoding),
1413 Util.str2byte(newpath, fEncoding));
1414
1415 Header header=new Header();
1416 header=header(buf, header);
1417 int length=header.length;
1418 int type=header.type;
1419
1420 fill(buf, length);
1421
1422 if(type!=SSH_FXP_STATUS){
1423 throw new SftpException(SSH_FX_FAILURE, "");
1424 }
1425
1426 int i=buf.getInt();
1427 if(i==SSH_FX_OK) return;
1428 throwStatusError(buf, i);
1429 }
1430 catch(Exception e){
1431 if(e instanceof SftpException) throw (SftpException)e;
1432 if(e instanceof Throwable)
1433 throw new SftpException(SSH_FX_FAILURE, "", (Throwable)e);
1434 throw new SftpException(SSH_FX_FAILURE, "");
1435 }
1436 }
1437
1438 public void rename(String oldpath, String newpath) throws SftpException{
1439 if(server_version<2){
1440 throw new SftpException(SSH_FX_OP_UNSUPPORTED,
1441 "The remote sshd is too old to support rename operation.");
1442 }
1443
1444 try{
1445 oldpath=remoteAbsolutePath(oldpath);
1446 newpath=remoteAbsolutePath(newpath);
1447
1448 oldpath=isUnique(oldpath);
1449
1450 Vector v=glob_remote(newpath);
1451 int vsize=v.size();
1452 if(vsize>=2){
1453 throw new SftpException(SSH_FX_FAILURE, v.toString());
1454 }
1455 if(vsize==1){
1456 newpath=(String)(v.elementAt(0));
1457 }
1458 else{ // vsize==0
1459 if(isPattern(newpath))
1460 throw new SftpException(SSH_FX_FAILURE, newpath);
1461 newpath=Util.unquote(newpath);
1462 }
1463
1464 sendRENAME(Util.str2byte(oldpath, fEncoding),
1465 Util.str2byte(newpath, fEncoding));
1466
1467 Header header=new Header();
1468 header=header(buf, header);
1469 int length=header.length;
1470 int type=header.type;
1471
1472 fill(buf, length);
1473
1474 if(type!=SSH_FXP_STATUS){
1475 throw new SftpException(SSH_FX_FAILURE, "");
1476 }
1477
1478 int i=buf.getInt();
1479 if(i==SSH_FX_OK) return;
1480 throwStatusError(buf, i);
1481 }
1482 catch(Exception e){
1483 if(e instanceof SftpException) throw (SftpException)e;
1484 if(e instanceof Throwable)
1485 throw new SftpException(SSH_FX_FAILURE, "", (Throwable)e);
1486 throw new SftpException(SSH_FX_FAILURE, "");
1487 }
1488 }
1489 public void rm(String path) throws SftpException{
1490 try{
1491 path=remoteAbsolutePath(path);
1492
1493 Vector v=glob_remote(path);
1494 int vsize=v.size();
1495
1496 Header header=new Header();
1497
1498 for(int j=0; j<vsize; j++){
1499 path=(String)(v.elementAt(j));
1500 sendREMOVE(Util.str2byte(path, fEncoding));
1501
1502 header=header(buf, header);
1503 int length=header.length;
1504 int type=header.type;
1505
1506 fill(buf, length);
1507
1508 if(type!=SSH_FXP_STATUS){
1509 throw new SftpException(SSH_FX_FAILURE, "");
1510 }
1511 int i=buf.getInt();
1512 if(i!=SSH_FX_OK){
1513 throwStatusError(buf, i);
1514 }
1515 }
1516 }
1517 catch(Exception e){
1518 if(e instanceof SftpException) throw (SftpException)e;
1519 if(e instanceof Throwable)
1520 throw new SftpException(SSH_FX_FAILURE, "", (Throwable)e);
1521 throw new SftpException(SSH_FX_FAILURE, "");
1522 }
1523 }
1524
1525 private boolean isRemoteDir(String path){
1526 try{
1527 sendSTAT(Util.str2byte(path, fEncoding));
1528
1529 Header header=new Header();
1530 header=header(buf, header);
1531 int length=header.length;
1532 int type=header.type;
1533
1534 fill(buf, length);
1535
1536 if(type!=SSH_FXP_ATTRS){
1537 return false;
1538 }
1539 SftpATTRS attr=SftpATTRS.getATTR(buf);
1540 return attr.isDir();
1541 }
1542 catch(Exception e){}
1543 return false;
1544 }
1545
1546 public void chgrp(int gid, String path) throws SftpException{
1547 try{
1548 path=remoteAbsolutePath(path);
1549
1550 Vector v=glob_remote(path);
1551 int vsize=v.size();
1552 for(int j=0; j<vsize; j++){
1553 path=(String)(v.elementAt(j));
1554
1555 SftpATTRS attr=_stat(path);
1556
1557 attr.setFLAGS(0);
1558 attr.setUIDGID(attr.uid, gid);
1559 _setStat(path, attr);
1560 }
1561 }
1562 catch(Exception e){
1563 if(e instanceof SftpException) throw (SftpException)e;
1564 if(e instanceof Throwable)
1565 throw new SftpException(SSH_FX_FAILURE, "", (Throwable)e);
1566 throw new SftpException(SSH_FX_FAILURE, "");
1567 }
1568 }
1569
1570 public void chown(int uid, String path) throws SftpException{
1571 try{
1572 path=remoteAbsolutePath(path);
1573
1574 Vector v=glob_remote(path);
1575 int vsize=v.size();
1576 for(int j=0; j<vsize; j++){
1577 path=(String)(v.elementAt(j));
1578
1579 SftpATTRS attr=_stat(path);
1580
1581 attr.setFLAGS(0);
1582 attr.setUIDGID(uid, attr.gid);
1583 _setStat(path, attr);
1584 }
1585 }
1586 catch(Exception e){
1587 if(e instanceof SftpException) throw (SftpException)e;
1588 if(e instanceof Throwable)
1589 throw new SftpException(SSH_FX_FAILURE, "", (Throwable)e);
1590 throw new SftpException(SSH_FX_FAILURE, "");
1591 }
1592 }
1593
1594 public void chmod(int permissions, String path) throws SftpException{
1595 try{
1596 path=remoteAbsolutePath(path);
1597
1598 Vector v=glob_remote(path);
1599 int vsize=v.size();
1600 for(int j=0; j<vsize; j++){
1601 path=(String)(v.elementAt(j));
1602
1603 SftpATTRS attr=_stat(path);
1604
1605 attr.setFLAGS(0);
1606 attr.setPERMISSIONS(permissions);
1607 _setStat(path, attr);
1608 }
1609 }
1610 catch(Exception e){
1611 if(e instanceof SftpException) throw (SftpException)e;
1612 if(e instanceof Throwable)
1613 throw new SftpException(SSH_FX_FAILURE, "", (Throwable)e);
1614 throw new SftpException(SSH_FX_FAILURE, "");
1615 }
1616 }
1617
1618 public void setMtime(String path, int mtime) throws SftpException{
1619 try{
1620 path=remoteAbsolutePath(path);
1621
1622 Vector v=glob_remote(path);
1623 int vsize=v.size();
1624 for(int j=0; j<vsize; j++){
1625 path=(String)(v.elementAt(j));
1626
1627 SftpATTRS attr=_stat(path);
1628
1629 attr.setFLAGS(0);
1630 attr.setACMODTIME(attr.getATime(), mtime);
1631 _setStat(path, attr);
1632 }
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 void rmdir(String path) throws SftpException{
1643 try{
1644 path=remoteAbsolutePath(path);
1645
1646 Vector v=glob_remote(path);
1647 int vsize=v.size();
1648
1649 Header header=new Header();
1650
1651 for(int j=0; j<vsize; j++){
1652 path=(String)(v.elementAt(j));
1653 sendRMDIR(Util.str2byte(path, fEncoding));
1654
1655 header=header(buf, header);
1656 int length=header.length;
1657 int type=header.type;
1658
1659 fill(buf, length);
1660
1661 if(type!=SSH_FXP_STATUS){
1662 throw new SftpException(SSH_FX_FAILURE, "");
1663 }
1664
1665 int i=buf.getInt();
1666 if(i!=SSH_FX_OK){
1667 throwStatusError(buf, i);
1668 }
1669 }
1670 }
1671 catch(Exception e){
1672 if(e instanceof SftpException) throw (SftpException)e;
1673 if(e instanceof Throwable)
1674 throw new SftpException(SSH_FX_FAILURE, "", (Throwable)e);
1675 throw new SftpException(SSH_FX_FAILURE, "");
1676 }
1677 }
1678
1679 public void mkdir(String path) throws SftpException{
1680 try{
1681 path=remoteAbsolutePath(path);
1682
1683 sendMKDIR(Util.str2byte(path, fEncoding), null);
1684
1685 Header header=new Header();
1686 header=header(buf, header);
1687 int length=header.length;
1688 int type=header.type;
1689
1690 fill(buf, length);
1691
1692 if(type!=SSH_FXP_STATUS){
1693 throw new SftpException(SSH_FX_FAILURE, "");
1694 }
1695
1696 int i=buf.getInt();
1697 if(i==SSH_FX_OK) return;
1698 throwStatusError(buf, i);
1699 }
1700 catch(Exception e){
1701 if(e instanceof SftpException) throw (SftpException)e;
1702 if(e instanceof Throwable)
1703 throw new SftpException(SSH_FX_FAILURE, "", (Throwable)e);
1704 throw new SftpException(SSH_FX_FAILURE, "");
1705 }
1706 }
1707
1708 public SftpATTRS stat(String path) throws SftpException{
1709 try{
1710 path=remoteAbsolutePath(path);
1711
1712 path=isUnique(path);
1713
1714 return _stat(path);
1715 }
1716 catch(Exception e){
1717 if(e instanceof SftpException) throw (SftpException)e;
1718 if(e instanceof Throwable)
1719 throw new SftpException(SSH_FX_FAILURE, "", (Throwable)e);
1720 throw new SftpException(SSH_FX_FAILURE, "");
1721 }
1722 //return null;
1723 }
1724
1725 private SftpATTRS _stat(byte[] path) throws SftpException{
1726 try{
1727
1728 sendSTAT(path);
1729
1730 Header header=new Header();
1731 header=header(buf, header);
1732 int length=header.length;
1733 int type=header.type;
1734
1735 fill(buf, length);
1736
1737 if(type!=SSH_FXP_ATTRS){
1738 if(type==SSH_FXP_STATUS){
1739 int i=buf.getInt();
1740 throwStatusError(buf, i);
1741 }
1742 throw new SftpException(SSH_FX_FAILURE, "");
1743 }
1744 SftpATTRS attr=SftpATTRS.getATTR(buf);
1745 return attr;
1746 }
1747 catch(Exception e){
1748 if(e instanceof SftpException) throw (SftpException)e;
1749 if(e instanceof Throwable)
1750 throw new SftpException(SSH_FX_FAILURE, "", (Throwable)e);
1751 throw new SftpException(SSH_FX_FAILURE, "");
1752 }
1753 //return null;
1754 }
1755
1756 private SftpATTRS _stat(String path) throws SftpException{
1757 return _stat(Util.str2byte(path, fEncoding));
1758 }
1759
1760 public SftpATTRS lstat(String path) throws SftpException{
1761 try{
1762 path=remoteAbsolutePath(path);
1763
1764 path=isUnique(path);
1765
1766 return _lstat(path);
1767 }
1768 catch(Exception e){
1769 if(e instanceof SftpException) throw (SftpException)e;
1770 if(e instanceof Throwable)
1771 throw new SftpException(SSH_FX_FAILURE, "", (Throwable)e);
1772 throw new SftpException(SSH_FX_FAILURE, "");
1773 }
1774 }
1775
1776 private SftpATTRS _lstat(String path) throws SftpException{
1777 try{
1778 sendLSTAT(Util.str2byte(path, fEncoding));
1779
1780 Header header=new Header();
1781 header=header(buf, header);
1782 int length=header.length;
1783 int type=header.type;
1784
1785 fill(buf, length);
1786
1787 if(type!=SSH_FXP_ATTRS){
1788 if(type==SSH_FXP_STATUS){
1789 int i=buf.getInt();
1790 throwStatusError(buf, i);
1791 }
1792 throw new SftpException(SSH_FX_FAILURE, "");
1793 }
1794 SftpATTRS attr=SftpATTRS.getATTR(buf);
1795 return attr;
1796 }
1797 catch(Exception e){
1798 if(e instanceof SftpException) throw (SftpException)e;
1799 if(e instanceof Throwable)
1800 throw new SftpException(SSH_FX_FAILURE, "", (Throwable)e);
1801 throw new SftpException(SSH_FX_FAILURE, "");
1802 }
1803 }
1804
1805 private byte[] _realpath(String path) throws SftpException, IOException, Exception{
1806 sendREALPATH(Util.str2byte(path, fEncoding));
1807
1808 Header header=new Header();
1809 header=header(buf, header);
1810 int length=header.length;
1811 int type=header.type;
1812
1813 fill(buf, length);
1814
1815 if(type!=SSH_FXP_STATUS && type!=SSH_FXP_NAME){
1816 throw new SftpException(SSH_FX_FAILURE, "");
1817 }
1818 int i;
1819 if(type==SSH_FXP_STATUS){
1820 i=buf.getInt();
1821 throwStatusError(buf, i);
1822 }
1823 i=buf.getInt(); // count
1824
1825 byte[] str=null;
1826 while(i-->0){
1827 str=buf.getString(); // absolute path;
1828 if(server_version<=3){
1829 byte[] lname=buf.getString(); // long filename
1830 }
1831 SftpATTRS attr=SftpATTRS.getATTR(buf); // dummy attribute
1832 }
1833 return str;
1834 }
1835
1836 public void setStat(String path, SftpATTRS attr) throws SftpException{
1837 try{
1838 path=remoteAbsolutePath(path);
1839
1840 Vector v=glob_remote(path);
1841 int vsize=v.size();
1842 for(int j=0; j<vsize; j++){
1843 path=(String)(v.elementAt(j));
1844 _setStat(path, attr);
1845 }
1846 }
1847 catch(Exception e){
1848 if(e instanceof SftpException) throw (SftpException)e;
1849 if(e instanceof Throwable)
1850 throw new SftpException(SSH_FX_FAILURE, "", (Throwable)e);
1851 throw new SftpException(SSH_FX_FAILURE, "");
1852 }
1853 }
1854 private void _setStat(String path, SftpATTRS attr) throws SftpException{
1855 try{
1856 sendSETSTAT(Util.str2byte(path, fEncoding), attr);
1857
1858 Header header=new Header();
1859 header=header(buf, header);
1860 int length=header.length;
1861 int type=header.type;
1862
1863 fill(buf, length);
1864
1865 if(type!=SSH_FXP_STATUS){
1866 throw new SftpException(SSH_FX_FAILURE, "");
1867 }
1868 int i=buf.getInt();
1869 if(i!=SSH_FX_OK){
1870 throwStatusError(buf, i);
1871 }
1872 }
1873 catch(Exception e){
1874 if(e instanceof SftpException) throw (SftpException)e;
1875 if(e instanceof Throwable)
1876 throw new SftpException(SSH_FX_FAILURE, "", (Throwable)e);
1877 throw new SftpException(SSH_FX_FAILURE, "");
1878 }
1879 }
1880
1881 public String pwd() throws SftpException{ return getCwd(); }
1882 public String lpwd(){ return lcwd; }
1883 public String version(){ return version; }
1884 public String getHome() throws SftpException {
1885 if(home==null){
1886 try{
1887 byte[] _home=_realpath("");
1888 home=Util.byte2str(_home, fEncoding);
1889 }
1890 catch(Exception e){
1891 if(e instanceof SftpException) throw (SftpException)e;
1892 if(e instanceof Throwable)
1893 throw new SftpException(SSH_FX_FAILURE, "", (Throwable)e);
1894 throw new SftpException(SSH_FX_FAILURE, "");
1895 }
1896 }
1897 return home;
1898 }
1899
1900 private String getCwd() throws SftpException{
1901 if(cwd==null)
1902 cwd=getHome();
1903 return cwd;
1904 }
1905
1906 private void setCwd(String cwd){
1907 this.cwd=cwd;
1908 }
1909
1910 private void read(byte[] buf, int s, int l) throws IOException, SftpException{
1911 int i=0;
1912 while(l>0){
1913 i=io_in.read(buf, s, l);
1914 if(i<=0){
1915 throw new SftpException(SSH_FX_FAILURE, "");
1916 }
1917 s+=i;
1918 l-=i;
1919 }
1920 }
1921
1922 private boolean checkStatus(int[] ackid, Header header) throws IOException, SftpException{
1923 header=header(buf, header);
1924 int length=header.length;
1925 int type=header.type;
1926 if(ackid!=null)
1927 ackid[0]=header.rid;
1928
1929 fill(buf, length);
1930
1931 if(type!=SSH_FXP_STATUS){
1932 throw new SftpException(SSH_FX_FAILURE, "");
1933 }
1934 int i=buf.getInt();
1935 if(i!=SSH_FX_OK){
1936 throwStatusError(buf, i);
1937 }
1938 return true;
1939 }
1940 private boolean _sendCLOSE(byte[] handle, Header header) throws Exception{
1941 sendCLOSE(handle);
1942 return checkStatus(null, header);
1943 }
1944
1945 private void sendINIT() throws Exception{
1946 packet.reset();
1947 putHEAD(SSH_FXP_INIT, 5);
1948 buf.putInt(3); // version 3
1949 getSession().write(packet, this, 5+4);
1950 }
1951
1952 private void sendREALPATH(byte[] path) throws Exception{
1953 sendPacketPath(SSH_FXP_REALPATH, path);
1954 }
1955 private void sendSTAT(byte[] path) throws Exception{
1956 sendPacketPath(SSH_FXP_STAT, path);
1957 }
1958 private void sendLSTAT(byte[] path) throws Exception{
1959 sendPacketPath(SSH_FXP_LSTAT, path);
1960 }
1961 private void sendFSTAT(byte[] handle) throws Exception{
1962 sendPacketPath(SSH_FXP_FSTAT, handle);
1963 }
1964 private void sendSETSTAT(byte[] path, SftpATTRS attr) throws Exception{
1965 packet.reset();
1966 putHEAD(SSH_FXP_SETSTAT, 9+path.length+attr.length());
1967 buf.putInt(seq++);
1968 buf.putString(path); // path
1969 attr.dump(buf);
1970 getSession().write(packet, this, 9+path.length+attr.length()+4);
1971 }
1972 private void sendREMOVE(byte[] path) throws Exception{
1973 sendPacketPath(SSH_FXP_REMOVE, path);
1974 }
1975 private void sendMKDIR(byte[] path, SftpATTRS attr) throws Exception{
1976 packet.reset();
1977 putHEAD(SSH_FXP_MKDIR, 9+path.length+(attr!=null?attr.length():4));
1978 buf.putInt(seq++);
1979 buf.putString(path); // path
1980 if(attr!=null) attr.dump(buf);
1981 else buf.putInt(0);
1982 getSession().write(packet, this, 9+path.length+(attr!=null?attr.length():4)+4);
1983 }
1984 private void sendRMDIR(byte[] path) throws Exception{
1985 sendPacketPath(SSH_FXP_RMDIR, path);
1986 }
1987 private void sendSYMLINK(byte[] p1, byte[] p2) throws Exception{
1988 sendPacketPath(SSH_FXP_SYMLINK, p1, p2);
1989 }
1990 private void sendREADLINK(byte[] path) throws Exception{
1991 sendPacketPath(SSH_FXP_READLINK, path);
1992 }
1993 private void sendOPENDIR(byte[] path) throws Exception{
1994 sendPacketPath(SSH_FXP_OPENDIR, path);
1995 }
1996 private void sendREADDIR(byte[] path) throws Exception{
1997 sendPacketPath(SSH_FXP_READDIR, path);
1998 }
1999 private void sendRENAME(byte[] p1, byte[] p2) throws Exception{
2000 sendPacketPath(SSH_FXP_RENAME, p1, p2);
2001 }
2002 private void sendCLOSE(byte[] path) throws Exception{
2003 sendPacketPath(SSH_FXP_CLOSE, path);
2004 }
2005 private void sendOPENR(byte[] path) throws Exception{
2006 sendOPEN(path, SSH_FXF_READ);
2007 }
2008 private void sendOPENW(byte[] path) throws Exception{
2009 sendOPEN(path, SSH_FXF_WRITE|SSH_FXF_CREAT|SSH_FXF_TRUNC);
2010 }
2011 private void sendOPENA(byte[] path) throws Exception{
2012 sendOPEN(path, SSH_FXF_WRITE|/*SSH_FXF_APPEND|*/SSH_FXF_CREAT);
2013 }
2014 private void sendOPEN(byte[] path, int mode) throws Exception{
2015 packet.reset();
2016 putHEAD(SSH_FXP_OPEN, 17+path.length);
2017 buf.putInt(seq++);
2018 buf.putString(path);
2019 buf.putInt(mode);
2020 buf.putInt(0); // attrs
2021 getSession().write(packet, this, 17+path.length+4);
2022 }
2023 private void sendPacketPath(byte fxp, byte[] path) throws Exception{
2024 packet.reset();
2025 putHEAD(fxp, 9+path.length);
2026 buf.putInt(seq++);
2027 buf.putString(path); // path
2028 getSession().write(packet, this, 9+path.length+4);
2029 }
2030 private void sendPacketPath(byte fxp, byte[] p1, byte[] p2) throws Exception{
2031 packet.reset();
2032 putHEAD(fxp, 13+p1.length+p2.length);
2033 buf.putInt(seq++);
2034 buf.putString(p1);
2035 buf.putString(p2);
2036 getSession().write(packet, this, 13+p1.length+p2.length+4);
2037 }
2038
2039 private int sendWRITE(byte[] handle, long offset,
2040 byte[] data, int start, int length) throws Exception{
2041 int _length=length;
2042 packet.reset();
2043 if(buf.buffer.length<buf.index+13+21+handle.length+length
2044 +32 +20 // padding and mac
2045){
2046 _length=buf.buffer.length-(buf.index+13+21+handle.length
2047 +32 +20 // padding and mac
2048);
2049 //System.err.println("_length="+_length+" length="+length);
2050 }
2051
2052 putHEAD(SSH_FXP_WRITE, 21+handle.length+_length); // 14
2053 buf.putInt(seq++); // 4
2054 buf.putString(handle); // 4+handle.length
2055 buf.putLong(offset); // 8
2056 if(buf.buffer!=data){
2057 buf.putString(data, start, _length); // 4+_length
2058 }
2059 else{
2060 buf.putInt(_length);
2061 buf.skip(_length);
2062 }
2063 getSession().write(packet, this, 21+handle.length+_length+4);
2064 return _length;
2065 }
2066
2067 private void sendREAD(byte[] handle, long offset, int length) throws Exception{
2068 packet.reset();
2069 putHEAD(SSH_FXP_READ, 21+handle.length);
2070 buf.putInt(seq++);
2071 buf.putString(handle);
2072 buf.putLong(offset);
2073 buf.putInt(length);
2074 getSession().write(packet, this, 21+handle.length+4);
2075 }
2076
2077 private void putHEAD(byte type, int length) throws Exception{
2078 buf.putByte((byte)Session.SSH_MSG_CHANNEL_DATA);
2079 buf.putInt(recipient);
2080 buf.putInt(length+4);
2081 buf.putInt(length);
2082 buf.putByte(type);
2083 }
2084
2085 private Vector glob_remote(String _path) throws Exception{
2086 Vector v=new Vector();
2087 int i=0;
2088
2089 int foo=_path.lastIndexOf('/');
2090 if(foo<0){ // it is not absolute path.
2091 v.addElement(Util.unquote(_path));
2092 return v;
2093 }
2094
2095 String dir=_path.substring(0, ((foo==0)?1:foo));
2096 String _pattern=_path.substring(foo+1);
2097
2098 dir=Util.unquote(dir);
2099
2100 byte[] pattern=null;
2101 byte[][] _pattern_utf8=new byte[1][];
2102 boolean pattern_has_wildcard=isPattern(_pattern, _pattern_utf8);
2103
2104 if(!pattern_has_wildcard){
2105 if(!dir.equals("/"))
2106 dir+="/";
2107 v.addElement(dir+Util.unquote(_pattern));
2108 return v;
2109 }
2110
2111 pattern=_pattern_utf8[0];
2112
2113 sendOPENDIR(Util.str2byte(dir, fEncoding));
2114
2115 Header header=new Header();
2116 header=header(buf, header);
2117 int length=header.length;
2118 int type=header.type;
2119
2120 fill(buf, length);
2121
2122 if(type!=SSH_FXP_STATUS && type!=SSH_FXP_HANDLE){
2123 throw new SftpException(SSH_FX_FAILURE, "");
2124 }
2125 if(type==SSH_FXP_STATUS){
2126 i=buf.getInt();
2127 throwStatusError(buf, i);
2128 }
2129
2130 byte[] handle=buf.getString(); // filename
2131 String pdir=null; // parent directory
2132
2133 while(true){
2134 sendREADDIR(handle);
2135 header=header(buf, header);
2136 length=header.length;
2137 type=header.type;
2138
2139 if(type!=SSH_FXP_STATUS && type!=SSH_FXP_NAME){
2140 throw new SftpException(SSH_FX_FAILURE, "");
2141 }
2142 if(type==SSH_FXP_STATUS){
2143 fill(buf, length);
2144 break;
2145 }
2146
2147 buf.rewind();
2148 fill(buf.buffer, 0, 4); length-=4;
2149 int count=buf.getInt();
2150
2151 byte[] str;
2152 int flags;
2153
2154 buf.reset();
2155 while(count>0){
2156 if(length>0){
2157 buf.shift();
2158 int j=(buf.buffer.length>(buf.index+length)) ? length : (buf.buffer.length-buf.index);
2159 i=io_in.read(buf.buffer, buf.index, j);
2160 if(i<=0)break;
2161 buf.index+=i;
2162 length-=i;
2163 }
2164
2165 byte[] filename=buf.getString();
2166 //System.err.println("filename: "+new String(filename));
2167 if(server_version<=3){
2168 str=buf.getString(); // longname
2169 }
2170 SftpATTRS attrs=SftpATTRS.getATTR(buf);
2171
2172 byte[] _filename=filename;
2173 String f=null;
2174 boolean found=false;
2175
2176 if(!fEncoding_is_utf8){
2177 f=Util.byte2str(filename, fEncoding);
2178 _filename=Util.str2byte(f, UTF8);
2179 }
2180 found=Util.glob(pattern, _filename);
2181
2182 if(found){
2183 if(f==null){
2184 f=Util.byte2str(filename, fEncoding);
2185 }
2186 if(pdir==null){
2187 pdir=dir;
2188 if(!pdir.endsWith("/")){
2189 pdir+="/";
2190 }
2191 }
2192 v.addElement(pdir+f);
2193 }
2194 count--;
2195 }
2196 }
2197 if(_sendCLOSE(handle, header))
2198 return v;
2199 return null;
2200 }
2201
2202 private boolean isPattern(byte[] path){
2203 int i=path.length-1;
2204 while(i>=0){
2205 if(path[i]=='*' || path[i]=='?'){
2206 if(i>0 && path[i-1]=='\\'){
2207 i--;
2208 if(i>0 && path[i-1]=='\\'){ // \\* or \\?
2209 break;
2210 }
2211 }
2212 else{
2213 break;
2214 }
2215 }
2216 i--;
2217 }
2218 // System.err.println("isPattern: ["+(new String(path))+"] "+(!(i<0)));
2219 return !(i<0);
2220 }
2221
2222 private Vector glob_local(String _path) throws Exception{
2223//System.err.println("glob_local: "+_path);
2224 Vector v=new Vector();
2225 byte[] path=Util.str2byte(_path, UTF8);
2226 int i=path.length-1;
2227 while(i>=0){
2228 if(path[i]!='*' && path[i]!='?'){
2229 i--;
2230 continue;
2231 }
2232 if(!fs_is_bs &&
2233 i>0 && path[i-1]=='\\'){
2234 i--;
2235 if(i>0 && path[i-1]=='\\'){
2236 i--;
2237 i--;
2238 continue;
2239 }
2240 }
2241 break;
2242 }
2243
2244 if(i<0){ v.addElement(fs_is_bs ? _path : Util.unquote(_path)); return v;}
2245
2246 while(i>=0){
2247 if(path[i]==file_separatorc ||
2248 (fs_is_bs && path[i]=='/')){ // On Windows, '/' is also the separator.
2249 break;
2250 }
2251 i--;
2252 }
2253
2254 if(i<0){ v.addElement(fs_is_bs ? _path : Util.unquote(_path)); return v;}
2255
2256 byte[] dir;
2257 if(i==0){dir=new byte[]{(byte)file_separatorc};}
2258 else{
2259 dir=new byte[i];
2260 System.arraycopy(path, 0, dir, 0, i);
2261 }
2262
2263 byte[] pattern=new byte[path.length-i-1];
2264 System.arraycopy(path, i+1, pattern, 0, pattern.length);
2265
2266//System.err.println("dir: "+new String(dir)+" pattern: "+new String(pattern));
2267 try{
2268 String[] children=(new File(Util.byte2str(dir, UTF8))).list();
2269 String pdir=Util.byte2str(dir)+file_separator;
2270 for(int j=0; j<children.length; j++){
2271//System.err.println("children: "+children[j]);
2272 if(Util.glob(pattern, Util.str2byte(children[j], UTF8))){
2273 v.addElement(pdir+children[j]);
2274 }
2275 }
2276 }
2277 catch(Exception e){
2278 }
2279 return v;
2280 }
2281
2282 private void throwStatusError(Buffer buf, int i) throws SftpException{
2283 if(server_version>=3 && // WindRiver's sftp will send invalid
2284 buf.getLength()>=4){ // SSH_FXP_STATUS packet.
2285 byte[] str=buf.getString();
2286 //byte[] tag=buf.getString();
2287 throw new SftpException(i, Util.byte2str(str, UTF8));
2288 }
2289 else{
2290 throw new SftpException(i, "Failure");
2291 }
2292 }
2293
2294 private static boolean isLocalAbsolutePath(String path){
2295 return (new File(path)).isAbsolute();
2296 }
2297
2298 public void disconnect(){
2299 super.disconnect();
2300 }
2301
2302 private boolean isPattern(String path, byte[][] utf8){
2303 byte[] _path=Util.str2byte(path, UTF8);
2304 if(utf8!=null)
2305 utf8[0]=_path;
2306 return isPattern(_path);
2307 }
2308
2309 private boolean isPattern(String path){
2310 return isPattern(path, null);
2311 }
2312
2313 private void fill(Buffer buf, int len) throws IOException{
2314 buf.reset();
2315 fill(buf.buffer, 0, len);
2316 buf.skip(len);
2317 }
2318
2319 private int fill(byte[] buf, int s, int len) throws IOException{
2320 int i=0;
2321 int foo=s;
2322 while(len>0){
2323 i=io_in.read(buf, s, len);
2324 if(i<=0){
2325 throw new IOException("inputstream is closed");
2326 //return (s-foo)==0 ? i : s-foo;
2327 }
2328 s+=i;
2329 len-=i;
2330 }
2331 return s-foo;
2332 }
2333 private void skip(long foo) throws IOException{
2334 while(foo>0){
2335 long bar=io_in.skip(foo);
2336 if(bar<=0)
2337 break;
2338 foo-=bar;
2339 }
2340 }
2341
2342 class Header{
2343 int length;
2344 int type;
2345 int rid;
2346 }
2347 private Header header(Buffer buf, Header header) throws IOException{
2348 buf.rewind();
2349 int i=fill(buf.buffer, 0, 9);
2350 header.length=buf.getInt()-5;
2351 header.type=buf.getByte()&0xff;
2352 header.rid=buf.getInt();
2353 return header;
2354 }
2355
2356 private String remoteAbsolutePath(String path) throws SftpException{
2357 if(path.charAt(0)=='/') return path;
2358 String cwd=getCwd();
2359// if(cwd.equals(getHome())) return path;
2360 if(cwd.endsWith("/")) return cwd+path;
2361 return cwd+"/"+path;
2362 }
2363
2364 private String localAbsolutePath(String path){
2365 if(isLocalAbsolutePath(path)) return path;
2366 if(lcwd.endsWith(file_separator)) return lcwd+path;
2367 return lcwd+file_separator+path;
2368 }
2369
2370 /**
2371 * This method will check if the given string can be expanded to the
2372 * unique string. If it can be expanded to mutiple files, SftpException
2373 * will be thrown.
2374 * @return the returned string is unquoted.
2375 */
2376 private String isUnique(String path) throws SftpException, Exception{
2377 Vector v=glob_remote(path);
2378 if(v.size()!=1){
2379 throw new SftpException(SSH_FX_FAILURE, path+" is not unique: "+v.toString());
2380 }
2381 return (String)(v.elementAt(0));
2382 }
2383
2384 public int getServerVersion() throws SftpException{
2385 if(!isConnected()){
2386 throw new SftpException(SSH_FX_FAILURE, "The channel is not connected.");
2387 }
2388 return server_version;
2389 }
2390
2391 public void setFilenameEncoding(String encoding) throws SftpException{
2392 int sversion=getServerVersion();
2393 if(sversion > 3 &&
2394 !encoding.equals(UTF8)){
2395 throw new SftpException(SSH_FX_FAILURE,
2396 "The encoding can not be changed for this sftp server.");
2397 }
2398 if(encoding.equals(UTF8)){
2399 encoding=UTF8;
2400 }
2401 fEncoding=encoding;
2402 fEncoding_is_utf8=fEncoding.equals(UTF8);
2403 }
2404
2405 public String getExtension(String key){
2406 if(extensions==null)
2407 return null;
2408 return (String)extensions.get(key);
2409 }
2410
2411 public String realpath(String path) throws SftpException{
2412 try{
2413 byte[] _path=_realpath(remoteAbsolutePath(path));
2414 return Util.byte2str(_path, fEncoding);
2415 }
2416 catch(Exception e){
2417 if(e instanceof SftpException) throw (SftpException)e;
2418 if(e instanceof Throwable)
2419 throw new SftpException(SSH_FX_FAILURE, "", (Throwable)e);
2420 throw new SftpException(SSH_FX_FAILURE, "");
2421 }
2422 }
2423
2424 public class LsEntry implements Comparable{
2425 private String filename;
2426 private String longname;
2427 private SftpATTRS attrs;
2428 LsEntry(String filename, String longname, SftpATTRS attrs){
2429 setFilename(filename);
2430 setLongname(longname);
2431 setAttrs(attrs);
2432 }
2433 public String getFilename(){return filename;};
2434 void setFilename(String filename){this.filename = filename;};
2435 public String getLongname(){return longname;};
2436 void setLongname(String longname){this.longname = longname;};
2437 public SftpATTRS getAttrs(){return attrs;};
2438 void setAttrs(SftpATTRS attrs) {this.attrs = attrs;};
2439 public String toString(){ return longname; }
2440 public int compareTo(Object o) throws ClassCastException{
2441 if(o instanceof LsEntry){
2442 return filename.compareTo(((LsEntry)o).getFilename());
2443 }
2444 throw new ClassCastException("a decendent of LsEntry must be given.");
2445 }
2446 }
2447}
This page took 0.045837 seconds and 4 git commands to generate.