NativeIoSupport.cs 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. using System;
  2. using System.IO;
  3. using System.Runtime.InteropServices;
  4. namespace SvdCli.Storage
  5. {
  6. internal static class NativeIoSupport
  7. {
  8. public static bool SetSparse(this FileStream fileStream)
  9. {
  10. if (fileStream == null) throw new ArgumentNullException(nameof(fileStream));
  11. if (fileStream.SafeFileHandle == null) throw new ArgumentException($"{nameof(fileStream.SafeFileHandle)} is null", nameof(fileStream));
  12. FILE_SET_SPARSE_BUFFER sparse;
  13. sparse.SetSparse = true;
  14. uint bytesTransferred;
  15. return DeviceIoControl(fileStream.SafeFileHandle.DangerousGetHandle(),
  16. 0x900c4/*FSCTL_SET_SPARSE*/,
  17. ref sparse, (uint)Marshal.SizeOf(sparse),
  18. IntPtr.Zero, 0, out bytesTransferred, IntPtr.Zero);
  19. }
  20. public static bool Trim(this FileStream fileStream, long offset, long length)
  21. {
  22. if (fileStream == null) throw new ArgumentNullException(nameof(fileStream));
  23. if (fileStream.SafeFileHandle == null) throw new ArgumentException($"{nameof(fileStream.SafeFileHandle)} is null", nameof(fileStream));
  24. FILE_ZERO_DATA_INFORMATION zero;
  25. uint bytesTransferred;
  26. zero.FileOffset = offset;
  27. zero.BeyondFinalZero = offset + length;
  28. return DeviceIoControl(fileStream.SafeFileHandle.DangerousGetHandle(),
  29. 0x980c8 /* FSCTL_SET_ZERO_DATA */,
  30. ref zero, (uint)Marshal.SizeOf(zero),
  31. IntPtr.Zero, 0, out bytesTransferred, IntPtr.Zero);
  32. }
  33. /* interop */
  34. [StructLayout(LayoutKind.Sequential)]
  35. private struct FILE_SET_SPARSE_BUFFER
  36. {
  37. public bool SetSparse;
  38. }
  39. [StructLayout(LayoutKind.Sequential)]
  40. private struct FILE_ZERO_DATA_INFORMATION
  41. {
  42. public long FileOffset;
  43. public long BeyondFinalZero;
  44. }
  45. [DllImport("kernel32.dll", SetLastError = true)]
  46. [return: MarshalAs(UnmanagedType.U1)]
  47. private static extern bool DeviceIoControl(
  48. IntPtr hDevice,
  49. uint dwIoControlCode,
  50. ref FILE_SET_SPARSE_BUFFER lpInBuffer,
  51. uint nInBufferSize,
  52. IntPtr lpOutBuffer,
  53. uint nOutBufferSize,
  54. out uint lpBytesReturned,
  55. IntPtr overlapped);
  56. [DllImport("kernel32.dll", SetLastError = true)]
  57. [return: MarshalAs(UnmanagedType.U1)]
  58. private static extern bool DeviceIoControl(
  59. IntPtr hDevice,
  60. uint dwIoControlCode,
  61. ref FILE_ZERO_DATA_INFORMATION lpInBuffer,
  62. uint nInBufferSize,
  63. IntPtr lpOutBuffer,
  64. uint nOutBufferSize,
  65. out uint lpBytesReturned,
  66. IntPtr overlapped);
  67. }
  68. }