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:
authorMitchell Hwang <mitchhwang1418@gmail.com>2020-04-02 21:13:42 +0300
committerGitHub <noreply@github.com>2020-04-02 21:13:42 +0300
commitbec934370587bdbe8a9e4305a5e9167dd7b63677 (patch)
tree0235ff7f1413edb34863f4ff1800d3b2aebd6555
parent7c9e2158925339a5a96ff8d09d21c600a0b27e5a (diff)
FileSystem.Unix.File.Move uses "rename" in more cases (#40611) (#395)
* FileSystem.Unix.File.Move uses "rename" in more cases (#40611) * FileSystem.Unix.File.Move use rename in more cases, avoid link/copy when possible, improve performance on file systems that do not support hard links, such as FAT * Adapt Unit Tests for accounting FileSystemWatcher events fired by FileSystem.Unix.File.Move implementation that use rename in more cases, avoiding link/copy when possible * [FileSystem] ReAdd check for same device Co-authored-by: Sylvain <sf@ellisys.com> Co-authored-by: Mitchell Hwang <mihw@microsoft.com>
-rw-r--r--src/System.IO.FileSystem.Watcher/tests/FileSystemWatcher.File.Move.cs8
-rw-r--r--src/System.IO.FileSystem/src/System/IO/FileSystem.Unix.cs21
2 files changed, 15 insertions, 14 deletions
diff --git a/src/System.IO.FileSystem.Watcher/tests/FileSystemWatcher.File.Move.cs b/src/System.IO.FileSystem.Watcher/tests/FileSystemWatcher.File.Move.cs
index be9d25490f..e772c85dae 100644
--- a/src/System.IO.FileSystem.Watcher/tests/FileSystemWatcher.File.Move.cs
+++ b/src/System.IO.FileSystem.Watcher/tests/FileSystemWatcher.File.Move.cs
@@ -22,7 +22,7 @@ namespace System.IO.Tests
[PlatformSpecific(TestPlatforms.AnyUnix)] // Expected WatcherChangeTypes are different based on OS
public void Unix_File_Move_To_Same_Directory()
{
- FileMove_SameDirectory(WatcherChangeTypes.Created | WatcherChangeTypes.Deleted);
+ FileMove_SameDirectory(WatcherChangeTypes.Renamed);
}
[Fact]
@@ -73,7 +73,7 @@ namespace System.IO.Tests
[PlatformSpecific(TestPlatforms.OSX)] // Expected WatcherChangeTypes are different based on OS
public void OSX_File_Move_To_Different_Watched_Directory()
{
- FileMove_DifferentWatchedDirectory(WatcherChangeTypes.Changed);
+ FileMove_DifferentWatchedDirectory(0);
}
[Fact]
@@ -104,7 +104,7 @@ namespace System.IO.Tests
[PlatformSpecific(TestPlatforms.AnyUnix)] // Expected WatcherChangeTypes are different based on OS
public void Unix_File_Move_In_Nested_Directory(bool includeSubdirectories)
{
- FileMove_NestedDirectory(includeSubdirectories ? WatcherChangeTypes.Created | WatcherChangeTypes.Deleted : 0, includeSubdirectories);
+ FileMove_NestedDirectory(includeSubdirectories ? WatcherChangeTypes.Renamed : 0, includeSubdirectories);
}
[Fact]
@@ -118,7 +118,7 @@ namespace System.IO.Tests
[PlatformSpecific(TestPlatforms.AnyUnix)] // Expected WatcherChangeTypes are different based on OS
public void Unix_File_Move_With_Set_NotifyFilter()
{
- FileMove_WithNotifyFilter(WatcherChangeTypes.Deleted);
+ FileMove_WithNotifyFilter(WatcherChangeTypes.Renamed);
}
#region Test Helpers
diff --git a/src/System.IO.FileSystem/src/System/IO/FileSystem.Unix.cs b/src/System.IO.FileSystem/src/System/IO/FileSystem.Unix.cs
index b2007ca32d..94b4557643 100644
--- a/src/System.IO.FileSystem/src/System/IO/FileSystem.Unix.cs
+++ b/src/System.IO.FileSystem/src/System/IO/FileSystem.Unix.cs
@@ -160,18 +160,19 @@ namespace System.IO
{
// The desired behavior for Move(source, dest) is to not overwrite the destination file
// if it exists. Since rename(source, dest) will replace the file at 'dest' if it exists,
- // link/unlink are used instead. However, if the source path and the dest path refer to
- // the same file, then do a rename rather than a link and an unlink. This is important
- // for case-insensitive file systems (e.g. renaming a file in a way that just changes casing),
- // so that we support changing the casing in the naming of the file. If this fails in any
- // way (e.g. source file doesn't exist, dest file doesn't exist, rename fails, etc.), we
- // just fall back to trying the link/unlink approach and generating any exceptional messages
- // from there as necessary.
+ // link/unlink are used instead. Rename is more efficient than link/unlink on file systems
+ // where hard links are not supported (such as FAT). Therefore, given that source file exists,
+ // rename is used in 2 cases: when dest file does not exist or when source path and dest
+ // path refer to the same file (on the same device). This is important for case-insensitive
+ // file systems (e.g. renaming a file in a way that just changes casing), so that we support
+ // changing the casing in the naming of the file. If this fails in any way (e.g. source file
+ // doesn't exist, dest file doesn't exist, rename fails, etc.), we just fall back to trying the
+ // link/unlink approach and generating any exceptional messages from there as necessary.
Interop.Sys.FileStatus sourceStat, destStat;
if (Interop.Sys.LStat(sourceFullPath, out sourceStat) == 0 && // source file exists
- Interop.Sys.LStat(destFullPath, out destStat) == 0 && // dest file exists
- sourceStat.Dev == destStat.Dev && // source and dest are on the same device
- sourceStat.Ino == destStat.Ino && // and source and dest are the same file on that device
+ (Interop.Sys.LStat(destFullPath, out destStat) != 0 || // dest file does not exist
+ (sourceStat.Dev == destStat.Dev && // source and dest are on the same device
+ sourceStat.Ino == destStat.Ino)) && // source and dest are the same file on that device
Interop.Sys.Rename(sourceFullPath, destFullPath) == 0) // try the rename
{
// Renamed successfully.