You've already forked linux-packaging-mono
Imported Upstream version 6.8.0.73
Former-commit-id: d18deab1b47cfd3ad8cba82b3f37d00eec2170af
This commit is contained in:
parent
bceda29824
commit
73ee7591e8
@@ -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);
|
||||
|
@@ -33,6 +33,7 @@ internal static partial class Interop
|
||||
internal long BirthTimeNsec;
|
||||
internal long Dev;
|
||||
internal long Ino;
|
||||
internal uint UserFlags;
|
||||
}
|
||||
|
||||
internal static class FileTypes
|
||||
|
26
external/corefx/src/Common/src/Interop/Unix/System.Native/Interop.LChflags.cs
vendored
Normal file
26
external/corefx/src/Common/src/Interop/Unix/System.Native/Interop.LChflags.cs
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// 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.Runtime.InteropServices;
|
||||
|
||||
internal static partial class Interop
|
||||
{
|
||||
internal static partial class Sys
|
||||
{
|
||||
[Flags]
|
||||
internal enum UserFlags : uint
|
||||
{
|
||||
UF_HIDDEN = 0x8000
|
||||
}
|
||||
|
||||
[DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_LChflags", SetLastError = true)]
|
||||
internal static extern int LChflags(string path, uint flags);
|
||||
|
||||
internal static readonly bool CanSetHiddenFlag = (LChflagsCanSetHiddenFlag() != 0);
|
||||
|
||||
[DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_LChflagsCanSetHiddenFlag")]
|
||||
private static extern int LChflagsCanSetHiddenFlag();
|
||||
}
|
||||
}
|
@@ -33,6 +33,7 @@ internal static partial class Interop
|
||||
internal long BirthTimeNsec;
|
||||
internal long Dev;
|
||||
internal long Ino;
|
||||
internal uint UserFlags;
|
||||
}
|
||||
|
||||
internal static class FileTypes
|
||||
|
@@ -16,6 +16,8 @@
|
||||
#cmakedefine01 HAVE_STAT_TIMESPEC
|
||||
#cmakedefine01 HAVE_STAT_TIM
|
||||
#cmakedefine01 HAVE_STAT_NSEC
|
||||
#cmakedefine01 HAVE_STAT_FLAGS
|
||||
#cmakedefine01 HAVE_LCHFLAGS
|
||||
#cmakedefine01 HAVE_GNU_STRERROR_R
|
||||
#cmakedefine01 HAVE_READDIR_R
|
||||
#cmakedefine01 HAVE_DIRENT_NAME_LEN
|
||||
|
@@ -166,6 +166,12 @@ static void ConvertFileStatus(const struct stat_* src, struct FileStatus* dst)
|
||||
dst->BirthTime = 0;
|
||||
dst->BirthTimeNsec = 0;
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_STAT_FLAGS) && defined(UF_HIDDEN)
|
||||
dst->UserFlags = ((src->st_flags & UF_HIDDEN) == UF_HIDDEN) ? PAL_UF_HIDDEN : 0;
|
||||
#else
|
||||
dst->UserFlags = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
// CoreCLR expects the "2" suffixes on these: they should be cleaned up in our
|
||||
@@ -1460,6 +1466,28 @@ int32_t SystemNative_LockFileRegion(intptr_t fd, int64_t offset, int64_t length,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t SystemNative_LChflags(const char* path, uint32_t flags)
|
||||
{
|
||||
#if HAVE_LCHFLAGS
|
||||
int32_t result;
|
||||
while ((result = lchflags(path, flags)) < 0 && errno == EINTR);
|
||||
return result;
|
||||
#else
|
||||
(void)path, (void)flags;
|
||||
errno = ENOTSUP;
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
int32_t SystemNative_LChflagsCanSetHiddenFlag(void)
|
||||
{
|
||||
#if defined(UF_HIDDEN) && defined(HAVE_STAT_FLAGS) && defined(HAVE_LCHFLAGS)
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
int32_t SystemNative_Symlink(const char* target, const char* linkPath)
|
||||
{
|
||||
return symlink(target, linkPath);
|
||||
|
@@ -35,6 +35,7 @@ struct FileStatus
|
||||
int64_t BirthTimeNsec; // nanosecond part
|
||||
int64_t Dev; // ID of the device containing the file
|
||||
int64_t Ino; // inode number of the file
|
||||
uint32_t UserFlags; // user defined flags
|
||||
};
|
||||
|
||||
/* Provide consistent access to nanosecond fields, if they exist. */
|
||||
@@ -153,6 +154,14 @@ enum
|
||||
FILESTATUS_FLAGS_HAS_BIRTHTIME = 1,
|
||||
};
|
||||
|
||||
/**
|
||||
* Constants for interpreting FileStatus.UserFlags.
|
||||
*/
|
||||
enum
|
||||
{
|
||||
PAL_UF_HIDDEN = 0x8000
|
||||
};
|
||||
|
||||
/**
|
||||
* Constants from dirent.h for the inode type returned from readdir variants
|
||||
*/
|
||||
@@ -750,6 +759,20 @@ DLLEXPORT int32_t SystemNative_GetPeerID(intptr_t socket, uid_t* euid);
|
||||
*/
|
||||
DLLEXPORT int32_t SystemNative_LockFileRegion(intptr_t fd, int64_t offset, int64_t length, int16_t lockType);
|
||||
|
||||
/**
|
||||
* Changes the file flags of the file whose location is specified in path
|
||||
*
|
||||
* Returns 0 for success, -1 for failure. Sets errno for failure.
|
||||
*/
|
||||
DLLEXPORT int32_t SystemNative_LChflags(const char* path, uint32_t flags);
|
||||
|
||||
/**
|
||||
* Determines if the current platform supports setting UF_HIDDEN (0x8000) flag
|
||||
*
|
||||
* Returns true (non-zero) if supported, false (zero) if not.
|
||||
*/
|
||||
DLLEXPORT int32_t SystemNative_LChflagsCanSetHiddenFlag(void);
|
||||
|
||||
/**
|
||||
* Creates a symbolic link at "linkPath", pointing at "target".
|
||||
* "target" may or may not exist (dangling symbolic links are valid filesystem objects)
|
||||
|
@@ -284,6 +284,9 @@
|
||||
<Compile Include="$(CommonPath)\Interop\Unix\System.Native\Interop.Read.cs">
|
||||
<Link>Common\Interop\Unix\Interop.Read.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\Interop\Unix\System.Native\Interop.LChflags.cs">
|
||||
<Link>Common\Interop\Unix\Interop.LChflags.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\Interop\Unix\System.Native\Interop.Rename.cs">
|
||||
<Link>Common\Interop\Unix\Interop.Rename.cs</Link>
|
||||
</Compile>
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
@@ -84,8 +84,8 @@ namespace System.IO
|
||||
if (_isDirectory)
|
||||
attributes |= FileAttributes.Directory;
|
||||
|
||||
// If the filename starts with a period, it's hidden.
|
||||
if (fileName.Length > 0 && fileName[0] == '.')
|
||||
// If the filename starts with a period or has UF_HIDDEN flag set, it's hidden.
|
||||
if (fileName.Length > 0 && (fileName[0] == '.' || (_fileStatus.UserFlags & (uint)Interop.Sys.UserFlags.UF_HIDDEN) == (uint)Interop.Sys.UserFlags.UF_HIDDEN))
|
||||
attributes |= FileAttributes.Hidden;
|
||||
|
||||
return attributes != default ? attributes : FileAttributes.Normal;
|
||||
@@ -98,10 +98,10 @@ namespace System.IO
|
||||
const FileAttributes allValidFlags =
|
||||
FileAttributes.Archive | FileAttributes.Compressed | FileAttributes.Device |
|
||||
FileAttributes.Directory | FileAttributes.Encrypted | FileAttributes.Hidden |
|
||||
FileAttributes.Hidden | FileAttributes.IntegrityStream | FileAttributes.Normal |
|
||||
FileAttributes.NoScrubData | FileAttributes.NotContentIndexed | FileAttributes.Offline |
|
||||
FileAttributes.ReadOnly | FileAttributes.ReparsePoint | FileAttributes.SparseFile |
|
||||
FileAttributes.System | FileAttributes.Temporary;
|
||||
FileAttributes.IntegrityStream | FileAttributes.Normal | FileAttributes.NoScrubData |
|
||||
FileAttributes.NotContentIndexed | FileAttributes.Offline | FileAttributes.ReadOnly |
|
||||
FileAttributes.ReparsePoint | FileAttributes.SparseFile | FileAttributes.System |
|
||||
FileAttributes.Temporary;
|
||||
if ((attributes & ~allValidFlags) != 0)
|
||||
{
|
||||
// Using constant string for argument to match historical throw
|
||||
@@ -113,6 +113,26 @@ namespace System.IO
|
||||
if (!_exists)
|
||||
FileSystemInfo.ThrowNotFound(path);
|
||||
|
||||
if (Interop.Sys.CanSetHiddenFlag)
|
||||
{
|
||||
if ((attributes & FileAttributes.Hidden) != 0)
|
||||
{
|
||||
if ((_fileStatus.UserFlags & (uint)Interop.Sys.UserFlags.UF_HIDDEN) == 0)
|
||||
{
|
||||
// If Hidden flag is set and cached file status does not have the flag set then set it
|
||||
Interop.CheckIo(Interop.Sys.LChflags(path, (_fileStatus.UserFlags | (uint)Interop.Sys.UserFlags.UF_HIDDEN)), path, InitiallyDirectory);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((_fileStatus.UserFlags & (uint)Interop.Sys.UserFlags.UF_HIDDEN) == (uint)Interop.Sys.UserFlags.UF_HIDDEN)
|
||||
{
|
||||
// If Hidden flag is not set and cached file status does have the flag set then remove it
|
||||
Interop.CheckIo(Interop.Sys.LChflags(path, (_fileStatus.UserFlags & ~(uint)Interop.Sys.UserFlags.UF_HIDDEN)), path, InitiallyDirectory);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The only thing we can reasonably change is whether the file object is readonly by changing permissions.
|
||||
|
||||
int newMode = _fileStatus.Mode;
|
||||
|
@@ -16,9 +16,16 @@ namespace System.IO.Tests
|
||||
public void SettingAttributes_Unix(FileAttributes attributes)
|
||||
{
|
||||
string path = CreateItem();
|
||||
SetAttributes(path, attributes);
|
||||
Assert.Equal(attributes, GetAttributes(path));
|
||||
SetAttributes(path, 0);
|
||||
AssertSettingAttributes(path, attributes);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(FileAttributes.Hidden)]
|
||||
[PlatformSpecific(TestPlatforms.OSX | TestPlatforms.FreeBSD)]
|
||||
public void SettingAttributes_OSXAndFreeBSD(FileAttributes attributes)
|
||||
{
|
||||
string path = CreateItem();
|
||||
AssertSettingAttributes(path, attributes);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
@@ -33,6 +40,11 @@ namespace System.IO.Tests
|
||||
public void SettingAttributes_Windows(FileAttributes attributes)
|
||||
{
|
||||
string path = CreateItem();
|
||||
AssertSettingAttributes(path, attributes);
|
||||
}
|
||||
|
||||
private void AssertSettingAttributes(string path, FileAttributes attributes)
|
||||
{
|
||||
SetAttributes(path, attributes);
|
||||
Assert.Equal(attributes, GetAttributes(path));
|
||||
SetAttributes(path, 0);
|
||||
@@ -48,8 +60,16 @@ namespace System.IO.Tests
|
||||
public void SettingInvalidAttributes_Unix(FileAttributes attributes)
|
||||
{
|
||||
string path = CreateItem();
|
||||
SetAttributes(path, attributes);
|
||||
Assert.Equal(FileAttributes.Normal, GetAttributes(path));
|
||||
AssertSettingInvalidAttributes(path, attributes);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(FileAttributes.Hidden)]
|
||||
[PlatformSpecific(TestPlatforms.AnyUnix & ~(TestPlatforms.OSX | TestPlatforms.FreeBSD))]
|
||||
public void SettingInvalidAttributes_UnixExceptOSXAndFreeBSD(FileAttributes attributes)
|
||||
{
|
||||
string path = CreateItem();
|
||||
AssertSettingInvalidAttributes(path, attributes);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
@@ -62,6 +82,11 @@ namespace System.IO.Tests
|
||||
public void SettingInvalidAttributes_Windows(FileAttributes attributes)
|
||||
{
|
||||
string path = CreateItem();
|
||||
AssertSettingInvalidAttributes(path, attributes);
|
||||
}
|
||||
|
||||
private void AssertSettingInvalidAttributes(string path, FileAttributes attributes)
|
||||
{
|
||||
SetAttributes(path, attributes);
|
||||
Assert.Equal(FileAttributes.Normal, GetAttributes(path));
|
||||
}
|
||||
|
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -168,6 +168,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()
|
||||
|
@@ -28,5 +28,18 @@ namespace System.IO.Tests
|
||||
test.Refresh();
|
||||
Assert.Equal(false, test.IsReadOnly);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(".", true)]
|
||||
[InlineData("", false)]
|
||||
[PlatformSpecific(TestPlatforms.OSX)]
|
||||
public void HiddenAttributeSetCorrectly_OSX(string filePrefix, bool hidden)
|
||||
{
|
||||
string testFilePath = Path.Combine(TestDirectory, $"{filePrefix}{GetTestFileName()}");
|
||||
FileInfo fileInfo = new FileInfo(testFilePath);
|
||||
fileInfo.Create().Dispose();
|
||||
|
||||
Assert.Equal(hidden, (fileInfo.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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)]
|
||||
|
@@ -31,9 +31,15 @@ namespace System.Linq.Parallel
|
||||
// Whether to preserve order by default, when neither AsOrdered nor AsUnordered is used.
|
||||
internal const bool DefaultPreserveOrder = false;
|
||||
|
||||
#if MONO
|
||||
// By default limit to degree of 16 to avoid too much contention. It's
|
||||
// still possible to override that to a maximum of MAX_SUPPORTED_DOP.
|
||||
internal static int DefaultDegreeOfParallelism = Math.Min(Environment.ProcessorCount, 16);
|
||||
#else
|
||||
// The default degree of parallelism, or -1 if unspecified. Dev unit tests set this value
|
||||
// to change the default DOP.
|
||||
internal static int DefaultDegreeOfParallelism = Math.Min(Environment.ProcessorCount, MAX_SUPPORTED_DOP);
|
||||
#endif
|
||||
|
||||
// The size to use for bounded buffers.
|
||||
internal const int DEFAULT_BOUNDED_BUFFER_CAPACITY = 512;
|
||||
|
@@ -13,8 +13,17 @@ namespace System.Net.Http.Headers
|
||||
{
|
||||
private UriKind _uriKind;
|
||||
|
||||
#if MONO
|
||||
// FIXME: Workaround for https://github.com/mono/mono/issues/17897.
|
||||
// This is the same as setting the MONO_URI_DOTNETRELATIVEORABSOLUTE=true
|
||||
// environment variable.
|
||||
// See https://github.com/mono/mono/blob/1454b010ae1165a0f2cf261b9420e32d1b52fdaf/mcs/class/referencesource/System/net/System/URI.cs#L991.
|
||||
internal static readonly UriHeaderParser RelativeOrAbsoluteUriParser =
|
||||
new UriHeaderParser((UriKind)300);
|
||||
#else
|
||||
internal static readonly UriHeaderParser RelativeOrAbsoluteUriParser =
|
||||
new UriHeaderParser(UriKind.RelativeOrAbsolute);
|
||||
#endif
|
||||
|
||||
private UriHeaderParser(UriKind uriKind)
|
||||
: base(false)
|
||||
|
Reference in New Issue
Block a user