Skip to content

Commit

Permalink
Fixes mono#16032
Browse files Browse the repository at this point in the history
Switching to corefx File.Copy on unix changed the behavior where it opened a source and destination stream in order to pass
the safe handles to Interop.Sys.CopyFile.  This exposed a flaw in our sharing validation rules in MonoIO.Open, which
threw an exception in this scenario:

new FileStream("source.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite, 2048, FileOptions.DeleteOnClose);
new FileStream("source.txt", FileMode.Open, FileAccess.Read, FileShare.Read, 2048, FileOptions.None);

The change is intended to take into account all sharing scenarios.
  • Loading branch information
Steve Pfister committed Aug 14, 2019
1 parent a6b8494 commit 6442251
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 7 deletions.
24 changes: 24 additions & 0 deletions mcs/class/corlib/Test/System.IO/FileStreamTest.cs
Expand Up @@ -1650,6 +1650,30 @@ public void DeleteOnClose ()

}

// See https://github.com/mono/mono/issues/16032
[Test]
public void DeleteOnCloseWithFileCopy ()
{
string source = TempFolder + DSC + "source.txt";
string target = TempFolder + DSC + "target.txt";

File.WriteAllText (source, "text");
FileStream fs = new FileStream (source, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite, 2048,
FileOptions.DeleteOnClose);

Assert.AreEqual (true, File.Exists (source), "DCFC#1");

try {
File.Copy (fs.Name, target, true);
}
finally {
fs.Dispose();
}

Assert.AreEqual (false, File.Exists (source), "DCFC#2");
Assert.AreEqual (true, File.Exists (target), "DCFC#3");
}

[Test]
public void OpenCharDeviceRepeatedly ()
{
Expand Down
13 changes: 6 additions & 7 deletions mono/metadata/w32file-unix.c
Expand Up @@ -1874,16 +1874,15 @@ static gboolean share_allows_open (struct stat *statbuf, guint32 sharemode,
return(FALSE);
}

if (((file_existing_access & GENERIC_READ) &&
!(sharemode & FILE_SHARE_READ)) ||
((file_existing_access & GENERIC_WRITE) &&
!(sharemode & FILE_SHARE_WRITE))) {
/* New share mode doesn't match up */
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_FILE, "%s: Access mode prevents open: requested share: 0x%" PRIx32 ", file has access: 0x%" PRIx32, __func__, sharemode, file_existing_access);
if (file_existing_share != sharemode &&
((sharemode | FILE_SHARE_READ) != sharemode) &&
((file_existing_share | sharemode) == file_existing_share)) {
/* Share mode is trying to be more strict */
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER_FILE, "%s: Can't restrict sharing mode: existing mode %d, requesting sharing mode: %d - the requested sharing mode is more strict", __func__, file_existing_share, sharemode);

file_share_release (*share_info);
*share_info = NULL;

return(FALSE);
}
} else {
Expand Down

0 comments on commit 6442251

Please sign in to comment.