mirror of https://github.com/raandree/NTFSSecurity
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
111 lines
3.7 KiB
111 lines
3.7 KiB
using Alphaleonis.Win32.Filesystem;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Management.Automation;
|
|
|
|
namespace NTFSSecurity
|
|
{
|
|
[Cmdlet(VerbsCommon.New, "NTFSHardLink")]
|
|
[OutputType(typeof(FileInfo), typeof(DirectoryInfo))]
|
|
public class NewHardLink : BaseCmdlet
|
|
{
|
|
string target;
|
|
private bool passThru;
|
|
System.Reflection.MethodInfo modeMethodInfo = null;
|
|
|
|
[Parameter(Position = 1, ValueFromPipeline = true, ValueFromPipelineByPropertyName = true)]
|
|
[ValidateNotNullOrEmpty]
|
|
[Alias("FullName")]
|
|
[FileSystemPathTransformation]
|
|
public string Path
|
|
{
|
|
get { return paths[0]; }
|
|
set
|
|
{
|
|
paths.Clear();
|
|
paths.Add(value);
|
|
}
|
|
}
|
|
|
|
[Parameter(Position = 2, ValueFromPipeline = true, ValueFromPipelineByPropertyName = true)]
|
|
[ValidateNotNullOrEmpty]
|
|
[FileSystemPathTransformation]
|
|
public string Target
|
|
{
|
|
get { return target; }
|
|
set { target = value; }
|
|
}
|
|
|
|
[Parameter]
|
|
public SwitchParameter PassThru
|
|
{
|
|
get { return passThru; }
|
|
set { passThru = value; }
|
|
}
|
|
|
|
protected override void BeginProcessing()
|
|
{
|
|
base.BeginProcessing();
|
|
|
|
modeMethodInfo = typeof(FileSystemCodeMembers).GetMethod("Mode");
|
|
}
|
|
|
|
protected override void ProcessRecord()
|
|
{
|
|
var path = paths[0];
|
|
|
|
path = GetRelativePath(path);
|
|
target = GetRelativePath(target);
|
|
var root = System.IO.Path.GetPathRoot(path);
|
|
|
|
try
|
|
{
|
|
FileSystemInfo temp = null;
|
|
|
|
if (TryGetFileSystemInfo2(path, out temp))
|
|
throw new ArgumentException(string.Format("The file '{0}' does already exist, cannot create the link", path));
|
|
|
|
if (!TryGetFileSystemInfo2(target, out temp))
|
|
throw new ArgumentException(string.Format("The target '{0}' does not exist, cannot create the link", target));
|
|
else
|
|
if (temp is DirectoryInfo)
|
|
throw new ArgumentException("The target is not a file, cannot create the link");
|
|
|
|
File.CreateHardlink(path, target);
|
|
|
|
if (passThru)
|
|
{
|
|
IEnumerable<string> links;
|
|
try
|
|
{
|
|
links = File.EnumerateHardlinks(path).ToList();
|
|
}
|
|
// Windows can't list the names of a file on a network share: (50) The request is not supported.
|
|
// The link exists; before 5.0.0-rc6, this stopped the cmdlet with a terminating error.
|
|
catch (System.IO.IOException ex)
|
|
{
|
|
WriteError(new ErrorRecord(ex, "GetHardLinkError", ErrorCategory.ReadError, path));
|
|
return;
|
|
}
|
|
|
|
foreach (var link in links)
|
|
{
|
|
var target = new PSObject(GetFileSystemInfo2(System.IO.Path.Combine(root, link.Substring(1))));
|
|
target.Properties.Add(new PSCodeProperty("Mode", modeMethodInfo));
|
|
WriteObject(target);
|
|
}
|
|
}
|
|
}
|
|
catch (System.IO.FileNotFoundException ex)
|
|
{
|
|
WriteError(new ErrorRecord(ex, "CreateHardLinkError", ErrorCategory.WriteError, path));
|
|
}
|
|
}
|
|
|
|
protected override void EndProcessing()
|
|
{
|
|
base.EndProcessing();
|
|
}
|
|
}
|
|
}
|
|
|