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

Fix CreateJunction when the target is a volume-prefixed path #517

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion src/AlphaFS/Device/Device.cs
Original file line number Diff line number Diff line change
@@ -352,7 +352,12 @@ internal static void ToggleCompressionCore(KernelTransaction transaction, bool i
/// <summary>[AlphaFS] Creates an NTFS directory junction (similar to CMD command: "MKLINK /J").</summary>
internal static void CreateDirectoryJunction(SafeFileHandle safeHandle, string directoryPath)
{
var targetDirBytes = Encoding.Unicode.GetBytes(Path.NonInterpretedPathPrefix + Path.GetRegularPathCore(directoryPath, GetFullPathOptions.AddTrailingDirectorySeparator, false));
var targetDir = Path.GetRegularPathCore(directoryPath, GetFullPathOptions.AddTrailingDirectorySeparator, false);
// junctions to volume-prefixed paths need the long path prefix removed. Correct: \??\Volume{000...}\foo, wrong: \??\\\?\Volume{000...}\foo
if (targetDir.StartsWith(Path.VolumePrefix))
targetDir = targetDir.Substring(Path.LongPathPrefix.Length);
targetDir = Path.NonInterpretedPathPrefix + targetDir;
var targetDirBytes = Encoding.Unicode.GetBytes(targetDir);

var header = new NativeMethods.ReparseDataBufferHeader
{
Original file line number Diff line number Diff line change
@@ -31,20 +31,41 @@ public partial class AlphaFS_JunctionsLinksTest

[TestMethod]
public void AlphaFS_DirectoryInfo_CreateJunction_And_ExistsJunction_And_DeleteJunction_Local_Success()
{
AlphaFS_DirectoryInfo_CreateJunction_And_ExistsJunction_And_DeleteJunction_Local_Success_core(false);
}

[TestMethod]
public void AlphaFS_DirectoryInfo_CreateJunction_And_ExistsJunction_And_DeleteJunction_Local_VolumePath_Success()
{
AlphaFS_DirectoryInfo_CreateJunction_And_ExistsJunction_And_DeleteJunction_Local_Success_core(true);
}

private void AlphaFS_DirectoryInfo_CreateJunction_And_ExistsJunction_And_DeleteJunction_Local_Success_core(bool volumeTarget)
{
using (var tempRoot = new TemporaryDirectory())
{
var toDelete = tempRoot.Directory.CreateSubdirectory("ToDelete");
var junction = System.IO.Path.Combine(toDelete.FullName, "MyJunctionPoint");
var target = tempRoot.Directory.CreateSubdirectory("JunctionTarget");
var target = tempRoot.Directory.CreateSubdirectory("JunctionTarget").FullName;

if (volumeTarget)
{
var volumeGuidPath = Alphaleonis.Win32.Filesystem.Volume.GetUniqueVolumeNameForPath(target);
var volumePath = Alphaleonis.Win32.Filesystem.Volume.GetVolumePathName(target);
var targetNew = target.Replace(volumePath, volumeGuidPath);
if (targetNew == target || !targetNew.StartsWith(Alphaleonis.Win32.Filesystem.Path.VolumePrefix))
Assert.Inconclusive(@"Failed to construct a \\?\Volume style path for this test");
target = targetNew;
}

Console.WriteLine("Input Directory JunctionPoint Path: [{0}]", junction);
Console.WriteLine("Input Directory JunctionTarget Path: [{0}]", target);


#region CreateJunction

var dirInfo = new Alphaleonis.Win32.Filesystem.DirectoryInfo(target.FullName);
var dirInfo = new Alphaleonis.Win32.Filesystem.DirectoryInfo(target);


// On success, dirInfo.FullName now points to the directory junction.
@@ -87,7 +108,7 @@ public void AlphaFS_DirectoryInfo_CreateJunction_And_ExistsJunction_And_DeleteJu
const string subFolder = "Test folder";
dirInfo.CreateSubdirectory(subFolder);

Assert.IsTrue(System.IO.Directory.Exists(System.IO.Path.Combine(target.FullName, subFolder)));
Assert.IsTrue(System.IO.Directory.Exists(System.IO.Path.Combine(target, subFolder)));

#endregion // CreateJunction