Imported Upstream version 5.10.0.47

Former-commit-id: d0813289fa2d35e1f8ed77530acb4fb1df441bc0
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2018-01-24 17:04:36 +00:00
parent 88ff76fe28
commit e46a49ecf1
5927 changed files with 226314 additions and 129848 deletions

View File

@@ -1,3 +0,0 @@
## need to create a uap config that uses CreateFileFromApp, then remove this baseline ##
# https://github.com/dotnet/corefx/issues/21025
kernel32.dll!CreateFileW

View File

@@ -41,9 +41,6 @@
<Compile Include="$(CommonPath)\Interop\Windows\Interop.Libraries.cs">
<Link>Common\Interop\Windows\Interop.Libraries.cs</Link>
</Compile>
<Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.CreateFile.cs">
<Link>Common\Interop\Windows\kernel32\Interop.CreateFile.cs</Link>
</Compile>
<Compile Include="$(CommonPath)\Interop\Windows\Interop.BOOL.cs">
<Link>Common\Interop\Windows\Interop.BOOL.cs</Link>
</Compile>
@@ -58,6 +55,30 @@
</Compile>
<Compile Include="System\IO\FileSystemWatcher.Win32.cs" />
</ItemGroup>
<!-- Windows : Win32 only -->
<ItemGroup Condition="'$(TargetsWindows)' == 'true' and '$(TargetGroup)' != 'uap'">
<Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.UnsafeCreateFile.cs">
<Link>Common\Interop\Windows\Interop.UnsafeCreateFile.cs</Link>
</Compile>
<Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.CreateFile.cs">
<Link>Common\Interop\Windows\Interop.CreateFile.cs</Link>
</Compile>
</ItemGroup>
<!-- Windows : UAP - Win32 + WinRT -->
<ItemGroup Condition="'$(TargetsWindows)' == 'true' and '$(TargetGroup)' == 'uap'">
<Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.CreateFile2.cs">
<Link>Common\Interop\Windows\Interop.CreateFile2.cs</Link>
</Compile>
<Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.UnsafeCreateFile.uap.cs">
<Link>Common\Interop\Windows\Interop.UnsafeCreateFile.uap.cs</Link>
</Compile>
<Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.COPYFILE2_EXTENDED_PARAMETERS.cs">
<Link>Common\Interop\Windows\Interop.COPYFILE2_EXTENDED_PARAMETERS.cs</Link>
</Compile>
<Compile Include="$(CommonPath)\Interop\Windows\kernel32\Interop.CREATEFILE2_EXTENDED_PARAMETERS.cs">
<Link>Common\Interop\Windows\Interop.CREATEFILE2_EXTENDED_PARAMETERS.cs</Link>
</Compile>
</ItemGroup>
<ItemGroup Condition=" '$(TargetsUnix)' == 'true'">
<Compile Include="$(CommonPath)\Interop\Unix\Interop.Libraries.cs">
<Link>Common\Interop\Unix\Interop.Libraries.cs</Link>

View File

