Пример #1
0
        private void _put(InputStream src, string dst, SftpProgressMonitor monitor, ChannelSftpModes mode)
        {
            try
            {
                long skip = 0;
                if (mode == ChannelSftpModes.RESUME || mode == ChannelSftpModes.APPEND)
                {
                    try
                    {
                        SftpATTRS attr = execStat(dst);
                        skip = attr.getSize();
                    }
                    catch (Exception)
                    { }
                }
                if (mode == ChannelSftpModes.RESUME && skip > 0)
                {
                    long skipped = src.Skip(skip);
                    if (skipped < skip)
                        throw new SftpException(ChannelSftpResult.SSH_FX_FAILURE, "failed to resume for " + dst);
                }
                if (mode == ChannelSftpModes.OVERWRITE)
                    sendOPENW(Util.getBytesUTF8(dst));
                else
                    sendOPENA(Util.getBytesUTF8(dst));

                Header header = new Header();
                header = fillHeader(m_buffer, header);
                int length = header.Length;
                int type = header.HeaderType;
                m_buffer.rewind();
                fill(m_buffer.m_buffer, 0, length);

                if (type != SSH_FXP_STATUS && type != SSH_FXP_HANDLE)
                    throw new SftpException(ChannelSftpResult.SSH_FX_FAILURE, "invalid type=" + type);

                if (type == SSH_FXP_STATUS)
                {
                    int i = m_buffer.getInt();
                    throwStatusError(m_buffer, i);
                }
                byte[] handle = m_buffer.getString();	// filename
                byte[] data = null;

                bool dontcopy = true;

                if (!dontcopy)
                {
                    data = new byte[m_buffer.m_buffer.Length
                                    - (5 + 13 + 21 + handle.Length
                                    + 32 + 20 // padding and mac
                                    )
                        ];
                }

                long offset = 0;
                if (mode == ChannelSftpModes.RESUME || mode == ChannelSftpModes.APPEND)
                    offset += skip;

                int startid = m_seq;
                int _ackid = m_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 = m_buffer.m_buffer;
                        s = 5 + 13 + 21 + handle.Length;
                        datalen = m_buffer.m_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 ((m_seq - 1) == startid ||
                           m_io.m_ins.Available() >= 1024)
                        {
                            while (m_io.m_ins.Available() > 0)
                            {
                                if (checkStatus(m_ackid, header))
                                {
                                    _ackid = m_ackid[0];
                                    if (startid > _ackid || _ackid > m_seq - 1)
                                    {
                                        if (_ackid != m_seq)
                                            throw new SftpException(ChannelSftpResult.SSH_FX_FAILURE, "ack error: startid=" + startid + " seq=" + m_seq + " _ackid=" + _ackid);
                                    }
                                    ackcount++;
                                }
                                else
                                    break;
                            }
                        }
                    }
                    offset += count;
                    if (monitor != null && !monitor.Count(count))
                    {
                        break;
                    }
                }
                int _ackcount = m_seq - startid;
                while (_ackcount > ackcount)
                {
                    if (!checkStatus(null, header))
                        break;
                    ackcount++;
                }
                if (monitor != null) monitor.End();
                sendCLOSE(handle, header);
            }
            catch (Exception e)
            {
                if (e is SftpException) throw (SftpException)e;
                throw new SftpException(ChannelSftpResult.SSH_FX_FAILURE, e.ToString());
            }
        }