nickdu
2009-04-28 17:50:13 UTC
I don't believe there is any built in support for sparse files in .NET. So I
created some pinvoke calls to get sparse file support within my managed
application. However, there seems to be some other resource limit I'm
running up against. When I run my sample application, which when the same
unmanaged application runs it creates a 16TB file (which only consumes a gig
or so), it fails early with an "insufficient resources" error when seeking.
Below is my sample application:
using System;
using System.IO;
using System.ComponentModel;
using System.Runtime.InteropServices;
namespace Win32
{
public class File
{
public const uint FILE_DEVICE_BEEP = 0x00000001;
public const uint FILE_DEVICE_CD_ROM = 0x00000002;
public const uint FILE_DEVICE_CD_ROM_FILE_SYSTEM = 0x00000003;
public const uint FILE_DEVICE_CONTROLLER = 0x00000004;
public const uint FILE_DEVICE_DATALINK = 0x00000005;
public const uint FILE_DEVICE_DFS = 0x00000006;
public const uint FILE_DEVICE_DISK = 0x00000007;
public const uint FILE_DEVICE_DISK_FILE_SYSTEM = 0x00000008;
public const uint FILE_DEVICE_FILE_SYSTEM = 0x00000009;
public const uint FILE_DEVICE_INPORT_PORT = 0x0000000a;
public const uint FILE_DEVICE_KEYBOARD = 0x0000000b;
public const uint FILE_DEVICE_MAILSLOT = 0x0000000c;
public const uint FILE_DEVICE_MIDI_IN = 0x0000000d;
public const uint FILE_DEVICE_MIDI_OUT = 0x0000000e;
public const uint FILE_DEVICE_MOUSE = 0x0000000f;
public const uint FILE_DEVICE_MULTI_UNC_PROVIDER = 0x00000010;
public const uint FILE_DEVICE_NAMED_PIPE = 0x00000011;
public const uint FILE_DEVICE_NETWORK = 0x00000012;
public const uint FILE_DEVICE_NETWORK_BROWSER = 0x00000013;
public const uint FILE_DEVICE_NETWORK_FILE_SYSTEM = 0x00000014;
public const uint FILE_DEVICE_NULL = 0x00000015;
public const uint FILE_DEVICE_PARALLEL_PORT = 0x00000016;
public const uint FILE_DEVICE_PHYSICAL_NETCARD = 0x00000017;
public const uint FILE_DEVICE_PRINTER = 0x00000018;
public const uint FILE_DEVICE_SCANNER = 0x00000019;
public const uint FILE_DEVICE_SERIAL_MOUSE_PORT = 0x0000001a;
public const uint FILE_DEVICE_SERIAL_PORT = 0x0000001b;
public const uint FILE_DEVICE_SCREEN = 0x0000001c;
public const uint FILE_DEVICE_SOUND = 0x0000001d;
public const uint FILE_DEVICE_STREAMS = 0x0000001e;
public const uint FILE_DEVICE_TAPE = 0x0000001f;
public const uint FILE_DEVICE_TAPE_FILE_SYSTEM = 0x00000020;
public const uint FILE_DEVICE_TRANSPORT = 0x00000021;
public const uint FILE_DEVICE_UNKNOWN = 0x00000022;
public const uint FILE_DEVICE_VIDEO = 0x00000023;
public const uint FILE_DEVICE_VIRTUAL_DISK = 0x00000024;
public const uint FILE_DEVICE_WAVE_IN = 0x00000025;
public const uint FILE_DEVICE_WAVE_OUT = 0x00000026;
public const uint FILE_DEVICE_8042_PORT = 0x00000027;
public const uint FILE_DEVICE_NETWORK_REDIRECTOR = 0x00000028;
public const uint FILE_DEVICE_BATTERY = 0x00000029;
public const uint FILE_DEVICE_BUS_EXTENDER = 0x0000002a;
public const uint FILE_DEVICE_MODEM = 0x0000002b;
public const uint FILE_DEVICE_VDM = 0x0000002c;
public const uint FILE_DEVICE_MASS_STORAGE = 0x0000002d;
public const uint FILE_DEVICE_SMB = 0x0000002e;
public const uint FILE_DEVICE_KS = 0x0000002f;
public const uint FILE_DEVICE_CHANGER = 0x00000030;
public const uint FILE_DEVICE_SMARTCARD = 0x00000031;
public const uint FILE_DEVICE_ACPI = 0x00000032;
public const uint FILE_DEVICE_DVD = 0x00000033;
public const uint FILE_DEVICE_FULLSCREEN_VIDEO = 0x00000034;
public const uint FILE_DEVICE_DFS_FILE_SYSTEM = 0x00000035;
public const uint FILE_DEVICE_DFS_VOLUME = 0x00000036;
public const uint FILE_DEVICE_SERENUM = 0x00000037;
public const uint FILE_DEVICE_TERMSRV = 0x00000038;
public const uint FILE_DEVICE_KSEC = 0x00000039;
public const uint FILE_DEVICE_FIPS = 0x0000003A;
public const uint FILE_DEVICE_INFINIBAND = 0x0000003B;
public const uint FILE_ANY_ACCESS = 0;
public const uint FILE_SPECIAL_ACCESS = (FILE_ANY_ACCESS);
public const uint FILE_READ_ACCESS = ( 0x0001 ); // file & pipe
public const uint FILE_WRITE_ACCESS = ( 0x0002 ); // file & pipe
public const uint METHOD_BUFFERED = 0;
public const uint METHOD_IN_DIRECT = 1;
public const uint METHOD_OUT_DIRECT = 2;
public const uint METHOD_NEITHER = 3;
public const uint FSCTL_SET_SPARSE = ((FILE_DEVICE_FILE_SYSTEM << 16) |
(FILE_SPECIAL_ACCESS << 14) | (49 << 2) | METHOD_BUFFERED);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern int DeviceIoControl(IntPtr device, uint code, IntPtr
inBuffer,
uint inBufferSize, IntPtr outBuffer, uint outBufferSize,
out uint bytesReturned, IntPtr overlapped);
}
}
public class Application
{
public static void Main(string[] args)
{
if (args.Length != 1)
Console.WriteLine("Error, expecting file name.");
else
{
FileStream file = File.Create(args[0]);
using(file)
{
uint bytesReturned;
if (Win32.File.DeviceIoControl(file.SafeFileHandle.DangerousGetHandle(),
Win32.File.FSCTL_SET_SPARSE, IntPtr.Zero, 0, IntPtr.Zero, 0,
out bytesReturned, IntPtr.Zero) == 0)
{
int result = Marshal.GetLastWin32Error();
throw(new Win32Exception(result, string.Format(
"Failed setting file {0} to sparse.", args[0])));
}
byte[] bytes = new byte[1024];
for (long i = 0; i < bytes.Length; ++i)
{
bytes[i] = (byte) 'A';
}
for (long i = 0; i < 1024 * 1024; ++i)
{
file.Seek(i * 1024 * 1024 * 1024, SeekOrigin.Begin);
file.Write(bytes, 0, bytes.Length);
}
}
}
}
}
created some pinvoke calls to get sparse file support within my managed
application. However, there seems to be some other resource limit I'm
running up against. When I run my sample application, which when the same
unmanaged application runs it creates a 16TB file (which only consumes a gig
or so), it fails early with an "insufficient resources" error when seeking.
Below is my sample application:
using System;
using System.IO;
using System.ComponentModel;
using System.Runtime.InteropServices;
namespace Win32
{
public class File
{
public const uint FILE_DEVICE_BEEP = 0x00000001;
public const uint FILE_DEVICE_CD_ROM = 0x00000002;
public const uint FILE_DEVICE_CD_ROM_FILE_SYSTEM = 0x00000003;
public const uint FILE_DEVICE_CONTROLLER = 0x00000004;
public const uint FILE_DEVICE_DATALINK = 0x00000005;
public const uint FILE_DEVICE_DFS = 0x00000006;
public const uint FILE_DEVICE_DISK = 0x00000007;
public const uint FILE_DEVICE_DISK_FILE_SYSTEM = 0x00000008;
public const uint FILE_DEVICE_FILE_SYSTEM = 0x00000009;
public const uint FILE_DEVICE_INPORT_PORT = 0x0000000a;
public const uint FILE_DEVICE_KEYBOARD = 0x0000000b;
public const uint FILE_DEVICE_MAILSLOT = 0x0000000c;
public const uint FILE_DEVICE_MIDI_IN = 0x0000000d;
public const uint FILE_DEVICE_MIDI_OUT = 0x0000000e;
public const uint FILE_DEVICE_MOUSE = 0x0000000f;
public const uint FILE_DEVICE_MULTI_UNC_PROVIDER = 0x00000010;
public const uint FILE_DEVICE_NAMED_PIPE = 0x00000011;
public const uint FILE_DEVICE_NETWORK = 0x00000012;
public const uint FILE_DEVICE_NETWORK_BROWSER = 0x00000013;
public const uint FILE_DEVICE_NETWORK_FILE_SYSTEM = 0x00000014;
public const uint FILE_DEVICE_NULL = 0x00000015;
public const uint FILE_DEVICE_PARALLEL_PORT = 0x00000016;
public const uint FILE_DEVICE_PHYSICAL_NETCARD = 0x00000017;
public const uint FILE_DEVICE_PRINTER = 0x00000018;
public const uint FILE_DEVICE_SCANNER = 0x00000019;
public const uint FILE_DEVICE_SERIAL_MOUSE_PORT = 0x0000001a;
public const uint FILE_DEVICE_SERIAL_PORT = 0x0000001b;
public const uint FILE_DEVICE_SCREEN = 0x0000001c;
public const uint FILE_DEVICE_SOUND = 0x0000001d;
public const uint FILE_DEVICE_STREAMS = 0x0000001e;
public const uint FILE_DEVICE_TAPE = 0x0000001f;
public const uint FILE_DEVICE_TAPE_FILE_SYSTEM = 0x00000020;
public const uint FILE_DEVICE_TRANSPORT = 0x00000021;
public const uint FILE_DEVICE_UNKNOWN = 0x00000022;
public const uint FILE_DEVICE_VIDEO = 0x00000023;
public const uint FILE_DEVICE_VIRTUAL_DISK = 0x00000024;
public const uint FILE_DEVICE_WAVE_IN = 0x00000025;
public const uint FILE_DEVICE_WAVE_OUT = 0x00000026;
public const uint FILE_DEVICE_8042_PORT = 0x00000027;
public const uint FILE_DEVICE_NETWORK_REDIRECTOR = 0x00000028;
public const uint FILE_DEVICE_BATTERY = 0x00000029;
public const uint FILE_DEVICE_BUS_EXTENDER = 0x0000002a;
public const uint FILE_DEVICE_MODEM = 0x0000002b;
public const uint FILE_DEVICE_VDM = 0x0000002c;
public const uint FILE_DEVICE_MASS_STORAGE = 0x0000002d;
public const uint FILE_DEVICE_SMB = 0x0000002e;
public const uint FILE_DEVICE_KS = 0x0000002f;
public const uint FILE_DEVICE_CHANGER = 0x00000030;
public const uint FILE_DEVICE_SMARTCARD = 0x00000031;
public const uint FILE_DEVICE_ACPI = 0x00000032;
public const uint FILE_DEVICE_DVD = 0x00000033;
public const uint FILE_DEVICE_FULLSCREEN_VIDEO = 0x00000034;
public const uint FILE_DEVICE_DFS_FILE_SYSTEM = 0x00000035;
public const uint FILE_DEVICE_DFS_VOLUME = 0x00000036;
public const uint FILE_DEVICE_SERENUM = 0x00000037;
public const uint FILE_DEVICE_TERMSRV = 0x00000038;
public const uint FILE_DEVICE_KSEC = 0x00000039;
public const uint FILE_DEVICE_FIPS = 0x0000003A;
public const uint FILE_DEVICE_INFINIBAND = 0x0000003B;
public const uint FILE_ANY_ACCESS = 0;
public const uint FILE_SPECIAL_ACCESS = (FILE_ANY_ACCESS);
public const uint FILE_READ_ACCESS = ( 0x0001 ); // file & pipe
public const uint FILE_WRITE_ACCESS = ( 0x0002 ); // file & pipe
public const uint METHOD_BUFFERED = 0;
public const uint METHOD_IN_DIRECT = 1;
public const uint METHOD_OUT_DIRECT = 2;
public const uint METHOD_NEITHER = 3;
public const uint FSCTL_SET_SPARSE = ((FILE_DEVICE_FILE_SYSTEM << 16) |
(FILE_SPECIAL_ACCESS << 14) | (49 << 2) | METHOD_BUFFERED);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern int DeviceIoControl(IntPtr device, uint code, IntPtr
inBuffer,
uint inBufferSize, IntPtr outBuffer, uint outBufferSize,
out uint bytesReturned, IntPtr overlapped);
}
}
public class Application
{
public static void Main(string[] args)
{
if (args.Length != 1)
Console.WriteLine("Error, expecting file name.");
else
{
FileStream file = File.Create(args[0]);
using(file)
{
uint bytesReturned;
if (Win32.File.DeviceIoControl(file.SafeFileHandle.DangerousGetHandle(),
Win32.File.FSCTL_SET_SPARSE, IntPtr.Zero, 0, IntPtr.Zero, 0,
out bytesReturned, IntPtr.Zero) == 0)
{
int result = Marshal.GetLastWin32Error();
throw(new Win32Exception(result, string.Format(
"Failed setting file {0} to sparse.", args[0])));
}
byte[] bytes = new byte[1024];
for (long i = 0; i < bytes.Length; ++i)
{
bytes[i] = (byte) 'A';
}
for (long i = 0; i < 1024 * 1024; ++i)
{
file.Seek(i * 1024 * 1024 * 1024, SeekOrigin.Begin);
file.Write(bytes, 0, bytes.Length);
}
}
}
}
}
--
Thanks,
Nick
***@community.nospam
remove "nospam" change community. to msn.com
Thanks,
Nick
***@community.nospam
remove "nospam" change community. to msn.com