/// <summary> /// Performs SSH_FXP_FSETSTAT request. /// </summary> /// <param name="handle">The handle.</param> /// <param name="attributes">The attributes.</param> public void RequestFSetStat(byte[] handle, SftpFileAttributes attributes) { SshException exception = null; using (var wait = new AutoResetEvent(false)) { var request = new SftpFSetStatRequest(ProtocolVersion, NextRequestId, handle, attributes, response => { exception = GetSftpException(response); wait.Set(); }); SendRequest(request); WaitOnHandle(wait, OperationTimeout); } if (exception != null) { throw exception; } }
/// <summary> /// Initializes a new instance of the <see cref="SftpFile"/> class. /// </summary> /// <param name="sftpSession">The SFTP session.</param> /// <param name="fullName">Full path of the directory or file.</param> /// <param name="attributes">Attributes of the directory or file.</param> /// <exception cref="ArgumentNullException"><paramref name="sftpSession"/> or <paramref name="fullName"/> is <c>null</c>.</exception> internal SftpFile(ISftpSession sftpSession, string fullName, SftpFileAttributes attributes) { if (sftpSession == null) { throw new SshConnectionException("Client not connected."); } if (attributes == null) { throw new ArgumentNullException("attributes"); } if (fullName == null) { throw new ArgumentNullException("fullName"); } _sftpSession = sftpSession; Attributes = attributes; Name = fullName.Substring(fullName.LastIndexOf('/') + 1); FullName = fullName; }
/// <summary> /// Sets the position within the current stream. /// </summary> /// <param name="offset">A byte offset relative to the <paramref name="origin"/> parameter.</param> /// <param name="origin">A value of type <see cref="T:System.IO.SeekOrigin"/> indicating the reference point used to obtain the new position.</param> /// <returns> /// The new position within the current stream. /// </returns> /// <exception cref="T:System.IO.IOException">An I/O error occurs. </exception> /// <exception cref="T:System.NotSupportedException">The stream does not support seeking, such as if the stream is constructed from a pipe or console output. </exception> /// <exception cref="T:System.ObjectDisposedException">Methods were called after the stream was closed. </exception> public override long Seek(long offset, SeekOrigin origin) { long newPosn = -1; // Lock down the file stream while we do this. lock (_lock) { CheckSessionIsOpen(); if (!CanSeek) { throw new NotSupportedException("Seek is not supported."); } // Don't do anything if the position won't be moving. if (origin == SeekOrigin.Begin && offset == _position) { return(offset); } if (origin == SeekOrigin.Current && offset == 0) { return(_position); } _attributes = _session.RequestFStat(_handle); // The behaviour depends upon the read/write mode. if (_bufferOwnedByWrite) { // Flush the write buffer and then seek. FlushWriteBuffer(); switch (origin) { case SeekOrigin.Begin: newPosn = offset; break; case SeekOrigin.Current: newPosn = _position + offset; break; case SeekOrigin.End: newPosn = _attributes.Size - offset; break; } if (newPosn == -1) { throw new EndOfStreamException("End of stream."); } _position = newPosn; _serverFilePosition = (ulong)newPosn; } else { // Determine if the seek is to somewhere inside // the current read buffer bounds. if (origin == SeekOrigin.Begin) { newPosn = _position - _bufferPosition; if (offset >= newPosn && offset < (newPosn + _bufferLen)) { _bufferPosition = (int)(offset - newPosn); _position = offset; return(_position); } } else if (origin == SeekOrigin.Current) { newPosn = _position + offset; if (newPosn >= (_position - _bufferPosition) && newPosn < (_position - _bufferPosition + _bufferLen)) { _bufferPosition = (int)(newPosn - (_position - _bufferPosition)); _position = newPosn; return(_position); } } // Abandon the read buffer. _bufferPosition = 0; _bufferLen = 0; // Seek to the new position. switch (origin) { case SeekOrigin.Begin: newPosn = offset; break; case SeekOrigin.Current: newPosn = _position + offset; break; case SeekOrigin.End: newPosn = _attributes.Size - offset; break; } if (newPosn < 0) { throw new EndOfStreamException(); } _position = newPosn; } return(_position); } }
internal SftpFileStream(ISftpSession session, string path, FileMode mode, FileAccess access, int bufferSize, bool useAsync) { // Validate the parameters. if (session == null) { throw new SshConnectionException("Client not connected."); } if (path == null) { throw new ArgumentNullException("path"); } if (bufferSize <= 0) { throw new ArgumentOutOfRangeException("bufferSize"); } if (access < FileAccess.Read || access > FileAccess.ReadWrite) { throw new ArgumentOutOfRangeException("access"); } if (mode < FileMode.CreateNew || mode > FileMode.Append) { throw new ArgumentOutOfRangeException("mode"); } Timeout = TimeSpan.FromSeconds(30); Name = path; // Initialize the object state. _session = session; _ownsHandle = true; _isAsync = useAsync; _bufferPosition = 0; _bufferLen = 0; _bufferOwnedByWrite = false; _canRead = ((access & FileAccess.Read) != 0); _canSeek = true; _canWrite = ((access & FileAccess.Write) != 0); _position = 0; _serverFilePosition = 0; var flags = Flags.None; switch (access) { case FileAccess.Read: flags |= Flags.Read; break; case FileAccess.Write: flags |= Flags.Write; break; case FileAccess.ReadWrite: flags |= Flags.Read; flags |= Flags.Write; break; } switch (mode) { case FileMode.Append: flags |= Flags.Append; break; case FileMode.Create: _handle = _session.RequestOpen(path, flags | Flags.Truncate, true); if (_handle == null) { flags |= Flags.CreateNew; } else { flags |= Flags.Truncate; } break; case FileMode.CreateNew: flags |= Flags.CreateNew; break; case FileMode.Open: break; case FileMode.OpenOrCreate: flags |= Flags.CreateNewOrOpen; break; case FileMode.Truncate: flags |= Flags.Truncate; break; } if (_handle == null) { _handle = _session.RequestOpen(path, flags); } _attributes = _session.RequestFStat(_handle); // instead of using the specified buffer size as is, we use it to calculate a buffer size // that ensures we always receive or send the max. number of bytes in a single SSH_FXP_READ // or SSH_FXP_WRITE message _readBufferSize = (int)session.CalculateOptimalReadLength((uint)bufferSize); _readBuffer = new byte[_readBufferSize]; _writeBufferSize = (int)session.CalculateOptimalWriteLength((uint)bufferSize, _handle); _writeBuffer = new byte[_writeBufferSize]; if (mode == FileMode.Append) { _position = _attributes.Size; _serverFilePosition = (ulong)_attributes.Size; } }
protected SftpFileAttributes ReadAttributes() { return(SftpFileAttributes.FromBytes(DataStream)); }