private void _put(InputStream src, String dst,
SftpProgressMonitor monitor, int mode)
{
try
{
long skip = 0;
if (mode == RESUME || mode == APPEND)
{
try
{
SftpATTRS attr = _stat(dst);
skip = attr.Size;
}
catch (Exception)
{
//System.err.println(eee);
}
}
if (mode == RESUME && skip > 0)
{
long skipped = src.skip(skip);
if (skipped < skip)
{
throw new SftpException(SSH_FX_FAILURE, "failed to resume for " + dst);
}
}
if (mode == OVERWRITE) { sendOPENW(dst); }
else { sendOPENA(dst); }
Header _header = new Header();
_header = ReadHeader(buf, _header);
int length = _header.length;
int type = _header.type;
buf.Rewind();
fill(buf.buffer, 0, length);
if (type != SSH_FXP_STATUS && type != SSH_FXP_HANDLE)
{
throw new SftpException(SSH_FX_FAILURE, "invalid type=" + type);
}
if (type == SSH_FXP_STATUS)
{
int i = buf.ReadInt();
throwStatusError(buf, i);
}
byte[] handle = buf.ReadString(); // filename
byte[] data = null;
bool dontcopy = true;
if (!dontcopy)
{
data = new byte[buf.buffer.Length
- (5 + 13 + 21 + handle.Length
+ 32 + 20 // padding and mac
)
];
}
long offset = 0;
if (mode == RESUME || mode == APPEND)
{
offset += skip;
}
int startid = seq;
int _ackid = seq;
int ackcount = 0;
while (true)
{
int nread = 0;
int s = 0;
int datalen = 0;
int count = 0;
if (!dontcopy)
{
datalen = data.Length - s;
}
else
{
data = buf.buffer;
s = 5 + 13 + 21 + handle.Length;
datalen = buf.buffer.Length - s
- 32 - 20; // padding and mac
}
do
{
nread = src.read(data, s, datalen);
if (nread > 0)
{
s += nread;
datalen -= nread;
count += nread;
}
}
while (datalen > 0 && nread > 0);
if (count <= 0) break;
int _i = count;
while (_i > 0)
{
_i -= sendWRITE(handle, offset, data, 0, _i);
if ((seq - 1) == startid ||
io.ins.available() >= 1024)
{
while (io.ins.available() > 0)
{
if (checkStatus(ackid, _header))
{
_ackid = ackid[0];
if (startid > _ackid || _ackid > seq - 1)
{
if (_ackid == seq)
{
System.Console.Error.WriteLine("ack error: startid=" + startid + " seq=" + seq + " _ackid=" + _ackid);
}
else
{
//throw new SftpException(SSH_FX_FAILURE, "ack error:");
throw new SftpException(SSH_FX_FAILURE, "ack error: startid=" + startid + " seq=" + seq + " _ackid=" + _ackid);
}
}
ackcount++;
}
else
{
break;
}
}
}
}
offset += count;
if (monitor != null && !monitor.count(count))
{
break;
}
}
int _ackcount = seq - startid;
while (_ackcount > ackcount)
{
if (!checkStatus(null, _header))
{
break;
}
ackcount++;
}
if (monitor != null) monitor.end();
_sendCLOSE(handle, _header);
//System.err.println("start end "+startid+" "+endid);
}
catch (Exception e)
{
if (e is SftpException) throw (SftpException)e;
throw new SftpException(SSH_FX_FAILURE, e.ToString());
}
}