diff --git a/src/Tgstation.Server.Host/Core/SynchronousIOManager.cs b/src/Tgstation.Server.Host/Core/SynchronousIOManager.cs index ee281a8cdd..dc56319f11 100644 --- a/src/Tgstation.Server.Host/Core/SynchronousIOManager.cs +++ b/src/Tgstation.Server.Host/Core/SynchronousIOManager.cs @@ -1,6 +1,9 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.IO; +using System.Linq; +using System.Security.Cryptography; using System.Threading; namespace Tgstation.Server.Host.Core @@ -36,7 +39,37 @@ namespace Tgstation.Server.Host.Core /// public bool WriteFileChecked(string path, byte[] data, string previousSha1, CancellationToken cancellationToken) { - throw new NotImplementedException(); + cancellationToken.ThrowIfCancellationRequested(); + using (var file = File.Open(path, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None)) + { + using (var readMs = new MemoryStream()) + { + cancellationToken.ThrowIfCancellationRequested(); + file.CopyTo(readMs); + if (readMs.Length != 0 && previousSha1 == null) + return false; //no sha1? no write + //suppressed due to only using for consistency checks +#pragma warning disable CA5350 // Do not use insecure cryptographic algorithm SHA1. + using (var sha1 = new SHA1Managed()) +#pragma warning restore CA5350 // Do not use insecure cryptographic algorithm SHA1. + { + var sha1String = String.Join("", sha1.ComputeHash(readMs).Select(b => b.ToString("x2", CultureInfo.InvariantCulture))); + if (sha1String != previousSha1) + return false; + } + } + + cancellationToken.ThrowIfCancellationRequested(); + file.Seek(0, SeekOrigin.Begin); + + cancellationToken.ThrowIfCancellationRequested(); + file.SetLength(data.Length); + + cancellationToken.ThrowIfCancellationRequested(); + file.Write(data, 0, data.Length); + + return true; + } } } }