@@ -69,7 +69,7 @@ namespace System.IO
// active operations to all be outstanding at the same time.
var runner = new RunningInstance(
this, handle, _directory,
IncludeSubdirectories, TranslateFilters(NotifyFilter), cancellation.Token);
IncludeSubdirectories, NotifyFilter, cancellation.Token);
// Now that we've created the runner, store the cancellation object and mark the instance
// as running. We wait to do this so that if there was a failure, StartRaisingEvents
@@ -256,7 +256,8 @@ namespace System.IO
/// <summary>
/// Filters to use when adding a watch on directories.
/// </summary>
private readonly Interop.Sys.NotifyEvents _notifyFilters;
private readonly NotifyFilters _notifyFilters;
private readonly Interop.Sys.NotifyEvents _watchFilters;
/// <summary>
/// Whether to monitor subdirectories. Unlike Win32, inotify does not implicitly monitor subdirectories;
/// watches must be explicitly added for those subdirectories.
@@ -282,7 +283,7 @@ namespace System.IO
/// <summary>Initializes the instance with all state necessary to operate a watch.</summary>
internal RunningInstance(
FileSystemWatcher watcher, SafeFileHandle inotifyHandle, string directoryPath,
bool includeSubdirectories, Interop.Sys.NotifyEvents notifyFilters, CancellationToken cancellationToken)
bool includeSubdirectories, NotifyFilters notifyFilters, CancellationToken cancellationToken)
{
Debug.Assert(watcher != null);
Debug.Assert(inotifyHandle != null && !inotifyHandle.IsInvalid && !inotifyHandle.IsClosed);
@@ -295,6 +296,7 @@ namespace System.IO
Debug.Assert(_buffer != null && _buffer.Length > (c_INotifyEventSize + NAME_MAX + 1));
_includeSubdirectories = includeSubdirectories;
_notifyFilters = notifyFilters;
_watchFilters = TranslateFilters(notifyFilters);
_cancellationToken = cancellationToken;
// Add a watch for this starting directory. We keep track of the watch descriptor => directory information
@@ -358,7 +360,7 @@ namespace System.IO
// the existing descriptor. This works even in the case of a rename. We also add the DONT_FOLLOW
// and EXCL_UNLINK flags to keep parity with Windows where we don't pickup symlinks or unlinked
// files (which don't exist in Windows)
int wd = Interop.Sys.INotifyAddWatch(_inotifyHandle, fullPath, (uint)(this._notifyFilters | Interop.Sys.NotifyEvents.IN_DONT_FOLLOW | Interop.Sys.NotifyEvents.IN_EXCL_UNLINK));
int wd = Interop.Sys.INotifyAddWatch(_inotifyHandle, fullPath, (uint)(this._watchFilters | Interop.Sys.NotifyEvents.IN_DONT_FOLLOW | Interop.Sys.NotifyEvents.IN_EXCL_UNLINK));
if (wd == -1)
{
// If we get an error when trying to add the watch, don't let that tear down processing. Instead,
@@ -637,10 +639,21 @@ namespace System.IO
AddDirectoryWatch(associatedDirectoryEntry, nextEvent.name);
}
const Interop.Sys.NotifyEvents switchMask =
Interop.Sys.NotifyEvents.IN_IGNORED |Interop.Sys.NotifyEvents.IN_CREATE | Interop.Sys.NotifyEvents.IN_DELETE |
Interop.Sys.NotifyEvents.IN_ACCESS | Interop.Sys.NotifyEvents.IN_MODIFY | Interop.Sys.NotifyEvents.IN_ATTRIB |
Interop.Sys.NotifyEvents.IN_MOVED_FROM | Interop.Sys.NotifyEvents.IN_MOVED_TO;
// Check if the event should have been filtered but was unable because of inotify's inability
// to filter files vs directories.
const Interop.Sys.NotifyEvents fileDirEvents = Interop.Sys.NotifyEvents.IN_CREATE |
Interop.Sys.NotifyEvents.IN_DELETE |
Interop.Sys.NotifyEvents.IN_MOVED_FROM |
Interop.Sys.NotifyEvents.IN_MOVED_TO;
if ((((uint)fileDirEvents & mask) > 0) &&
(isDir && ((_notifyFilters & NotifyFilters.DirectoryName) == 0) ||
(!isDir && ((_notifyFilters & NotifyFilters.FileName) == 0))))
{
continue;
}
const Interop.Sys.NotifyEvents switchMask = fileDirEvents | Interop.Sys.NotifyEvents.IN_IGNORED |
Interop.Sys.NotifyEvents.IN_ACCESS | Interop.Sys.NotifyEvents.IN_MODIFY | Interop.Sys.NotifyEvents.IN_ATTRIB;
switch ((Interop.Sys.NotifyEvents)(mask & (uint)switchMask))
{
case Interop.Sys.NotifyEvents.IN_CREATE:

View File

@@ -27,7 +27,7 @@ namespace System.IO
// Create handle to directory being monitored
var defaultSecAttrs = default(Interop.Kernel32.SECURITY_ATTRIBUTES);
_directoryHandle = Interop.Kernel32.CreateFile(
_directoryHandle = Interop.Kernel32.UnsafeCreateFile(
lpFileName: _directory,
dwDesiredAccess: Interop.Kernel32.FileOperations.FILE_LIST_DIRECTORY,
dwShareMode: FileShare.Read | FileShare.Delete | FileShare.Write,

View File

@@ -87,8 +87,6 @@ namespace System.IO.Tests
WatcherChangeTypes expected = 0;
if (filter == NotifyFilters.DirectoryName)
expected |= WatcherChangeTypes.Renamed;
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) && (filter == NotifyFilters.FileName))
expected |= WatcherChangeTypes.Renamed;
ExpectEvent(watcher, expected, action, cleanup, targetPath);
}
@@ -140,6 +138,33 @@ namespace System.IO.Tests
}
}
[Theory]
[OuterLoop]
[MemberData(nameof(FilterTypes))]
public void FileSystemWatcher_Directory_NotifyFilter_LastWriteTime_TwoFilters(NotifyFilters filter)
{
Assert.All(FilterTypes(), (filter2Arr =>
{
using (var testDirectory = new TempDirectory(GetTestFilePath()))
using (var dir = new TempDirectory(Path.Combine(testDirectory.Path, "dir")))
using (var watcher = new FileSystemWatcher(testDirectory.Path, Path.GetFileName(dir.Path)))
{
filter |= (NotifyFilters)filter2Arr[0];
watcher.NotifyFilter = filter;
Action action = () => Directory.SetLastWriteTime(dir.Path, DateTime.Now + TimeSpan.FromSeconds(10));
WatcherChangeTypes expected = 0;
if ((filter & NotifyFilters.LastWrite) > 0)
expected |= WatcherChangeTypes.Changed;
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) && ((filter & LinuxFiltersForAttribute) > 0))
expected |= WatcherChangeTypes.Changed;
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) && ((filter & OSXFiltersForModify) > 0))
expected |= WatcherChangeTypes.Changed;
ExpectEvent(watcher, expected, action, expectedPath: dir.Path);
}
}));
}
[Theory]
[MemberData(nameof(FilterTypes))]
[PlatformSpecific(TestPlatforms.Windows)] // Uses P/Invokes to set security info
@@ -255,5 +280,35 @@ namespace System.IO.Tests
ExpectEvent(watcher, expected, action, cleanup, new string[] { otherDir, dir.Path });
}
}
[Fact]
public void FileSystemWatcher_Directory_NotifyFilter_DirectoryNameDoesntTriggerOnFileEvent()
{
using (var testDirectory = new TempDirectory(GetTestFilePath()))
using (var dir = new TempDirectory(Path.Combine(testDirectory.Path, "dir")))
using (var watcher = new FileSystemWatcher(testDirectory.Path, "*"))
{
watcher.NotifyFilter = NotifyFilters.FileName;
string renameDirSource = Path.Combine(testDirectory.Path, "dir2_source");
string renameDirDest = Path.Combine(testDirectory.Path, "dir2_dest");
string otherDir = Path.Combine(testDirectory.Path, "dir3");
Directory.CreateDirectory(renameDirSource);
Action action = () =>
{
Directory.CreateDirectory(otherDir);
Directory.Move(renameDirSource, renameDirDest);
Directory.SetLastWriteTime(dir.Path, DateTime.Now + TimeSpan.FromSeconds(10));
Directory.Delete(otherDir);
};
Action cleanup = () =>
{
Directory.Move(renameDirDest, renameDirSource);
};
WatcherChangeTypes expected = 0;
ExpectEvent(watcher, expected, action, cleanup, new string[] { otherDir, dir.Path });
}
}
}
}

