From 70ca1f65dbe7fdfb17893ec730424dc3c610f8b2 Mon Sep 17 00:00:00 2001 From: code liturgy Date: Fri, 11 Nov 2022 17:08:45 -0500 Subject: [PATCH] Add match and fix some bugs --- Sharp.Augeas.Test/AugeasTests.cs | 32 +++++--- Sharp.Augeas/Augeas/Augeas.cs | 117 +++++++++++++++++++++++----- Sharp.Augeas/Augeas/AugeasExtern.cs | 28 ++++++- 3 files changed, 144 insertions(+), 33 deletions(-) diff --git a/Sharp.Augeas.Test/AugeasTests.cs b/Sharp.Augeas.Test/AugeasTests.cs index 03efea3..c87a24a 100644 --- a/Sharp.Augeas.Test/AugeasTests.cs +++ b/Sharp.Augeas.Test/AugeasTests.cs @@ -10,6 +10,10 @@ public class AugeasTests var rootDir = Environment.CurrentDirectory + "/root"; var lensDir = Environment.CurrentDirectory + "/lens"; _augeas = new Augeas(new AugSettings(rootDir, lensDir)); + _augeas.LoadFile("/etc/apache2/sites-available/00-ci.codeliturgy.com.conf"); + _augeas.LoadFile("/etc/apache2/sites-available/02-codeliturgy.com.conf"); + + // Load a bunch of files } [Test] @@ -19,8 +23,7 @@ public class AugeasTests _augeas.PrintVirtualHostTree(virtualHostConfig); Assert.Pass(); } - - + [Test] public void NoExceptionThrownWhenPrintingPreview() { @@ -29,27 +32,34 @@ public class AugeasTests Assert.Pass(); } - - + [Test] public void GetPreviewReturnsValid() { - _ = _augeas.LoadFile("/etc/apache2/sites-available/00-ci.codeliturgy.com.conf"); - var preview = _augeas.GetPreview("/files/etc/apache2/sites-available/00-ci.codeliturgy.com.conf/*"); + + var preview = _augeas.GetPreview("/files/etc/apache2/sites-available/00-ci.codeliturgy.com.conf"); var stringInvalid = string.IsNullOrEmpty(preview); Assert.That(!stringInvalid); } - + [Test] - public void GetTreeVirtualHostReturnsDictionaryWithKeys() + public void MatchReturnsTwoSites() { - var virtualHostConfig = "/etc/apache2/sites-available/00-ci.codeliturgy.com.conf"; - var tree = _augeas.GetVirtualHostTree(virtualHostConfig); - Assert.That(tree.Count > 0); + var sites = _augeas.Match("/files/etc/apache2/sites-available/*"); + Assert.That(sites.Length == 2); } + + [Test] + public void GetTreeVirtualHostReturnsDictionaryWithKeys() + { + var path = "/etc/apache2/sites-available/00-ci.codeliturgy.com.conf"; + var tree = _augeas.GetVirtualHostTree(path); + Assert.That(tree.Count > 0); + } + } \ No newline at end of file diff --git a/Sharp.Augeas/Augeas/Augeas.cs b/Sharp.Augeas/Augeas/Augeas.cs index 8e1a435..7eff32f 100644 --- a/Sharp.Augeas/Augeas/Augeas.cs +++ b/Sharp.Augeas/Augeas/Augeas.cs @@ -6,9 +6,13 @@ namespace Sharp.Augeas /// /// Augeas Core containing the settings of this instance. /// - public sealed class Augeas + public sealed unsafe class Augeas { + #region Flags + /// + /// + /// public static int NONE = 0; public static int SAVE_BACKUP = (1 << 0); public static int SAVE_NEWFILE = (1 << 1); @@ -20,6 +24,7 @@ namespace Sharp.Augeas public static int NO_MODL_AUTOLOAD = (1 << 6); public static int AUG_ENABLE_SPAN = (1 << 7); #endregion Flags + private readonly IntPtr _augeas; private HashSet _loadedFiles = new(); @@ -81,8 +86,7 @@ namespace Sharp.Augeas /// /// Prints a preview of the desired segment in /// - /// Augeas path to filter out the configuration - /// The actual configuration file path + /// Augeas path. public void PrintPreview(string matchPath) { print_preview(_augeas, matchPath); @@ -92,21 +96,13 @@ namespace Sharp.Augeas /// Get the exact value of the matchPath. /// Returns a empty string if no match is valid. /// - /// Augeas path to filter out the configuration. + /// Augeas path. public string GetNode(string matchPath) { var res = get_node(_augeas, matchPath); return res != IntPtr.Zero ? Marshal.PtrToStringAnsi(res) : string.Empty; } - - /// - /// Loads a file. - /// - /// - /// - - /// /// Binding for aug_load_file /// @@ -147,7 +143,7 @@ namespace Sharp.Augeas /// /// Returns the tree given the augeas configuration path. /// - /// configuration path. + /// Configuration path. /// Dictionary with the Tree private Dictionary GetTree(string matchPath) { @@ -166,13 +162,51 @@ namespace Sharp.Augeas FreeString(raw); return result; } - + + /// + /// Sets a value of exactly one node. + /// + /// Configuration path. + /// The value to set. + /// True if the value was set. + public bool SetNode(string matchPath, string value) + { + bool success = set_node(_augeas, matchPath, value); + return success; + } + + /// + /// Removes a node from the tree given the + /// + /// Configuration path. + /// Removed nodes count. + public int RemoveNode(string matchPath) + { + int removedCount = rm_node(_augeas, matchPath); + return removedCount; + } + + + + /// + /// Write all pending changes to disk. Only files that had any changes made to them are written. + /// If AUG_SAVE_NEWFILE is set in the FLAGS passed to AUG_INIT, create changed files as new files with the extension ".augnew", and leave the + /// original file unmodified. Otherwise, if AUG_SAVE_BACKUP is set in the FLAGS passed to the constructor, + /// move the original file to a new file with extension ".augsave". + /// If neither of these flags is set, overwrite the original file + /// + /// True on success. Only files that had any changes made to them are written. + public bool Save() + { + bool saved = save(_augeas); + return saved; + } /// /// Gets a preview of the configuration segment of . /// The file must be loaded first. /// - /// Augeas path of the configuration + /// Augeas path. /// public string GetPreview(string matchPath) { @@ -182,9 +216,45 @@ namespace Sharp.Augeas return sb; } - #endregion + #endregion + + + /// + /// Matches of the path expression PATH in AUG. + /// + /// Augeas path. + /// + public string[] Match (string matchPath) + { + sbyte** result = null; + var count = match(_augeas, matchPath, &result); + var managedArray = GetStringsAndFreeAllocations(count, result); + result = null; + return managedArray; + } + private string[] GetStringsAndFreeAllocations(int count, sbyte** list) + { + var result = new string[count]; + if (count <= 0) return Array.Empty(); + + for (var i = 0; i < count; i++) + { + result[i] = Marshal.PtrToStringUTF8((IntPtr)list[i]); + Marshal.FreeCoTaskMem((IntPtr)list[i]); + } + + return result; + } + + + + + /// + /// Given a , prints the Virtual Host tree. + /// + /// Apache configuration file. public void PrintVirtualHostTree(string apacheSitePath) { LoadFile(apacheSitePath); @@ -192,6 +262,11 @@ namespace Sharp.Augeas PrintTree(virtualHostTree); } + /// + /// Given a , gets a virtual host tree. + /// + /// Apache configuration file. + /// public Dictionary GetVirtualHostTree(string apacheSitePath) { LoadFile(apacheSitePath); @@ -200,10 +275,14 @@ namespace Sharp.Augeas } - void PrintVirtualHostProxyTree(string configFilePath) + /// + /// Given a , prints the proxy segment of the configuration. + /// + /// + void PrintVirtualHostProxyTree(string apacheSitePath) { - LoadFile(configFilePath); - string virtualHostProxyMatchPath = $"/files{configFilePath}/VirtualHost/Proxy/*"; + LoadFile(apacheSitePath); + string virtualHostProxyMatchPath = $"/files{apacheSitePath}/VirtualHost/Proxy/*"; PrintTree(virtualHostProxyMatchPath); } diff --git a/Sharp.Augeas/Augeas/AugeasExtern.cs b/Sharp.Augeas/Augeas/AugeasExtern.cs index ec1c89b..cbe3b42 100644 --- a/Sharp.Augeas/Augeas/AugeasExtern.cs +++ b/Sharp.Augeas/Augeas/AugeasExtern.cs @@ -7,7 +7,7 @@ using Sharp.Augeas.Test; namespace Sharp.Augeas { [SuppressUnmanagedCodeSecurity] - public static unsafe partial class AugeasExtern + public static unsafe class AugeasExtern { [DllImport(_libName)] public static extern IntPtr init_aug(AugSettings settings, int flags); @@ -40,8 +40,30 @@ namespace Sharp.Augeas [DllImport(_libName)] public static extern IntPtr get_node(IntPtr augeas, [MarshalAs(UnmanagedType.LPStr)] string matchPath); - - [DllImport(_libName)] public static extern bool load_file(IntPtr augeas, [MarshalAs(UnmanagedType.LPStr)] string filePath); + [DllImport(_libName)] + public static extern int insert_node(IntPtr augeas, [MarshalAs(UnmanagedType.LPStr)] string matchPath, [MarshalAs(UnmanagedType.LPStr)] string label, int before); + + + [DllImport(_libName)] + public static extern bool set_node(IntPtr augeas, [MarshalAs(UnmanagedType.LPStr)] string matchPath, [MarshalAs(UnmanagedType.LPStr)] string value); + + + [DllImport(_libName)] + public static extern int rm_node(IntPtr augeas, [MarshalAs(UnmanagedType.LPStr)] string matchPath); + + + [DllImport(_libName)] + public static extern bool save(IntPtr augeas); + + + [DllImport(_libName)] + public static extern bool load_file(IntPtr augeas, [MarshalAs(UnmanagedType.LPStr)] string filePath); + + + [DllImport(_libName)] + internal static extern int match(IntPtr augeas, [MarshalAs(UnmanagedType.LPStr)] string matchPath, sbyte*** matches); + + } } \ No newline at end of file