Imported Upstream version 6.4.0.150

Former-commit-id: 2cf3acd45014a53dda66c13f7378a88695d3c93e
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2019-08-02 08:37:10 +00:00
parent 7eed0321b0
commit 345224e2bc
67 changed files with 352 additions and 91 deletions

View File

@@ -12,6 +12,32 @@ namespace System.IO
{
internal const int DefaultBufferSize = 4096;
private static bool CopyDanglingSymlink(string sourceFullPath, string destFullPath)
{
// Check if the source is a dangling symlink. In those cases, we just want to copy the link
Interop.Sys.FileStatus ignored;
if (! (Interop.Sys.Stat(sourceFullPath, out ignored) < 0 &&
Interop.Sys.LStat(sourceFullPath, out ignored) == 0))
{
return false;
}
Interop.ErrorInfo errorInfo;
// get the target of the symlink
string linkTarget = Interop.Sys.ReadLink(sourceFullPath);
if (linkTarget == null)
{
errorInfo = Interop.Sys.GetLastErrorInfo();
throw Interop.GetExceptionForIoErrno(errorInfo, sourceFullPath);
}
if (Interop.Sys.Symlink(linkTarget, destFullPath) == 0)
return true;
errorInfo = Interop.Sys.GetLastErrorInfo();
throw Interop.GetExceptionForIoErrno(errorInfo, destFullPath);
}
public static void CopyFile(string sourceFullPath, string destFullPath, bool overwrite)
{
// The destination path may just be a directory into which the file should be copied.
@@ -21,6 +47,9 @@ namespace System.IO
destFullPath = Path.Combine(destFullPath, Path.GetFileName(sourceFullPath));
}
if (CopyDanglingSymlink(sourceFullPath, destFullPath))
return;
// Copy the contents of the file from the source to the destination, creating the destination in the process
using (var src = new FileStream(sourceFullPath, FileMode.Open, FileAccess.Read, FileShare.Read, DefaultBufferSize, FileOptions.None))
using (var dst = new FileStream(destFullPath, overwrite ? FileMode.Create : FileMode.CreateNew, FileAccess.ReadWrite, FileShare.None, DefaultBufferSize, FileOptions.None))
@@ -31,6 +60,9 @@ namespace System.IO
private static void LinkOrCopyFile (string sourceFullPath, string destFullPath)
{
if (CopyDanglingSymlink(sourceFullPath, destFullPath))
return;
if (Interop.Sys.Link(sourceFullPath, destFullPath) >= 0)
return;

View File

@@ -5,6 +5,7 @@
using System.Collections.Generic;
using System.Linq;
using Xunit;
using System.Runtime.InteropServices;
namespace System.IO.Tests
{
@@ -48,6 +49,22 @@ namespace System.IO.Tests
Assert.Throws<IOException>(() => Copy(testFile, testFile));
}
[DllImport("libc", SetLastError = true)]
private static extern int symlink(string target, string linkpath);
[Fact]
[PlatformSpecific(TestPlatforms.AnyUnix)]
public void DanglingSymlinkCopy()
{
string dangling_symlink = GetTestFileName();
string missing_target = GetTestFileName();
string dangling_symlink_new_location = GetTestFileName();
Assert.False(File.Exists(missing_target));
Assert.Equal(symlink(missing_target, dangling_symlink), 0);
Copy(dangling_symlink, dangling_symlink_new_location);
Assert.True(File.Exists(dangling_symlink_new_location)); // File.Exists returns true for dangling symlinks
}
[Fact]
[SkipOnTargetFramework(TargetFrameworkMonikers.Mono, "CoreFX FileStream not yet imported")]
public void NonExistentPath()

View File

@@ -4,6 +4,7 @@
using Xunit;
using System.Linq;
using System.Runtime.InteropServices;
namespace System.IO.Tests
{
@@ -174,6 +175,22 @@ namespace System.IO.Tests
Assert.False(File.Exists(testFileSource.FullName));
}
[DllImport("libc", SetLastError = true)]
private static extern int symlink(string target, string linkpath);
[Fact]
[PlatformSpecific(TestPlatforms.AnyUnix)]
public void DanglingSymlinkMove()
{
string dangling_symlink = GetTestFileName();
string missing_target = GetTestFileName();
string dangling_symlink_new_location = GetTestFileName();
Assert.False(File.Exists(missing_target));
Assert.Equal(symlink(missing_target, dangling_symlink), 0);
Move(dangling_symlink, dangling_symlink_new_location);
Assert.True(File.Exists(dangling_symlink_new_location)); // File.Exists returns true for dangling symlinks
}
[Fact]
public void FileNameWithSignificantWhitespace()
{