diff options
Diffstat (limited to 'src/Agent.Windows/Recovery/TransactionalFileEditor.cs')
| -rw-r--r-- | src/Agent.Windows/Recovery/TransactionalFileEditor.cs | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/src/Agent.Windows/Recovery/TransactionalFileEditor.cs b/src/Agent.Windows/Recovery/TransactionalFileEditor.cs index 52963a0..805a069 100644 --- a/src/Agent.Windows/Recovery/TransactionalFileEditor.cs +++ b/src/Agent.Windows/Recovery/TransactionalFileEditor.cs @@ -1,5 +1,6 @@ using System.Security.Cryptography; using System.Text; +using Agent.Core.Tools; using Agent.Windows.Security; namespace Agent.Windows.Recovery; @@ -68,6 +69,30 @@ public sealed class TransactionalFileEditor(TaskResourceJournal journal, string return new(journal, entryId, canonical, originalHash, backupPath, inline); } + public DirectoryMkdirTransaction Mkdir(string path) + { + string canonical = CanonicalPath.Resolve(path, requireExisting: false); + bool existed = Directory.Exists(canonical); + if (existed) throw new InvalidOperationException($"Directory already exists: '{canonical}'."); + if (File.Exists(canonical)) throw new InvalidOperationException($"A file exists at the target path: '{canonical}'."); + Guid entryId = journal.Prepare("dir.mkdir", canonical, new Dictionary<string, string> { ["existed"] = existed.ToString() }); + Directory.CreateDirectory(canonical); + journal.MarkApplied(entryId); + return new(journal, entryId, canonical); + } + + public DirectoryRmdirTransaction Rmdir(string path) + { + string canonical = CanonicalPath.Resolve(path); + if (!Directory.Exists(canonical)) throw new DirectoryNotFoundException($"Directory does not exist: '{canonical}'."); + if (Directory.EnumerateFileSystemEntries(canonical, "*", SearchOption.TopDirectoryOnly).Any()) + throw new ToolValidationException("Directory is not empty. Remove contents first before removing the directory."); + Guid entryId = journal.Prepare("dir.rmdir", canonical, new Dictionary<string, string>()); + Directory.Delete(canonical, recursive: false); + journal.MarkApplied(entryId); + return new(journal, entryId, canonical); + } + private static string NormalizeHash(string hash) => hash.Replace("-", string.Empty, StringComparison.Ordinal).Trim().ToUpperInvariant(); } @@ -93,6 +118,32 @@ public sealed class FileDeleteTransaction(TaskResourceJournal journal, Guid entr } } +public sealed class DirectoryMkdirTransaction(TaskResourceJournal journal, Guid entryId, string path) +{ + private bool _finished; + public void Commit() { if (_finished) return; journal.MarkCleaned(entryId); _finished = true; } + public void Rollback() + { + if (_finished) return; + if (Directory.Exists(path)) Directory.Delete(path, recursive: false); + journal.MarkCleaned(entryId); + _finished = true; + } +} + +public sealed class DirectoryRmdirTransaction(TaskResourceJournal journal, Guid entryId, string path) +{ + private bool _finished; + public void Commit() { if (_finished) return; journal.MarkCleaned(entryId); _finished = true; } + public void Rollback() + { + if (_finished) return; + if (!Directory.Exists(path)) Directory.CreateDirectory(path); + journal.MarkCleaned(entryId); + _finished = true; + } +} + public sealed class FileEditTransaction( TaskResourceJournal journal, Guid entryId, string path, string originalHash, string replacementHash, string backupPath, string originalBase64, bool originallyExisted) |
