public void CreateWholeDisk() { long capacity = 3 * 1024 * 1024; SparseMemoryStream ms = new SparseMemoryStream(); ms.SetLength(capacity); Geometry geom = Geometry.FromCapacity(capacity); BiosPartitionTable table = BiosPartitionTable.Initialize(ms, geom); int idx = table.Create(WellKnownPartitionType.WindowsFat, true); // Make sure the partition fills all but the first track on the disk. Assert.AreEqual(geom.TotalSectors, table[idx].SectorCount + geom.SectorsPerTrack); // Make sure FAT16 was selected for a disk of this size Assert.AreEqual(BiosPartitionTypes.Fat16, table[idx].BiosType); // Make sure partition starts where expected Assert.AreEqual(new ChsAddress(0, 1, 1), ((BiosPartitionInfo)table[idx]).Start); // Make sure partition ends at end of disk Assert.AreEqual(geom.ToLogicalBlockAddress(geom.LastSector), table[idx].LastSector); Assert.AreEqual(geom.LastSector, ((BiosPartitionInfo)table[idx]).End); // Make sure the 'active' flag made it through... Assert.IsTrue(((BiosPartitionInfo)table[idx]).IsActive); // Make sure the partition index is Zero Assert.AreEqual(0, ((BiosPartitionInfo)table[idx]).PrimaryIndex); }
public void HonoursReadOnly() { SparseMemoryStream diskStream = new SparseMemoryStream(); FatFileSystem fs = FatFileSystem.FormatFloppy(diskStream, FloppyDiskType.HighDensity, "FLOPPY_IMG "); fs.CreateDirectory(@"AAA"); fs.CreateDirectory(@"BAR"); using (Stream t = fs.OpenFile(@"BAR\AAA.TXT", FileMode.Create, FileAccess.ReadWrite)) { } using (Stream s = fs.OpenFile(@"BAR\FOO.TXT", FileMode.Create, FileAccess.ReadWrite)) { StreamWriter w = new StreamWriter(s); w.WriteLine("FOO - some sample text"); w.Flush(); } fs.SetLastAccessTimeUtc(@"BAR", new DateTime(1980, 1, 1)); fs.SetLastAccessTimeUtc(@"BAR\FOO.TXT", new DateTime(1980, 1, 1)); // Check we can access a file without any errors SparseStream roDiskStream = SparseStream.ReadOnly(diskStream, Ownership.None); FatFileSystem fatFs = new FatFileSystem(roDiskStream); using (Stream fileStream = fatFs.OpenFile(@"BAR\FOO.TXT", FileMode.Open)) { fileStream.ReadByte(); } }
/// <summary> /// Uses BinarySearch to locate the index of the block that contains start /// </summary> /// <param name="cache"></param> /// <param name="start"></param> /// <param name="match">True if match found. If this is false, the index returned is where the item would appear if it existed.</param> /// <returns>Index</returns> private int FindIndexOfBlockAtOffset(SparseMemoryStream cache, long start, out bool match) { if (cache.MemoryBlockCollection.Count == 0) { match = false; return(0); } // use BinarySearch to locate blocks of interest quickly if (_comparisonBlock == null) { _comparisonBlock = new MemoryStreamBlock(null, start); } else { _comparisonBlock.Offset = start; } int index = cache.MemoryBlockCollection.BinarySearch(_comparisonBlock); if (index < 0) // no match { // ~index represents the place at which the block we asked for // would appear if it existed index = ~index; match = false; } else { match = true; } return(index); }
public void ViewIO() { SparseMemoryStream memStream = new SparseMemoryStream(); memStream.SetLength(1024); ThreadSafeStream tss = new ThreadSafeStream(memStream); SparseStream altView = tss.OpenView(); // Check positions are independant tss.Position = 100; Assert.Equal(0, altView.Position); Assert.Equal(100, tss.Position); // Check I/O is synchronous byte[] buffer = new byte[200]; tss.WriteByte(99); altView.Read(buffer, 0, 200); Assert.Equal(99, buffer[100]); // Check positions are updated correctly Assert.Equal(200, altView.Position); Assert.Equal(101, tss.Position); }
/// <summary> /// Initializes a new instance of the BiosPartitionedDiskBuilder class by /// cloning the partition structure of a source disk. /// </summary> /// <param name="sourceDisk">The disk to clone.</param> public BiosPartitionedDiskBuilder(VirtualDisk sourceDisk) { if (sourceDisk == null) { throw new ArgumentNullException(nameof(sourceDisk)); } _capacity = sourceDisk.Capacity; _biosGeometry = sourceDisk.BiosGeometry; _bootSectors = new SparseMemoryStream(); _bootSectors.SetLength(_capacity); foreach (StreamExtent extent in new BiosPartitionTable(sourceDisk).GetMetadataDiskExtents()) { sourceDisk.Content.Position = extent.Start; byte[] buffer = StreamUtilities.ReadExact(sourceDisk.Content, (int)extent.Length); _bootSectors.Position = extent.Start; _bootSectors.Write(buffer, 0, buffer.Length); } PartitionTable = new BiosPartitionTable(_bootSectors, _biosGeometry); _partitionContents = new Dictionary <int, BuilderExtent>(); }
public static DiscUtils.Ntfs.NtfsFileSystem NtfsFileSystem() { SparseMemoryBuffer buffer = new SparseMemoryBuffer(4096); SparseMemoryStream ms = new SparseMemoryStream(); Geometry diskGeometry = Geometry.FromCapacity(30 * 1024 * 1024); return(DiscUtils.Ntfs.NtfsFileSystem.Format(ms, "", diskGeometry, 0, diskGeometry.TotalSectorsLong)); }
private static DiscFileSystem FatFileSystem() { SparseMemoryBuffer buffer = new SparseMemoryBuffer(4096); SparseMemoryStream ms = new SparseMemoryStream(); Geometry diskGeometry = Geometry.FromCapacity(30 * 1024 * 1024); return(DiscUtils.Fat.FatFileSystem.FormatFloppy(ms, FloppyDiskType.Extended, null)); }
protected V8Container NewContainer() { var baseStream = SparseMemoryStream.WritableStream(); var container = new V8Container(baseStream, V8ContainerMode.Write); _disposables.Add(container); return(container); }
public void InvalidImageThrowsException() { SparseMemoryStream stream = new SparseMemoryStream(); byte[] buffer = new byte[1024 * 1024]; stream.Write(buffer, 0, 1024 * 1024); stream.Position = 0; Assert.Throws <InvalidFileSystemException>(() => new FatFileSystem(stream)); }
public void CreateBySizeInGap() { SparseMemoryStream ms = new SparseMemoryStream(); Geometry geom = new Geometry(15, 30, 63); ms.SetLength(geom.Capacity); BiosPartitionTable table = BiosPartitionTable.Initialize(ms, geom); Assert.AreEqual(0, table.CreatePrimaryByCylinder(0, 4, 33, false)); Assert.AreEqual(1, table.CreatePrimaryByCylinder(10, 14, 33, false)); table.Create(geom.ToLogicalBlockAddress(new ChsAddress(4, 0, 1)) * 512, WellKnownPartitionType.WindowsFat, true); }
public void CanRead() { SparseMemoryStream memStream = new SparseMemoryStream(new SparseMemoryBuffer(1), FileAccess.ReadWrite); ThreadSafeStream tss = new ThreadSafeStream(memStream); Assert.Equal(true, tss.CanRead); memStream = new SparseMemoryStream(new SparseMemoryBuffer(1), FileAccess.Write); tss = new ThreadSafeStream(memStream); Assert.Equal(false, tss.CanRead); }
public void Format_LargeDisk() { long size = 1024L * 1024 * 1024L * 1024; // 1 TB SparseMemoryStream partStream = new SparseMemoryStream(); NtfsFileSystem.Format(partStream, "New Partition", Geometry.FromCapacity(size), 0, size / 512); NtfsFileSystem ntfs = new NtfsFileSystem(partStream); ntfs.Dump(TextWriter.Null, ""); }
/// <summary> /// Initializes a new instance of the BiosPartitionedDiskBuilder class. /// </summary> /// <param name="capacity">The capacity of the disk (in bytes)</param> /// <param name="biosGeometry">The BIOS geometry of the disk</param> public BiosPartitionedDiskBuilder(long capacity, Geometry biosGeometry) { _capacity = capacity; _biosGeometry = biosGeometry; _bootSectors = new SparseMemoryStream(); _bootSectors.SetLength(capacity); _partitionTable = BiosPartitionTable.Initialize(_bootSectors, _biosGeometry); _partitionContents = new Dictionary<int, BuilderExtent>(); }
/// <summary> /// Initializes a new instance of the BiosPartitionedDiskBuilder class. /// </summary> /// <param name="capacity">The capacity of the disk (in bytes)</param> /// <param name="biosGeometry">The BIOS geometry of the disk</param> public BiosPartitionedDiskBuilder(long capacity, Geometry biosGeometry) { _capacity = capacity; _biosGeometry = biosGeometry; _bootSectors = new SparseMemoryStream(); _bootSectors.SetLength(capacity); _partitionTable = BiosPartitionTable.Initialize(_bootSectors, _biosGeometry); _partitionContents = new Dictionary <int, BuilderExtent>(); }
public void Initialize() { long capacity = 3 * 1024 * 1024; SparseMemoryStream ms = new SparseMemoryStream(); ms.SetLength(capacity); Geometry geom = Geometry.FromCapacity(capacity); BiosPartitionTable table = BiosPartitionTable.Initialize(ms, geom); Assert.AreEqual(0, table.Count); }
public BiosPartitionedDiskBuilder(long capacity, byte[] bootSectors, Geometry biosGeometry) { _capacity = capacity; _biosGeometry = biosGeometry; _bootSectors = new SparseMemoryStream(); _bootSectors.SetLength(capacity); _bootSectors.Write(bootSectors, 0, bootSectors.Length); _partitionTable = new BiosPartitionTable(_bootSectors, biosGeometry); _partitionContents = new Dictionary <int, BuilderExtent>(); }
public void Format_SmallDisk() { long size = 8 * 1024 * 1024; SparseMemoryStream partStream = new SparseMemoryStream(); //VirtualDisk disk = Vhd.Disk.InitializeDynamic(partStream, Ownership.Dispose, size); NtfsFileSystem.Format(partStream, "New Partition", Geometry.FromCapacity(size), 0, size / 512); NtfsFileSystem ntfs = new NtfsFileSystem(partStream); ntfs.Dump(TextWriter.Null, ""); }
public BiosPartitionedDiskBuilder(long capacity, byte[] bootSectors, Geometry biosGeometry) { _capacity = capacity; _biosGeometry = biosGeometry; _bootSectors = new SparseMemoryStream(); _bootSectors.SetLength(capacity); _bootSectors.Write(bootSectors, 0, bootSectors.Length); _partitionTable = new BiosPartitionTable(_bootSectors, biosGeometry); _partitionContents = new Dictionary<int, BuilderExtent>(); }
IDataTransform.GetTransformedStream( Stream encodedStream, IDictionary transformContext ) { Stream tempStream = new SparseMemoryStream(_lowWaterMark, _highWaterMark); tempStream = new CompressEmulationStream(encodedStream, tempStream, 0, new CompoundFileDeflateTransform()); // return a VersionedStream that works with the VersionedStreamOwner // to verify/update our FormatVersion info return(new VersionedStream(tempStream, _versionedStreamOwner)); }
public static DiscFileSystem DiagnosticNtfsFileSystem() { SparseMemoryBuffer buffer = new SparseMemoryBuffer(4096); SparseMemoryStream ms = new SparseMemoryStream(); Geometry diskGeometry = Geometry.FromCapacity(30 * 1024 * 1024); DiscUtils.Ntfs.NtfsFileSystem.Format(ms, "", diskGeometry, 0, diskGeometry.TotalSectorsLong); var discFs = new DiscUtils.Diagnostics.ValidatingFileSystem <NtfsFileSystem, NtfsFileSystemChecker>(ms); discFs.CheckpointInterval = 1; discFs.GlobalIOTraceCapturesStackTraces = false; return(discFs); }
public void VeryLargePartition() { long capacity = 1300 * 1024L * 1024L * 1024; SparseMemoryStream ms = new SparseMemoryStream(); ms.SetLength(capacity); Geometry geom = Geometry.LbaAssistedBiosGeometry(capacity); BiosPartitionTable table = BiosPartitionTable.Initialize(ms, geom); // exception occurs here int i = table.CreatePrimaryByCylinder(0, 150000, (byte)WellKnownPartitionType.WindowsNtfs, true); Assert.AreEqual(150000, geom.ToChsAddress(table[0].LastSector).Cylinder); }
public override void SetLength(long newLength) { CheckDisposed(); Debug.Assert(_cachePrefixStream == null); // we only expect this thing to be not null during Archive Save execution // that would between PreSaveNotofication call and Save SaveStreaming if (newLength < 0) { throw new ArgumentOutOfRangeException("newLength"); } if (_currentStreamLength != newLength) { _dirtyFlag = true; _dataChanged = true; if (newLength <= _persistedSize) { // the stream becomes smaller than our disk block, which means that // we can drop the in-memory-sparse-suffix if (_sparseMemoryStreamSuffix != null) { _sparseMemoryStreamSuffix.Close(); _sparseMemoryStreamSuffix = null; } } else { // we need to construct Sparse Memory stream if we do not have one yet if (_sparseMemoryStreamSuffix == null) { _sparseMemoryStreamSuffix = new SparseMemoryStream(_lowWaterMark, _highWaterMark); } // set size on the Sparse Memory Stream _sparseMemoryStreamSuffix.SetLength(newLength - _persistedSize); // no need for checked as it was verified above } _currentStreamLength = newLength; // if stream was truncated to the point that our current position is beyond the end of the stream, // we need to reset position so it is at the end of the stream if (_currentStreamLength < _currentStreamPosition) { Seek(_currentStreamLength, SeekOrigin.Begin); } } }
public void CreateByCylinder() { SparseMemoryStream ms = new SparseMemoryStream(); Geometry geom = new Geometry(15, 30, 63); ms.SetLength(geom.Capacity); BiosPartitionTable table = BiosPartitionTable.Initialize(ms, geom); Assert.AreEqual(0, table.CreatePrimaryByCylinder(0, 4, 33, false)); Assert.AreEqual(1, table.CreatePrimaryByCylinder(10, 14, 33, false)); Assert.AreEqual(geom.ToLogicalBlockAddress(new ChsAddress(0, 1, 1)), table[0].FirstSector); Assert.AreEqual(geom.ToLogicalBlockAddress(new ChsAddress(5, 0, 1)) - 1, table[0].LastSector); Assert.AreEqual(geom.ToLogicalBlockAddress(new ChsAddress(10, 0, 1)), table[1].FirstSector); Assert.AreEqual(geom.ToLogicalBlockAddress(new ChsAddress(14, 29, 63)), table[1].LastSector); }
private int ReadFromCache(SparseMemoryStream cache, long start, int count, byte[] buffer, int bufferOffset) { #if DEBUG // debug only check for valid parameters, as we generally expect callers to verify them PackagingUtilities.VerifyStreamReadArgs(this, buffer, bufferOffset, count); #endif Debug.Assert(cache != null); Debug.Assert(start >= 0); IList <MemoryStreamBlock> collection = cache.MemoryBlockCollection; checked { // use BinarySearch to locate blocks of interest quickly bool match; // exact match? int index = FindIndexOfBlockAtOffset(cache, start, out match); // if match was found, read from it int bytesRead = 0; if (match) { MemoryStreamBlock memStreamBlock = collection[index]; long overlapBlockOffset; long overlapBlockSize; // we have got an overlap which can be used to satisfy the read request, // at least partially PackagingUtilities.CalculateOverlap(memStreamBlock.Offset, memStreamBlock.Stream.Length, start, count, out overlapBlockOffset, out overlapBlockSize); if (overlapBlockSize > 0) { // overlap must be starting at the start as we know for sure that // memStreamBlock.Offset <= start Debug.Assert(overlapBlockOffset == start); memStreamBlock.Stream.Seek(overlapBlockOffset - memStreamBlock.Offset, SeekOrigin.Begin); // we know that memStream will return as much data as we requested // even if this logic changes we do not have to return everything // a partially complete read is acceptable here bytesRead = memStreamBlock.Stream.Read(buffer, bufferOffset, (int)overlapBlockSize); } } return(bytesRead); } }
public DiskBuilderTest() { SparseMemoryStream sourceStream = new SparseMemoryStream(); sourceStream.SetLength(160 * 1024L * 1024); for (int i = 0; i < 8; ++i) { sourceStream.Position = i * 1024L * 1024; sourceStream.WriteByte((byte)i); } sourceStream.Position = 150 * 1024 * 1024; sourceStream.WriteByte(0xFF); diskContent = sourceStream; }
public void ExtentInfo() { using (SparseMemoryStream ms = new SparseMemoryStream()) { Geometry diskGeometry = Geometry.FromCapacity(30 * 1024 * 1024); NtfsFileSystem ntfs = NtfsFileSystem.Format(ms, "", diskGeometry, 0, diskGeometry.TotalSectorsLong); // Check non-resident attribute using (Stream s = ntfs.OpenFile(@"file", FileMode.Create, FileAccess.ReadWrite)) { byte[] data = new byte[(int)ntfs.ClusterSize]; data[0] = 0xAE; data[1] = 0x3F; data[2] = 0x8D; s.Write(data, 0, (int)ntfs.ClusterSize); } var extents = ntfs.PathToExtents("file"); Assert.Equal(1, extents.Length); Assert.Equal(ntfs.ClusterSize, extents[0].Length); ms.Position = extents[0].Start; Assert.Equal(0xAE, ms.ReadByte()); Assert.Equal(0x3F, ms.ReadByte()); Assert.Equal(0x8D, ms.ReadByte()); // Check resident attribute using (Stream s = ntfs.OpenFile(@"file2", FileMode.Create, FileAccess.ReadWrite)) { s.WriteByte(0xBA); s.WriteByte(0x82); s.WriteByte(0x2C); } extents = ntfs.PathToExtents("file2"); Assert.Equal(1, extents.Length); Assert.Equal(3, extents[0].Length); byte[] read = new byte[100]; ms.Position = extents[0].Start; ms.Read(read, 0, 100); Assert.Equal(0xBA, read[0]); Assert.Equal(0x82, read[1]); Assert.Equal(0x2C, read[2]); } }
public BiosPartitionedDiskBuilder(long capacity, byte[] bootSectors, Geometry biosGeometry) { if (bootSectors == null) { throw new ArgumentNullException(nameof(bootSectors)); } _capacity = capacity; _biosGeometry = biosGeometry; _bootSectors = new SparseMemoryStream(); _bootSectors.SetLength(capacity); _bootSectors.Write(bootSectors, 0, bootSectors.Length); PartitionTable = new BiosPartitionTable(_bootSectors, biosGeometry); _partitionContents = new Dictionary <int, BuilderExtent>(); }
public void V8Container_Constructor_ThrowsIfOnIncorrectStream( V8ContainerMode mode, bool canSeek, bool canRead, bool canWrite, string expectedMessage) { using (var baseStream = new SparseMemoryStream(canRead, canWrite, canSeek)) { Action ctor = () => { using (new V8Container(baseStream, mode)) { } }; ctor.Should() .Throw <ArgumentException>() .WithMessage(expectedMessage); } }
public void Seek() { SparseMemoryStream memStream = new SparseMemoryStream(new SparseMemoryBuffer(1), FileAccess.ReadWrite); memStream.SetLength(1024); ThreadSafeStream tss = new ThreadSafeStream(memStream); tss.Seek(10, SeekOrigin.Begin); Assert.Equal(10, tss.Position); tss.Seek(10, SeekOrigin.Current); Assert.Equal(20, tss.Position); tss.Seek(-10, SeekOrigin.End); Assert.Equal(1014, tss.Position); }
public void CreateBySize() { long capacity = 3 * 1024 * 1024; SparseMemoryStream ms = new SparseMemoryStream(); ms.SetLength(capacity); Geometry geom = Geometry.FromCapacity(capacity); BiosPartitionTable table = BiosPartitionTable.Initialize(ms, geom); int idx = table.Create(2 * 1024 * 1024, WellKnownPartitionType.WindowsFat, false); // Make sure the partition is within 10% of the size requested. Assert.That((2 * 1024 * 2) * 0.9 < table[idx].SectorCount); Assert.AreEqual(geom.ToLogicalBlockAddress(new ChsAddress(0, 1, 1)), table[idx].FirstSector); Assert.AreEqual(geom.HeadsPerCylinder - 1, geom.ToChsAddress((int)table[idx].LastSector).Head); Assert.AreEqual(geom.SectorsPerTrack, geom.ToChsAddress((int)table[idx].LastSector).Sector); }
public void DisposeView() { SparseMemoryStream memStream = new SparseMemoryStream(new SparseMemoryBuffer(1), FileAccess.ReadWrite); memStream.SetLength(1024); ThreadSafeStream tss = new ThreadSafeStream(memStream); SparseStream altView = tss.OpenView(); altView.Dispose(); tss.ReadByte(); SparseStream altView2 = tss.OpenView(); altView2.ReadByte(); }
public void FieldUpdating(PXCache sender, PXFieldUpdatingEventArgs e) { if (e.NewValue != null) { if (e.NewValue is byte[][]) { return; } var fileStream = new SparseMemoryStream(); var gZipStream = new GZipStream(fileStream, CompressionMode.Compress); PXReflectionSerializer.Serialize(gZipStream, e.NewValue, false); gZipStream.Close(); fileStream.Close(); e.NewValue = fileStream.GetBuf(); } }
/// <summary> /// Find offset of next available block after this offset /// </summary> /// <param name="cache">cache to inspect</param> /// <param name="start">offset to start search from</param> /// <returns>offset of block start if found, otherwise -1</returns> /// <remarks>Contract: Call only when start is not inside any existing block.</remarks> private long FindOffsetOfNextAvailableBlockAfter(SparseMemoryStream cache, long start) { Debug.Assert(start >= 0); Debug.Assert(cache != null); // Find the index where a new block with offset start would be placed bool match; int index = FindIndexOfBlockAtOffset(cache, start, out match); Debug.Assert(!match, "Must only be called when there is no match"); // If we have an exact match, we return the offset of the next block, unless // there are no more blocks - then we return -1 if (index >= (cache.MemoryBlockCollection.Count)) return -1; // no block beyond start else { return cache.MemoryBlockCollection[index].Offset; } }
/// <summary> /// Uses BinarySearch to locate the index of the block that contains start /// </summary> /// <param name="cache"></param> /// <param name="start"></param> /// <param name="match">True if match found. If this is false, the index returned is where the item would appear if it existed.</param> /// <returns>Index</returns> private int FindIndexOfBlockAtOffset(SparseMemoryStream cache, long start, out bool match) { if (cache.MemoryBlockCollection.Count == 0) { match = false; return 0; } // use BinarySearch to locate blocks of interest quickly if (_comparisonBlock == null) _comparisonBlock = new MemoryStreamBlock(null, start); else _comparisonBlock.Offset = start; int index = cache.MemoryBlockCollection.BinarySearch(_comparisonBlock); if (index < 0) // no match { // ~index represents the place at which the block we asked for // would appear if it existed index = ~index; match = false; } else { match = true; } return index; }
private int ReadFromCache(SparseMemoryStream cache, long start, int count, byte[] buffer, int bufferOffset) { #if DEBUG // debug only check for valid parameters, as we generally expect callers to verify them PackagingUtilities.VerifyStreamReadArgs(this, buffer, bufferOffset, count); #endif Debug.Assert(cache != null); Debug.Assert(start >=0); IList<MemoryStreamBlock> collection = cache.MemoryBlockCollection; checked { // use BinarySearch to locate blocks of interest quickly bool match; // exact match? int index = FindIndexOfBlockAtOffset(cache, start, out match); // if match was found, read from it int bytesRead = 0; if (match) { MemoryStreamBlock memStreamBlock = collection[index]; long overlapBlockOffset; long overlapBlockSize; // we have got an overlap which can be used to satisfy the read request, // at least partially PackagingUtilities.CalculateOverlap(memStreamBlock.Offset, memStreamBlock.Stream.Length, start, count, out overlapBlockOffset, out overlapBlockSize); if (overlapBlockSize > 0) { // overlap must be starting at the start as we know for sure that // memStreamBlock.Offset <= start Debug.Assert(overlapBlockOffset == start); memStreamBlock.Stream.Seek(overlapBlockOffset - memStreamBlock.Offset, SeekOrigin.Begin); // we know that memStream will return as much data as we requested // even if this logic changes we do not have to return everything // a partially complete read is acceptable here bytesRead = memStreamBlock.Stream.Read(buffer, bufferOffset, (int)overlapBlockSize); } } return bytesRead; } }
public void CreateWholeDiskAligned() { long capacity = 3 * 1024 * 1024; SparseMemoryStream ms = new SparseMemoryStream(); ms.SetLength(capacity); Geometry geom = Geometry.FromCapacity(capacity); BiosPartitionTable table = BiosPartitionTable.Initialize(ms, geom); int idx = table.CreateAligned(WellKnownPartitionType.WindowsFat, true, 64 * 1024); Assert.AreEqual(0, table[idx].FirstSector % 128); Assert.AreEqual(0, (table[idx].LastSector + 1) % 128); Assert.Greater(table[idx].SectorCount * 512, capacity * 0.9); // Make sure the partition index is Zero Assert.AreEqual(0, ((BiosPartitionInfo)table[idx]).PrimaryIndex); }
public override void SetLength(long newLength) { CheckDisposed(); Debug.Assert(_cachePrefixStream == null); // we only expect this thing to be not null during Archive Save execution // that would between PreSaveNotofication call and Save SaveStreaming if (newLength < 0) { throw new ArgumentOutOfRangeException("newLength"); } if (_currentStreamLength != newLength) { _dirtyFlag = true; _dataChanged = true; if (newLength <= _persistedSize) { // the stream becomes smaller than our disk block, which means that // we can drop the in-memory-sparse-suffix if (_sparseMemoryStreamSuffix != null) { _sparseMemoryStreamSuffix.Close(); _sparseMemoryStreamSuffix = null; } } else { // we need to construct Sparse Memory stream if we do not have one yet if (_sparseMemoryStreamSuffix == null) { _sparseMemoryStreamSuffix = new SparseMemoryStream(_lowWaterMark, _highWaterMark); } // set size on the Sparse Memory Stream _sparseMemoryStreamSuffix.SetLength(newLength - _persistedSize); // no need for checked as it was verified above } _currentStreamLength = newLength; // if stream was truncated to the point that our current position is beyond the end of the stream, // we need to reset position so it is at the end of the stream if (_currentStreamLength < _currentStreamPosition) Seek(_currentStreamLength, SeekOrigin.Begin); } }
IDataTransform.GetTransformedStream( Stream encodedStream, IDictionary transformContext ) { Stream tempStream = new SparseMemoryStream(_lowWaterMark, _highWaterMark); tempStream = new CompressEmulationStream(encodedStream, tempStream, 0, new CompoundFileDeflateTransform()); // return a VersionedStream that works with the VersionedStreamOwner // to verify/update our FormatVersion info return new VersionedStream(tempStream, _versionedStreamOwner); }
public void CreateBySizeInGapAligned() { SparseMemoryStream ms = new SparseMemoryStream(); Geometry geom = new Geometry(15, 30, 63); ms.SetLength(geom.Capacity); BiosPartitionTable table = BiosPartitionTable.Initialize(ms, geom); Assert.AreEqual(0, table.CreatePrimaryByCylinder(0, 4, 33, false)); Assert.AreEqual(1, table.CreatePrimaryByCylinder(10, 14, 33, false)); int idx = table.CreateAligned(3 * 1024 * 1024, WellKnownPartitionType.WindowsFat, true, 64 * 1024); Assert.AreEqual(2, idx); Assert.AreEqual(0, table[idx].FirstSector % 128); Assert.AreEqual(0, (table[idx].LastSector + 1) % 128); }
/// <summary> /// Write /// </summary> /// <param name="buffer"></param> /// <param name="offset"></param> /// <param name="count"></param> /// <remarks>In streaming mode, write should accumulate data into the SparseMemoryStream.</remarks> override public void Write(byte[] buffer, int offset, int count) { CheckDisposed(); PackagingUtilities.VerifyStreamWriteArgs(this, buffer, offset, count); Debug.Assert(_cachePrefixStream == null); // we only expect this thing to be not null during Archive Save execution // that would between PreSaveNotofication call and Save SaveStreaming Debug.Assert(_currentStreamPosition >= 0); if (count == 0) { return; } int diskBytesToWrite = 0; _dirtyFlag = true; _dataChanged = true; long newStreamPosition = _currentStreamPosition; checked { // Try to satisfy request with the Write to the Disk if (newStreamPosition < _persistedSize) { Debug.Assert(!_blockManager.Streaming); // we have at least partial overlap between request and the data on disk _blockManager.Stream.Seek(_persistedOffset + newStreamPosition, SeekOrigin.Begin); // Note on casting: // It is safe to cast the result of Math.Min(count, _persistedSize - newStreamPosition)) // from long to int since it cannot be bigger than count and count is int type diskBytesToWrite = (int) (Math.Min(count, _persistedSize - newStreamPosition)); // this is a safe cast as count has int type _blockManager.Stream.Write(buffer, offset, diskBytesToWrite); newStreamPosition += diskBytesToWrite; count -= diskBytesToWrite; offset += diskBytesToWrite; } // check whether we need to save data to the memory Stream; if (newStreamPosition + count > _persistedSize) { if (_sparseMemoryStreamSuffix == null) { _sparseMemoryStreamSuffix = new SparseMemoryStream(_lowWaterMark, _highWaterMark); } _sparseMemoryStreamSuffix.Seek(newStreamPosition - _persistedSize, SeekOrigin.Begin); _sparseMemoryStreamSuffix.Write(buffer, offset, count); newStreamPosition += count; } _currentStreamPosition = newStreamPosition; _currentStreamLength = Math.Max(_currentStreamLength, _currentStreamPosition); } return; }
public void LargeDisk() { long capacity = 300 * 1024L * 1024L * 1024; SparseMemoryStream ms = new SparseMemoryStream(); ms.SetLength(capacity); Geometry geom = Geometry.LbaAssistedBiosGeometry(capacity); BiosPartitionTable table = BiosPartitionTable.Initialize(ms, geom); table.Create(150 * 1024L * 1024L * 1024, WellKnownPartitionType.WindowsNtfs, false); table.Create(20 * 1024L * 1024L * 1024, WellKnownPartitionType.WindowsNtfs, false); table.Create(20 * 1024L * 1024L * 1024, WellKnownPartitionType.WindowsNtfs, false); Assert.AreEqual(3, table.Partitions.Count); Assert.Greater(table[0].SectorCount * 512L, 140 * 1024L * 1024L * 1024); Assert.Greater(table[1].SectorCount * 512L, 19 * 1024L * 1024L * 1024); Assert.Greater(table[2].SectorCount * 512L, 19 * 1024L * 1024L * 1024); Assert.Greater(table[0].FirstSector, 0); Assert.Greater(table[1].FirstSector, table[0].LastSector); Assert.Greater(table[2].FirstSector, table[1].LastSector); }
public void ExtentInfo() { using (SparseMemoryStream ms = new SparseMemoryStream()) { Geometry diskGeometry = Geometry.FromCapacity(30 * 1024 * 1024); NtfsFileSystem ntfs = NtfsFileSystem.Format(ms, "", diskGeometry, 0, diskGeometry.TotalSectors); // Check non-resident attribute using (Stream s = ntfs.OpenFile(@"file", FileMode.Create, FileAccess.ReadWrite)) { byte[] data = new byte[(int)ntfs.ClusterSize]; data[0] = 0xAE; data[1] = 0x3F; data[2] = 0x8D; s.Write(data, 0, (int)ntfs.ClusterSize); } var extents = ntfs.PathToExtents("file"); Assert.AreEqual(1, extents.Length); Assert.AreEqual(ntfs.ClusterSize, extents[0].Length); ms.Position = extents[0].Start; Assert.AreEqual(0xAE, ms.ReadByte()); Assert.AreEqual(0x3F, ms.ReadByte()); Assert.AreEqual(0x8D, ms.ReadByte()); // Check resident attribute using (Stream s = ntfs.OpenFile(@"file2", FileMode.Create, FileAccess.ReadWrite)) { s.WriteByte(0xBA); s.WriteByte(0x82); s.WriteByte(0x2C); } extents = ntfs.PathToExtents("file2"); Assert.AreEqual(1, extents.Length); Assert.AreEqual(3, extents[0].Length); byte[] read = new byte[100]; ms.Position = extents[0].Start; ms.Read(read, 0, 100); Assert.AreEqual(0xBA, read[0]); Assert.AreEqual(0x82, read[1]); Assert.AreEqual(0x2C, read[2]); } }
/// <summary> /// This is the common Pre Save notiofication handler for /// RawDataFile Block and File Item Stream /// It makes assumption that the overlap generally start coming in at the beginning of a /// large disk image, so we should only try to cache cache overlaped data in the prefix /// of the disk block /// Block can also return a value indicating whether PreSaveNotification should be extended to the blocks that are positioned after /// it in the Block List. For example, if block has completely handled PreSaveNotification in a way that it cached the whole area that /// was in danger (of being overwritten) it means that no blocks need to worry about this anymore. After all no 2 blocks should have /// share on disk buffers. Another scenario is when block can determine that area in danger is positioned before the block's on disk /// buffers; this means that all blocks that are positioned later in the block list do not need to worry about this PreSaveNotification /// as their buffers should be positioned even further alone in the file. /// </summary> internal static PreSaveNotificationScanControlInstruction CommonPreSaveNotificationHandler( Stream stream, long offset, long size, long onDiskOffset, long onDiskSize, ref SparseMemoryStream cachePrefixStream) { checked { Debug.Assert(size >=0); Debug.Assert(offset >=0); Debug.Assert(onDiskSize >=0); Debug.Assert(onDiskOffset >=0); // trivial request if (size == 0) { // The area being overwritten is of size 0 so there is no need to notify any blocks about this. return PreSaveNotificationScanControlInstruction.Stop; } if (cachePrefixStream != null) { // if we have something in cache prefix buffer we only should check whatever tail data isn't cached checked{onDiskOffset += cachePrefixStream.Length;} checked{onDiskSize -= cachePrefixStream.Length;} Debug.Assert(onDiskSize >=0); } if (onDiskSize == 0) { // the raw data block happened to be fully cached // in this case (onDiskSize==0) can not be used as a reliable indicator of the position of the // on disk buffer relative to the other; it is just an indicator of an empty buffer which might have a meaningless offset // that shouldn't be driving any decisions return PreSaveNotificationScanControlInstruction.Continue; } // we need to first find out if the raw data that isn't cached yet overlaps with any disk space // that is about to be overriden long overlapBlockOffset; long overlapBlockSize; PackagingUtilities.CalculateOverlap(onDiskOffset, onDiskSize, offset, size , out overlapBlockOffset, out overlapBlockSize); if (overlapBlockSize <= 0) { // No overlap , we can ignore this message. // In addition to that, if (onDiskOffset > offset) it means that, given the fact that all blocks after // the current one will have even larger offsets, they couldn't possibly overlap with (offset ,size ) chunk . return (onDiskOffset > offset) ? PreSaveNotificationScanControlInstruction.Stop : PreSaveNotificationScanControlInstruction.Continue; } // at this point we have an overlap, we need to read the data that is overlapped // and merge it with whatever we already have in cache // let's figure out the part that isn't cached yet, and needs to be long blockSizeToCache; checked { blockSizeToCache = overlapBlockOffset + overlapBlockSize - onDiskOffset; } Debug.Assert(blockSizeToCache >0); // there must be a non empty block at this point that needs to be cached // We need to ensure that we do have a place to store this data if (cachePrefixStream == null) { cachePrefixStream = new SparseMemoryStream(_lowWaterMark, _highWaterMark); } else { // if we already have some cached prefix data we have to make sure we are // appending new data tro the tail of the already cached chunk cachePrefixStream.Seek(0, SeekOrigin.End); } stream.Seek(onDiskOffset, SeekOrigin.Begin); long bytesCopied = PackagingUtilities.CopyStream(stream, cachePrefixStream, blockSizeToCache, 4096); if (bytesCopied != blockSizeToCache) { throw new FileFormatException(SR.Get(SRID.CorruptedData)); } // if the contdition below is true it means that, given the fact that all blocks after // the current one will have even larger offsets, they couldn't possibly overlap with (offset ,size ) chunk return ((onDiskOffset + onDiskSize) >= (offset + size)) ? PreSaveNotificationScanControlInstruction.Stop : PreSaveNotificationScanControlInstruction.Continue; } }
public void Setup() { SparseMemoryStream sourceStream = new SparseMemoryStream(); sourceStream.SetLength(160 * 1024L * 1024); for (int i = 0; i < 8; ++i) { sourceStream.Position = i * 1024L * 1024; sourceStream.WriteByte((byte)i); } sourceStream.Position = 150 * 1024 * 1024; sourceStream.WriteByte(0xFF); diskContent = sourceStream; }
/// <summary> /// Initializes a new instance of the BiosPartitionedDiskBuilder class by /// cloning the partition structure of a source disk. /// </summary> /// <param name="sourceDisk">The disk to clone</param> public BiosPartitionedDiskBuilder(VirtualDisk sourceDisk) { _capacity = sourceDisk.Capacity; _biosGeometry = sourceDisk.BiosGeometry; _bootSectors = new SparseMemoryStream(); _bootSectors.SetLength(_capacity); foreach (var extent in new BiosPartitionTable(sourceDisk).GetMetadataDiskExtents()) { sourceDisk.Content.Position = extent.Start; byte[] buffer = Utilities.ReadFully(sourceDisk.Content, (int)extent.Length); _bootSectors.Position = extent.Start; _bootSectors.Write(buffer, 0, buffer.Length); } _partitionTable = new BiosPartitionTable(_bootSectors, _biosGeometry); _partitionContents = new Dictionary<int, BuilderExtent>(); }
/// <summary> /// ChangeMode /// </summary> /// <param name="newMode"></param> /// <remarks>Does not update Position of _current for change to ReadPassThroughMode.</remarks> private void ChangeMode(Mode newMode) { // ignore redundant calls (allowing these actually simplifies the logic in SetLength) if (newMode == _mode) return; // every state change requires this logic if (_current != null) { _current.Close(); _dirtyForClosing = false; _dirtyForFlushing = false; } // set the new mode - must be done before the call to Seek _mode = newMode; switch (newMode) { case Mode.Start: { _current = null; _baseStream.Position = 0; break; } case Mode.ReadPassThrough: case Mode.WritePassThrough: { Debug.Assert(_baseStream.Position == 0); // create the appropriate DeflateStream _current = new DeflateStream(_baseStream, newMode == Mode.WritePassThrough ? CompressionMode.Compress : CompressionMode.Decompress, true); break; } case Mode.Emulation: { // Create emulation stream. Use a MemoryStream for local caching. // Do not change this logic for RM cases because the data is "in the clear" and must // not be persisted in a vulnerable location. SparseMemoryStream memStream = new SparseMemoryStream(_lowWaterMark, _highWaterMark); _current = new CompressEmulationStream(_baseStream, memStream, _position, new DeflateEmulationTransform()); // verify and set length UpdateUncompressedDataLength(_current.Length); break; } case Mode.Disposed: break; default: Debug.Assert(false, "Illegal state for CompressStream - logic error"); break; } }
public void SetActive() { long capacity = 10 * 1024 * 1024; SparseMemoryStream ms = new SparseMemoryStream(); ms.SetLength(capacity); Geometry geom = Geometry.FromCapacity(capacity); BiosPartitionTable table = BiosPartitionTable.Initialize(ms, geom); table.Create(1 * 1024 * 1024, WellKnownPartitionType.WindowsFat, false); table.Create(2 * 1024 * 1024, WellKnownPartitionType.WindowsFat, false); table.Create(3 * 1024 * 1024, WellKnownPartitionType.WindowsFat, false); table.SetActivePartition(1); table.SetActivePartition(2); Assert.IsFalse(((BiosPartitionInfo)table.Partitions[1]).IsActive); Assert.IsTrue(((BiosPartitionInfo)table.Partitions[2]).IsActive); }
public void Delete() { long capacity = 10 * 1024 * 1024; SparseMemoryStream ms = new SparseMemoryStream(); ms.SetLength(capacity); Geometry geom = Geometry.FromCapacity(capacity); BiosPartitionTable table = BiosPartitionTable.Initialize(ms, geom); Assert.AreEqual(0, table.Create(1 * 1024 * 1024, WellKnownPartitionType.WindowsFat, false)); Assert.AreEqual(1, table.Create(2 * 1024 * 1024, WellKnownPartitionType.WindowsFat, false)); Assert.AreEqual(2, table.Create(3 * 1024 * 1024, WellKnownPartitionType.WindowsFat, false)); long[] sectorCount = new long[] { table[0].SectorCount, table[1].SectorCount, table[2].SectorCount }; table.Delete(1); Assert.AreEqual(2, table.Count); Assert.AreEqual(sectorCount[2], table[1].SectorCount); }