Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/Common/src/CoreLib/System/IO/PathInternal.Windows.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ internal static bool IsValidDriveChar(char value)
return ((value >= 'A' && value <= 'Z') || (value >= 'a' && value <= 'z'));
}

private static bool EndsWithPeriodOrSpace(string path)
internal static bool EndsWithPeriodOrSpace(string path)
{
if (string.IsNullOrEmpty(path))
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ partial class FileSystemInfo

// Cache any error retrieving the file/directory information
// We use this field in conjunction with the Refresh method which should never throw.
// If we succeed we store a zero, on failure we store the HResult so that we can
// If we succeed we store a zero, on failure we store the error code so that we can
// throw an appropriate error when attempting to access the cached info.
private int _dataInitialized = -1;

Expand Down Expand Up @@ -153,6 +153,7 @@ public void Refresh()

// If we're opened around a enumerated path that ends in a period or space we need to be able to
// act on the path normally (open streams/writers/etc.)
internal string NormalizedPath => PathInternal.EnsureExtendedPrefixIfNeeded(FullPath);
internal string NormalizedPath
=> PathInternal.EndsWithPeriodOrSpace(FullPath) ? PathInternal.EnsureExtendedPrefix(FullPath) : FullPath;
}
}
62 changes: 12 additions & 50 deletions src/System.IO.FileSystem/src/System/IO/FileSystemInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ public string Extension
{
get
{
// GetFullPathInternal would have already stripped out the terminating "." if present.
int length = FullPath.Length;
for (int i = length; --i >= 0;)
{
Expand Down Expand Up @@ -68,76 +67,39 @@ public virtual bool Exists

public DateTime CreationTime
{
get
{
// depends on the security check in get_CreationTimeUtc
return CreationTimeUtc.ToLocalTime();
}
set
{
CreationTimeUtc = value.ToUniversalTime();
}
get => CreationTimeUtc.ToLocalTime();
set => CreationTimeUtc = value.ToUniversalTime();
}

public DateTime CreationTimeUtc
{
get
{
return CreationTimeCore.UtcDateTime;
}
set
{
CreationTimeCore = File.GetUtcDateTimeOffset(value);
}
get => CreationTimeCore.UtcDateTime;
set => CreationTimeCore = File.GetUtcDateTimeOffset(value);
}


public DateTime LastAccessTime
{
get
{
return LastAccessTimeUtc.ToLocalTime();
}
set
{
LastAccessTimeUtc = value.ToUniversalTime();
}
get => LastAccessTimeUtc.ToLocalTime();
set => LastAccessTimeUtc = value.ToUniversalTime();
}

public DateTime LastAccessTimeUtc
{
get
{
return LastAccessTimeCore.UtcDateTime;
}
set
{
LastAccessTimeCore = File.GetUtcDateTimeOffset(value);
}
get => LastAccessTimeCore.UtcDateTime;
set => LastAccessTimeCore = File.GetUtcDateTimeOffset(value);
}

public DateTime LastWriteTime
{
get
{
return LastWriteTimeUtc.ToLocalTime();
}
set
{
LastWriteTimeUtc = value.ToUniversalTime();
}
get => LastWriteTimeUtc.ToLocalTime();
set => LastWriteTimeUtc = value.ToUniversalTime();
}

public DateTime LastWriteTimeUtc
{
get
{
return LastWriteTimeCore.UtcDateTime;
}
set
{
LastWriteTimeCore = File.GetUtcDateTimeOffset(value);
}
get => LastWriteTimeCore.UtcDateTime;
set => LastWriteTimeCore = File.GetUtcDateTimeOffset(value);
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -225,5 +225,60 @@ public void TrimmedPathsReplace_Windows()
}
}
}

[Fact]
[PlatformSpecific(TestPlatforms.Windows)]
public void TrimmedPathsMoveTo_Windows()
{
// Trailing spaces and periods are eaten when normalizing in Windows, making them impossible
// to access without using the \\?\ device syntax. We should, however, be able to move them
// without the special syntax from the info class when enumerating.

DirectoryInfo directory = Directory.CreateDirectory(GetTestFilePath());
DirectoryInfo spaceDirectory = Directory.CreateDirectory(Path.Join(@"\\?\", directory.FullName, "Trailing space "));
DirectoryInfo periodDirectory = Directory.CreateDirectory(Path.Join(@"\\?\", directory.FullName, "Trailing period."));
string spaceFile = Path.Join(spaceDirectory.FullName, "space");
string periodFile = Path.Join(periodDirectory.FullName, "period");
File.Create(spaceFile).Dispose();
File.Create(periodFile).Dispose();

DirectoryInfo[] directories = directory.GetDirectories();
Assert.Equal(2, directories.Length);
foreach (DirectoryInfo di in directories)
{
if (di.Name == "Trailing space ")
{
di.MoveTo(Path.Join(directory.FullName, "WasSpace"));
}
else if (di.Name == "Trailing period.")
{
di.MoveTo(Path.Join(directory.FullName, "WasPeriod"));
}
else
{
Assert.False(true, $"Found unexpected name '{di.Name}'");
}
}

directories = directory.GetDirectories();
Assert.Equal(2, directories.Length);
foreach (DirectoryInfo di in directories)
{
if (di.Name == "WasSpace")
{
FileInfo fi = di.GetFiles().Single();
Assert.Equal("space", fi.Name);
}
else if (di.Name == "WasPeriod")
{
FileInfo fi = di.GetFiles().Single();
Assert.Equal("period", fi.Name);
}
else
{
Assert.False(true, $"Found unexpected name '{di.Name}'");
}
}
}
}
}