Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit cc4abca

Browse files
authored
Dial back \\?\ insertion (#27827)
Only premptively adding for FileSystemInfo if we end in period or space. Long path is taken care of later. Clean up code a little and add test for DirectoryInfo.Move.
1 parent 98a173b commit cc4abca

File tree

4 files changed

+71
-53
lines changed

4 files changed

+71
-53
lines changed

src/Common/src/CoreLib/System/IO/PathInternal.Windows.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ internal static bool IsValidDriveChar(char value)
7070
return ((value >= 'A' && value <= 'Z') || (value >= 'a' && value <= 'z'));
7171
}
7272

73-
private static bool EndsWithPeriodOrSpace(string path)
73+
internal static bool EndsWithPeriodOrSpace(string path)
7474
{
7575
if (string.IsNullOrEmpty(path))
7676
return false;

src/System.IO.FileSystem/src/System/IO/FileSystemInfo.Windows.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ partial class FileSystemInfo
1414

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

@@ -153,6 +153,7 @@ public void Refresh()
153153

154154
// If we're opened around a enumerated path that ends in a period or space we need to be able to
155155
// act on the path normally (open streams/writers/etc.)
156-
internal string NormalizedPath => PathInternal.EnsureExtendedPrefixIfNeeded(FullPath);
156+
internal string NormalizedPath
157+
=> PathInternal.EndsWithPeriodOrSpace(FullPath) ? PathInternal.EnsureExtendedPrefix(FullPath) : FullPath;
157158
}
158159
}

src/System.IO.FileSystem/src/System/IO/FileSystemInfo.cs

Lines changed: 12 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ public string Extension
3131
{
3232
get
3333
{
34-
// GetFullPathInternal would have already stripped out the terminating "." if present.
3534
int length = FullPath.Length;
3635
for (int i = length; --i >= 0;)
3736
{
@@ -68,76 +67,39 @@ public virtual bool Exists
6867

6968
public DateTime CreationTime
7069
{
71-
get
72-
{
73-
// depends on the security check in get_CreationTimeUtc
74-
return CreationTimeUtc.ToLocalTime();
75-
}
76-
set
77-
{
78-
CreationTimeUtc = value.ToUniversalTime();
79-
}
70+
get => CreationTimeUtc.ToLocalTime();
71+
set => CreationTimeUtc = value.ToUniversalTime();
8072
}
8173

8274
public DateTime CreationTimeUtc
8375
{
84-
get
85-
{
86-
return CreationTimeCore.UtcDateTime;
87-
}
88-
set
89-
{
90-
CreationTimeCore = File.GetUtcDateTimeOffset(value);
91-
}
76+
get => CreationTimeCore.UtcDateTime;
77+
set => CreationTimeCore = File.GetUtcDateTimeOffset(value);
9278
}
9379

9480

9581
public DateTime LastAccessTime
9682
{
97-
get
98-
{
99-
return LastAccessTimeUtc.ToLocalTime();
100-
}
101-
set
102-
{
103-
LastAccessTimeUtc = value.ToUniversalTime();
104-
}
83+
get => LastAccessTimeUtc.ToLocalTime();
84+
set => LastAccessTimeUtc = value.ToUniversalTime();
10585
}
10686

10787
public DateTime LastAccessTimeUtc
10888
{
109-
get
110-
{
111-
return LastAccessTimeCore.UtcDateTime;
112-
}
113-
set
114-
{
115-
LastAccessTimeCore = File.GetUtcDateTimeOffset(value);
116-
}
89+
get => LastAccessTimeCore.UtcDateTime;
90+
set => LastAccessTimeCore = File.GetUtcDateTimeOffset(value);
11791
}
11892

11993
public DateTime LastWriteTime
12094
{
121-
get
122-
{
123-
return LastWriteTimeUtc.ToLocalTime();
124-
}
125-
set
126-
{
127-
LastWriteTimeUtc = value.ToUniversalTime();
128-
}
95+
get => LastWriteTimeUtc.ToLocalTime();
96+
set => LastWriteTimeUtc = value.ToUniversalTime();
12997
}
13098

13199
public DateTime LastWriteTimeUtc
132100
{
133-
get
134-
{
135-
return LastWriteTimeCore.UtcDateTime;
136-
}
137-
set
138-
{
139-
LastWriteTimeCore = File.GetUtcDateTimeOffset(value);
140-
}
101+
get => LastWriteTimeCore.UtcDateTime;
102+
set => LastWriteTimeCore = File.GetUtcDateTimeOffset(value);
141103
}
142104

143105
/// <summary>

src/System.IO.FileSystem/tests/Enumeration/TrimmedPaths.netcoreapp.cs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,5 +225,60 @@ public void TrimmedPathsReplace_Windows()
225225
}
226226
}
227227
}
228+
229+
[Fact]
230+
[PlatformSpecific(TestPlatforms.Windows)]
231+
public void TrimmedPathsMoveTo_Windows()
232+
{
233+
// Trailing spaces and periods are eaten when normalizing in Windows, making them impossible
234+
// to access without using the \\?\ device syntax. We should, however, be able to move them
235+
// without the special syntax from the info class when enumerating.
236+
237+
DirectoryInfo directory = Directory.CreateDirectory(GetTestFilePath());
238+
DirectoryInfo spaceDirectory = Directory.CreateDirectory(Path.Join(@"\\?\", directory.FullName, "Trailing space "));
239+
DirectoryInfo periodDirectory = Directory.CreateDirectory(Path.Join(@"\\?\", directory.FullName, "Trailing period."));
240+
string spaceFile = Path.Join(spaceDirectory.FullName, "space");
241+
string periodFile = Path.Join(periodDirectory.FullName, "period");
242+
File.Create(spaceFile).Dispose();
243+
File.Create(periodFile).Dispose();
244+
245+
DirectoryInfo[] directories = directory.GetDirectories();
246+
Assert.Equal(2, directories.Length);
247+
foreach (DirectoryInfo di in directories)
248+
{
249+
if (di.Name == "Trailing space ")
250+
{
251+
di.MoveTo(Path.Join(directory.FullName, "WasSpace"));
252+
}
253+
else if (di.Name == "Trailing period.")
254+
{
255+
di.MoveTo(Path.Join(directory.FullName, "WasPeriod"));
256+
}
257+
else
258+
{
259+
Assert.False(true, $"Found unexpected name '{di.Name}'");
260+
}
261+
}
262+
263+
directories = directory.GetDirectories();
264+
Assert.Equal(2, directories.Length);
265+
foreach (DirectoryInfo di in directories)
266+
{
267+
if (di.Name == "WasSpace")
268+
{
269+
FileInfo fi = di.GetFiles().Single();
270+
Assert.Equal("space", fi.Name);
271+
}
272+
else if (di.Name == "WasPeriod")
273+
{
274+
FileInfo fi = di.GetFiles().Single();
275+
Assert.Equal("period", fi.Name);
276+
}
277+
else
278+
{
279+
Assert.False(true, $"Found unexpected name '{di.Name}'");
280+
}
281+
}
282+
}
228283
}
229284
}

0 commit comments

Comments
 (0)