public void SparseFile()
        {
            byte[] randomData = new byte[35 * 4096];
            _random.NextBytes(randomData);

            // Clear the 16 * 4096 -> 32 * 4096 range
            Array.Clear(randomData, 16 * 4096, 16 * 4096);

            using (TempFile tmpFile = new TempFile())
            {
                // Create a file
                File.WriteAllBytes(tmpFile.File.FullName, randomData);

                using (FilesystemDeviceWrapper wrapper = Win32.GetFileWrapper(tmpFile.File.FullName))
                {
                    wrapper.FileSystemSetSparseFile(true);
                    wrapper.FileSystemSetZeroData(16 * 4096, 16 * 4096);

                    FILE_ALLOCATED_RANGE_BUFFER[] rangesData = wrapper.FileSystemQueryAllocatedRanges(0, randomData.Length);

                    // We should have 2 ranges on non-zero data
                    Assert.AreEqual(2, rangesData.Length);
                }

                // Discover it via the NTFS lib
                char    driveLetter = tmpFile.File.FullName[0];
                RawDisk disk        = new RawDisk(driveLetter);

                NTFSDiskProvider provider = new NTFSDiskProvider(disk);

                NTFSWrapper ntfsWrapper = new NTFSWrapper(provider, 0);

                NtfsDirectory ntfsDir  = NTFSHelpers.OpenDir(ntfsWrapper, tmpFile.File.DirectoryName);
                NtfsFile      ntfsFile = NTFSHelpers.OpenFile(ntfsDir, tmpFile.File.Name);

                Assert.IsNotNull(ntfsFile);
                Assert.IsTrue(tmpFile.File.Attributes.HasFlag(FileAttributes.SparseFile));
                AttributeData attributeData = ntfsFile.MFTRecord.Attributes.OfType <AttributeData>().Single();
                Assert.IsTrue(attributeData.DataFragments.Length > 1);
                Assert.IsTrue(attributeData.DataFragments.Any(s => s.IsSparseFragment));

                // Read it
                using (Stream actualStream = File.OpenRead(tmpFile.File.FullName))
                    using (Stream ntfsStream = ntfsFile.OpenRead())
                    {
                        bool equal = StreamUtils.CompareStreams(actualStream, ntfsStream);

                        Assert.IsTrue(equal);
                    }
            }
        }
        private static void ExampleSparseFile()
        {
            string file = Path.GetTempFileName();

            try
            {
                // Write file data
                const int length = 1 * 1024 * 1024; // 1 MB
                const int sparseLength = 512 * 1024; // 0.5 MB
                using (FileStream fs = File.OpenWrite(file))
                {
                    byte[] data = new byte[length];
                    for (int i = 0; i < data.Length; i++)
                        data[i] = 1;        // Set the data to non-zero
                    fs.Write(data, 0, data.Length);
                }

                Console.WriteLine(@"## Exmaple with {0} ##", file);
                SafeFileHandle fileHandle = CreateFile(file, FileAccess.ReadWrite, FileShare.ReadWrite, IntPtr.Zero, FileMode.Open, FileAttributes.Normal, IntPtr.Zero);

                if (fileHandle.IsInvalid)
                {
                    int lastError = Marshal.GetLastWin32Error();

                    Console.WriteLine(@"!! Invalid {0}; Error ({1}): {2}", file, lastError, new Win32Exception(lastError).Message);
                    Console.WriteLine();
                    return;
                }

                using (FilesystemDeviceWrapper fileIo = new FilesystemDeviceWrapper(fileHandle, true))
                {
                    FileInfo fileInfo = new FileInfo(file);
                    Console.WriteLine("File size: " + fileInfo.Length);
                    Console.WriteLine("Sparse: " + fileInfo.Attributes.HasFlag(FileAttributes.SparseFile));

                    // Enable sparse ranges
                    Console.WriteLine("Enabling Sparse file");
                    fileIo.FileSystemSetSparseFile(true);

                    fileInfo.Refresh();
                    Console.WriteLine("Sparse: " + fileInfo.Attributes.HasFlag(FileAttributes.SparseFile));

                    // Set sparse range
                    Console.WriteLine("  Setting sparse range: " + sparseLength + " (length: " + ((fileInfo.Length - sparseLength) / 2) + ")");
                    fileIo.FileSystemSetZeroData(sparseLength, (fileInfo.Length - sparseLength) / 2);

                    // Query sparse range
                    fileInfo.Refresh();
                    FILE_ALLOCATED_RANGE_BUFFER[] ranges = fileIo.FileSystemQueryAllocatedRanges(0, length);
                    Console.WriteLine("File size: " + fileInfo.Length);

                    Console.WriteLine("Sparse ranges (" + ranges.Length + "):");
                    foreach (FILE_ALLOCATED_RANGE_BUFFER range in ranges)
                    {
                        Console.WriteLine("  Non-sparse range: " + range.FileOffset + " (length: " + range.Length + ")");
                    }
                }
            }
            finally
            {
                if (File.Exists(file))
                    File.Delete(file);
            }
        }