View File

@@ -102,4 +102,4 @@ namespace System.IO.Tests
}
}
}
}
}

View File

@@ -91,9 +91,6 @@ namespace System.IO.Tests
if (filter == NotifyFilters.DirectoryName)
expected |= WatcherChangeTypes.Renamed;
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) && (filter == NotifyFilters.FileName))
expected |= WatcherChangeTypes.Renamed;
ExpectEvent(watcher, expected, action, cleanup, targetPath);
}
}
@@ -167,6 +164,36 @@ namespace System.IO.Tests
}
}
[Theory]
[OuterLoop]
[MemberData(nameof(FilterTypes))]
public void FileSystemWatcher_File_NotifyFilter_Size_TwoFilters(NotifyFilters filter)
{
Assert.All(FilterTypes(), (filter2Arr =>
{
using (var testDirectory = new TempDirectory(GetTestFilePath()))
using (var file = new TempFile(Path.Combine(testDirectory.Path, "file")))
using (var watcher = new FileSystemWatcher(testDirectory.Path, Path.GetFileName(file.Path)))
{
filter |= (NotifyFilters)filter2Arr[0];
watcher.NotifyFilter = filter;
Action action = () => File.AppendAllText(file.Path, "longText!");
Action cleanup = () => File.AppendAllText(file.Path, "short");
WatcherChangeTypes expected = 0;
if (((filter & NotifyFilters.Size) > 0) || ((filter & NotifyFilters.LastWrite) > 0))
expected |= WatcherChangeTypes.Changed;
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) && ((filter & LinuxFiltersForModify) > 0))
expected |= WatcherChangeTypes.Changed;
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) && ((filter & OSXFiltersForModify) > 0))
expected |= WatcherChangeTypes.Changed;
else if (PlatformDetection.IsWindows7 && ((filter & NotifyFilters.Attributes) > 0)) // win7 FSW Size change passes the Attribute filter
expected |= WatcherChangeTypes.Changed;
ExpectEvent(watcher, expected, action, expectedPath: file.Path);
}
}));
}
[Theory]
[MemberData(nameof(FilterTypes))]
[PlatformSpecific(TestPlatforms.Windows)] // Uses P/Invokes to set security info
@@ -281,5 +308,34 @@ namespace System.IO.Tests
ExpectEvent(watcher, expected, action, cleanup, new string[] { otherFile, file.Path });
}
}
[Fact]
public void FileSystemWatcher_File_NotifyFilter_FileNameDoesntTriggerOnDirectoryEvent()
{
using (var testDirectory = new TempDirectory(GetTestFilePath()))
using (var file = new TempFile(Path.Combine(testDirectory.Path, "file")))
using (var sourcePath = new TempFile(Path.Combine(testDirectory.Path, "sourceFile")))
using (var watcher = new FileSystemWatcher(testDirectory.Path, "*"))
{
watcher.NotifyFilter = NotifyFilters.DirectoryName;
string otherFile = Path.Combine(testDirectory.Path, "file2");
string destPath = Path.Combine(testDirectory.Path, "destFile");
Action action = () =>
{
File.Create(otherFile).Dispose();
File.SetLastWriteTime(file.Path, DateTime.Now + TimeSpan.FromSeconds(10));
File.Delete(otherFile);
File.Move(sourcePath.Path, destPath);
};
Action cleanup = () =>
{
File.Move(destPath, sourcePath.Path);
};
WatcherChangeTypes expected = 0;
ExpectEvent(watcher, expected, action, cleanup, new string[] { otherFile, file.Path });
}
}
}
}

