Skip to content
This repository has been archived by the owner on Dec 6, 2024. It is now read-only.

Commit

Permalink
-Implemented #292: CopyOptions.CopySymbolicLink not working in 2.1.2
Browse files Browse the repository at this point in the history
-Implemented #351: Enable copying of Directory symbolic links.
-Renamed COPY/MOVE_FILE_OPTIONS to COPY/MOVE_FILE_FLAGS.
  • Loading branch information
Yomodo authored and Yomodo committed Jun 22, 2017
1 parent 9944ab2 commit 097fca1
Show file tree
Hide file tree
Showing 25 changed files with 239 additions and 76 deletions.
56 changes: 56 additions & 0 deletions AlphaFS.UnitTest/Directory Class/AlphaFS_Directory_Copy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,17 @@ public void AlphaFS_Directory_Copy_Overwrite_DestinationFileAlreadyExists_LocalA
}


[TestMethod]
public void AlphaFS_Directory_Copy_CopyOptions_CopySymbolicLink_SourceIsASymbolicLink_TargetMustAlsoBeASymbolicLink_LocalAndNetwork_Success()
{
if (!UnitTestConstants.IsAdmin())
Assert.Inconclusive();

Directory_Copy_CopyOptions_CopySymbolicLink_SourceIsASymbolicLink_TargetMustAlsoBeASymbolicLink(false);
Directory_Copy_CopyOptions_CopySymbolicLink_SourceIsASymbolicLink_TargetMustAlsoBeASymbolicLink(true);
}


