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

Commit

Permalink
add - Added parameters support for the magic helper
Browse files Browse the repository at this point in the history
---

We've added support for libmagic parameters for customizability.

---

Type: add
Breaking: False
Doc Required: False
Part: 1/1
  • Loading branch information
AptiviCEO committed Mar 25, 2024
1 parent 3f2bb3c commit 88ae1b1
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 19 deletions.
4 changes: 2 additions & 2 deletions FileMagic.Native/Interop/MagicHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -125,13 +125,13 @@ internal static unsafe class MagicHelper
/// file_public int magic_setparam(struct magic_set *ms, int param, const void *val)
/// </summary>
[DllImport("libmagic")]
public static extern int magic_setparam(MagicSet* ms, MagicParameters param, [In] IntPtr val);
public static extern int magic_setparam(MagicSet* ms, MagicParameters param, IntPtr val);

/// <summary>
/// file_public int magic_getparam(struct magic_set *ms, int param, void *val)
/// </summary>
[DllImport("libmagic")]
public static extern int magic_getparam(MagicSet* ms, MagicParameters param, [Out] IntPtr val);
public static extern int magic_getparam(MagicSet* ms, MagicParameters param, IntPtr val);

internal static string GetError(MagicSet* handle)
{
Expand Down
4 changes: 4 additions & 0 deletions FileMagic.Native/Interop/MagicParameters.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ namespace FileMagic.Native.Interop
/// </summary>
public enum MagicParameters
{
/// <summary>
/// No parameters
/// </summary>
None = -1,
/// <summary>
/// #define MAGIC_PARAM_INDIR_MAX 0
/// </summary>
Expand Down
77 changes: 60 additions & 17 deletions FileMagic/MagicHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,65 +37,81 @@ public static class MagicHandler
/// Gets the file magic information
/// </summary>
/// <param name="filePath">Target file path</param>
public static string GetMagicInfo(string filePath) =>
GetMagicInfo(filePath, magicPathDefault);
/// <param name="parameter">Parameter to use</param>
/// <param name="paramValue">Parameter value to set to</param>
public static string GetMagicInfo(string filePath, MagicParameters parameter = MagicParameters.None, int paramValue = 0) =>
GetMagicInfo(filePath, magicPathDefault, parameter, paramValue);

/// <summary>
/// Gets the file magic information
/// </summary>
/// <param name="filePath">Target file path</param>
/// <param name="magicPath">Path to the file magic database</param>
public static string GetMagicInfo(string filePath, string magicPath) =>
HandleMagic(filePath, !string.IsNullOrEmpty(magicPath) ? magicPath : magicPathDefault, MagicFlags.None);
/// <param name="parameter">Parameter to use</param>
/// <param name="paramValue">Parameter value to set to</param>
public static string GetMagicInfo(string filePath, string magicPath, MagicParameters parameter = MagicParameters.None, int paramValue = 0) =>
HandleMagic(filePath, !string.IsNullOrEmpty(magicPath) ? magicPath : magicPathDefault, MagicFlags.None, parameter, paramValue);

/// <summary>
/// Gets the file magic Mime information
/// </summary>
/// <param name="filePath">Target file path</param>
public static string GetMagicMimeInfo(string filePath) =>
GetMagicMimeInfo(filePath, magicPathDefault);
/// <param name="parameter">Parameter to use</param>
/// <param name="paramValue">Parameter value to set to</param>
public static string GetMagicMimeInfo(string filePath, MagicParameters parameter = MagicParameters.None, int paramValue = 0) =>
GetMagicMimeInfo(filePath, magicPathDefault, parameter, paramValue);

/// <summary>
/// Gets the file magic Mime information
/// </summary>
/// <param name="filePath">Target file path</param>
/// <param name="magicPath">Path to the file magic database</param>
public static string GetMagicMimeInfo(string filePath, string magicPath) =>
HandleMagic(filePath, !string.IsNullOrEmpty(magicPath) ? magicPath : magicPathDefault, MagicFlags.Mime);
/// <param name="parameter">Parameter to use</param>
/// <param name="paramValue">Parameter value to set to</param>
public static string GetMagicMimeInfo(string filePath, string magicPath, MagicParameters parameter = MagicParameters.None, int paramValue = 0) =>
HandleMagic(filePath, !string.IsNullOrEmpty(magicPath) ? magicPath : magicPathDefault, MagicFlags.Mime, parameter, paramValue);

/// <summary>
/// Gets the file magic Mime type information
/// </summary>
/// <param name="filePath">Target file path</param>
public static string GetMagicMimeType(string filePath) =>
GetMagicMimeType(filePath, magicPathDefault);
/// <param name="parameter">Parameter to use</param>
/// <param name="paramValue">Parameter value to set to</param>
public static string GetMagicMimeType(string filePath, MagicParameters parameter = MagicParameters.None, int paramValue = 0) =>
GetMagicMimeType(filePath, magicPathDefault, parameter, paramValue);

/// <summary>
/// Gets the file magic Mime type information
/// </summary>
/// <param name="filePath">Target file path</param>
/// <param name="magicPath">Path to the file magic database</param>
public static string GetMagicMimeType(string filePath, string magicPath) =>
HandleMagic(filePath, !string.IsNullOrEmpty(magicPath) ? magicPath : magicPathDefault, MagicFlags.MimeType);
/// <param name="parameter">Parameter to use</param>
/// <param name="paramValue">Parameter value to set to</param>
public static string GetMagicMimeType(string filePath, string magicPath, MagicParameters parameter = MagicParameters.None, int paramValue = 0) =>
HandleMagic(filePath, !string.IsNullOrEmpty(magicPath) ? magicPath : magicPathDefault, MagicFlags.MimeType, parameter, paramValue);

/// <summary>
/// Gets the file magic Mime type information
/// </summary>
/// <param name="filePath">Target file path</param>
/// <param name="flags">Magic flags to customize the output and the behavior of the native library</param>
public static string GetMagicCustomType(string filePath, MagicFlags flags) =>
GetMagicCustomType(filePath, magicPathDefault, flags);
/// <param name="parameter">Parameter to use</param>
/// <param name="paramValue">Parameter value to set to</param>
public static string GetMagicCustomType(string filePath, MagicFlags flags, MagicParameters parameter = MagicParameters.None, int paramValue = 0) =>
GetMagicCustomType(filePath, magicPathDefault, flags, parameter, paramValue);

/// <summary>
/// Gets the file magic Mime type information
/// </summary>
/// <param name="filePath">Target file path</param>
/// <param name="magicPath">Path to the file magic database</param>
/// <param name="flags">Magic flags to customize the output and the behavior of the native library</param>
public static string GetMagicCustomType(string filePath, string magicPath, MagicFlags flags) =>
HandleMagic(filePath, !string.IsNullOrEmpty(magicPath) ? magicPath : magicPathDefault, flags);
/// <param name="parameter">Parameter to use</param>
/// <param name="paramValue">Parameter value to set to</param>
public static string GetMagicCustomType(string filePath, string magicPath, MagicFlags flags, MagicParameters parameter = MagicParameters.None, int paramValue = 0) =>
HandleMagic(filePath, !string.IsNullOrEmpty(magicPath) ? magicPath : magicPathDefault, flags, parameter, paramValue);

internal static string HandleMagic(string filePath, string magicPath, MagicFlags flags)
internal static string HandleMagic(string filePath, string magicPath, MagicFlags flags, MagicParameters parameter = MagicParameters.None, int paramValue = 0)
{
IntPtr magicStringHandle;

Expand All @@ -111,6 +127,33 @@ internal static string HandleMagic(string filePath, string magicPath, MagicFlags
// Open the magic handle
var handle = MagicHelper.magic_open(flags);

// Check to see if we're going to set the parameter
if (parameter != MagicParameters.None)
{
var valuePtr = (IntPtr)paramValue;
var valueHandle = Marshal.AllocHGlobal(IntPtr.Size);
var valueHandleResult = Marshal.AllocHGlobal(IntPtr.Size);
Marshal.WriteIntPtr(valueHandle, valuePtr);

// Set the parameter
int paramResult = MagicHelper.magic_setparam(handle, parameter, valueHandle);
if (paramResult != 0)
throw new MagicException($"Failed to set parameter {parameter} to {paramValue}: [{MagicHelper.GetErrorNumber(handle)}] {MagicHelper.GetError(handle)}");

// Validate the parameter
IntPtr result;
int paramGetResult = MagicHelper.magic_getparam(handle, parameter, valueHandleResult);
if (paramGetResult != 0)
throw new MagicException($"Failed to get parameter {parameter} value: [{MagicHelper.GetErrorNumber(handle)}] {MagicHelper.GetError(handle)}");
result = Marshal.ReadIntPtr(valueHandleResult);
if (result != valuePtr)
throw new MagicException($"Failed to validate parameter {parameter} for value {paramValue} (got {result}): [{MagicHelper.GetErrorNumber(handle)}] {MagicHelper.GetError(handle)}");

// Free the addresses
Marshal.FreeHGlobal(valueHandle);
Marshal.FreeHGlobal(valueHandleResult);
}

// Use this handle to load the magic database
int loadResult = MagicHelper.magic_load(handle, magicPath);
if (loadResult != 0)
Expand Down

0 comments on commit 88ae1b1

Please sign in to comment.