View File

@@ -497,7 +497,7 @@ namespace System.IO.Tests
watcher.Path = ".";
Assert.Equal(".", watcher.Path);
if (!PlatformDetection.IsWinRT)
if (!PlatformDetection.IsInAppContainer)
{
watcher.Path = "..";
Assert.Equal("..", watcher.Path);

View File

@@ -43,9 +43,6 @@
<Compile Include="$(CommonTestPath)\System\IO\TempDirectory.cs">
<Link>Common\System\IO\TempDirectory.cs</Link>
</Compile>
<Compile Include="$(CommonTestPath)\System\PlatformDetection.cs">
<Link>Common\System\PlatformDetection.cs</Link>
</Compile>
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
</Project>

View File

@@ -202,26 +202,14 @@ namespace System.IO.Tests
AutoResetEvent changed = null, created = null, deleted = null, renamed = null;
string[] expectedFullPaths = expectedPaths == null ? null : expectedPaths.Select(e => Path.GetFullPath(e)).ToArray();
// On OSX we get a number of extra events tacked onto valid events. As such, we can not ever confidently
// say that a event won't occur, only that one will occur.
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
if (verifyChanged = ((expectedEvents & WatcherChangeTypes.Changed) > 0))
changed = WatchChanged(watcher, expectedPaths);
if (verifyCreated = ((expectedEvents & WatcherChangeTypes.Created) > 0))
created = WatchCreated(watcher, expectedPaths);
if (verifyDeleted = ((expectedEvents & WatcherChangeTypes.Deleted) > 0))
deleted = WatchDeleted(watcher, expectedPaths);
if (verifyRenamed = ((expectedEvents & WatcherChangeTypes.Renamed) > 0))
renamed = WatchRenamed(watcher, expectedPaths);
}
else
{
changed = WatchChanged(watcher, (expectedEvents & WatcherChangeTypes.Changed) > 0 ? expectedPaths : null);
created = WatchCreated(watcher, (expectedEvents & WatcherChangeTypes.Created) > 0 ? expectedPaths : null);
deleted = WatchDeleted(watcher, (expectedEvents & WatcherChangeTypes.Deleted) > 0 ? expectedPaths : null);
renamed = WatchRenamed(watcher, (expectedEvents & WatcherChangeTypes.Renamed) > 0 ? expectedPaths : null);
}
if (verifyChanged = ((expectedEvents & WatcherChangeTypes.Changed) > 0))
changed = WatchChanged(watcher, expectedPaths);
if (verifyCreated = ((expectedEvents & WatcherChangeTypes.Created) > 0))
created = WatchCreated(watcher, expectedPaths);
if (verifyDeleted = ((expectedEvents & WatcherChangeTypes.Deleted) > 0))
deleted = WatchDeleted(watcher, expectedPaths);
if (verifyRenamed = ((expectedEvents & WatcherChangeTypes.Renamed) > 0))
renamed = WatchRenamed(watcher, expectedPaths);
watcher.EnableRaisingEvents = true;
action();
@@ -443,4 +431,4 @@ namespace System.IO.Tests
NotifyFilters.LastWrite |
NotifyFilters.Size;
}
}
}