Exemple #3
0
        private static void ExampleSparseFile()
        {
            string file = Path.GetTempFileName();

            try
            {
                // Write file data
                const int length       = 1 * 1024 * 1024; // 1 MB
                const int sparseLength = 512 * 1024;      // 0.5 MB
                using (FileStream fs = File.OpenWrite(file))
                {
                    byte[] data = new byte[length];
                    for (int i = 0; i < data.Length; i++)
                    {
                        data[i] = 1;        // Set the data to non-zero
                    }
                    fs.Write(data, 0, data.Length);
                }

                Console.WriteLine(@"## Exmaple with {0} ##", file);
                SafeFileHandle fileHandle = CreateFile(file, FileAccess.ReadWrite, FileShare.ReadWrite, IntPtr.Zero, FileMode.Open, FileAttributes.Normal, IntPtr.Zero);

                if (fileHandle.IsInvalid)
                {
                    int lastError = Marshal.GetLastWin32Error();

                    Console.WriteLine(@"!! Invalid {0}; Error ({1}): {2}", file, lastError, new Win32Exception(lastError).Message);
                    Console.WriteLine();
                    return;
                }

                using (FilesystemDeviceWrapper fileIo = new FilesystemDeviceWrapper(fileHandle, true))
                {
                    FileInfo fileInfo = new FileInfo(file);
                    Console.WriteLine("File size: " + fileInfo.Length);
                    Console.WriteLine("Sparse: " + fileInfo.Attributes.HasFlag(FileAttributes.SparseFile));

                    // Enable sparse ranges
                    Console.WriteLine("Enabling Sparse file");
                    fileIo.FileSystemSetSparseFile(true);

                    fileInfo.Refresh();
                    Console.WriteLine("Sparse: " + fileInfo.Attributes.HasFlag(FileAttributes.SparseFile));

                    // Set sparse range
                    Console.WriteLine("  Setting sparse range: " + sparseLength + " (length: " + ((fileInfo.Length - sparseLength) / 2) + ")");
                    fileIo.FileSystemSetZeroData(sparseLength, (fileInfo.Length - sparseLength) / 2);

                    // Query sparse range
                    fileInfo.Refresh();
                    FILE_ALLOCATED_RANGE_BUFFER[] ranges = fileIo.FileSystemQueryAllocatedRanges(0, length);
                    Console.WriteLine("File size: " + fileInfo.Length);

                    Console.WriteLine("Sparse ranges (" + ranges.Length + "):");
                    foreach (FILE_ALLOCATED_RANGE_BUFFER range in ranges)
                    {
                        Console.WriteLine("  Non-sparse range: " + range.FileOffset + " (length: " + range.Length + ")");
                    }
                }
            }
            finally
            {
                if (File.Exists(file))
                {
                    File.Delete(file);
                }
            }
        }