Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/corefx.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteve Pfister <steveisok@users.noreply.github.com>2019-12-09 16:01:47 +0300
committerGitHub <noreply@github.com>2019-12-09 16:01:47 +0300
commitf3815a94011e12cbce7ce2e41328f5faa54cad0e (patch)
tree5e5d6cc9379c762731e6da92fd495a541e71df99
parent5951d0ebe97b523b7110d93c250c062c952201d1 (diff)
Backport FixPathLength 255 PR
Fixes https://github.com/mono/mono/issues/17948 Pulled in upstream change https://github.com/dotnet/corefx/pull/34389
-rw-r--r--src/Common/src/CoreLib/Interop/Unix/System.Native/Interop.ReadDir.cs10
-rw-r--r--src/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemEntry.Unix.cs7
-rw-r--r--src/System.IO.FileSystem/tests/Enumeration/ErrorHandlingTests.netcoreapp.cs37
-rw-r--r--src/System.IO.FileSystem/tests/File/Create.cs27
-rw-r--r--src/System.IO.FileSystem/tests/FileStream/LockUnlock.cs2
5 files changed, 73 insertions, 10 deletions
diff --git a/src/Common/src/CoreLib/Interop/Unix/System.Native/Interop.ReadDir.cs b/src/Common/src/CoreLib/Interop/Unix/System.Native/Interop.ReadDir.cs
index 9e32f1ccc2..5888c80fbc 100644
--- a/src/Common/src/CoreLib/Interop/Unix/System.Native/Interop.ReadDir.cs
+++ b/src/Common/src/CoreLib/Interop/Unix/System.Native/Interop.ReadDir.cs
@@ -30,21 +30,21 @@ internal static partial class Interop
internal byte* Name;
internal int NameLength;
internal NodeType InodeType;
- internal const int NameBufferSize = 256;
+ internal const int NameBufferSize = 256; // sizeof(dirent->d_name) == NAME_MAX + 1
internal ReadOnlySpan<char> GetName(Span<char> buffer)
{
- Debug.Assert(buffer.Length >= Encoding.UTF8.GetMaxCharCount(NameBufferSize - 1), "should have enough space for the max file name");
+ // -1 for null terminator (buffer will not include one),
+ // and -1 because GetMaxCharCount pessimistically assumes the buffer may start with a partial surrogate
+ Debug.Assert(buffer.Length >= Encoding.UTF8.GetMaxCharCount(NameBufferSize - 1 - 1));
Debug.Assert(Name != null, "should not have a null name");
ReadOnlySpan<byte> nameBytes = (NameLength == -1)
// In this case the struct was allocated via struct dirent *readdir(DIR *dirp);
- ? new ReadOnlySpan<byte>(Name, new ReadOnlySpan<byte>(Name, NameBufferSize - 1).IndexOf<byte>(0))
+ ? new ReadOnlySpan<byte>(Name, new ReadOnlySpan<byte>(Name, NameBufferSize).IndexOf<byte>(0))
: new ReadOnlySpan<byte>(Name, NameLength);
Debug.Assert(nameBytes.Length > 0, "we shouldn't have gotten a garbage value from the OS");
- if (nameBytes.Length == 0)
- return buffer.Slice(0, 0);
int charCount = Encoding.UTF8.GetChars(nameBytes, buffer);
ReadOnlySpan<char> value = buffer.Slice(0, charCount);
diff --git a/src/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemEntry.Unix.cs b/src/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemEntry.Unix.cs
index 1139d2f3f5..728275bf95 100644
--- a/src/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemEntry.Unix.cs
+++ b/src/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemEntry.Unix.cs
@@ -10,14 +10,13 @@ namespace System.IO.Enumeration
/// Lower level view of FileSystemInfo used for processing and filtering find results.
/// </summary>
public unsafe ref partial struct FileSystemEntry
- {
- private const int FileNameBufferSize = 256;
+ {
internal Interop.Sys.DirectoryEntry _directoryEntry;
private FileStatus _status;
private Span<char> _pathBuffer;
private ReadOnlySpan<char> _fullPath;
private ReadOnlySpan<char> _fileName;
- private fixed char _fileNameBuffer[FileNameBufferSize];
+ private fixed char _fileNameBuffer[Interop.Sys.DirectoryEntry.NameBufferSize];
private FileAttributes _initialAttributes;
internal static FileAttributes Initialize(
@@ -112,7 +111,7 @@ namespace System.IO.Enumeration
{
fixed (char* c = _fileNameBuffer)
{
- Span<char> buffer = new Span<char>(c, FileNameBufferSize);
+ Span<char> buffer = new Span<char>(c, Interop.Sys.DirectoryEntry.NameBufferSize);
_fileName = _directoryEntry.GetName(buffer);
}
}
diff --git a/src/System.IO.FileSystem/tests/Enumeration/ErrorHandlingTests.netcoreapp.cs b/src/System.IO.FileSystem/tests/Enumeration/ErrorHandlingTests.netcoreapp.cs
index e4c85d831e..60bc3d9224 100644
--- a/src/System.IO.FileSystem/tests/Enumeration/ErrorHandlingTests.netcoreapp.cs
+++ b/src/System.IO.FileSystem/tests/Enumeration/ErrorHandlingTests.netcoreapp.cs
@@ -2,6 +2,9 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
+using System;
+using System.Collections.Generic;
+using System.Linq;
using System.IO.Enumeration;
using Xunit;
@@ -96,5 +99,39 @@ namespace System.IO.Tests
Assert.Equal(info.FullName, ie.DirectoryFinished);
}
}
+
+ [Fact]
+ public void VariableLengthFileNames_AllCreatableFilesAreEnumerable()
+ {
+ DirectoryInfo testDirectory = Directory.CreateDirectory(GetTestFilePath());
+ var names = new List<string>();
+
+ for (int length = 1; length < 10_000; length++) // arbitrarily large limit for the test
+ {
+ string name = new string('a', length);
+ try { File.Create(Path.Join(testDirectory.FullName, name)).Dispose(); }
+ catch { break; }
+ names.Add(name);
+ }
+ Assert.InRange(names.Count, 1, int.MaxValue);
+ Assert.Equal(names.OrderBy(n => n), Directory.GetFiles(testDirectory.FullName).Select(n => Path.GetFileName(n)).OrderBy(n => n));
+ }
+
+ [Fact]
+ public void VariableLengthDirectoryNames_AllCreatableDirectoriesAreEnumerable()
+ {
+ DirectoryInfo testDirectory = Directory.CreateDirectory(GetTestFilePath());
+ var names = new List<string>();
+
+ for (int length = 1; length < 10_000; length++) // arbitrarily large limit for the test
+ {
+ string name = new string('a', length);
+ try { Directory.CreateDirectory(Path.Join(testDirectory.FullName, name)); }
+ catch { break; }
+ names.Add(name);
+ }
+ Assert.InRange(names.Count, 1, int.MaxValue);
+ Assert.Equal(names.OrderBy(n => n), Directory.GetDirectories(testDirectory.FullName).Select(n => Path.GetFileName(n)).OrderBy(n => n));
+ }
}
}
diff --git a/src/System.IO.FileSystem/tests/File/Create.cs b/src/System.IO.FileSystem/tests/File/Create.cs
index c910e735b3..be16528e76 100644
--- a/src/System.IO.FileSystem/tests/File/Create.cs
+++ b/src/System.IO.FileSystem/tests/File/Create.cs
@@ -169,6 +169,33 @@ namespace System.IO.Tests
#region PlatformSpecific
[Fact]
+ [PlatformSpecific(TestPlatforms.AnyUnix)]
+ public void LongDirectoryName()
+ {
+ // 255 = NAME_MAX on Linux and macOS
+ DirectoryInfo path = Directory.CreateDirectory(Path.Combine(GetTestFilePath(), new string('a', 255)));
+
+ Assert.True(Directory.Exists(path.FullName));
+ Directory.Delete(path.FullName);
+ Assert.False(Directory.Exists(path.FullName));
+ }
+
+ [Fact]
+ [PlatformSpecific(TestPlatforms.AnyUnix)]
+ public void LongFileName()
+ {
+ // 255 = NAME_MAX on Linux and macOS
+ var dir = GetTestFilePath();
+ Directory.CreateDirectory(dir);
+ var path = Path.Combine(dir, new string('b', 255));
+ File.Create(path).Dispose();
+
+ Assert.True(File.Exists(path));
+ File.Delete(path);
+ Assert.False(File.Exists(path));
+ }
+
+ [Fact]
[PlatformSpecific(CaseSensitivePlatforms)]
public void CaseSensitive()
{
diff --git a/src/System.IO.FileSystem/tests/FileStream/LockUnlock.cs b/src/System.IO.FileSystem/tests/FileStream/LockUnlock.cs
index 2d7207e8d5..68e7a56336 100644
--- a/src/System.IO.FileSystem/tests/FileStream/LockUnlock.cs
+++ b/src/System.IO.FileSystem/tests/FileStream/LockUnlock.cs
@@ -153,7 +153,7 @@ namespace System.IO.Tests
}
}
- [Theory]
+ [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNotWindowsSubsystemForLinux))] // https://github.com/dotnet/corefx/issues/34397
[InlineData(10, 0, 10, 1, 2)]
[InlineData(10, 3, 5, 3, 5)]
[InlineData(10, 3, 5, 3, 4)]