source: other-projects/trunk/gs3-release-maker/tasks/sshtaskdef/src/mindbright/ssh/SSHSCP.java@ 14627

Last change on this file since 14627 was 14627, checked in by oranfry, 17 years ago

initial import of the gs3-release-maker

File size: 12.0 KB
Line 
1/******************************************************************************
2 *
3 * Copyright (c) 1998,99 by Mindbright Technology AB, Stockholm, Sweden.
4 * www.mindbright.se, [email protected]
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 *****************************************************************************
17 * $Author: mats $
18 * $Date: 2000/03/27 07:53:54 $
19 * $Name: rel1-2-1 $
20 *****************************************************************************/
21package mindbright.ssh;
22
23import java.io.*;
24import java.net.Socket;
25
26import mindbright.terminal.Terminal;
27import mindbright.security.Cipher;
28
29public class SSHSCP extends SSHClientUserAdaptor implements SSHConsole {
30
31 SSHClient client;
32 SSHInteractor interactor = null;
33 SSHClientUser proxyUser = null;
34 SSHSCPIndicator indicator = null;
35
36 SSHInteractor ourInteractAdapter = null;
37
38 File cwd;
39 boolean recursive;
40 boolean verbose;
41
42 String sshHost;
43
44 PipedInputStream inTop;
45 PipedOutputStream inBottom;
46
47 public SSHSCP(String sshHost, int port, SSHAuthenticator authenticator,
48 File cwd, boolean recursive, boolean verbose) throws IOException {
49 super(sshHost, port);
50
51 // OUCH: Note must be set before constructing SSHClient since
52 // its constructor calls getInteractor to fetch this
53 //
54 ourInteractAdapter = new SSHInteractorAdapter() {
55 public void open(SSHClient client) {
56 SSHSCP.this.open(client);
57 }
58 public void disconnected(SSHClient client, boolean graceful) {
59 SSHSCP.this.disconnected(client, graceful);
60 }
61 public void alert(String msg) {
62 SSHSCP.this.alert(msg);
63 }
64 };
65
66 client = new SSHClient(authenticator, this);
67 inTop = new PipedInputStream();
68 inBottom = new PipedOutputStream(inTop);
69 this.cwd = cwd;
70 this.recursive = recursive;
71 this.verbose = verbose;
72 this.sshHost = sshHost;
73
74 client.setConsole(this);
75 client.activateTunnels = false;
76 }
77
78 public void setInteractor(SSHInteractor interactor) {
79 this.interactor = interactor;
80 }
81
82 public void setClientUser(SSHClientUser proxyUser) {
83 this.proxyUser = proxyUser;
84 }
85
86 public void setIndicator(SSHSCPIndicator indicator) {
87 this.indicator = indicator;
88 }
89
90 public void abort() {
91 interactor = null;
92 indicator = null;
93 client.forcedDisconnect();
94 }
95
96 public void copyToRemote(String localFile, String remoteFile) throws IOException {
97 File lf = new File(localFile);
98
99 if(!lf.isAbsolute())
100 lf = new File(cwd, localFile);
101
102 if(!lf.exists()) {
103 throw new IOException("File: " + localFile + " does not exist");
104 }
105 if(!lf.isFile() && !lf.isDirectory()) {
106 throw new IOException("File: " + localFile + " is not a regular file or directory");
107 }
108 if(lf.isDirectory() && !recursive) {
109 throw new IOException("File: " + localFile + " is a directory, use recursive mode");
110 }
111 if(remoteFile == null || remoteFile.equals(""))
112 remoteFile = ".";
113
114 client.doSingleCommand("scp " + (lf.isDirectory() ? "-d " : "") + "-t " +
115 (recursive ? "-r " : "") + (verbose ? "-v " : "") + remoteFile, true, 0);
116 readResponse("After starting remote scp");
117 writeFileToRemote(lf);
118 client.forcedDisconnect();
119 }
120
121 public void copyToRemote(String[] localFiles, String remoteFile) throws IOException {
122 if(remoteFile == null || remoteFile.equals(""))
123 remoteFile = ".";
124 if(localFiles.length == 1) {
125 copyToRemote(localFiles[0], remoteFile);
126 } else {
127 client.doSingleCommand("scp " + "-d -t " + (recursive ? "-r " : "") +
128 (verbose ? "-v " : "") + remoteFile, true, 0);
129 readResponse("After starting remote scp");
130 for(int i = 0; i < localFiles.length; i++) {
131 File lf = new File(localFiles[i]);
132 if(!lf.isAbsolute())
133 lf = new File(cwd, localFiles[i]);
134 if(!lf.isFile() && !lf.isDirectory()) {
135 alert("File: " + lf.getName() + " is not a regular file or directory");
136 continue;
137 }
138 writeFileToRemote(lf);
139 }
140 client.forcedDisconnect();
141 }
142 }
143
144 public void copyToLocal(String localFile, String remoteFile) throws IOException {
145 if(localFile == null || localFile.equals(""))
146 localFile = ".";
147
148 File lf = new File(localFile);
149 if(!lf.isAbsolute())
150 lf = new File(cwd, localFile);
151
152 if(lf.exists() && !lf.isFile() && !lf.isDirectory()) {
153 throw new IOException("File: " + localFile + " is not a regular file or directory");
154 }
155 client.doSingleCommand("scp " + "-f " + (recursive ? "-r " : "") + (verbose ? "-v " : "") +
156 remoteFile, true, 0);
157 readFromRemote(lf);
158 client.forcedDisconnect();
159 }
160
161 boolean writeDirToRemote(File dir) throws IOException {
162 if(!recursive) {
163 writeError("File " + dir.getName() + " is a directory, use recursive mode");
164 return false;
165 }
166 writeString("D0755 0 " + dir.getName() + "\n");
167 if(indicator != null)
168 indicator.startDir(dir.getAbsolutePath());
169 readResponse("After sedning dirdata");
170 String[] dirList = dir.list();
171 for(int i = 0; i < dirList.length; i++) {
172 File f = new File(dir, dirList[i]);
173 writeFileToRemote(f);
174 }
175 writeString("E\n");
176 if(indicator != null)
177 indicator.endDir();
178 return true;
179 }
180
181 void writeFileToRemote(File file) throws IOException {
182 if(file.isDirectory()) {
183 if(!writeDirToRemote(file))
184 return;
185 } else if(file.isFile()) {
186 writeString("C0644 " + file.length() + " " + file.getName() + "\n");
187 if(indicator != null)
188 indicator.startFile(file.getName(), (int)file.length());
189 readResponse("After sending filedata");
190 FileInputStream fi = new FileInputStream(file);
191 writeFully(fi, (int)file.length());
192 writeByte(0);
193 if(indicator != null)
194 indicator.endFile();
195 } else {
196 throw new IOException("Not ordinary file: " + file.getName());
197 }
198 readResponse("After writing file");
199 }
200
201 void readFromRemote(File file) throws IOException {
202 String cmd;
203 String[] cmdParts = new String[3];
204 writeByte(0);
205 while(true) {
206 do {
207 try {
208 cmd = readString();
209 } catch (EOFException e) {
210 return;
211 }
212 } while(cmd == null);
213 char cmdChar = cmd.charAt(0);
214 switch(cmdChar) {
215 case 'E':
216 writeByte(0);
217 return;
218 case 'T':
219 // !!!
220 System.out.println("(T)ime not supported: " + cmd);
221 break;
222 case 'C':
223 case 'D':
224 String targetName = file.getAbsolutePath();
225 parseCommand(cmd, cmdParts);
226 if(file.isDirectory()) {
227 targetName += File.separator + cmdParts[2];
228 }
229 File targetFile = new File(targetName);
230 if(cmdChar == 'D') {
231 if(targetFile.exists()) {
232 if(!targetFile.isDirectory())
233 writeError("Invalid target " + targetFile.getName() +
234 ", must be a directory");
235 } else {
236 if(!targetFile.mkdir())
237 writeError("Could not create directory: " + targetFile.getName());
238 }
239 if(indicator != null)
240 indicator.startDir(targetFile.getAbsolutePath());
241 readFromRemote(targetFile);
242 if(indicator != null)
243 indicator.endDir();
244 continue;
245 }
246 FileOutputStream fo = new FileOutputStream(targetFile);
247 writeByte(0);
248 int len = Integer.parseInt(cmdParts[1]);
249 if(indicator != null)
250 indicator.startFile(targetFile.getName(), len);
251 readFully(fo, len);
252 readResponse("After reading file");
253 if(indicator != null)
254 indicator.endFile();
255 writeByte(0);
256 break;
257 default:
258 writeError("Unexpected cmd: " + cmd);
259 throw new IOException("Unexpected cmd: " + cmd);
260 }
261 }
262 }
263
264 void parseCommand(String cmd, String[] cmdParts) throws IOException {
265 int l, r;
266 l = cmd.indexOf(' ');
267 r = cmd.indexOf(' ', l + 1);
268 if(l == -1 || r == -1) {
269 writeError("Syntax error in cmd");
270 throw new IOException("Syntax error in cmd");
271 }
272 cmdParts[0] = cmd.substring(1, l);
273 cmdParts[1] = cmd.substring(l + 1, r);
274 cmdParts[2] = cmd.substring(r + 1);
275 }
276
277 void readResponse(String where) throws IOException {
278 int r = readByte();
279 if(r == 0) {
280 // All is well, no error
281 return;
282 }
283 String errMsg = readString();
284 if(r == (byte)'\02')
285 throw new IOException(errMsg);
286 alert(errMsg);
287 }
288
289 void writeError(String reason) throws IOException {
290 writeByte(1);
291 writeString(reason);
292 alert(reason);
293 }
294
295 int readByte() throws IOException {
296 return inTop.read();
297 }
298
299 String readString() throws IOException {
300 byte[] buf = new byte[2048];
301 int ch, i = 0;
302 while(((ch = readByte()) != ((int)'\n')) && ch >= 0) {
303 buf[i++] = (byte)ch;
304 }
305 if(ch == -1) {
306 throw new EOFException();
307 }
308 if(buf[0] == (byte)'\n')
309 throw new IOException("Unexpected <NL>");
310 if(buf[0] == (byte)'\02' || buf[0] == (byte)'\01') {
311 // !!!
312 String errMsg = new String(buf, 1, i - 1);
313 if(buf[0] == (byte)'\02')
314 throw new IOException(errMsg);
315 alert(errMsg);
316 return null;
317 }
318 return new String(buf, 0, i);
319 }
320
321 void readFully(FileOutputStream file, int size) throws IOException {
322 byte[] buf = new byte[2048];
323 int cnt = 0, n;
324 while(cnt < size) {
325 n = inTop.read(buf, 0, ((size - cnt) < 2048 ? (size - cnt) : 2048));
326 if(n == -1) {
327 alert("Premature EOF");
328 throw new IOException("Premature EOF");
329 }
330 cnt += n;
331 file.write(buf, 0, n);
332 if(indicator != null)
333 indicator.progress(n);
334 }
335 file.close();
336 }
337
338 void writeByte(int b) throws IOException {
339 byte[] buf = new byte[1];
340 buf[0] = (byte)b;
341 client.stdinWriteString(buf);
342 }
343
344 void writeString(String str) throws IOException {
345 byte[] buf = str.getBytes();
346 client.stdinWriteString(buf);
347 }
348
349 void writeFully(FileInputStream file, int size) throws IOException {
350 byte[] buf = new byte[2048];
351 int cnt = 0, n;
352 while(cnt < size) {
353 n = file.read(buf, 0, ((size - cnt) < 2048 ? (size - cnt) : 2048));
354 if(n == -1)
355 throw new IOException("Premature EOF");
356 cnt += n;
357 client.stdinWriteString(buf, 0, n);
358 if(indicator != null)
359 indicator.progress(n);
360 Thread.yield();
361 }
362 file.close();
363 }
364
365 public void stdoutWriteString(byte[] str) {
366 try {
367 inBottom.write(str);
368 } catch(IOException e) {
369 try {
370 inBottom.close();
371 } catch (IOException ee) {
372 // !!!
373 }
374 alert("Error writing data to stdout-pipe");
375 }
376 }
377
378 public void stderrWriteString(byte[] str) {
379 if(verbose) alert("Remote warning/error: " + new String(str));
380 }
381
382 public Terminal getTerminal() {
383 return null;
384 }
385 public void print(String str) {
386 }
387 public void println(String str) {
388 }
389 public void serverConnect(SSHChannelController controller, Cipher sndCipher) {
390 }
391 public void serverDisconnect(String reason) {
392 }
393 public boolean wantPTY() {
394 return false;
395 }
396 public void open(SSHClient client) {
397 if(indicator != null)
398 indicator.connected(sshHost);
399 }
400 public void disconnected(SSHClient client, boolean graceful) {
401 try {
402 inBottom.close();
403 } catch (IOException e) {
404 // !!!
405 }
406 }
407 public void alert(String msg) {
408 if(interactor != null) {
409 interactor.alert(msg);
410 }
411 }
412
413 public Socket getProxyConnection() throws IOException {
414 if(proxyUser != null) {
415 return proxyUser.getProxyConnection();
416 }
417 return null;
418 }
419
420 public SSHInteractor getInteractor() {
421 return ourInteractAdapter;
422 }
423
424 /* !!! TESTING !!!
425 public static void main(String[] argv) {
426 try {
427 SSHSCP scp = new SSHSCP("hal", 22, new SSHPasswordAuthenticator("mats", "********"),
428 new File("."), true, true);
429 String[] files = { "foo.h", "foo.c" };
430 scp.copyToRemote(files, "");
431 scp.copyToRemote(files, "foodir");
432 scp.copyToRemote("dummies/", "");
433 scp.copyToLocal("bar.c", "foo.c");
434 scp.copyToLocal("", "foodir");
435 System.exit(0);
436 } catch (IOException e) {
437 System.out.println("Error here: " + e);
438 e.printStackTrace();
439 }
440 }
441 */
442
443}
Note: See TracBrowser for help on using the repository browser.