diff --git a/src/Renci.SshNet.Silverlight/Renci.SshNet.Silverlight.csproj b/src/Renci.SshNet.Silverlight/Renci.SshNet.Silverlight.csproj
index beeef21a0..7505a175a 100644
--- a/src/Renci.SshNet.Silverlight/Renci.SshNet.Silverlight.csproj
+++ b/src/Renci.SshNet.Silverlight/Renci.SshNet.Silverlight.csproj
@@ -1358,6 +1358,9 @@
Sftp\SftpFile.cs
+
+ Sftp\ISftpFile.cs
+
Sftp\SftpFileAttributes.cs
diff --git a/src/Renci.SshNet.Silverlight5/Renci.SshNet.Silverlight5.csproj b/src/Renci.SshNet.Silverlight5/Renci.SshNet.Silverlight5.csproj
index 93b950edc..cff69e1cd 100644
--- a/src/Renci.SshNet.Silverlight5/Renci.SshNet.Silverlight5.csproj
+++ b/src/Renci.SshNet.Silverlight5/Renci.SshNet.Silverlight5.csproj
@@ -1364,6 +1364,9 @@
Sftp\SftpFile.cs
+
+ Sftp\ISftpFile.cs
+
Sftp\SftpFileAttributes.cs
diff --git a/src/Renci.SshNet.Tests/Classes/SftpClientTest.cs b/src/Renci.SshNet.Tests/Classes/SftpClientTest.cs
index f562f66bb..8f84546bf 100644
--- a/src/Renci.SshNet.Tests/Classes/SftpClientTest.cs
+++ b/src/Renci.SshNet.Tests/Classes/SftpClientTest.cs
@@ -562,8 +562,8 @@ public void EndListDirectoryTest()
ConnectionInfo connectionInfo = null; // TODO: Initialize to an appropriate value
SftpClient target = new SftpClient(connectionInfo); // TODO: Initialize to an appropriate value
IAsyncResult asyncResult = null; // TODO: Initialize to an appropriate value
- IEnumerable expected = null; // TODO: Initialize to an appropriate value
- IEnumerable actual;
+ IEnumerable expected = null; // TODO: Initialize to an appropriate value
+ IEnumerable actual;
actual = target.EndListDirectory(asyncResult);
Assert.AreEqual(expected, actual);
Assert.Inconclusive("Verify the correctness of this test method.");
@@ -702,8 +702,8 @@ public void GetTest()
ConnectionInfo connectionInfo = null; // TODO: Initialize to an appropriate value
SftpClient target = new SftpClient(connectionInfo); // TODO: Initialize to an appropriate value
string path = string.Empty; // TODO: Initialize to an appropriate value
- SftpFile expected = null; // TODO: Initialize to an appropriate value
- SftpFile actual;
+ ISftpFile expected = null; // TODO: Initialize to an appropriate value
+ ISftpFile actual;
actual = target.Get(path);
Assert.AreEqual(expected, actual);
Assert.Inconclusive("Verify the correctness of this test method.");
@@ -802,8 +802,8 @@ public void ListDirectoryTest()
SftpClient target = new SftpClient(connectionInfo); // TODO: Initialize to an appropriate value
string path = string.Empty; // TODO: Initialize to an appropriate value
Action listCallback = null; // TODO: Initialize to an appropriate value
- IEnumerable expected = null; // TODO: Initialize to an appropriate value
- IEnumerable actual;
+ IEnumerable expected = null; // TODO: Initialize to an appropriate value
+ IEnumerable actual;
actual = target.ListDirectory(path, listCallback);
Assert.AreEqual(expected, actual);
Assert.Inconclusive("Verify the correctness of this test method.");
diff --git a/src/Renci.SshNet.UAP10/Renci.SshNet.UAP10.csproj b/src/Renci.SshNet.UAP10/Renci.SshNet.UAP10.csproj
index d0eb423a2..a1f0c994f 100644
--- a/src/Renci.SshNet.UAP10/Renci.SshNet.UAP10.csproj
+++ b/src/Renci.SshNet.UAP10/Renci.SshNet.UAP10.csproj
@@ -1440,6 +1440,9 @@
Sftp\SftpFile.cs
+
+ Sftp\ISftpFile.cs
+
Sftp\SftpFileAttributes.cs
diff --git a/src/Renci.SshNet.WindowsPhone/Renci.SshNet.WindowsPhone.csproj b/src/Renci.SshNet.WindowsPhone/Renci.SshNet.WindowsPhone.csproj
index 317dbc845..f8342e11b 100644
--- a/src/Renci.SshNet.WindowsPhone/Renci.SshNet.WindowsPhone.csproj
+++ b/src/Renci.SshNet.WindowsPhone/Renci.SshNet.WindowsPhone.csproj
@@ -1343,6 +1343,9 @@
Sftp\SftpFile.cs
+
+ Sftp\ISftpFile.cs
+
Sftp\SftpFileAttributes.cs
diff --git a/src/Renci.SshNet.WindowsPhone8/Renci.SshNet.WindowsPhone8.csproj b/src/Renci.SshNet.WindowsPhone8/Renci.SshNet.WindowsPhone8.csproj
index f34c1d8e8..fb301e597 100644
--- a/src/Renci.SshNet.WindowsPhone8/Renci.SshNet.WindowsPhone8.csproj
+++ b/src/Renci.SshNet.WindowsPhone8/Renci.SshNet.WindowsPhone8.csproj
@@ -1396,6 +1396,9 @@
Sftp\SftpFile.cs
+
+ Sftp\ISftpFile.cs
+
Sftp\SftpFileAttributes.cs
diff --git a/src/Renci.SshNet/ISftpClient.cs b/src/Renci.SshNet/ISftpClient.cs
index b1212cfea..62f432491 100644
--- a/src/Renci.SshNet/ISftpClient.cs
+++ b/src/Renci.SshNet/ISftpClient.cs
@@ -10,7 +10,7 @@ namespace Renci.SshNet
///
/// Implementation of the SSH File Transfer Protocol (SFTP) over SSH.
///
- public interface ISftpClient
+ public interface ISftpClient : IDisposable
{
///
/// Gets or sets the maximum size of the buffer in bytes.
@@ -525,7 +525,7 @@ public interface ISftpClient
/// A list of files.
///
/// The object did not come from the corresponding async method on this type.-or- was called multiple times with the same .
- IEnumerable EndListDirectory(IAsyncResult asyncResult);
+ IEnumerable EndListDirectory(IAsyncResult asyncResult);
///
/// Ends the synchronize directories.
@@ -568,13 +568,13 @@ public interface ISftpClient
///
/// The path.
///
- /// A reference to file object.
+ /// A reference to file object.
///
/// Client is not connected.
/// was not found on the remote host.
/// is null.
/// The method was called after the client was disposed.
- SftpFile Get(string path);
+ ISftpFile Get(string path);
///
/// Gets the of the file on the path.
@@ -666,7 +666,7 @@ public interface ISftpClient
/// Permission to list the contents of the directory was denied by the remote host. -or- A SSH command was denied by the server.
/// A SSH error where is the message from the remote host.
/// The method was called after the client was disposed.
- IEnumerable ListDirectory(string path, Action listCallback = null);
+ IEnumerable ListDirectory(string path, Action listCallback = null);
///
/// Opens a on the specified path with read/write access.
diff --git a/src/Renci.SshNet/Sftp/ISftpFile.cs b/src/Renci.SshNet/Sftp/ISftpFile.cs
new file mode 100644
index 000000000..60c4a7a52
--- /dev/null
+++ b/src/Renci.SshNet/Sftp/ISftpFile.cs
@@ -0,0 +1,233 @@
+using System;
+
+namespace Renci.SshNet.Sftp
+{
+ ///
+ /// Represents SFTP file information
+ ///
+ public interface ISftpFile
+ {
+ ///
+ /// Gets the file attributes.
+ ///
+ SftpFileAttributes Attributes { get; }
+
+ ///
+ /// Gets the full path of the directory or file.
+ ///
+ string FullName { get; }
+
+ ///
+ /// For files, gets the name of the file. For directories, gets the name of the last directory in the hierarchy if a hierarchy exists.
+ /// Otherwise, the Name property gets the name of the directory.
+ ///
+ string Name { get; }
+
+ ///
+ /// Gets or sets the time the current file or directory was last accessed.
+ ///
+ ///
+ /// The time that the current file or directory was last accessed.
+ ///
+ DateTime LastAccessTime { get; set; }
+
+ ///
+ /// Gets or sets the time when the current file or directory was last written to.
+ ///
+ ///
+ /// The time the current file was last written.
+ ///
+ DateTime LastWriteTime { get; set; }
+
+ ///
+ /// Gets or sets the time, in coordinated universal time (UTC), the current file or directory was last accessed.
+ ///
+ ///
+ /// The time that the current file or directory was last accessed.
+ ///
+ DateTime LastAccessTimeUtc { get; set; }
+
+ ///
+ /// Gets or sets the time, in coordinated universal time (UTC), when the current file or directory was last written to.
+ ///
+ ///
+ /// The time the current file was last written.
+ ///
+ DateTime LastWriteTimeUtc { get; set; }
+
+ ///
+ /// Gets or sets the size, in bytes, of the current file.
+ ///
+ ///
+ /// The size of the current file in bytes.
+ ///
+ long Length { get; }
+
+ ///
+ /// Gets or sets file user id.
+ ///
+ ///
+ /// File user id.
+ ///
+ int UserId { get; set; }
+
+ ///
+ /// Gets or sets file group id.
+ ///
+ ///
+ /// File group id.
+ ///
+ int GroupId { get; set; }
+
+ ///
+ /// Gets a value indicating whether file represents a socket.
+ ///
+ ///
+ /// true if file represents a socket; otherwise, false.
+ ///
+ bool IsSocket { get; }
+
+ ///
+ /// Gets a value indicating whether file represents a symbolic link.
+ ///
+ ///
+ /// true if file represents a symbolic link; otherwise, false.
+ ///
+ bool IsSymbolicLink { get; }
+
+ ///
+ /// Gets a value indicating whether file represents a regular file.
+ ///
+ ///
+ /// true if file represents a regular file; otherwise, false.
+ ///
+ bool IsRegularFile { get; }
+
+ ///
+ /// Gets a value indicating whether file represents a block device.
+ ///
+ ///
+ /// true if file represents a block device; otherwise, false.
+ ///
+ bool IsBlockDevice { get; }
+
+ ///
+ /// Gets a value indicating whether file represents a directory.
+ ///
+ ///
+ /// true if file represents a directory; otherwise, false.
+ ///
+ bool IsDirectory { get; }
+
+ ///
+ /// Gets a value indicating whether file represents a character device.
+ ///
+ ///
+ /// true if file represents a character device; otherwise, false.
+ ///
+ bool IsCharacterDevice { get; }
+
+ ///
+ /// Gets a value indicating whether file represents a named pipe.
+ ///
+ ///
+ /// true if file represents a named pipe; otherwise, false.
+ ///
+ bool IsNamedPipe { get; }
+
+ ///
+ /// Gets or sets a value indicating whether the owner can read from this file.
+ ///
+ ///
+ /// true if owner can read from this file; otherwise, false.
+ ///
+ bool OwnerCanRead { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether the owner can write into this file.
+ ///
+ ///
+ /// true if owner can write into this file; otherwise, false.
+ ///
+ bool OwnerCanWrite { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether the owner can execute this file.
+ ///
+ ///
+ /// true if owner can execute this file; otherwise, false.
+ ///
+ bool OwnerCanExecute { get; set; }
+
+ ///
+ /// 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.
+ ///
+ bool GroupCanRead { get; set; }
+
+ ///
+ /// 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.
+ ///
+ bool GroupCanWrite { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether the group members can execute this file.
+ ///
+ ///
+ /// true if group members can execute this file; otherwise, false.
+ ///
+ bool GroupCanExecute { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether the others can read from this file.
+ ///
+ ///
+ /// true if others can read from this file; otherwise, false.
+ ///
+ bool OthersCanRead { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether the others can write into this file.
+ ///
+ ///
+ /// true if others can write into this file; otherwise, false.
+ ///
+ bool OthersCanWrite { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether the others can execute this file.
+ ///
+ ///
+ /// true if others can execute this file; otherwise, false.
+ ///
+ bool OthersCanExecute { get; set; }
+
+ ///
+ /// Sets file permissions.
+ ///
+ /// The mode.
+ void SetPermissions(short mode);
+
+ ///
+ /// Permanently deletes a file on remote machine.
+ ///
+ void Delete();
+
+ ///
+ /// 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.
+ /// is null.
+ void MoveTo(string destFileName);
+
+ ///
+ /// Updates file status on the server.
+ ///
+ void UpdateStatus();
+ }
+}
\ No newline at end of file
diff --git a/src/Renci.SshNet/Sftp/SftpFile.cs b/src/Renci.SshNet/Sftp/SftpFile.cs
index cfcc37a2f..6356d26ce 100644
--- a/src/Renci.SshNet/Sftp/SftpFile.cs
+++ b/src/Renci.SshNet/Sftp/SftpFile.cs
@@ -7,7 +7,7 @@ namespace Renci.SshNet.Sftp
///
/// Represents SFTP file information
///
- public class SftpFile
+ public sealed class SftpFile : ISftpFile
{
private readonly ISftpSession _sftpSession;
diff --git a/src/Renci.SshNet/Sftp/SftpListDirectoryAsyncResult.cs b/src/Renci.SshNet/Sftp/SftpListDirectoryAsyncResult.cs
index cb7b60132..2b791e54c 100644
--- a/src/Renci.SshNet/Sftp/SftpListDirectoryAsyncResult.cs
+++ b/src/Renci.SshNet/Sftp/SftpListDirectoryAsyncResult.cs
@@ -7,7 +7,7 @@ namespace Renci.SshNet.Sftp
///
/// Encapsulates the results of an asynchronous directory list operation.
///
- public class SftpListDirectoryAsyncResult : AsyncResult>
+ public class SftpListDirectoryAsyncResult : AsyncResult>
{
///
/// Gets the number of files read so far.
diff --git a/src/Renci.SshNet/SftpClient.cs b/src/Renci.SshNet/SftpClient.cs
index 3c22290d0..d0cb449d6 100644
--- a/src/Renci.SshNet/SftpClient.cs
+++ b/src/Renci.SshNet/SftpClient.cs
@@ -469,7 +469,7 @@ public void SymbolicLink(string path, string linkPath)
/// Permission to list the contents of the directory was denied by the remote host. -or- A SSH command was denied by the server.
/// A SSH error where is the message from the remote host.
/// The method was called after the client was disposed.
- public IEnumerable ListDirectory(string path, Action listCallback = null)
+ public IEnumerable ListDirectory(string path, Action listCallback = null)
{
CheckDisposed();
@@ -526,7 +526,7 @@ public IAsyncResult BeginListDirectory(string path, AsyncCallback asyncCallback,
/// A list of files.
///
/// The object did not come from the corresponding async method on this type.-or- was called multiple times with the same .
- public IEnumerable EndListDirectory(IAsyncResult asyncResult)
+ public IEnumerable EndListDirectory(IAsyncResult asyncResult)
{
var ar = asyncResult as SftpListDirectoryAsyncResult;
@@ -542,13 +542,13 @@ public IEnumerable EndListDirectory(IAsyncResult asyncResult)
///
/// The path.
///
- /// A reference to file object.
+ /// A reference to file object.
///
/// Client is not connected.
/// was not found on the remote host.
/// is null.
/// The method was called after the client was disposed.
- public SftpFile Get(string path)
+ public ISftpFile Get(string path)
{
CheckDisposed();
@@ -1920,7 +1920,7 @@ private IEnumerable InternalSynchronizeDirectories(string sourcePath,
#region Existing Files at The Destination
var destFiles = InternalListDirectory(destinationPath, null);
- var destDict = new Dictionary();
+ var destDict = new Dictionary();
foreach (var destFile in destFiles)
{
if (destFile.IsDirectory)
@@ -1986,7 +1986,7 @@ private IEnumerable InternalSynchronizeDirectories(string sourcePath,
///
/// is null.
/// Client not connected.
- private IEnumerable InternalListDirectory(string path, Action listCallback)
+ private IEnumerable InternalListDirectory(string path, Action listCallback)
{
if (path == null)
throw new ArgumentNullException("path");
@@ -2003,14 +2003,19 @@ private IEnumerable InternalListDirectory(string path, Action lis
if (!basePath.EndsWith("/"))
basePath = string.Format("{0}/", fullPath);
- var result = new List();
+ var result = new List();
var files = _sftpSession.RequestReadDir(handle);
while (files != null)
{
- result.AddRange(from f in files
- select new SftpFile(_sftpSession, string.Format(CultureInfo.InvariantCulture, "{0}{1}", basePath, f.Key), f.Value));
+ foreach (var f in files)
+ {
+ result.Add(new SftpFile(
+ _sftpSession,
+ string.Format(CultureInfo.InvariantCulture, "{0}{1}", basePath, f.Key),
+ f.Value));
+ }
// Call callback to report number of files read
if (listCallback != null)