diff --git a/src/Renci.SshNet.Tests/Classes/ClientAuthenticationTest_Success_MultiList_PartialSuccessLimitReachedFollowedBySuccessInAlternateBranch.cs b/src/Renci.SshNet.Tests/Classes/ClientAuthenticationTest_Success_MultiList_PartialSuccessLimitReachedFollowedBySuccessInAlternateBranch.cs
index d60549e5f..16f08ba92 100644
--- a/src/Renci.SshNet.Tests/Classes/ClientAuthenticationTest_Success_MultiList_PartialSuccessLimitReachedFollowedBySuccessInAlternateBranch.cs
+++ b/src/Renci.SshNet.Tests/Classes/ClientAuthenticationTest_Success_MultiList_PartialSuccessLimitReachedFollowedBySuccessInAlternateBranch.cs
@@ -181,4 +181,4 @@ public void AuthenticateOnPublicKeyAuthenticationMethodShouldHaveBeenInvokedTwic
PublicKeyAuthenticationMethodMock.Verify(p => p.Authenticate(SessionMock.Object), Times.Exactly(2));
}
}
-}
\ No newline at end of file
+}
diff --git a/src/Renci.SshNet.Tests/Classes/Common/BigIntegerTest.cs b/src/Renci.SshNet.Tests/Classes/Common/BigIntegerTest.cs
index 8cca838d2..c99fb2a6e 100644
--- a/src/Renci.SshNet.Tests/Classes/Common/BigIntegerTest.cs
+++ b/src/Renci.SshNet.Tests/Classes/Common/BigIntegerTest.cs
@@ -1506,10 +1506,12 @@ public void DefaultCtorWorks()
Assert.AreEqual("0", a.ToString(), "#4");
a = new BigInteger();
+#pragma warning disable CS1718 // Comparison made to same variable
Assert.AreEqual(true, a == a, "#5");
a = new BigInteger();
Assert.AreEqual(false, a < a, "#6");
+#pragma warning restore CS1718 // Comparison made to same variable
a = new BigInteger();
Assert.AreEqual(true, a < 10L, "#7");
diff --git a/src/Renci.SshNet.Tests/Classes/Messages/Connection/ChannelExtendedDataMessageTest.cs b/src/Renci.SshNet.Tests/Classes/Messages/Connection/ChannelExtendedDataMessageTest.cs
index e50f5fa48..469908ea3 100644
--- a/src/Renci.SshNet.Tests/Classes/Messages/Connection/ChannelExtendedDataMessageTest.cs
+++ b/src/Renci.SshNet.Tests/Classes/Messages/Connection/ChannelExtendedDataMessageTest.cs
@@ -30,7 +30,7 @@ public void ChannelExtendedDataMessageConstructorTest()
[Ignore] // placeholder
public void ChannelExtendedDataMessageConstructorTest1()
{
- uint localChannelNumber = 0; // TODO: Initialize to an appropriate value
+ //uint localChannelNumber = 0; // TODO: Initialize to an appropriate value
//ChannelExtendedDataMessage target = new ChannelExtendedDataMessage(localChannelNumber, null, null);
Assert.Inconclusive("TODO: Implement code to verify target");
}
diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileReaderTestBase.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileReaderTestBase.cs
index fe73f9a6d..2f2f1bbf0 100644
--- a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileReaderTestBase.cs
+++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileReaderTestBase.cs
@@ -38,7 +38,8 @@ public void SetUp()
protected static SftpFileAttributes CreateSftpFileAttributes(long size)
{
- return new SftpFileAttributes(default(DateTime), default(DateTime), size, default(int), default(int), default(uint), null);
+ var utcDefault = DateTime.SpecifyKind(default(DateTime), DateTimeKind.Utc);
+ return new SftpFileAttributes(utcDefault, utcDefault, size, default(int), default(int), default(uint), null);
}
protected static byte[] CreateByteArray(Random random, int length)
diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_Ctor_FileModeAppend_FileAccessWrite.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_Ctor_FileModeAppend_FileAccessWrite.cs
index d8c4904cc..871830670 100644
--- a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_Ctor_FileModeAppend_FileAccessWrite.cs
+++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_Ctor_FileModeAppend_FileAccessWrite.cs
@@ -34,8 +34,8 @@ protected override void SetupData()
_readBufferSize = (uint) _random.Next(5, 1000);
_writeBufferSize = (uint) _random.Next(5, 1000);
_handle = GenerateRandom(_random.Next(1, 10), _random);
- _fileAttributes = new SftpFileAttributesBuilder().WithLastAccessTime(DateTime.Now.AddSeconds(_random.Next()))
- .WithLastWriteTime(DateTime.Now.AddSeconds(_random.Next()))
+ _fileAttributes = new SftpFileAttributesBuilder().WithLastAccessTime(DateTime.UtcNow.AddSeconds(_random.Next()))
+ .WithLastWriteTime(DateTime.UtcNow.AddSeconds(_random.Next()))
.WithSize(_random.Next())
.WithUserId(_random.Next())
.WithGroupId(_random.Next())
diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_SetLength_DataInReadBuffer_NewLengthGreatherThanPosition.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_SetLength_DataInReadBuffer_NewLengthGreatherThanPosition.cs
index aee4b2762..59a0135f0 100644
--- a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_SetLength_DataInReadBuffer_NewLengthGreatherThanPosition.cs
+++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_SetLength_DataInReadBuffer_NewLengthGreatherThanPosition.cs
@@ -53,8 +53,8 @@ protected override void SetupData()
_fileAttributes = new SftpFileAttributesBuilder().WithExtension("X", "ABC")
.WithExtension("V", "VValue")
.WithGroupId(random.Next())
- .WithLastAccessTime(DateTime.Now.AddSeconds(random.Next()))
- .WithLastWriteTime(DateTime.Now.AddSeconds(random.Next()))
+ .WithLastAccessTime(DateTime.UtcNow.AddSeconds(random.Next()))
+ .WithLastWriteTime(DateTime.UtcNow.AddSeconds(random.Next()))
.WithPermissions((uint) random.Next())
.WithSize(_length + 100)
.WithUserId(random.Next())
@@ -201,4 +201,4 @@ public void WriteShouldStartFromSamePositionAsBeforeSetLength()
SftpSessionMock.Verify(p => p.IsOpen, Times.Exactly(4));
}
}
-}
\ No newline at end of file
+}
diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_SetLength_DataInReadBuffer_NewLengthLessThanPosition.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_SetLength_DataInReadBuffer_NewLengthLessThanPosition.cs
index ae3952cc6..a61163392 100644
--- a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_SetLength_DataInReadBuffer_NewLengthLessThanPosition.cs
+++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_SetLength_DataInReadBuffer_NewLengthLessThanPosition.cs
@@ -50,8 +50,8 @@ protected override void SetupData()
_fileAttributes = new SftpFileAttributesBuilder().WithExtension("X", "ABC")
.WithExtension("V", "VValue")
.WithGroupId(random.Next())
- .WithLastAccessTime(DateTime.Now.AddSeconds(random.Next()))
- .WithLastWriteTime(DateTime.Now.AddSeconds(random.Next()))
+ .WithLastAccessTime(DateTime.UtcNow.AddSeconds(random.Next()))
+ .WithLastWriteTime(DateTime.UtcNow.AddSeconds(random.Next()))
.WithPermissions((uint)random.Next())
.WithSize(_length + 100)
.WithUserId(random.Next())
diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_SetLength_DataInWriteBuffer_NewLengthGreatherThanPosition.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_SetLength_DataInWriteBuffer_NewLengthGreatherThanPosition.cs
index 5a19aa3ef..c71b43c85 100644
--- a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_SetLength_DataInWriteBuffer_NewLengthGreatherThanPosition.cs
+++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_SetLength_DataInWriteBuffer_NewLengthGreatherThanPosition.cs
@@ -54,8 +54,8 @@ protected override void SetupData()
_fileAttributes = new SftpFileAttributesBuilder().WithExtension("X", "ABC")
.WithExtension("V", "VValue")
.WithGroupId(random.Next())
- .WithLastAccessTime(DateTime.Now.AddSeconds(random.Next()))
- .WithLastWriteTime(DateTime.Now.AddSeconds(random.Next()))
+ .WithLastAccessTime(DateTime.UtcNow.AddSeconds(random.Next()))
+ .WithLastWriteTime(DateTime.UtcNow.AddSeconds(random.Next()))
.WithPermissions((uint)random.Next())
.WithSize(_length + 100)
.WithUserId(random.Next())
diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_SetLength_DataInWriteBuffer_NewLengthLessThanPosition.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_SetLength_DataInWriteBuffer_NewLengthLessThanPosition.cs
index cfcf23155..96ad14b18 100644
--- a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_SetLength_DataInWriteBuffer_NewLengthLessThanPosition.cs
+++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_SetLength_DataInWriteBuffer_NewLengthLessThanPosition.cs
@@ -54,8 +54,8 @@ protected override void SetupData()
_fileAttributes = new SftpFileAttributesBuilder().WithExtension("X", "ABC")
.WithExtension("V", "VValue")
.WithGroupId(random.Next())
- .WithLastAccessTime(DateTime.Now.AddSeconds(random.Next()))
- .WithLastWriteTime(DateTime.Now.AddSeconds(random.Next()))
+ .WithLastAccessTime(DateTime.UtcNow.AddSeconds(random.Next()))
+ .WithLastWriteTime(DateTime.UtcNow.AddSeconds(random.Next()))
.WithPermissions((uint) random.Next())
.WithSize(_length + 100)
.WithUserId(random.Next())
diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_SetLength_SessionOpen_FIleAccessReadWrite.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_SetLength_SessionOpen_FIleAccessReadWrite.cs
index 0fde319a1..ef89483b3 100644
--- a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_SetLength_SessionOpen_FIleAccessReadWrite.cs
+++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_SetLength_SessionOpen_FIleAccessReadWrite.cs
@@ -48,8 +48,8 @@ protected void Arrange()
_writeBufferSize = (uint) random.Next(0, 1000);
_length = random.Next();
- _fileAttributesLastAccessTime = DateTime.Now.AddSeconds(random.Next());
- _fileAttributesLastWriteTime = DateTime.Now.AddSeconds(random.Next());
+ _fileAttributesLastAccessTime = DateTime.UtcNow.AddSeconds(random.Next());
+ _fileAttributesLastWriteTime = DateTime.UtcNow.AddSeconds(random.Next());
_fileAttributesSize = random.Next();
_fileAttributesUserId = random.Next();
_fileAttributesGroupId = random.Next();
diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_SetLength_SessionOpen_FIleAccessWrite.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_SetLength_SessionOpen_FIleAccessWrite.cs
index ce2619a5b..73b5a9536 100644
--- a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_SetLength_SessionOpen_FIleAccessWrite.cs
+++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_SetLength_SessionOpen_FIleAccessWrite.cs
@@ -48,8 +48,8 @@ protected void Arrange()
_writeBufferSize = (uint) random.Next(0, 1000);
_length = random.Next();
- _fileAttributesLastAccessTime = DateTime.Now.AddSeconds(random.Next());
- _fileAttributesLastWriteTime = DateTime.Now.AddSeconds(random.Next());
+ _fileAttributesLastAccessTime = DateTime.UtcNow.AddSeconds(random.Next());
+ _fileAttributesLastWriteTime = DateTime.UtcNow.AddSeconds(random.Next());
_fileAttributesSize = random.Next();
_fileAttributesUserId = random.Next();
_fileAttributesGroupId = random.Next();
diff --git a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_Write_SessionOpen_CountGreatherThanTwoTimesTheWriteBufferSize.cs b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_Write_SessionOpen_CountGreatherThanTwoTimesTheWriteBufferSize.cs
index 68020d553..e7d537069 100644
--- a/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_Write_SessionOpen_CountGreatherThanTwoTimesTheWriteBufferSize.cs
+++ b/src/Renci.SshNet.Tests/Classes/Sftp/SftpFileStreamTest_Write_SessionOpen_CountGreatherThanTwoTimesTheWriteBufferSize.cs
@@ -119,8 +119,8 @@ public void PositionShouldBeNumberOfBytesWrittenToFileAndNUmberOfBytesInBuffer()
[TestMethod]
public void LengthShouldFlushBufferAndReturnSizeOfFile()
{
- var lengthFileAttributes = new SftpFileAttributes(DateTime.Now,
- DateTime.Now,
+ var lengthFileAttributes = new SftpFileAttributes(DateTime.UtcNow,
+ DateTime.UtcNow,
_random.Next(),
_random.Next(),
_random.Next(),
diff --git a/src/Renci.SshNet.Tests/Classes/SftpClientTest.cs b/src/Renci.SshNet.Tests/Classes/SftpClientTest.cs
index 3edd7c7b7..f562f66bb 100644
--- a/src/Renci.SshNet.Tests/Classes/SftpClientTest.cs
+++ b/src/Renci.SshNet.Tests/Classes/SftpClientTest.cs
@@ -1076,7 +1076,9 @@ public void SetLastAccessTimeTest()
SftpClient target = new SftpClient(connectionInfo); // TODO: Initialize to an appropriate value
string path = string.Empty; // TODO: Initialize to an appropriate value
DateTime lastAccessTime = new DateTime(); // TODO: Initialize to an appropriate value
+#pragma warning disable CS0618 // Type or member is obsolete
target.SetLastAccessTime(path, lastAccessTime);
+#pragma warning restore CS0618 // Type or member is obsolete
Assert.Inconclusive("A method that does not return a value cannot be verified.");
}
@@ -1091,7 +1093,9 @@ public void SetLastAccessTimeUtcTest()
SftpClient target = new SftpClient(connectionInfo); // TODO: Initialize to an appropriate value
string path = string.Empty; // TODO: Initialize to an appropriate value
DateTime lastAccessTimeUtc = new DateTime(); // TODO: Initialize to an appropriate value
+#pragma warning disable CS0618 // Type or member is obsolete
target.SetLastAccessTimeUtc(path, lastAccessTimeUtc);
+#pragma warning restore CS0618 // Type or member is obsolete
Assert.Inconclusive("A method that does not return a value cannot be verified.");
}
@@ -1106,7 +1110,9 @@ public void SetLastWriteTimeTest()
SftpClient target = new SftpClient(connectionInfo); // TODO: Initialize to an appropriate value
string path = string.Empty; // TODO: Initialize to an appropriate value
DateTime lastWriteTime = new DateTime(); // TODO: Initialize to an appropriate value
+#pragma warning disable CS0618 // Type or member is obsolete
target.SetLastWriteTime(path, lastWriteTime);
+#pragma warning restore CS0618 // Type or member is obsolete
Assert.Inconclusive("A method that does not return a value cannot be verified.");
}
@@ -1121,7 +1127,9 @@ public void SetLastWriteTimeUtcTest()
SftpClient target = new SftpClient(connectionInfo); // TODO: Initialize to an appropriate value
string path = string.Empty; // TODO: Initialize to an appropriate value
DateTime lastWriteTimeUtc = new DateTime(); // TODO: Initialize to an appropriate value
+#pragma warning disable CS0618 // Type or member is obsolete
target.SetLastWriteTimeUtc(path, lastWriteTimeUtc);
+#pragma warning restore CS0618 // Type or member is obsolete
Assert.Inconclusive("A method that does not return a value cannot be verified.");
}
@@ -1403,4 +1411,4 @@ private class TestInfo
public SftpDownloadAsyncResult DownloadResult { get; set; }
}
}
-}
\ No newline at end of file
+}
diff --git a/src/Renci.SshNet.Tests/Common/Extensions.cs b/src/Renci.SshNet.Tests/Common/Extensions.cs
index 911f34139..4e88a7900 100644
--- a/src/Renci.SshNet.Tests/Common/Extensions.cs
+++ b/src/Renci.SshNet.Tests/Common/Extensions.cs
@@ -49,8 +49,8 @@ internal static SftpFileAttributes Clone(this SftpFileAttributes value)
clonedExtensions = null;
}
- return new SftpFileAttributes(value.LastAccessTime,
- value.LastWriteTime,
+ return new SftpFileAttributes(value.LastAccessTimeUtc,
+ value.LastWriteTimeUtc,
value.Size,
value.UserId,
value.GroupId,
diff --git a/src/Renci.SshNet.Tests/Common/SftpFileAttributesBuilder.cs b/src/Renci.SshNet.Tests/Common/SftpFileAttributesBuilder.cs
index 1f2d33240..2cf1b11a8 100644
--- a/src/Renci.SshNet.Tests/Common/SftpFileAttributesBuilder.cs
+++ b/src/Renci.SshNet.Tests/Common/SftpFileAttributesBuilder.cs
@@ -64,9 +64,15 @@ public SftpFileAttributesBuilder WithExtension(string name, string value)
public SftpFileAttributes Build()
{
if (_lastAccessTime == null)
- _lastAccessTime = DateTime.MinValue;
+ _lastAccessTime = DateTime.SpecifyKind(DateTime.MinValue, DateTimeKind.Utc);
+ else if (_lastAccessTime.Value.Kind != DateTimeKind.Utc)
+ _lastAccessTime = _lastAccessTime.Value.ToUniversalTime();
+
if (_lastWriteTime == null)
- _lastWriteTime = DateTime.MinValue;
+ _lastWriteTime = DateTime.SpecifyKind(DateTime.MinValue, DateTimeKind.Utc);
+ else if (_lastWriteTime.Value.Kind != DateTimeKind.Utc)
+ _lastWriteTime = _lastWriteTime.Value.ToUniversalTime();
+
if (_size == null)
_size = 0;
if (_userId == null)
diff --git a/src/Renci.SshNet/Sftp/SftpFile.cs b/src/Renci.SshNet/Sftp/SftpFile.cs
index de729e130..cfcc37a2f 100644
--- a/src/Renci.SshNet/Sftp/SftpFile.cs
+++ b/src/Renci.SshNet/Sftp/SftpFile.cs
@@ -99,11 +99,11 @@ public DateTime LastAccessTimeUtc
{
get
{
- return Attributes.LastAccessTime.ToUniversalTime();
+ return Attributes.LastAccessTimeUtc;
}
set
{
- Attributes.LastAccessTime = value.ToLocalTime();
+ Attributes.LastAccessTimeUtc = value;
}
}
@@ -117,11 +117,11 @@ public DateTime LastWriteTimeUtc
{
get
{
- return Attributes.LastWriteTime.ToUniversalTime();
+ return Attributes.LastWriteTimeUtc;
}
set
{
- Attributes.LastWriteTime = value.ToLocalTime();
+ Attributes.LastWriteTimeUtc = value;
}
}
diff --git a/src/Renci.SshNet/Sftp/SftpFileAttributes.cs b/src/Renci.SshNet/Sftp/SftpFileAttributes.cs
index d99dfc2df..573deb92a 100644
--- a/src/Renci.SshNet/Sftp/SftpFileAttributes.cs
+++ b/src/Renci.SshNet/Sftp/SftpFileAttributes.cs
@@ -3,6 +3,7 @@
using System.Linq;
using System.Globalization;
using Renci.SshNet.Common;
+using System.Diagnostics;
namespace Renci.SshNet.Sftp
{
@@ -11,7 +12,7 @@ namespace Renci.SshNet.Sftp
///
public class SftpFileAttributes
{
- #region Bitmask constats
+ #region Bitmask constants
private const uint S_IFMT = 0xF000; // bitmask for the file type bitfields
@@ -60,8 +61,8 @@ public class SftpFileAttributes
private bool _isGroupIDBitSet;
private bool _isStickyBitSet;
- private readonly DateTime _originalLastAccessTime;
- private readonly DateTime _originalLastWriteTime;
+ private readonly DateTime _originalLastAccessTimeUtc;
+ private readonly DateTime _originalLastWriteTimeUtc;
private readonly long _originalSize;
private readonly int _originalUserId;
private readonly int _originalGroupId;
@@ -70,12 +71,12 @@ public class SftpFileAttributes
internal bool IsLastAccessTimeChanged
{
- get { return _originalLastAccessTime != LastAccessTime; }
+ get { return _originalLastAccessTimeUtc != LastAccessTimeUtc; }
}
internal bool IsLastWriteTimeChanged
{
- get { return _originalLastWriteTime != LastWriteTime; }
+ get { return _originalLastWriteTimeUtc != LastWriteTimeUtc; }
}
internal bool IsSizeChanged
@@ -104,20 +105,58 @@ internal bool IsExtensionsChanged
}
///
- /// Gets or sets the time the current file or directory was last accessed.
+ /// Gets or sets the local time the current file or directory was last accessed.
///
///
- /// The time that the current file or directory was last accessed.
+ /// The local time that the current file or directory was last accessed.
///
- public DateTime LastAccessTime { get; set; }
+ public DateTime LastAccessTime
+ {
+ get
+ {
+ return ToLocalTime(this.LastAccessTimeUtc);
+ }
+
+ set
+ {
+ this.LastAccessTimeUtc = ToUniversalTime(value);
+ }
+ }
+
+ ///
+ /// Gets or sets the local time when the current file or directory was last written to.
+ ///
+ ///
+ /// The local time the current file was last written.
+ ///
+ public DateTime LastWriteTime
+ {
+ get
+ {
+ return ToLocalTime(this.LastWriteTimeUtc);
+ }
+
+ set
+ {
+ this.LastWriteTimeUtc = ToUniversalTime(value);
+ }
+ }
+
+ ///
+ /// Gets or sets the UTC time the current file or directory was last accessed.
+ ///
+ ///
+ /// The UTC time that the current file or directory was last accessed.
+ ///
+ public DateTime LastAccessTimeUtc { get; set; }
///
- /// Gets or sets the time when the current file or directory was last written to.
+ /// Gets or sets the UTC time when the current file or directory was last written to.
///
///
- /// The time the current file was last written.
+ /// The UTC time the current file was last written.
///
- public DateTime LastWriteTime { get; set; }
+ public DateTime LastWriteTimeUtc { get; set; }
///
/// Gets or sets the size, in bytes, of the current file.
@@ -395,10 +434,10 @@ private SftpFileAttributes()
{
}
- internal SftpFileAttributes(DateTime lastAccessTime, DateTime lastWriteTime, long size, int userId, int groupId, uint permissions, IDictionary extensions)
+ internal SftpFileAttributes(DateTime lastAccessTimeUtc, DateTime lastWriteTimeUtc, long size, int userId, int groupId, uint permissions, IDictionary extensions)
{
- LastAccessTime = _originalLastAccessTime = lastAccessTime;
- LastWriteTime = _originalLastWriteTime = lastWriteTime;
+ LastAccessTimeUtc = _originalLastAccessTimeUtc = lastAccessTimeUtc;
+ LastWriteTimeUtc = _originalLastWriteTimeUtc = lastWriteTimeUtc;
Size = _originalSize = size;
UserId = _originalUserId = userId;
GroupId = _originalGroupId = groupId;
@@ -491,9 +530,9 @@ public byte[] GetBytes()
if (IsLastAccessTimeChanged || IsLastWriteTimeChanged)
{
- var time = (uint)(LastAccessTime.ToFileTime() / 10000000 - 11644473600);
+ var time = (uint)(LastAccessTimeUtc.ToFileTimeUtc() / 10000000 - 11644473600);
stream.Write(time);
- time = (uint)(LastWriteTime.ToFileTime() / 10000000 - 11644473600);
+ time = (uint)(LastWriteTimeUtc.ToFileTimeUtc() / 10000000 - 11644473600);
stream.Write(time);
}
@@ -521,8 +560,8 @@ internal static SftpFileAttributes FromBytes(SshDataStream stream)
var userId = -1;
var groupId = -1;
uint permissions = 0;
- var accessTime = DateTime.MinValue;
- var modifyTime = DateTime.MinValue;
+ DateTime accessTime;
+ DateTime modifyTime;
IDictionary extensions = null;
if ((flag & 0x00000001) == 0x00000001) // SSH_FILEXFER_ATTR_SIZE
@@ -544,10 +583,17 @@ internal static SftpFileAttributes FromBytes(SshDataStream stream)
if ((flag & 0x00000008) == 0x00000008) // SSH_FILEXFER_ATTR_ACMODTIME
{
+ // The incoming times are "Unix times", so they're already in UTC. We need to preserve that
+ // to avoid losing information in a local time conversion during the "fall back" hour in DST.
var time = stream.ReadUInt32();
- accessTime = DateTime.FromFileTime((time + 11644473600) * 10000000);
+ accessTime = DateTime.FromFileTimeUtc((time + 11644473600) * 10000000);
time = stream.ReadUInt32();
- modifyTime = DateTime.FromFileTime((time + 11644473600) * 10000000);
+ modifyTime = DateTime.FromFileTimeUtc((time + 11644473600) * 10000000);
+ }
+ else
+ {
+ accessTime = DateTime.SpecifyKind(DateTime.MinValue, DateTimeKind.Utc);
+ modifyTime = DateTime.SpecifyKind(DateTime.MinValue, DateTimeKind.Utc);
}
if ((flag & 0x80000000) == 0x80000000) // SSH_FILEXFER_ATTR_EXTENDED
@@ -572,5 +618,37 @@ internal static SftpFileAttributes FromBytes(byte[] buffer)
return FromBytes(stream);
}
}
+
+ private static DateTime ToLocalTime(DateTime value)
+ {
+ DateTime result;
+
+ if (value == DateTime.MinValue)
+ {
+ result = DateTime.SpecifyKind(DateTime.MinValue, DateTimeKind.Local);
+ }
+ else
+ {
+ result = value.ToLocalTime();
+ }
+
+ return result;
+ }
+
+ private static DateTime ToUniversalTime(DateTime value)
+ {
+ DateTime result;
+
+ if (value == DateTime.MinValue)
+ {
+ result = DateTime.SpecifyKind(DateTime.MinValue, DateTimeKind.Utc);
+ }
+ else
+ {
+ result = value.ToUniversalTime();
+ }
+
+ return result;
+ }
}
}