Beispiel #1
0
        protected SftpFileAttributes ReadAttributes()
        {
            var flag = this.ReadUInt32();

            long size        = -1;
            int  userId      = -1;
            int  groupId     = -1;
            uint permissions = 0;
            var  accessTime  = DateTime.MinValue;
            var  modifyTime  = DateTime.MinValue;
            IDictionary <string, string> extensions = null;

            if ((flag & 0x00000001) == 0x00000001)   //  SSH_FILEXFER_ATTR_SIZE
            {
                size = (long)this.ReadUInt64();
            }

            if ((flag & 0x00000002) == 0x00000002)   //  SSH_FILEXFER_ATTR_UIDGID
            {
                userId = (int)this.ReadUInt32();

                groupId = (int)this.ReadUInt32();
            }

            if ((flag & 0x00000004) == 0x00000004)   //  SSH_FILEXFER_ATTR_PERMISSIONS
            {
                permissions = this.ReadUInt32();
            }

            if ((flag & 0x00000008) == 0x00000008)   //  SSH_FILEXFER_ATTR_ACMODTIME
            {
                var time = this.ReadUInt32();
                accessTime = DateTime.FromFileTime((time + 11644473600) * 10000000);
                time       = this.ReadUInt32();
                modifyTime = DateTime.FromFileTime((time + 11644473600) * 10000000);
            }

            if ((flag & 0x80000000) == 0x80000000)   //  SSH_FILEXFER_ATTR_ACMODTIME
            {
                var extendedCount = this.ReadUInt32();
                extensions = this.ReadExtensionPair();
            }
            var attributes = new SftpFileAttributes(accessTime, modifyTime, size, userId, groupId, permissions, extensions);

            return(attributes);
        }
Beispiel #2
0
        /// <summary>
        /// Performs SSH_FXP_FSETSTAT request.
        /// </summary>
        /// <param name="handle">The handle.</param>
        /// <param name="attributes">The attributes.</param>
        internal void RequestFSetStat(byte[] handle, SftpFileAttributes attributes)
        {
            SshException exception = null;

            using (var wait = new AutoResetEvent(false))
            {
                var request = new SftpFSetStatRequest(this.ProtocolVersion, this.NextRequestId, handle, attributes,
                                                      (response) =>
                {
                    exception = this.GetSftpException(response);
                    wait.Set();
                });

                this.SendRequest(request);

                this.WaitHandle(wait, this._operationTimeout);
            }

            if (exception != null)
            {
                throw exception;
            }
        }
Beispiel #3
0
        /// <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 null.</exception>
        internal SftpFile(SftpSession 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");
            }

            this._sftpSession = sftpSession;
            this.Attributes   = attributes;

            this.Name = fullName.Substring(fullName.LastIndexOf('/') + 1);

            this.FullName = fullName;
        }
Beispiel #4
0
        protected void Write(SftpFileAttributes attributes)
        {
            if (attributes == null)
            {
                this.Write((uint)0);
                return;
            }
            else
            {
                UInt32 flag = 0;

                if (attributes.IsSizeChanged && attributes.IsRegularFile)
                {
                    flag |= 0x00000001;
                }

                if (attributes.IsUserIdChanged || attributes.IsGroupIdChanged)
                {
                    flag |= 0x00000002;
                }

                if (attributes.IsPermissionsChanged)
                {
                    flag |= 0x00000004;
                }

                if (attributes.IsLastAccessTimeChanged || attributes.IsLastWriteTimeChanged)
                {
                    flag |= 0x00000008;
                }

                if (attributes.IsExtensionsChanged)
                {
                    flag |= 0x80000000;
                }

                this.Write(flag);

                if (attributes.IsSizeChanged && attributes.IsRegularFile)
                {
                    this.Write((UInt64)attributes.Size);
                }

                if (attributes.IsUserIdChanged || attributes.IsGroupIdChanged)
                {
                    this.Write((UInt32)attributes.UserId);
                    this.Write((UInt32)attributes.GroupId);
                }

                if (attributes.IsPermissionsChanged)
                {
                    this.Write(attributes.Permissions);
                }

                if (attributes.IsLastAccessTimeChanged || attributes.IsLastWriteTimeChanged)
                {
                    uint time = (uint)(attributes.LastAccessTime.ToFileTime() / 10000000 - 11644473600);
                    this.Write(time);
                    time = (uint)(attributes.LastWriteTime.ToFileTime() / 10000000 - 11644473600);
                    this.Write(time);
                }

                if (attributes.IsExtensionsChanged)
                {
                    this.Write(attributes.Extensions);
                }
            }
        }
