private static void AppendTest(ExFatPartition partition, string fileName, Func <ulong, ulong> getOffsetValue) { var fileEntry = partition.GetMetaEntries(partition.RootDirectoryDataDescriptor) .Single(e => e.ExtensionsFileName == fileName); var buffer = new Byte[8]; var dataDescriptor = fileEntry.DataDescriptor; using (var append = partition.OpenDataStream(dataDescriptor, FileAccess.ReadWrite)) { var offset = (ulong)append.Seek(0, SeekOrigin.End); LittleEndian.GetBytes(getOffsetValue(offset), buffer); append.Write(buffer, 0, 8); } using (var read = partition.OpenDataStream( new DataDescriptor(dataDescriptor.FirstCluster, false, DiskContent.LongFileSize + 8, DiskContent.LongFileSize + 8), FileAccess.Read)) { for (ulong offset = 0; offset < DiskContent.LongFileSize + 8; offset += 8) { var bytesRead = read.Read(buffer, 0, buffer.Length); Assert.AreEqual(bytesRead, buffer.Length); var readValue = LittleEndian.ToUInt64(buffer); var expectedValue = getOffsetValue(offset); Assert.AreEqual(expectedValue, readValue); } Assert.AreEqual(0, read.Read(buffer, 0, buffer.Length)); } }
internal static void ReadFile(string fileName, Func <ulong, ulong> getValueAtOffset, ulong?overrideLength = null, bool forward = true, bool forceSeek = false) { using (var testEnvironment = StreamTestEnvironment.FromExistingVhdx()) { var fs = new ExFatPartition(testEnvironment.PartitionStream); ReadFile(fs, fileName, getValueAtOffset, overrideLength, forward, forceSeek); } }
public void ValidGroupedEntries() { using (var testEnvironment = StreamTestEnvironment.FromExistingVhdx()) { var partition = new ExFatPartition(testEnvironment.PartitionStream); var entries = partition.GetMetaEntries(partition.RootDirectoryDataDescriptor).ToArray(); Assert.IsTrue(entries.Any(e => e.ExtensionsFileName == DiskContent.LongContiguousFileName)); } }
public void DirectoryEntries() { using (var testEnvironment = StreamTestEnvironment.FromExistingVhdx()) { var partition = new ExFatPartition(testEnvironment.PartitionStream); var entries = partition.GetEntries(partition.RootDirectoryDataDescriptor).ToArray(); Assert.IsTrue(entries.OfType <FileNameExtensionExFatDirectoryEntry>() .Any(e => e.FileName.Value == DiskContent.LongContiguousFileName)); } }
/// <summary> /// Initializes a new instance of the <see cref="T:ExFat.DiscUtils.ExFatFileSystem" /> class. /// </summary> /// <param name="partitionStream">The partition stream.</param> /// <param name="pathSeparators">The path separators.</param> /// <exception cref="InvalidOperationException">Given stream is not exFAT volume</exception> /// <exception cref="T:System.InvalidOperationException">Given stream is not exFAT volume</exception> /// <inheritdoc /> public ExFatFileSystem(Stream partitionStream, char[] pathSeparators = null) { _filesystem = new ExFatPathFilesystem(partitionStream); PathSeparators = pathSeparators ?? DefaultSeparators; var bootSector = ExFatPartition.ReadBootSector(partitionStream); if (!bootSector.IsValid) { throw new InvalidOperationException("Given stream is not exFAT volume"); } _partitionStream = partitionStream; }
public void OverwriteSparseTest() { using (var testEnvironment = StreamTestEnvironment.FromExistingVhdx()) { using (var partition = new ExFatPartition(testEnvironment.PartitionStream)) { OverwriteTest(partition, DiskContent.LongSparseFile1Name, offset => offset / 7); // now check nothing was overwritten PartitionReadTests.ReadFile(partition, DiskContent.LongSparseFile2Name, DiskContent.GetLongSparseFile2NameOffsetValue); } } }
public void CheckChecksums() { using (var testEnvironment = StreamTestEnvironment.FromExistingVhdx()) { var partition = new ExFatPartition(testEnvironment.PartitionStream); foreach (var entry in partition.GetMetaEntries(partition.RootDirectoryDataDescriptor)) { if (entry.Primary is FileExFatDirectoryEntry fileEntry) { var checksum = fileEntry.ComputeChecksum(entry.Secondaries); Assert.AreEqual(fileEntry.SetChecksum.Value, checksum); } } } }
public void CheckHashes() { using (var testEnvironment = StreamTestEnvironment.FromExistingVhdx()) { var partition = new ExFatPartition(testEnvironment.PartitionStream); foreach (var entry in partition.GetMetaEntries(partition.RootDirectoryDataDescriptor)) { if (entry.Primary is FileExFatDirectoryEntry) { var hash = partition.ComputeNameHash(entry.ExtensionsFileName); Assert.AreEqual(entry.SecondaryStreamExtension.NameHash.Value, hash); } } } }
public void CreateStreamTest() { using (var testEnvironment = StreamTestEnvironment.FromExistingVhdx()) { using (var partition = new ExFatPartition(testEnvironment.PartitionStream)) { DataDescriptor dataDescriptor = null; using (var stream = partition.CreateDataStream(d => dataDescriptor = d)) { stream.WriteByte(1); } using (var s2 = partition.OpenDataStream(dataDescriptor, FileAccess.Read)) { Assert.AreEqual(1, s2.ReadByte()); Assert.AreEqual(-1, s2.ReadByte()); } } } }
public void AllocationBitmapExists() { using (var testEnvironment = StreamTestEnvironment.FromExistingVhdx()) { var partition = new ExFatPartition(testEnvironment.PartitionStream); var bitmap = partition.GetAllocationBitmap(); Assert.IsTrue(bitmap[2]); var allocate1 = bitmap.FindUnallocated(); Assert.IsFalse(bitmap[allocate1]); var allocate10 = bitmap.FindUnallocated(10); Assert.IsFalse(bitmap[allocate10]); Assert.IsFalse(bitmap[allocate10 + 1]); Assert.IsFalse(bitmap[allocate10 + 2]); Assert.IsFalse(bitmap[allocate10 + 3]); Assert.IsFalse(bitmap[allocate10 + 4]); Assert.IsFalse(bitmap[allocate10 + 5]); Assert.IsFalse(bitmap[allocate10 + 6]); Assert.IsFalse(bitmap[allocate10 + 7]); Assert.IsFalse(bitmap[allocate10 + 8]); Assert.IsFalse(bitmap[allocate10 + 9]); } }
public void ReadLongFileClusters() { using (var testEnvironment = StreamTestEnvironment.FromExistingVhdx()) using (var partition = new ExFatPartition(testEnvironment.PartitionStream)) { var oneM = partition.GetMetaEntries(partition.RootDirectoryDataDescriptor) .Single(e => e.ExtensionsFileName == DiskContent.LongSparseFile1Name); var clusters = new List <Cluster>(); for (Cluster c = oneM.SecondaryStreamExtension.FirstCluster.Value;; c = partition.GetNextCluster(c)) { if (c.IsLast) { break; } if (!c.IsData) { Assert.Fail("Found invalid cluster (o'brother, where art thou?)"); } clusters.Add(c); } } }
internal static void ReadFile(ExFatPartition partition, string fileName, Func <ulong, ulong> getValueAtOffset, ulong?overrideLength = null, bool forward = true, bool forceSeek = false) { var fileEntry = partition.GetMetaEntries(partition.RootDirectoryDataDescriptor) .Single(e => e.ExtensionsFileName == fileName); var length = overrideLength ?? fileEntry.SecondaryStreamExtension.DataLength.Value; var contiguous = fileEntry.SecondaryStreamExtension.GeneralSecondaryFlags.Value.HasAny(ExFatGeneralSecondaryFlags .NoFatChain); using (var stream = partition.OpenDataStream( new DataDescriptor(fileEntry.SecondaryStreamExtension.FirstCluster.Value, contiguous, length, length), FileAccess.Read)) { var vb = new byte[sizeof(ulong)]; var range = Enumerable.Range(0, (int)(length / sizeof(ulong))).Select(r => r * sizeof(ulong)); if (!forward) { range = range.Reverse(); forceSeek = true; } foreach (var offset in range) { if (forceSeek) { stream.Seek(offset, SeekOrigin.Begin); } stream.Read(vb, 0, vb.Length); var v = LittleEndian.ToUInt64(vb); Assert.AreEqual(v, getValueAtOffset((ulong)offset)); } if (forward) { Assert.AreEqual(0, stream.Read(vb, 0, vb.Length)); } } }
/// <summary> /// Detects the specified partition stream. /// </summary> /// <param name="partitionStream">The partition stream.</param> /// <returns></returns> public static bool Detect(Stream partitionStream) { var bootSector = ExFatPartition.ReadBootSector(partitionStream); return(bootSector.IsValid); }
/// <summary> /// Initializes a new instance of the <see cref="ExFatEntryFilesystem"/> class. /// </summary> /// <param name="partition">The partition.</param> /// <param name="options">The flags.</param> public ExFatEntryFilesystem(ExFatPartition partition, ExFatOptions options = ExFatOptions.Default) { _options = options; _partition = partition; }
/// <summary> /// Formats the specified partition. /// </summary> /// <param name="partitionStream">The partition stream.</param> /// <param name="options">The options.</param> /// <param name="volumeLabel">The volume label.</param> /// <returns></returns> public static ExFatEntryFilesystem Format(Stream partitionStream, ExFatFormatOptions options, string volumeLabel = null) { var partition = ExFatPartition.Format(partitionStream, options, volumeLabel); return(new ExFatEntryFilesystem(partition)); }
/// <summary> /// Initializes a new instance of the <see cref="T:ExFat.Filesystem.ExFatPathFilesystem" /> class. /// </summary> /// <param name="partition">The partition.</param> /// <param name="flags">The flags.</param> /// <param name="pathSeparators">The path separators.</param> /// <inheritdoc /> public ExFatPathFilesystem(ExFatPartition partition, ExFatOptions flags = ExFatOptions.Default, char[] pathSeparators = null) : this(new ExFatEntryFilesystem(partition, flags), pathSeparators) { }