diff options
Diffstat (limited to 'src/Agent.Windows/Recovery/RecoveryManager.cs')
| -rw-r--r-- | src/Agent.Windows/Recovery/RecoveryManager.cs | 13 |
1 files changed, 13 insertions, 0 deletions
diff --git a/src/Agent.Windows/Recovery/RecoveryManager.cs b/src/Agent.Windows/Recovery/RecoveryManager.cs index 8fd7368..c9b28bf 100644 --- a/src/Agent.Windows/Recovery/RecoveryManager.cs +++ b/src/Agent.Windows/Recovery/RecoveryManager.cs @@ -49,6 +49,7 @@ public sealed class RecoveryManager(string journalDirectory, ISecurityAuditSink { case "file.replace": RecoverFile(entry); break; case "file.delete": RecoverDeletedFile(entry); break; + case "file.rename": RecoverRenamedFile(entry); break; case "dir.mkdir": RecoverMkdir(entry); break; case "dir.rmdir": RecoverRmdir(entry); break; case "acl": RecoverAcl(entry); break; @@ -96,6 +97,18 @@ public sealed class RecoveryManager(string journalDirectory, ISecurityAuditSink File.WriteAllBytes(entry.Target, original); } + private static void RecoverRenamedFile(JournalEntry entry) + { + string destination = entry.Data["destination_path"]; + string sourceHash = entry.Data["source_sha256"]; + if (!File.Exists(destination)) return; // Already rolled back or destination missing — skip. + if (!Hash(destination).Equals(sourceHash, StringComparison.Ordinal)) + throw new InvalidOperationException($"Renamed destination '{destination}' hash does not match journal record; automatic recovery refused."); + if (File.Exists(entry.Target)) + throw new InvalidOperationException($"Source path '{entry.Target}' was recreated after crash; automatic recovery refused."); + File.Move(destination, entry.Target); + } + private static void RecoverMkdir(JournalEntry entry) { if (!Directory.Exists(entry.Target)) return; |