Beispiel #5
0
        /// <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;

            // Bail out if this stream is not capable of seeking.
            if (!this._canSeek)
            {
                throw new NotSupportedException("Seek is not supported.");
            }

            // Lock down the file stream while we do this.
            lock (this._lock)
            {
                // Bail out if the handle is invalid.
                if (this._handle == null)
                {
                    throw new ObjectDisposedException("Stream is closed.");
                }

                // Don't do anything if the position won't be moving.
                if (origin == SeekOrigin.Begin && offset == this._position)
                {
                    return(offset);
                }
                else if (origin == SeekOrigin.Current && offset == 0)
                {
                    return(this._position);
                }

                this._attributes = this._session.RequestFStat(this._handle);

                // The behaviour depends upon the read/write mode.
                if (this._bufferOwnedByWrite)
                {
                    // Flush the write buffer and then seek.
                    this.FlushWriteBuffer();

                    switch (origin)
                    {
                    case SeekOrigin.Begin:
                        newPosn = offset;
                        break;

                    case SeekOrigin.Current:
                        newPosn = this._position + offset;
                        break;

                    case SeekOrigin.End:
                        newPosn = this._attributes.Size - offset;
                        break;

                    default:
                        break;
                    }

                    if (newPosn == -1)
                    {
                        throw new EndOfStreamException("End of stream.");
                    }
                    this._position           = newPosn;
                    this._serverFilePosition = (ulong)newPosn;
                }
                else
                {
                    // Determine if the seek is to somewhere inside
                    // the current read buffer bounds.
                    if (origin == SeekOrigin.Begin)
                    {
                        newPosn = this._position - this._bufferPosn;
                        if (offset >= newPosn && offset <
                            (newPosn + this._bufferLen))
                        {
                            this._bufferPosn = (int)(offset - newPosn);
                            this._position   = offset;
                            return(this._position);
                        }
                    }
                    else if (origin == SeekOrigin.Current)
                    {
                        newPosn = this._position + offset;
                        if (newPosn >= (this._position - this._bufferPosn) &&
                            newPosn < (this._position - this._bufferPosn + this._bufferLen))
                        {
                            this._bufferPosn =
                                (int)(newPosn - (this._position - this._bufferPosn));
                            this._position = newPosn;
                            return(this._position);
                        }
                    }

                    // Abandon the read buffer.
                    this._bufferPosn = 0;
                    this._bufferLen  = 0;

                    // Seek to the new position.
                    switch (origin)
                    {
                    case SeekOrigin.Begin:
                        newPosn = offset;
                        break;

                    case SeekOrigin.Current:
                        newPosn = this._position + offset;
                        break;

                    case SeekOrigin.End:
                        newPosn = this._attributes.Size - offset;
                        break;

                    default:
                        break;
                    }

                    if (newPosn < 0)
                    {
                        throw new EndOfStreamException();
                    }

                    this._position = newPosn;
                }
                return(this._position);
            }
        }
Beispiel #6
0
        internal SftpFileStream(SftpSession 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 || bufferSize > 16 * 1024)
            {
                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");
            }

            this.Timeout = TimeSpan.FromSeconds(30);
            this.Name    = path;

            // Initialize the object state.
            this._session               = session;
            this._access                = access;
            this._ownsHandle            = true;
            this._isAsync               = useAsync;
            this._path                  = path;
            this._bufferSize            = bufferSize;
            this._buffer                = new byte[bufferSize];
            this._bufferPosn            = 0;
            this._bufferLen             = 0;
            this._bufferOwnedByWrite    = false;
            this._canSeek               = true;
            this._position              = 0;
            this._serverFilePosition    = 0;
            this._session.Disconnected += Session_Disconnected;

            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;

            default:
                break;
            }

            switch (mode)
            {
            case FileMode.Append:
                flags |= Flags.Append;
                break;

            case FileMode.Create:
                this._handle = this._session.RequestOpen(path, flags | Flags.Truncate, true);
                if (this._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;

            default:
                break;
            }

            if (this._handle == null)
            {
                this._handle = this._session.RequestOpen(this._path, flags);
            }

            this._attributes = this._session.RequestFStat(this._handle);

            if (mode == FileMode.Append)
            {
                this._position           = this._attributes.Size;
                this._serverFilePosition = (ulong)this._attributes.Size;
            }
        }