1/*
2 * Copyright (c) 2011 David Kocher. All rights reserved.
3 * Please refer to the LICENSE.txt for licensing details.
4 */
5package ch.ethz.ssh2;
6
7import java.io.BufferedInputStream;
8import java.io.BufferedOutputStream;
9import java.io.IOException;
10import java.io.OutputStream;
11
12/**
13 * @version $Id:$
14 */
15public class SCPInputStream extends BufferedInputStream
16{
17	private Session session;
18
19	/**
20	 * Bytes remaining to be read from the stream
21	 */
22	private long remaining;
23
24	public SCPInputStream(SCPClient client, Session session) throws IOException
25	{
26		super(session.getStdout());
27
28		this.session = session;
29
30		OutputStream os = new BufferedOutputStream(session.getStdin(), 512);
31
32		os.write(0x0);
33		os.flush();
34
35		final SCPClient.LenNamePair lnp;
36
37		while (true)
38		{
39			int c = session.getStdout().read();
40			if (c < 0)
41			{
42				throw new IOException("Remote scp terminated unexpectedly.");
43			}
44
45			String line = client.receiveLine(session.getStdout());
46
47			if (c == 'T')
48			{
49				/* Ignore modification times */
50				continue;
51			}
52
53			if ((c == 1) || (c == 2))
54			{
55				throw new IOException("Remote SCP error: " + line);
56			}
57
58			if (c == 'C')
59			{
60				lnp = client.parseCLine(line);
61				break;
62
63			}
64			throw new IOException("Remote SCP error: " + ((char) c) + line);
65		}
66
67		os.write(0x0);
68		os.flush();
69
70		this.remaining = lnp.length;
71	}
72
73	@Override
74	public int read() throws IOException
75	{
76		if (!(remaining > 0))
77		{
78			return -1;
79		}
80
81		int read = super.read();
82		if (read < 0)
83		{
84			throw new IOException("Remote scp terminated connection unexpectedly");
85		}
86
87		remaining -= read;
88
89		return read;
90	}
91
92	@Override
93	public int read(byte b[], int off, int len) throws IOException
94	{
95		if (!(remaining > 0))
96		{
97			return -1;
98		}
99
100		int trans = (int) remaining;
101		if (remaining > len)
102		{
103			trans = len;
104		}
105
106		int read = super.read(b, off, trans);
107		if (read < 0)
108		{
109			throw new IOException("Remote scp terminated connection unexpectedly");
110		}
111
112		remaining -= read;
113
114		return read;
115	}
116
117	@Override
118	public void close() throws IOException
119	{
120		try
121		{
122			session.getStdin().write(0x0);
123			session.getStdin().flush();
124		}
125		finally
126		{
127			if (session != null)
128			{
129				session.close();
130			}
131		}
132	}
133}
134