mirror of
https://github.com/revenz/FileFlowsPlugins.git
synced 2025-12-29 10:49:31 -06:00
FF-1347 - added has hard links
This commit is contained in:
@@ -101,7 +101,18 @@
|
||||
},
|
||||
"Fields": {
|
||||
"FileName": "File Name",
|
||||
"FileName-Help": "The file to check if exists. This should be used with a variable from a previous node."
|
||||
"FileName-Help": "The file to check. Leave empty to check the current working file."
|
||||
}
|
||||
},
|
||||
"HasHardLinks": {
|
||||
"Description": "Checks if a file has hard links to it or not",
|
||||
"Outputs": {
|
||||
"1": "Hard links detected",
|
||||
"2": "No hard links detected"
|
||||
},
|
||||
"Fields": {
|
||||
"FileName": "File Name",
|
||||
"FileName-Help": "The file to check. Leave empty to check the current working file."
|
||||
}
|
||||
},
|
||||
"Delete": {
|
||||
|
||||
@@ -1,27 +1,42 @@
|
||||
namespace FileFlows.BasicNodes.File;
|
||||
using FileFlows.Plugin;
|
||||
using FileFlows.Plugin.Attributes;
|
||||
|
||||
namespace FileFlows.BasicNodes.File;
|
||||
|
||||
/// <summary>
|
||||
/// Checks if a file exists
|
||||
/// </summary>
|
||||
public class FileExists: Node
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override int Inputs => 1;
|
||||
/// <inheritdoc />
|
||||
public override int Outputs => 2;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override FlowElementType Type => FlowElementType.Logic;
|
||||
/// <inheritdoc />
|
||||
public override string Icon => "fas fa-question-circle";
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string HelpUrl => "https://fileflows.com/docs/plugins/basic-nodes/file-exists";
|
||||
/// <inheritdoc />
|
||||
public override bool NoEditorOnAdd => true;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name of the file to check
|
||||
/// Leave blank to test the working file
|
||||
/// </summary>
|
||||
[TextVariable(1)]
|
||||
public string FileName { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override int Execute(NodeParameters args)
|
||||
{
|
||||
string file = args.ReplaceVariables(FileName ?? string.Empty, true);
|
||||
string file = args.ReplaceVariables(FileName ?? string.Empty, true)?.EmptyAsNull() ?? args.WorkingFile;
|
||||
if(string.IsNullOrWhiteSpace(file))
|
||||
{
|
||||
args.Logger?.ELog("FileName not set");
|
||||
args.FailureReason = "FileName not set";
|
||||
args.Logger?.ELog(args.FailureReason);
|
||||
return -1;
|
||||
}
|
||||
try
|
||||
@@ -37,7 +52,8 @@ public class FileExists: Node
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
args.Logger?.ELog($"Failed testing if file '{file}' exists: " + ex.Message);
|
||||
args.FailureReason = $"Failed testing if file '{file}' exists: " + ex.Message;
|
||||
args.Logger?.ELog(args.FailureReason);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
187
BasicNodes/File/HasHardLinks.cs
Normal file
187
BasicNodes/File/HasHardLinks.cs
Normal file
@@ -0,0 +1,187 @@
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using FileFlows.Plugin;
|
||||
using FileFlows.Plugin.Attributes;
|
||||
|
||||
namespace FileFlows.BasicNodes.File;
|
||||
|
||||
/// <summary>
|
||||
/// Checks if a file has hard links
|
||||
/// </summary>
|
||||
public class HasHardLinks: Node
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override int Inputs => 1;
|
||||
/// <inheritdoc />
|
||||
public override int Outputs => 2;
|
||||
/// <inheritdoc />
|
||||
public override FlowElementType Type => FlowElementType.Logic;
|
||||
/// <inheritdoc />
|
||||
public override string Icon => "fas fa-link";
|
||||
/// <inheritdoc />
|
||||
public override string HelpUrl => "https://fileflows.com/docs/plugins/basic-nodes/has-hard-links";
|
||||
/// <inheritdoc />
|
||||
public override bool NoEditorOnAdd => true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name of the file to check
|
||||
/// Leave blank to test the working file
|
||||
/// </summary>
|
||||
[TextVariable(1)]
|
||||
public string FileName { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override int Execute(NodeParameters args)
|
||||
{
|
||||
string file = args.ReplaceVariables(FileName ?? string.Empty, true)?.EmptyAsNull() ?? args.WorkingFile;
|
||||
if(string.IsNullOrWhiteSpace(file))
|
||||
{
|
||||
args.FailureReason = "FileName not set";
|
||||
args.Logger?.ELog(args.FailureReason);
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool hasHardLinks = false;
|
||||
if (OperatingSystem.IsWindows())
|
||||
hasHardLinks = HasHardLinkWindows(args, file);
|
||||
else if(OperatingSystem.IsLinux())
|
||||
hasHardLinks = HasHardLinkLinux(args, file);
|
||||
else if(OperatingSystem.IsMacOS())
|
||||
hasHardLinks = HasHardLinkMacOS(args, file);
|
||||
else
|
||||
{
|
||||
args.Logger?.WLog("Unable to determine operating system to check for hard links");
|
||||
}
|
||||
|
||||
return hasHardLinks ? 1 : 2;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Checks if a file has hard links on Windows.
|
||||
/// </summary>
|
||||
/// <param name="args">Node parameters containing logger.</param>
|
||||
/// <param name="file">File path to check for hard links.</param>
|
||||
/// <returns>True if the file has hard links; otherwise, false.</returns>
|
||||
bool HasHardLinkWindows(NodeParameters args, string file)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Get file attributes
|
||||
FileAttributes attributes = System.IO.File.GetAttributes(file);
|
||||
|
||||
// Check if the file has the ReparsePoint or Directory flags set
|
||||
// A file with these flags set may have hard links
|
||||
if ((attributes & FileAttributes.ReparsePoint) == FileAttributes.ReparsePoint ||
|
||||
(attributes & FileAttributes.Directory) == FileAttributes.Directory)
|
||||
{
|
||||
args.Logger?.ILog("The file may have hard links.");
|
||||
return true;
|
||||
}
|
||||
|
||||
args.Logger?.ILog("The file does not appear to have hard links.");
|
||||
return false;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
args.Logger?.WLog("Failed to test if file has hard links: " + ex.Message);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if a file has hard links on Linux.
|
||||
/// </summary>
|
||||
/// <param name="args">Node parameters containing logger.</param>
|
||||
/// <param name="file">File path to check for hard links.</param>
|
||||
/// <returns>True if the file has hard links; otherwise, false.</returns>
|
||||
bool HasHardLinkLinux(NodeParameters args, string file)
|
||||
{
|
||||
try
|
||||
{
|
||||
Process process = new Process();
|
||||
process.StartInfo.FileName = "stat";
|
||||
process.StartInfo.ArgumentList.Add("-c");
|
||||
process.StartInfo.ArgumentList.Add("%h");
|
||||
process.StartInfo.ArgumentList.Add(file);
|
||||
process.StartInfo.RedirectStandardOutput = true;
|
||||
process.StartInfo.RedirectStandardError = true;
|
||||
process.StartInfo.UseShellExecute = false;
|
||||
process.StartInfo.CreateNoWindow = true;
|
||||
|
||||
process.Start();
|
||||
string output = process.StandardOutput.ReadToEnd();
|
||||
string error = process.StandardError.ReadToEnd();
|
||||
process.WaitForExit();
|
||||
|
||||
int linkCount;
|
||||
if (int.TryParse(output.Trim(), out linkCount))
|
||||
{
|
||||
if (linkCount > 1)
|
||||
{
|
||||
args.Logger?.ILog("The file has hard links.");
|
||||
return true;
|
||||
}
|
||||
args.Logger?.ILog("The file does not have hard links.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(string.IsNullOrWhiteSpace(error))
|
||||
args.Logger?.ELog(error);
|
||||
|
||||
args.Logger?.ILog("Failed to retrieve link count.");
|
||||
return false;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
args.Logger?.ELog($"An error occurred: {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if a file has hard links on macOS.
|
||||
/// </summary>
|
||||
/// <param name="args">Node parameters containing logger.</param>
|
||||
/// <param name="file">File path to check for hard links.</param>
|
||||
/// <returns>True if the file has hard links; otherwise, false.</returns>
|
||||
public bool HasHardLinkMacOS(NodeParameters args, string file)
|
||||
{
|
||||
try
|
||||
{
|
||||
Process process = new Process();
|
||||
process.StartInfo.FileName = "stat";
|
||||
process.StartInfo.ArgumentList.Add("-f");
|
||||
process.StartInfo.ArgumentList.Add("%l");
|
||||
process.StartInfo.ArgumentList.Add(file);
|
||||
process.StartInfo.RedirectStandardOutput = true;
|
||||
process.StartInfo.UseShellExecute = false;
|
||||
process.StartInfo.CreateNoWindow = true;
|
||||
|
||||
process.Start();
|
||||
string output = process.StandardOutput.ReadToEnd();
|
||||
process.WaitForExit();
|
||||
|
||||
int linkCount;
|
||||
if (int.TryParse(output.Trim(), out linkCount))
|
||||
{
|
||||
if (linkCount > 1)
|
||||
{
|
||||
args.Logger?.ILog("The file has hard links.");
|
||||
return true;
|
||||
}
|
||||
args.Logger?.ILog("The file does not have hard links.");
|
||||
return false;
|
||||
}
|
||||
|
||||
args.Logger?.ILog("Failed to retrieve link count.");
|
||||
return false;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
args.Logger?.ELog($"An error occurred: {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
36
BasicNodes/Tests/HasHardLinksTest.cs
Normal file
36
BasicNodes/Tests/HasHardLinksTest.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
#if(DEBUG)
|
||||
|
||||
namespace BasicNodes.Tests;
|
||||
|
||||
using FileFlows.BasicNodes.File;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
[TestClass]
|
||||
public class HasHardLinksTest
|
||||
{
|
||||
[TestMethod]
|
||||
public void HasHardLink()
|
||||
{
|
||||
var logger = new TestLogger();
|
||||
var args = new FileFlows.Plugin.NodeParameters(@"/home/john/temp/test.file", logger, false, string.Empty, new LocalFileService());;
|
||||
|
||||
HasHardLinks element = new ();
|
||||
|
||||
var result = element.Execute(args);
|
||||
Assert.AreEqual(1, result);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void NoHardLinks()
|
||||
{
|
||||
var logger = new TestLogger();
|
||||
var args = new FileFlows.Plugin.NodeParameters(@"/home/john/temp/other.test", logger, false, string.Empty, new LocalFileService());;
|
||||
|
||||
HasHardLinks element = new ();
|
||||
|
||||
var result = element.Execute(args);
|
||||
Assert.AreEqual(2, result);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user