diff --git a/LightlessSync/FileCache/FileCompactor.cs b/LightlessSync/FileCache/FileCompactor.cs index e5d219e..dbc2574 100644 --- a/LightlessSync/FileCache/FileCompactor.cs +++ b/LightlessSync/FileCache/FileCompactor.cs @@ -372,6 +372,22 @@ public sealed class FileCompactor : IDisposable return _clusterSizes[root]; } + public static bool UseSafeHandle(SafeHandle handle, Func action) + { + bool addedRef = false; + try + { + handle.DangerousAddRef(ref addedRef); + IntPtr ptr = handle.DangerousGetHandle(); + return action(ptr); + } + finally + { + if (addedRef) + handle.DangerousRelease(); + } + } + private static bool IsWOFCompactedFile(string filePath) { uint buf = 8; @@ -424,22 +440,25 @@ public sealed class FileCompactor : IDisposable ulong length = (ulong)Marshal.SizeOf(_efInfo); try { - using var fs = new FileStream(path, FileMode.Open); - #pragma warning disable S3869 // "SafeHandle.DangerousGetHandle" should not be called - var hFile = fs.SafeFileHandle.DangerousGetHandle(); - #pragma warning restore S3869 // "SafeHandle.DangerousGetHandle" should not be called - if (fs.SafeFileHandle.IsInvalid) + using var fs = new FileStream(path, FileMode.Open, FileAccess.ReadWrite, FileShare.None); + var handle = fs.SafeFileHandle; + + if (handle.IsInvalid) { _logger.LogWarning("Invalid file handle to {file}", path); return false; } - var ret = WofSetFileDataLocation(hFile, WOF_PROVIDER_FILE, efInfoPtr, length); - if (!(ret == 0 || ret == unchecked((int)0x80070158))) + return UseSafeHandle(handle, hFile => { - _logger.LogWarning("Failed to compact {file}: {ret}", path, ret.ToString("X")); - return false; - } + int ret = WofSetFileDataLocation(hFile, WOF_PROVIDER_FILE, efInfoPtr, length); + if (ret != 0 && ret != unchecked((int)0x80070158)) + { + _logger.LogWarning("Failed to compact {file}: {ret}", path, ret.ToString("X")); + return false; + } + return true; + }); } catch (Exception ex) { @@ -450,7 +469,6 @@ public sealed class FileCompactor : IDisposable { Marshal.FreeHGlobal(efInfoPtr); } - return true; } private bool BtrfsCompressFile(string path)