diff --git a/Renci.SshClient/Renci.SshNet/Renci.SshNet.csproj b/Renci.SshClient/Renci.SshNet/Renci.SshNet.csproj
index 27fc6771..08890cce 100644
--- a/Renci.SshClient/Renci.SshNet/Renci.SshNet.csproj
+++ b/Renci.SshClient/Renci.SshNet/Renci.SshNet.csproj
@@ -131,7 +131,6 @@
-
@@ -187,7 +186,6 @@
-
diff --git a/Renci.SshClient/Renci.SshNet/Sftp/Messages/Attributes.cs b/Renci.SshClient/Renci.SshNet/Sftp/Messages/Attributes.cs
deleted file mode 100644
index 6f2ee568..00000000
--- a/Renci.SshClient/Renci.SshNet/Sftp/Messages/Attributes.cs
+++ /dev/null
@@ -1,67 +0,0 @@
-using System;
-using System.Collections.Generic;
-
-namespace Renci.SshNet.Sftp.Messages
-{
- ///
- /// Represents SFTP File attribute.
- ///
- public class SftpFileAttributes
- {
- ///
- /// Gets or sets the size.
- ///
- ///
- /// The size.
- ///
- public ulong? Size { get; set; }
-
- ///
- /// Gets or sets the user id.
- ///
- ///
- /// The user id.
- ///
- public uint? UserId { get; set; }
-
- ///
- /// Gets or sets the group id.
- ///
- ///
- /// The group id.
- ///
- public uint? GroupId { get; set; }
-
- ///
- /// Gets or sets the permissions.
- ///
- ///
- /// The permissions.
- ///
- public uint Permissions { get; set; }
-
- ///
- /// Gets or sets the access time.
- ///
- ///
- /// The access time.
- ///
- public DateTime? AccessTime { get; set; }
-
- ///
- /// Gets or sets the modify time.
- ///
- ///
- /// The modify time.
- ///
- public DateTime? ModifyTime { get; set; }
-
- ///
- /// Gets or sets the extensions.
- ///
- ///
- /// The extensions.
- ///
- public IDictionary Extensions { get; set; }
- }
-}
diff --git a/Renci.SshClient/Renci.SshNet/Sftp/Messages/MkDirMessage.cs b/Renci.SshClient/Renci.SshNet/Sftp/Messages/MkDirMessage.cs
index 447b0705..937458e2 100644
--- a/Renci.SshClient/Renci.SshNet/Sftp/Messages/MkDirMessage.cs
+++ b/Renci.SshClient/Renci.SshNet/Sftp/Messages/MkDirMessage.cs
@@ -13,14 +13,14 @@
public MkDirMessage()
{
- this.Attributes = new SftpFileAttributes();
+ this.Attributes = SftpFileAttributes.Empty;
}
public MkDirMessage(uint requestId, string path)
: base(requestId)
{
this.Path = path;
- this.Attributes = new SftpFileAttributes();
+ this.Attributes = SftpFileAttributes.Empty;
}
public MkDirMessage(uint requestId, string path, SftpFileAttributes attributes)
diff --git a/Renci.SshClient/Renci.SshNet/Sftp/Messages/OpenMessage.cs b/Renci.SshClient/Renci.SshNet/Sftp/Messages/OpenMessage.cs
index 719cf640..852e0bb5 100644
--- a/Renci.SshClient/Renci.SshNet/Sftp/Messages/OpenMessage.cs
+++ b/Renci.SshClient/Renci.SshNet/Sftp/Messages/OpenMessage.cs
@@ -25,7 +25,7 @@ namespace Renci.SshNet.Sftp.Messages
{
this.Filename = fileName;
this.Flags = flags;
- this.Attributes = new SftpFileAttributes();
+ this.Attributes = SftpFileAttributes.Empty;
}
public OpenMessage(uint requestId, string fileName, Flags flags, SftpFileAttributes attributes)
diff --git a/Renci.SshClient/Renci.SshNet/Sftp/Messages/SftpMessage.cs b/Renci.SshClient/Renci.SshNet/Sftp/Messages/SftpMessage.cs
index f58c4a3a..7b82da9d 100644
--- a/Renci.SshClient/Renci.SshNet/Sftp/Messages/SftpMessage.cs
+++ b/Renci.SshClient/Renci.SshNet/Sftp/Messages/SftpMessage.cs
@@ -52,42 +52,48 @@ namespace Renci.SshNet.Sftp.Messages
protected SftpFileAttributes ReadAttributes()
{
- var attributes = new SftpFileAttributes();
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 extensions = null;
if ((flag & 0x00000001) == 0x00000001) // SSH_FILEXFER_ATTR_SIZE
{
- attributes.Size = this.ReadUInt64();
-
+ size = (long)this.ReadUInt64();
}
if ((flag & 0x00000002) == 0x00000002) // SSH_FILEXFER_ATTR_UIDGID
{
- attributes.UserId = this.ReadUInt32();
+ userId = (int)this.ReadUInt32();
- attributes.GroupId = this.ReadUInt32();
+ groupId = (int)this.ReadUInt32();
}
if ((flag & 0x00000004) == 0x00000004) // SSH_FILEXFER_ATTR_PERMISSIONS
{
- attributes.Permissions = this.ReadUInt32();
+ permissions = this.ReadUInt32();
}
if ((flag & 0x00000008) == 0x00000008) // SSH_FILEXFER_ATTR_ACMODTIME
{
var time = this.ReadUInt32();
- attributes.AccessTime = DateTime.FromFileTime((time + 11644473600) * 10000000);
+ accessTime = DateTime.FromFileTime((time + 11644473600) * 10000000);
time = this.ReadUInt32();
- attributes.ModifyTime = DateTime.FromFileTime((time + 11644473600) * 10000000);
+ modifyTime = DateTime.FromFileTime((time + 11644473600) * 10000000);
}
if ((flag & 0x80000000) == 0x80000000) // SSH_FILEXFER_ATTR_ACMODTIME
{
var extendedCount = this.ReadUInt32();
- attributes.Extensions = this.ReadExtensionPair();
+ extensions = this.ReadExtensionPair();
}
+ var attributes = new SftpFileAttributes(accessTime, modifyTime, size, userId, groupId, permissions, extensions);
return attributes;
}
@@ -103,12 +109,12 @@ namespace Renci.SshNet.Sftp.Messages
{
UInt32 flag = 0;
- if (attributes.Size.HasValue)
+ if (attributes.Size > -1)
{
flag |= 0x00000001;
}
- if (attributes.UserId.HasValue && attributes.GroupId.HasValue)
+ if (attributes.UserId > -1 && attributes.GroupId > -1)
{
flag |= 0x00000002;
}
@@ -118,7 +124,7 @@ namespace Renci.SshNet.Sftp.Messages
flag |= 0x00000004;
}
- if (attributes.AccessTime.HasValue && attributes.ModifyTime.HasValue)
+ if (attributes.LastAccessTime > DateTime.MinValue && attributes.LastWriteTime > DateTime.MinValue)
{
flag |= 0x00000008;
}
@@ -130,15 +136,15 @@ namespace Renci.SshNet.Sftp.Messages
this.Write(flag);
- if (attributes.Size.HasValue)
+ if (attributes.Size > -1)
{
- this.Write(attributes.Size.Value);
+ this.Write((UInt64)attributes.Size);
}
- if (attributes.UserId.HasValue && attributes.GroupId.HasValue)
+ if (attributes.UserId > -1 && attributes.GroupId > -1)
{
- this.Write(attributes.UserId.Value);
- this.Write(attributes.GroupId.Value);
+ this.Write((UInt32)attributes.UserId);
+ this.Write((UInt32)attributes.GroupId);
}
if (attributes.Permissions > 0)
@@ -146,11 +152,11 @@ namespace Renci.SshNet.Sftp.Messages
this.Write(attributes.Permissions);
}
- if (attributes.AccessTime.HasValue && attributes.ModifyTime.HasValue)
+ if (attributes.LastAccessTime > DateTime.MinValue && attributes.LastWriteTime > DateTime.MinValue)
{
- uint time = (uint)(attributes.AccessTime.Value.ToFileTime() / 10000000 - 11644473600);
+ uint time = (uint)(attributes.LastAccessTime.ToFileTime() / 10000000 - 11644473600);
this.Write(time);
- time = (uint)(attributes.ModifyTime.Value.ToFileTime() / 10000000 - 11644473600);
+ time = (uint)(attributes.LastWriteTime.ToFileTime() / 10000000 - 11644473600);
this.Write(time);
}
diff --git a/Renci.SshClient/Renci.SshNet/Sftp/SetFileStatusCommand.cs b/Renci.SshClient/Renci.SshNet/Sftp/SetFileStatusCommand.cs
deleted file mode 100644
index a0c1b1e1..00000000
--- a/Renci.SshClient/Renci.SshNet/Sftp/SetFileStatusCommand.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Renci.SshNet.Sftp.Messages;
-
-namespace Renci.SshNet.Sftp
-{
- internal class SetFileStatusCommand : SftpCommand
- {
- private string _path;
-
- private SftpFileAttributes _attributes;
-
- public SftpFile SftpFile { get; private set; }
-
- public SetFileStatusCommand(SftpSession sftpSession, string path, SftpFileAttributes attributes)
- : base(sftpSession)
- {
- this._path = path;
-
- this._attributes = attributes;
- }
-
- protected override void OnExecute()
- {
- this.SendSetStatMessage(this._path, this._attributes);
- }
-
- protected override void OnStatus(StatusCodes statusCode, string errorMessage, string language)
- {
- base.OnStatus(statusCode, errorMessage, language);
-
- if (statusCode == StatusCodes.Ok)
- {
- this.CompleteExecution();
- }
- }
- }
-}
diff --git a/Renci.SshClient/Renci.SshNet/Sftp/SftpFile.cs b/Renci.SshClient/Renci.SshNet/Sftp/SftpFile.cs
index ad26f841..7e64a368 100644
--- a/Renci.SshClient/Renci.SshNet/Sftp/SftpFile.cs
+++ b/Renci.SshClient/Renci.SshNet/Sftp/SftpFile.cs
@@ -12,57 +12,10 @@ namespace Renci.SshNet.Sftp
///
public class SftpFile
{
- #region Bitmask constats
-
- private static UInt32 S_IFMT = 0xF000; // bitmask for the file type bitfields
-
- private static UInt32 S_IFSOCK = 0xC000; // socket
-
- private static UInt32 S_IFLNK = 0xA000; // symbolic link
-
- private static UInt32 S_IFREG = 0x8000; // regular file
-
- private static UInt32 S_IFBLK = 0x6000; // block device
-
- private static UInt32 S_IFDIR = 0x4000; // directory
-
- private static UInt32 S_IFCHR = 0x2000; // character device
-
- private static UInt32 S_IFIFO = 0x1000; // FIFO
-
- private static UInt32 S_ISUID = 0x0800; // set UID bit
-
- private static UInt32 S_ISGID = 0x0400; // set-group-ID bit (see below)
-
- private static UInt32 S_ISVTX = 0x0200; // sticky bit (see below)
-
- private static UInt32 S_IRUSR = 0x0100; // owner has read permission
-
- private static UInt32 S_IWUSR = 0x0080; // owner has write permission
-
- private static UInt32 S_IXUSR = 0x0040; // owner has execute permission
-
- private static UInt32 S_IRGRP = 0x0020; // group has read permission
-
- private static UInt32 S_IWGRP = 0x0010; // group has write permission
-
- private static UInt32 S_IXGRP = 0x0008; // group has execute permission
-
- private static UInt32 S_IROTH = 0x0004; // others have read permission
-
- private static UInt32 S_IWOTH = 0x0002; // others have write permission
-
- private static UInt32 S_IXOTH = 0x0001; // others have execute permission
-
- #endregion
-
- private bool _isBitFiledsBitSet;
- private bool _isUIDBitSet;
- private bool _isGroupIDBitSet;
- private bool _isStickyBitSet;
-
private SftpSession _sftpSession;
+ public SftpFileAttributes Attributes { get; private set; }
+
///
/// Initializes a new instance of the class.
///
@@ -75,77 +28,11 @@ namespace Renci.SshNet.Sftp
throw new ArgumentNullException("attributes");
this._sftpSession = sftpSession;
+ this.Attributes = attributes;
this.Name = fullName.Substring(fullName.LastIndexOf('/') + 1);
this.FullName = fullName;
-
- if (attributes.AccessTime.HasValue)
- this.LastAccessTime = attributes.AccessTime.Value;
- else
- this.LastAccessTime = DateTime.MinValue;
-
- if (attributes.ModifyTime.HasValue)
- this.LastWriteTime = attributes.ModifyTime.Value;
- else
- this.LastWriteTime = DateTime.MinValue;
-
- if (attributes.Size.HasValue)
- this.Size = (long)attributes.Size.Value;
- else
- this.Size = -1;
-
- if (attributes.UserId.HasValue)
- this.UserId = (int)attributes.UserId.Value;
- else
- this.UserId = -1;
-
- if (attributes.GroupId.HasValue)
- this.GroupId = (int)attributes.GroupId.Value;
- else
- this.GroupId = -1;
-
- this._isBitFiledsBitSet = ((attributes.Permissions & S_IFMT) == S_IFMT);
-
- this.IsSocket = ((attributes.Permissions & S_IFSOCK) == S_IFSOCK);
-
- this.IsSymbolicLink = ((attributes.Permissions & S_IFLNK) == S_IFLNK);
-
- this.IsRegularFile = ((attributes.Permissions & S_IFREG) == S_IFREG);
-
- this.IsBlockDevice = ((attributes.Permissions & S_IFBLK) == S_IFBLK);
-
- this.IsDirectory = ((attributes.Permissions & S_IFDIR) == S_IFDIR);
-
- this.IsCharacterDevice = ((attributes.Permissions & S_IFCHR) == S_IFCHR);
-
- this.IsNamedPipe = ((attributes.Permissions & S_IFIFO) == S_IFIFO);
-
- this._isUIDBitSet = ((attributes.Permissions & S_ISUID) == S_ISUID);
-
- this._isGroupIDBitSet = ((attributes.Permissions & S_ISGID) == S_ISGID);
-
- this._isStickyBitSet = ((attributes.Permissions & S_ISVTX) == S_ISVTX);
-
- this.OwnerCanRead = ((attributes.Permissions & S_IRUSR) == S_IRUSR);
-
- this.OwnerCanWrite = ((attributes.Permissions & S_IWUSR) == S_IWUSR);
-
- this.OwnerCanExecute = ((attributes.Permissions & S_IXUSR) == S_IXUSR);
-
- this.GroupCanRead = ((attributes.Permissions & S_IRGRP) == S_IRGRP);
-
- this.GroupCanWrite = ((attributes.Permissions & S_IWGRP) == S_IWGRP);
-
- this.GroupCanExecute = ((attributes.Permissions & S_IXGRP) == S_IXGRP);
-
- this.OthersCanRead = ((attributes.Permissions & S_IROTH) == S_IROTH);
-
- this.OthersCanWrite = ((attributes.Permissions & S_IWOTH) == S_IWOTH);
-
- this.OthersCanExecute = ((attributes.Permissions & S_IXOTH) == S_IXOTH);
-
- this.Extensions = attributes.Extensions;
}
///
@@ -165,7 +52,13 @@ namespace Renci.SshNet.Sftp
///
/// The time that the current file or directory was last accessed.
///
- public DateTime LastAccessTime { get; private set; }
+ public DateTime LastAccessTime
+ {
+ get
+ {
+ return this.Attributes.LastAccessTime;
+ }
+ }
///
/// Gets or sets the time when the current file or directory was last written to.
@@ -173,7 +66,13 @@ namespace Renci.SshNet.Sftp
///
/// The time the current file was last written.
///
- public DateTime LastWriteTime { get; private set; }
+ public DateTime LastWriteTime
+ {
+ get
+ {
+ return this.Attributes.LastWriteTime;
+ }
+ }
///
/// Gets or sets the size, in bytes, of the current file.
@@ -181,7 +80,13 @@ namespace Renci.SshNet.Sftp
///
/// The size of the current file in bytes.
///
- public long Size { get; private set; }
+ public long Size
+ {
+ get
+ {
+ return this.Attributes.Size;
+ }
+ }
///
/// Gets or sets file user id.
@@ -189,7 +94,17 @@ namespace Renci.SshNet.Sftp
///
/// File user id.
///
- public int UserId { get; set; }
+ public int UserId
+ {
+ get
+ {
+ return this.Attributes.UserId;
+ }
+ set
+ {
+ this.Attributes.UserId = value;
+ }
+ }
///
/// Gets or sets file group id.
@@ -197,7 +112,17 @@ namespace Renci.SshNet.Sftp
///
/// File group id.
///
- public int GroupId { get; set; }
+ public int GroupId
+ {
+ get
+ {
+ return this.Attributes.GroupId;
+ }
+ set
+ {
+ this.Attributes.GroupId = value;
+ }
+ }
///
/// Gets a value indicating whether file represents a socket.
@@ -205,7 +130,13 @@ namespace Renci.SshNet.Sftp
///
/// true if file represents a socket; otherwise, false.
///
- public bool IsSocket { get; private set; }
+ public bool IsSocket
+ {
+ get
+ {
+ return this.Attributes.IsSocket;
+ }
+ }
///
/// Gets a value indicating whether file represents a symbolic link.
@@ -213,7 +144,13 @@ namespace Renci.SshNet.Sftp
///
/// true if file represents a symbolic link; otherwise, false.
///
- public bool IsSymbolicLink { get; private set; }
+ public bool IsSymbolicLink
+ {
+ get
+ {
+ return this.Attributes.IsSymbolicLink;
+ }
+ }
///
/// Gets a value indicating whether file represents a regular file.
@@ -221,7 +158,13 @@ namespace Renci.SshNet.Sftp
///
/// true if file represents a regular file; otherwise, false.
///
- public bool IsRegularFile { get; private set; }
+ public bool IsRegularFile
+ {
+ get
+ {
+ return this.Attributes.IsRegularFile;
+ }
+ }
///
/// Gets a value indicating whether file represents a block device.
@@ -229,7 +172,13 @@ namespace Renci.SshNet.Sftp
///
/// true if file represents a block device; otherwise, false.
///
- public bool IsBlockDevice { get; private set; }
+ public bool IsBlockDevice
+ {
+ get
+ {
+ return this.Attributes.IsBlockDevice;
+ }
+ }
///
/// Gets a value indicating whether file represents a directory.
@@ -237,7 +186,13 @@ namespace Renci.SshNet.Sftp
///
/// true if file represents a directory; otherwise, false.
///
- public bool IsDirectory { get; private set; }
+ public bool IsDirectory
+ {
+ get
+ {
+ return this.Attributes.IsDirectory;
+ }
+ }
///
/// Gets a value indicating whether file represents a character device.
@@ -245,7 +200,13 @@ namespace Renci.SshNet.Sftp
///
/// true if file represents a character device; otherwise, false.
///
- public bool IsCharacterDevice { get; private set; }
+ public bool IsCharacterDevice
+ {
+ get
+ {
+ return this.Attributes.IsCharacterDevice;
+ }
+ }
///
/// Gets a value indicating whether file represents a named pipe.
@@ -253,79 +214,175 @@ namespace Renci.SshNet.Sftp
///
/// true if file represents a named pipe; otherwise, false.
///
- public bool IsNamedPipe { get; private set; }
+ public bool IsNamedPipe
+ {
+ get
+ {
+ return this.Attributes.IsNamedPipe;
+ }
+ }
///
- /// Gets a value indicating whether the owner can read from this file.
+ /// Gets or sets a value indicating whether the owner can read from this file.
///
///
/// true if owner can read from this file; otherwise, false.
///
- public bool OwnerCanRead { get; set; }
+ public bool OwnerCanRead
+ {
+ get
+ {
+ return this.Attributes.OwnerCanRead;
+ }
+ set
+ {
+ this.Attributes.OwnerCanRead = value;
+ }
+ }
///
- /// Gets a value indicating whether the owner can write into this file.
+ /// Gets or sets a value indicating whether the owner can write into this file.
///
///
/// true if owner can write into this file; otherwise, false.
///
- public bool OwnerCanWrite { get; set; }
+ public bool OwnerCanWrite
+ {
+ get
+ {
+ return this.Attributes.OwnerCanWrite;
+ }
+ set
+ {
+ this.Attributes.OwnerCanWrite = value;
+ }
+ }
///
- /// Gets a value indicating whether the owner can execute this file.
+ /// Gets or sets a value indicating whether the owner can execute this file.
///
///
/// true if owner can execute this file; otherwise, false.
///
- public bool OwnerCanExecute { get; set; }
+ public bool OwnerCanExecute
+ {
+ get
+ {
+ return this.Attributes.OwnerCanExecute;
+ }
+ set
+ {
+ this.Attributes.OwnerCanExecute = value;
+ }
+ }
///
- /// Gets a value indicating whether the group members can read from this file.
+ /// Gets or sets a value indicating whether the group members can read from this file.
///
///
/// true if group members can read from this file; otherwise, false.
///
- public bool GroupCanRead { get; set; }
+ public bool GroupCanRead
+ {
+ get
+ {
+ return this.Attributes.GroupCanRead;
+ }
+ set
+ {
+ this.Attributes.GroupCanRead = value;
+ }
+ }
///
- /// Gets a value indicating whether the group members can write into this file.
+ /// Gets or sets a value indicating whether the group members can write into this file.
///
///
/// true if group members can write into this file; otherwise, false.
///
- public bool GroupCanWrite { get; set; }
+ public bool GroupCanWrite
+ {
+ get
+ {
+ return this.Attributes.GroupCanWrite;
+ }
+ set
+ {
+ this.Attributes.GroupCanWrite = value;
+ }
+ }
///
- /// Gets a value indicating whether the group members can execute this file.
+ /// Gets or sets a value indicating whether the group members can execute this file.
///
///
/// true if group members can execute this file; otherwise, false.
///
- public bool GroupCanExecute { get; set; }
+ public bool GroupCanExecute
+ {
+ get
+ {
+ return this.Attributes.GroupCanExecute;
+ }
+ set
+ {
+ this.Attributes.GroupCanExecute = value;
+ }
+ }
///
- /// Gets a value indicating whether the others can read from this file.
+ /// Gets or sets a value indicating whether the others can read from this file.
///
///
/// true if others can read from this file; otherwise, false.
///
- public bool OthersCanRead { get; set; }
+ public bool OthersCanRead
+ {
+ get
+ {
+ return this.Attributes.OthersCanRead;
+ }
+ set
+ {
+ this.Attributes.OthersCanRead = value;
+ }
+ }
///
- /// Gets a value indicating whether the others can write into this file.
+ /// Gets or sets a value indicating whether the others can write into this file.
///
///
/// true if others can write into this file; otherwise, false.
///
- public bool OthersCanWrite { get; set; }
+ public bool OthersCanWrite
+ {
+ get
+ {
+ return this.Attributes.OthersCanWrite;
+ }
+ set
+ {
+ this.Attributes.OthersCanWrite = value;
+ }
+ }
///
- /// Gets a value indicating whether the others can execute this file.
+ /// Gets or sets a value indicating whether the others can execute this file.
///
///
/// true if others can execute this file; otherwise, false.
///
- public bool OthersCanExecute { get; set; }
+ public bool OthersCanExecute
+ {
+ get
+ {
+ return this.Attributes.OthersCanExecute;
+ }
+ set
+ {
+ this.Attributes.OthersCanExecute = value;
+ }
+ }
///
/// Gets the extension part of the file.
@@ -335,41 +392,13 @@ namespace Renci.SshNet.Sftp
///
public IDictionary Extensions { get; private set; }
- ///
- /// Updates file status on the server.
- ///
- public void UpdateStatus()
- {
- using (var setCmd = new SetFileStatusCommand(this._sftpSession, this.FullName, this.GetAttributes()))
- {
- setCmd.CommandTimeout = TimeSpan.FromSeconds(30);
-
- setCmd.Execute();
- }
- }
-
///
/// Sets file permissions.
///
/// The mode.
- public void SetPermissions(ushort mode)
+ public void SetPermissions(short mode)
{
- var modeBytes = mode.ToString(CultureInfo.InvariantCulture).ToArray();
-
- var permission = (modeBytes[0] & 0x0F) * 8 * 8 + (modeBytes[1] & 0x0F) * 8 + (modeBytes[2] & 0x0F);
-
-
- this.OwnerCanRead = (permission & S_IRUSR) == S_IRUSR;
- this.OwnerCanWrite = (permission & S_IWUSR) == S_IWUSR;
- this.OwnerCanExecute = (permission & S_IXUSR) == S_IXUSR;
-
- this.GroupCanRead = (permission & S_IRGRP) == S_IRGRP;
- this.GroupCanWrite = (permission & S_IWGRP) == S_IWGRP;
- this.GroupCanExecute = (permission & S_IXGRP) == S_IXGRP;
-
- this.OthersCanRead = (permission & S_IROTH) == S_IROTH;
- this.OthersCanWrite = (permission & S_IWOTH) == S_IWOTH;
- this.OthersCanExecute = (permission & S_IXOTH) == S_IXOTH;
+ this.Attributes.SetPermissions(mode);
this.UpdateStatus();
}
@@ -377,7 +406,6 @@ namespace Renci.SshNet.Sftp
///
/// Permanently deletes a file on remote machine.
///
- [SecuritySafeCritical]
public void Delete()
{
SftpCommand cmd = null;
@@ -409,7 +437,6 @@ namespace Renci.SshNet.Sftp
/// Moves a specified file to a new location on remote machine, providing the option to specify a new file name.
///
/// The path to move the file to, which can specify a different file name.
- [SecuritySafeCritical]
public void MoveTo(string destFileName)
{
using (var setCmd = new RenameFileCommand(this._sftpSession, this.FullName, destFileName))
@@ -421,99 +448,19 @@ namespace Renci.SshNet.Sftp
}
///
- /// Gets the file attributes.
+ /// Updates file status on the server.
///
- ///
- private SftpFileAttributes GetAttributes()
+ public void UpdateStatus()
{
- var attributes = new SftpFileAttributes();
-
- // Populate only updateable attributes
- if (this.UserId > -1)
+ using (var setCmd = new SetStatusCommand(this._sftpSession, this.FullName, this.Attributes))
{
- attributes.UserId = new Nullable((uint)this.UserId);
+ setCmd.CommandTimeout = TimeSpan.FromSeconds(30);
+
+ setCmd.Execute();
}
- else
- {
- attributes.UserId = null;
- }
-
- if (this.GroupId > -1)
- {
- attributes.GroupId = new Nullable((uint)this.GroupId);
- }
- else
- {
- attributes.GroupId = null;
- }
-
- UInt32 permission = 0;
-
- if (this._isBitFiledsBitSet)
- permission = permission | S_IFMT;
-
- if (this.IsSocket)
- permission = permission | S_IFSOCK;
-
- if (this.IsSymbolicLink)
- permission = permission | S_IFLNK;
-
- if (this.IsRegularFile)
- permission = permission | S_IFREG;
-
- if (this.IsBlockDevice)
- permission = permission | S_IFBLK;
-
- if (this.IsDirectory)
- permission = permission | S_IFDIR;
-
- if (this.IsCharacterDevice)
- permission = permission | S_IFCHR;
-
- if (this.IsNamedPipe)
- permission = permission | S_IFIFO;
-
- if (this._isUIDBitSet)
- permission = permission | S_ISUID;
-
- if (this._isGroupIDBitSet)
- permission = permission | S_ISGID;
-
- if (this._isStickyBitSet)
- permission = permission | S_ISVTX;
-
- if (this.OwnerCanRead)
- permission = permission | S_IRUSR;
-
- if (this.OwnerCanWrite)
- permission = permission | S_IWUSR;
-
- if (this.OwnerCanExecute)
- permission = permission | S_IXUSR;
-
- if (this.GroupCanRead)
- permission = permission | S_IRGRP;
-
- if (this.GroupCanWrite)
- permission = permission | S_IWGRP;
-
- if (this.GroupCanExecute)
- permission = permission | S_IXGRP;
-
- if (this.OthersCanRead)
- permission = permission | S_IROTH;
-
- if (this.OthersCanWrite)
- permission = permission | S_IWOTH;
-
- if (this.OthersCanExecute)
- permission = permission | S_IXOTH;
-
- attributes.Permissions = permission;
-
- return attributes;
}
+
///
/// Returns a that represents this instance.
///
diff --git a/Renci.SshClient/Renci.SshNet/Sftp/SftpFileAttributes.cs b/Renci.SshClient/Renci.SshNet/Sftp/SftpFileAttributes.cs
index f195c7e7..7568523c 100644
--- a/Renci.SshClient/Renci.SshNet/Sftp/SftpFileAttributes.cs
+++ b/Renci.SshClient/Renci.SshNet/Sftp/SftpFileAttributes.cs
@@ -2,10 +2,11 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
+using System.Globalization;
namespace Renci.SshNet.Sftp
{
- public class SftpFileAttributes1
+ public class SftpFileAttributes
{
#region Bitmask constats
@@ -50,7 +51,7 @@ namespace Renci.SshNet.Sftp
private static UInt32 S_IXOTH = 0x0001; // others have execute permission
#endregion
-
+
private bool _isBitFiledsBitSet;
private bool _isUIDBitSet;
private bool _isGroupIDBitSet;
@@ -78,7 +79,7 @@ namespace Renci.SshNet.Sftp
///
/// The size of the current file in bytes.
///
- public long Size { get; private set; }
+ public long Size { get; set; }
///
/// Gets or sets file user id.
@@ -345,7 +346,19 @@ namespace Renci.SshNet.Sftp
}
}
- internal SftpFileAttributes1(DateTime lastAccessTime, DateTime lastWriteTime, long size, int userId, int groupId, uint permissions)
+ private static SftpFileAttributes _empty = new SftpFileAttributes(DateTime.MinValue, DateTime.MinValue, -1, -1, -1, 0, null);
+ ///
+ /// Gets the empty SftpFileAttributes instance.
+ ///
+ public static SftpFileAttributes Empty
+ {
+ get
+ {
+ return SftpFileAttributes._empty;
+ }
+ }
+
+ internal SftpFileAttributes(DateTime lastAccessTime, DateTime lastWriteTime, long size, int userId, int groupId, uint permissions, IDictionary extensions)
{
this.LastAccessTime = lastAccessTime;
this.LastWriteTime = lastWriteTime;
@@ -353,6 +366,31 @@ namespace Renci.SshNet.Sftp
this.UserId = userId;
this.GroupId = groupId;
this.Permissions = permissions;
+ this.Extensions = extensions;
+ }
+
+ public void SetPermissions(short mode)
+ {
+ if (mode < 0 || mode > 999)
+ {
+ throw new ArgumentOutOfRangeException("mode");
+ }
+
+ var modeBytes = mode.ToString(CultureInfo.InvariantCulture).PadLeft(3,'0').ToArray();
+
+ var permission = (modeBytes[0] & 0x0F) * 8 * 8 + (modeBytes[1] & 0x0F) * 8 + (modeBytes[2] & 0x0F);
+
+ this.OwnerCanRead = (permission & S_IRUSR) == S_IRUSR;
+ this.OwnerCanWrite = (permission & S_IWUSR) == S_IWUSR;
+ this.OwnerCanExecute = (permission & S_IXUSR) == S_IXUSR;
+
+ this.GroupCanRead = (permission & S_IRGRP) == S_IRGRP;
+ this.GroupCanWrite = (permission & S_IWGRP) == S_IWGRP;
+ this.GroupCanExecute = (permission & S_IXGRP) == S_IXGRP;
+
+ this.OthersCanRead = (permission & S_IROTH) == S_IROTH;
+ this.OthersCanWrite = (permission & S_IWOTH) == S_IWOTH;
+ this.OthersCanExecute = (permission & S_IXOTH) == S_IXOTH;
}
}
}
diff --git a/Renci.SshClient/Renci.SshNet/Sftp/SftpFileStream.cs b/Renci.SshClient/Renci.SshNet/Sftp/SftpFileStream.cs
index d7da96fa..3c896e84 100644
--- a/Renci.SshClient/Renci.SshNet/Sftp/SftpFileStream.cs
+++ b/Renci.SshClient/Renci.SshNet/Sftp/SftpFileStream.cs
@@ -109,10 +109,9 @@ namespace Renci.SshNet.Sftp
// Update file attributes
this._attributes = this._session.GetFileAttributes(this._handle);
- if (this._attributes != null && this._attributes.Size.HasValue)
+ if (this._attributes != null && this._attributes.Size > -1)
{
- // TODO: Test file size that greater then long.Max
- return (long)this._attributes.Size.Value;
+ return this._attributes.Size;
}
else
{
@@ -291,7 +290,7 @@ namespace Renci.SshNet.Sftp
if (mode == FileMode.Append)
{
// TODO: Validate Size property value exists
- this._position = (long)this._attributes.Size.Value;
+ this._position = this._attributes.Size;
}
}
@@ -681,7 +680,7 @@ namespace Renci.SshNet.Sftp
newPosn = this._position + offset;
break;
case SeekOrigin.End:
- newPosn = ((long)this._attributes.Size.Value) - offset;
+ newPosn = this._attributes.Size - offset;
break;
default:
break;
@@ -726,7 +725,6 @@ namespace Renci.SshNet.Sftp
this._bufferLen = 0;
// Seek to the new position.
- //newPosn = FileMethods.Seek(this._handle, offset, origin);
switch (origin)
{
case SeekOrigin.Begin:
@@ -736,16 +734,17 @@ namespace Renci.SshNet.Sftp
newPosn = this._position + offset;
break;
case SeekOrigin.End:
- newPosn = ((long)this._attributes.Size.Value) - offset;
+ newPosn = this._attributes.Size - offset;
break;
default:
break;
}
- if (newPosn == -1)
+ if (newPosn < 0)
{
throw new EndOfStreamException();
}
+
this._position = newPosn;
}
return this._position;
@@ -779,7 +778,7 @@ namespace Renci.SshNet.Sftp
// Setup this object for writing.
this.SetupWrite();
- this._attributes.Size = (ulong)value;
+ this._attributes.Size = value;
this._session.SetFileAttributes(this._handle, this._attributes);
}
diff --git a/Renci.SshClient/Renci.SshNet/Sftp/SftpSession.cs b/Renci.SshClient/Renci.SshNet/Sftp/SftpSession.cs
index 74ba2ac2..62520b1b 100644
--- a/Renci.SshClient/Renci.SshNet/Sftp/SftpSession.cs
+++ b/Renci.SshClient/Renci.SshNet/Sftp/SftpSession.cs
@@ -212,6 +212,18 @@ namespace Renci.SshNet.Sftp
}
}
+ public SftpFileAttributes GetFileAttributes(string path)
+ {
+ using (var cmd = new StatusCommand(this, path))
+ {
+ cmd.CommandTimeout = this._operationTimeout;
+
+ cmd.Execute();
+
+ return cmd.Attributes;
+ }
+ }
+
public void SetFileAttributes(byte[] handle, SftpFileAttributes attributes)
{
using (var cmd = new SetStatusCommand(this, handle, attributes))
@@ -222,6 +234,17 @@ namespace Renci.SshNet.Sftp
}
}
+ public void SetFileAttributes(string path, SftpFileAttributes attributes)
+ {
+ using (var cmd = new SetStatusCommand(this, path, attributes))
+ {
+ cmd.CommandTimeout = this._operationTimeout;
+
+ cmd.Execute();
+ }
+ }
+
+
internal void SendMessage(SftpMessage sftpMessage)
{
this._session.SendMessage(new SftpDataMessage(this._channel.RemoteChannelNumber, sftpMessage));
diff --git a/Renci.SshClient/Renci.SshNet/SftpClient.cs b/Renci.SshClient/Renci.SshNet/SftpClient.cs
index 62ebe8a9..35e1e159 100644
--- a/Renci.SshClient/Renci.SshNet/SftpClient.cs
+++ b/Renci.SshClient/Renci.SshNet/SftpClient.cs
@@ -134,7 +134,7 @@ namespace Renci.SshNet
///
/// File(s) path, may match multiple files.
/// The mode.
- public void ChangePermissions(string path, ushort mode)
+ public void ChangePermissions(string path, short mode)
{
if (path == null)
throw new ArgumentNullException("path");
@@ -705,16 +705,6 @@ namespace Renci.SshNet
return file != null;
}
- ///
- /// Gets the System.IO.FileAttributes of the file on the path.
- ///
- /// The path to the file.
- /// The System.IO.FileAttributes of the file on the path.
- public FileAttributes GetAttributes(string path)
- {
- throw new NotImplementedException();
- }
-
///
/// Returns the date and time the specified file or directory was last accessed.
///
@@ -1036,12 +1026,35 @@ namespace Renci.SshNet
}
}
+ ///
+ /// Gets the of the file on the path.
+ ///
+ /// The path to the file.
+ /// The of the file on the path.
+ public SftpFileAttributes GetAttributes(string path)
+ {
+ var fullPath = this._sftpSession.GetCanonicalPath(path);
+
+ return this._sftpSession.GetFileAttributes(fullPath);
+ }
+
+ ///
+ /// Sets the specified of the file on the specified path.
+ ///
+ /// The path to the file.
+ /// The desired .
+ public void SetAttributes(string path, SftpFileAttributes fileAttributes)
+ {
+ var fullPath = this._sftpSession.GetCanonicalPath(path);
+
+ this._sftpSession.SetFileAttributes(fullPath, fileAttributes);
+ }
+
//public FileSecurity GetAccessControl(string path);
//public FileSecurity GetAccessControl(string path, AccessControlSections includeSections);
//public DateTime GetCreationTime(string path);
//public DateTime GetCreationTimeUtc(string path);
//public void SetAccessControl(string path, FileSecurity fileSecurity);
- //public void SetAttributes(string path, FileAttributes fileAttributes);
//public void SetCreationTime(string path, DateTime creationTime);
//public void SetCreationTimeUtc(string path, DateTime creationTimeUtc);