summaryrefslogtreecommitdiff
path: root/src/Agent.Windows/Recovery/RecoveryManager.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/Agent.Windows/Recovery/RecoveryManager.cs')
-rw-r--r--src/Agent.Windows/Recovery/RecoveryManager.cs16
1 files changed, 16 insertions, 0 deletions
diff --git a/src/Agent.Windows/Recovery/RecoveryManager.cs b/src/Agent.Windows/Recovery/RecoveryManager.cs
index df69a5e..8fd7368 100644
--- a/src/Agent.Windows/Recovery/RecoveryManager.cs
+++ b/src/Agent.Windows/Recovery/RecoveryManager.cs
@@ -49,6 +49,8 @@ public sealed class RecoveryManager(string journalDirectory, ISecurityAuditSink
{
case "file.replace": RecoverFile(entry); break;
case "file.delete": RecoverDeletedFile(entry); break;
+ case "dir.mkdir": RecoverMkdir(entry); break;
+ case "dir.rmdir": RecoverRmdir(entry); break;
case "acl": RecoverAcl(entry); break;
case "wfp.dynamic": break; // BFE removes every object when the originating dynamic session ends.
case "network.loopback_exemption": RecoverLoopback(entry); break;
@@ -94,6 +96,20 @@ public sealed class RecoveryManager(string journalDirectory, ISecurityAuditSink
File.WriteAllBytes(entry.Target, original);
}
+ private static void RecoverMkdir(JournalEntry entry)
+ {
+ if (!Directory.Exists(entry.Target)) return;
+ if (Directory.EnumerateFileSystemEntries(entry.Target, "*", SearchOption.TopDirectoryOnly).Any())
+ throw new InvalidOperationException($"Directory '{entry.Target}' created by mkdir is not empty; automatic rollback refused.");
+ Directory.Delete(entry.Target, recursive: false);
+ }
+
+ private static void RecoverRmdir(JournalEntry entry)
+ {
+ if (Directory.Exists(entry.Target)) throw new InvalidOperationException($"Directory '{entry.Target}' was recreated after crash; automatic recovery refused.");
+ Directory.CreateDirectory(entry.Target);
+ }
+
private static void CleanupPrepared(JournalEntry entry)
{
if (entry.Kind == "network.loopback_exemption" && !bool.Parse(entry.Data["originally_present"]))