94 ArgumentNullException.ThrowIfNull(path);
95 ArgumentNullException.ThrowIfNull(data);
97 cancellationToken.ThrowIfCancellationRequested();
98 var directory =
fileSystem.Path.GetDirectoryName(path) ??
throw new ArgumentException(
"path cannot be rooted!", nameof(path));
99 fileSystem.Directory.CreateDirectory(directory);
103 cancellationToken.ThrowIfCancellationRequested();
105 logger.LogTrace(
"Starting checked write to {path} ({fileType} file)", path, newFile ?
"New" :
"Pre-existing");
107 using (var file =
fileSystem.File.Open(path, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None))
109 cancellationToken.ThrowIfCancellationRequested();
112 if (file.Length != 0 && sha1InOut ==
null)
114 logger.LogDebug(
"Aborting checked write due to missing SHA!");
119 using (var sha1 = SHA1.Create())
121 string? GetSha1(
Stream dataToHash)
123 if (dataToHash ==
null)
126 byte[] sha1Computed = dataToHash.Length != 0
127 ? sha1.ComputeHash(dataToHash)
128 : sha1.ComputeHash(Array.Empty<
byte>());
130 return String.Join(String.Empty, sha1Computed.Select(b => b.ToString(
"x2", CultureInfo.InvariantCulture)));
133 var originalSha1 = GetSha1(file);
136 logger.LogTrace(
"Existing SHA calculated to be {sha}", originalSha1);
138 if (originalSha1 != sha1InOut && !(newFile && sha1InOut ==
null))
140 sha1InOut = originalSha1;
144 sha1InOut = GetSha1(data);
147 cancellationToken.ThrowIfCancellationRequested();
149 if (data.Length != 0)
151 logger.LogDebug(
"Writing file of length {size}", data.Length);
152 file.Seek(0, SeekOrigin.Begin);
153 data.Seek(0, SeekOrigin.Begin);
155 cancellationToken.ThrowIfCancellationRequested();
156 file.SetLength(data.Length);
161 if (data.Length == 0)
163 logger.LogDebug(
"Stream is empty, deleting file");