[TestMethod]
public void AlphaFS_Directory_Copy_CatchAlreadyExistsException_DestinationFileAlreadyExists_LocalAndNetwork_Success()
{
Expand Down Expand Up @@ -226,6 +237,51 @@ private void Directory_Copy_Overwrite_DestinationFileAlreadyExists(bool isNetwor
}


private void Directory_Copy_CopyOptions_CopySymbolicLink_SourceIsASymbolicLink_TargetMustAlsoBeASymbolicLink(bool isNetwork)
{
UnitTestConstants.PrintUnitTestHeader(isNetwork);

var tempPath = System.IO.Path.GetTempPath();
if (isNetwork)
tempPath = Alphaleonis.Win32.Filesystem.Path.LocalToUnc(tempPath);


using (var rootDir = new TemporaryDirectory(tempPath, MethodBase.GetCurrentMethod().Name))
{
var sourceFolderLink = System.IO.Path.Combine(rootDir.Directory.FullName, "SourceDirectoryLink-ToOriginalDirectory");

var dirInfo = new System.IO.DirectoryInfo(System.IO.Path.Combine(rootDir.Directory.FullName, "OriginalDirectory"));
dirInfo.Create();

Console.WriteLine("\nInput Directory Path: [{0}]", dirInfo.FullName);
Console.WriteLine("Input Directory Link: [{0}]", sourceFolderLink);

Alphaleonis.Win32.Filesystem.Directory.CreateSymbolicLink(sourceFolderLink, dirInfo.FullName);


var destinationFolderLink = System.IO.Path.Combine(rootDir.Directory.FullName, "DestinationDirectoryLink-ToOriginalDirectory");

Alphaleonis.Win32.Filesystem.Directory.Copy(sourceFolderLink, destinationFolderLink, Alphaleonis.Win32.Filesystem.CopyOptions.CopySymbolicLink);


var lviSrc = Alphaleonis.Win32.Filesystem.Directory.GetLinkTargetInfo(sourceFolderLink);
var lviDst = Alphaleonis.Win32.Filesystem.Directory.GetLinkTargetInfo(destinationFolderLink);

Console.WriteLine("\n\tLink Info of source Link:");
UnitTestConstants.Dump(lviSrc, -14);

Console.WriteLine("\n\tLink Info of copied Link:");
UnitTestConstants.Dump(lviDst, -14);


Assert.AreEqual(lviSrc.PrintName, lviDst.PrintName);
Assert.AreEqual(lviSrc.SubstituteName, lviDst.SubstituteName);
}

Console.WriteLine();
}


private void Directory_Copy_CatchAlreadyExistsException_DestinationFileAlreadyExists(bool isNetwork)
{
UnitTestConstants.PrintUnitTestHeader(isNetwork);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,13 +117,13 @@ private void Directory_CreateSymbolicLink_CatchIOException_FileExistsWithSameNam

using (var rootDir = new TemporaryDirectory(tempPath, MethodBase.GetCurrentMethod().Name))
{
var folderLink = System.IO.Path.Combine(rootDir.Directory.FullName, "FolderLink-ToDestinationFolder");
var folderLink = System.IO.Path.Combine(rootDir.Directory.FullName, "FolderLink-ToOriginalFolder");

var fileInfo = new System.IO.FileInfo(System.IO.Path.Combine(rootDir.Directory.FullName, "DestinationFile.txt"));
var fileInfo = new System.IO.FileInfo(System.IO.Path.Combine(rootDir.Directory.FullName, "OriginalFile.txt"));
using (fileInfo.Create()) {}

Console.WriteLine("\nInput File Path: [{0}]", fileInfo.FullName);
Console.WriteLine("Folder Link : [{0}]", folderLink);
Console.WriteLine("\nInput File Path : [{0}]", fileInfo.FullName);
Console.WriteLine("Input Folder Link: [{0}]", folderLink);


var gotException = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,9 @@ private void File_CreateSymbolicLink_And_GetLinkTargetInfo(bool isNetwork)

using (var rootDir = new TemporaryDirectory(tempPath, MethodBase.GetCurrentMethod().Name))
{
var fileLink = System.IO.Path.Combine(rootDir.Directory.FullName, "FileLink-ToDestinationFile.txt");
var fileLink = System.IO.Path.Combine(rootDir.Directory.FullName, "FileLink-ToOriginalFile.txt");

var fileInfo = new System.IO.FileInfo(System.IO.Path.Combine(rootDir.Directory.FullName, "DestinationFile.txt"));
var fileInfo = new System.IO.FileInfo(System.IO.Path.Combine(rootDir.Directory.FullName, "OriginalFile.txt"));
using (fileInfo.CreateText()) {}

Console.WriteLine("\nInput File Path: [{0}]", fileInfo.FullName);
Expand Down
56 changes: 56 additions & 0 deletions AlphaFS.UnitTest/File Class/File_Copy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,17 @@ public void File_Copy_Overwrite_DestinationFileAlreadyExists_LocalAndNetwork_Suc
}


[TestMethod]
public void AlphaFS_File_Copy_CopyOptions_CopySymbolicLink_SourceIsASymbolicLink_TargetMustAlsoBeASymbolicLink_LocalAndNetwork_Success()
{
if (!UnitTestConstants.IsAdmin())
Assert.Inconclusive();

File_Copy_CopyOptions_CopySymbolicLink_SourceIsASymbolicLink_TargetMustAlsoBeASymbolicLink(false);
File_Copy_CopyOptions_CopySymbolicLink_SourceIsASymbolicLink_TargetMustAlsoBeASymbolicLink(true);
}


[TestMethod]
public void File_Copy_CatchAlreadyExistsException_DestinationFileAlreadyExists_LocalAndNetwork_Success()
{
Expand Down Expand Up @@ -177,6 +188,51 @@ private void File_Copy_Overwrite_DestinationFileAlreadyExists(bool isNetwork)
}


private void File_Copy_CopyOptions_CopySymbolicLink_SourceIsASymbolicLink_TargetMustAlsoBeASymbolicLink(bool isNetwork)
{
UnitTestConstants.PrintUnitTestHeader(isNetwork);

var tempPath = System.IO.Path.GetTempPath();
if (isNetwork)
tempPath = Alphaleonis.Win32.Filesystem.Path.LocalToUnc(tempPath);


using (var rootDir = new TemporaryDirectory(tempPath, MethodBase.GetCurrentMethod().Name))
{
var sourceFileLink = System.IO.Path.Combine(rootDir.Directory.FullName, "SourceFileLink-ToOriginalFile.txt");

var fileInfo = new System.IO.FileInfo(System.IO.Path.Combine(rootDir.Directory.FullName, "OriginalFile.txt"));
using (fileInfo.CreateText()) { }

Console.WriteLine("\nInput File Path: [{0}]", fileInfo.FullName);
Console.WriteLine("Input File Link: [{0}]", sourceFileLink);

Alphaleonis.Win32.Filesystem.File.CreateSymbolicLink(sourceFileLink, fileInfo.FullName);


var destinationFileLink = System.IO.Path.Combine(rootDir.Directory.FullName, "DestinationFileLink-ToOriginalFile.txt");

Alphaleonis.Win32.Filesystem.File.Copy(sourceFileLink, destinationFileLink, Alphaleonis.Win32.Filesystem.CopyOptions.CopySymbolicLink);


var lviSrc = Alphaleonis.Win32.Filesystem.File.GetLinkTargetInfo(sourceFileLink);
var lviDst = Alphaleonis.Win32.Filesystem.File.GetLinkTargetInfo(destinationFileLink);

Console.WriteLine("\n\tLink Info of source Link:");
UnitTestConstants.Dump(lviSrc, -14);

Console.WriteLine("\n\tLink Info of copied Link:");
UnitTestConstants.Dump(lviDst, -14);


Assert.AreEqual(lviSrc.PrintName, lviDst.PrintName);
Assert.AreEqual(lviSrc.SubstituteName, lviDst.SubstituteName);
}

Console.WriteLine();
}


private void File_Copy_CatchAlreadyExistsException_DestinationFileAlreadyExists(bool isNetwork)
{
UnitTestConstants.PrintUnitTestHeader(isNetwork);
Expand Down
4 changes: 2 additions & 2 deletions AlphaFS/AlphaFS.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -392,8 +392,8 @@
<Compile Include="Filesystem\Native Methods\NativeMethods.BackupStreams.cs" />
<Compile Include="Filesystem\Native Methods\NativeMethods.Utilities.cs" />
<Compile Include="Filesystem\Native Methods\NativeMethods.PathManagement.cs" />
<Compile Include="Filesystem\Native Structures And Enumerations\MOVE_FILE_OPTIONS.cs" />
<Compile Include="Filesystem\Native Structures And Enumerations\COPY_FILE_OPTIONS.cs" />
<Compile Include="Filesystem\Native Structures And Enumerations\MOVE_FILE_FLAGS.cs" />
<Compile Include="Filesystem\Native Structures And Enumerations\COPY_FILE_FLAGS.cs" />
<Compile Include="Filesystem\Native Structures And Enumerations\FILE_BASIC_INFO.cs" />
<Compile Include="Filesystem\Native Structures And Enumerations\REPARSE_DATA_BUFFER.cs" />
<Compile Include="Filesystem\Native Structures And Enumerations\WIN32_FIND_STREAM_DATA.cs" />
Expand Down
20 changes: 10 additions & 10 deletions AlphaFS/Filesystem/BackupFileStream.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public sealed class BackupFileStream : Stream
/// <remarks>The file will be opened for exclusive access for both reading and writing.</remarks>
[SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope")]
[SecurityCritical]
public BackupFileStream(string path, FileMode mode) : this(File.CreateFileCore(null, path, ExtendedFileAttributes.Normal, null, mode, FileSystemRights.Read | FileSystemRights.Write, FileShare.None, true, PathFormat.RelativePath), FileSystemRights.Read | FileSystemRights.Write)
public BackupFileStream(string path, FileMode mode) : this(File.CreateFileCore(null, path, ExtendedFileAttributes.Normal, null, mode, FileSystemRights.Read | FileSystemRights.Write, FileShare.None, true, false, PathFormat.RelativePath), FileSystemRights.Read | FileSystemRights.Write)
{
}

Expand All @@ -67,7 +67,7 @@ public BackupFileStream(string path, FileMode mode) : this(File.CreateFileCore(n
/// <remarks>The file will be opened for exclusive access.</remarks>
[SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope")]
[SecurityCritical]
public BackupFileStream(string path, FileMode mode, FileSystemRights access) : this(File.CreateFileCore(null, path, ExtendedFileAttributes.Normal, null, mode, access, FileShare.None, true, PathFormat.RelativePath), access)
public BackupFileStream(string path, FileMode mode, FileSystemRights access) : this(File.CreateFileCore(null, path, ExtendedFileAttributes.Normal, null, mode, access, FileShare.None, true, false, PathFormat.RelativePath), access)
{
}

Expand All @@ -79,7 +79,7 @@ public BackupFileStream(string path, FileMode mode, FileSystemRights access) : t
/// <param name="share">A <see cref="FileShare"/> constant that determines how the file will be shared by processes.</param>
[SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope")]
[SecurityCritical]
public BackupFileStream(string path, FileMode mode, FileSystemRights access, FileShare share) : this(File.CreateFileCore(null, path, ExtendedFileAttributes.Normal, null, mode, access, share, true, PathFormat.RelativePath), access)
public BackupFileStream(string path, FileMode mode, FileSystemRights access, FileShare share) : this(File.CreateFileCore(null, path, ExtendedFileAttributes.Normal, null, mode, access, share, true, false, PathFormat.RelativePath), access)
{
}

Expand All @@ -92,7 +92,7 @@ public BackupFileStream(string path, FileMode mode, FileSystemRights access, Fil
/// <param name="attributes">A <see cref="ExtendedFileAttributes"/> constant that specifies additional file attributes.</param>
[SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope")]
[SecurityCritical]
public BackupFileStream(string path, FileMode mode, FileSystemRights access, FileShare share, ExtendedFileAttributes attributes) : this(File.CreateFileCore(null, path, attributes, null, mode, access, share, true, PathFormat.RelativePath), access)
public BackupFileStream(string path, FileMode mode, FileSystemRights access, FileShare share, ExtendedFileAttributes attributes) : this(File.CreateFileCore(null, path, attributes, null, mode, access, share, true, false, PathFormat.RelativePath), access)
{
}

Expand All @@ -106,7 +106,7 @@ public BackupFileStream(string path, FileMode mode, FileSystemRights access, Fil
/// <param name="security">A <see cref="FileSecurity"/> constant that determines the access control and audit security for the file. This parameter This parameter may be <see langword="null"/>.</param>
[SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope")]
[SecurityCritical]
public BackupFileStream(string path, FileMode mode, FileSystemRights access, FileShare share, ExtendedFileAttributes attributes, FileSecurity security) : this(File.CreateFileCore(null, path, attributes, security, mode, access, share, true, PathFormat.RelativePath), access)
public BackupFileStream(string path, FileMode mode, FileSystemRights access, FileShare share, ExtendedFileAttributes attributes, FileSecurity security) : this(File.CreateFileCore(null, path, attributes, security, mode, access, share, true, false, PathFormat.RelativePath), access)
{
}

Expand All @@ -118,7 +118,7 @@ public BackupFileStream(string path, FileMode mode, FileSystemRights access, Fil
/// <remarks>The file will be opened for exclusive access for both reading and writing.</remarks>
[SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope")]
[SecurityCritical]
public BackupFileStream(KernelTransaction transaction, string path, FileMode mode) : this(File.CreateFileCore(transaction, path, ExtendedFileAttributes.Normal, null, mode, FileSystemRights.Read | FileSystemRights.Write, FileShare.None, true, PathFormat.RelativePath), FileSystemRights.Read | FileSystemRights.Write)
public BackupFileStream(KernelTransaction transaction, string path, FileMode mode) : this(File.CreateFileCore(transaction, path, ExtendedFileAttributes.Normal, null, mode, FileSystemRights.Read | FileSystemRights.Write, FileShare.None, true, false, PathFormat.RelativePath), FileSystemRights.Read | FileSystemRights.Write)
{
}

Expand All @@ -131,7 +131,7 @@ public BackupFileStream(KernelTransaction transaction, string path, FileMode mod
/// <remarks>The file will be opened for exclusive access.</remarks>
[SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope")]
[SecurityCritical]
public BackupFileStream(KernelTransaction transaction, string path, FileMode mode, FileSystemRights access) : this(File.CreateFileCore(transaction, path, ExtendedFileAttributes.Normal, null, mode, access, FileShare.None, true, PathFormat.RelativePath), access)
public BackupFileStream(KernelTransaction transaction, string path, FileMode mode, FileSystemRights access) : this(File.CreateFileCore(transaction, path, ExtendedFileAttributes.Normal, null, mode, access, FileShare.None, true, false, PathFormat.RelativePath), access)
{
}

Expand All @@ -144,7 +144,7 @@ public BackupFileStream(KernelTransaction transaction, string path, FileMode mod
/// <param name="share">A <see cref="FileShare"/> constant that determines how the file will be shared by processes.</param>
[SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope")]
[SecurityCritical]
public BackupFileStream(KernelTransaction transaction, string path, FileMode mode, FileSystemRights access, FileShare share) : this(File.CreateFileCore(transaction, path, ExtendedFileAttributes.Normal, null, mode, access, share, true, PathFormat.RelativePath), access)
public BackupFileStream(KernelTransaction transaction, string path, FileMode mode, FileSystemRights access, FileShare share) : this(File.CreateFileCore(transaction, path, ExtendedFileAttributes.Normal, null, mode, access, share, true, false, PathFormat.RelativePath), access)
{
}

Expand All @@ -158,7 +158,7 @@ public BackupFileStream(KernelTransaction transaction, string path, FileMode mod
/// <param name="attributes">A <see cref="ExtendedFileAttributes"/> constant that specifies additional file attributes.</param>
[SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope")]
[SecurityCritical]
public BackupFileStream(KernelTransaction transaction, string path, FileMode mode, FileSystemRights access, FileShare share, ExtendedFileAttributes attributes) : this(File.CreateFileCore(transaction, path, attributes, null, mode, access, share, true, PathFormat.RelativePath), access)
public BackupFileStream(KernelTransaction transaction, string path, FileMode mode, FileSystemRights access, FileShare share, ExtendedFileAttributes attributes) : this(File.CreateFileCore(transaction, path, attributes, null, mode, access, share, true, false, PathFormat.RelativePath), access)
{
}

Expand All @@ -173,7 +173,7 @@ public BackupFileStream(KernelTransaction transaction, string path, FileMode mod
/// <param name="security">A <see cref="FileSecurity"/> constant that determines the access control and audit security for the file. This parameter This parameter may be <see langword="null"/>.</param>
[SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope")]
[SecurityCritical]
public BackupFileStream(KernelTransaction transaction, string path, FileMode mode, FileSystemRights access, FileShare share, ExtendedFileAttributes attributes, FileSecurity security) : this(File.CreateFileCore(transaction, path, attributes, security, mode, access, share, true, PathFormat.RelativePath), access)
public BackupFileStream(KernelTransaction transaction, string path, FileMode mode, FileSystemRights access, FileShare share, ExtendedFileAttributes attributes, FileSecurity security) : this(File.CreateFileCore(transaction, path, attributes, security, mode, access, share, true, false, PathFormat.RelativePath), access)
{
}

Expand Down
2 changes: 1 addition & 1 deletion AlphaFS/Filesystem/Device.cs
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ private static byte[] InvokeIoControlUnknownSize<T>(SafeFileHandle handle, uint
[SecurityCritical]
internal static void ToggleCompressionCore(KernelTransaction transaction, bool isFolder, string path, bool compress, PathFormat pathFormat)
{
using (var handle = File.CreateFileCore(transaction, path, isFolder ? ExtendedFileAttributes.BackupSemantics : ExtendedFileAttributes.Normal, null, FileMode.Open, FileSystemRights.Modify, FileShare.None, true, pathFormat))
using (var handle = File.CreateFileCore(transaction, path, isFolder ? ExtendedFileAttributes.BackupSemantics : ExtendedFileAttributes.Normal, null, FileMode.Open, FileSystemRights.Modify, FileShare.None, true, false, pathFormat))
InvokeIoControlUnknownSize(handle, NativeMethods.FSCTL_SET_COMPRESSION, compress ? 1 : 0);
}

Expand Down
Loading

0 comments on commit 097fca1

Please sign in to comment.