public HostedSparseExtentStream(Stream file, Ownership ownsFile, long diskOffset, SparseStream parentDiskStream, Ownership ownsParentDiskStream) { _fileStream = file; _ownsFileStream = ownsFile; _diskOffset = diskOffset; _parentDiskStream = parentDiskStream; _ownsParentDiskStream = ownsParentDiskStream; file.Position = 0; byte[] headerSector = Utilities.ReadFully(file, Sizes.Sector); _hostedHeader = HostedSparseExtentHeader.Read(headerSector, 0); if (_hostedHeader.GdOffset == -1) { // Fall back to secondary copy that (should) be at the end of the stream, just before the end-of-stream sector marker file.Position = file.Length - Sizes.OneKiB; headerSector = Utilities.ReadFully(file, Sizes.Sector); _hostedHeader = HostedSparseExtentHeader.Read(headerSector, 0); if (_hostedHeader.MagicNumber != HostedSparseExtentHeader.VmdkMagicNumber) { throw new IOException("Unable to locate valid VMDK header or footer"); } } _header = _hostedHeader; if (_hostedHeader.CompressAlgorithm != 0 && _hostedHeader.CompressAlgorithm != 1) { throw new NotSupportedException("Only uncompressed and DEFLATE compressed disks supported"); } _gtCoverage = _header.NumGTEsPerGT * _header.GrainSize * Sizes.Sector; LoadGlobalDirectory(); }
private void LoadDescriptor(Stream s) { s.Position = 0; byte[] header = Utilities.ReadFully(s, (int)Math.Min(Sizes.Sector, s.Length)); if (header.Length < Sizes.Sector || Utilities.ToUInt32LittleEndian(header, 0) != HostedSparseExtentHeader.VmdkMagicNumber) { s.Position = 0; _descriptor = new DescriptorFile(s); if (_access != FileAccess.Read) { _descriptor.ContentId = (uint)_rng.Next(); s.Position = 0; _descriptor.Write(s); s.SetLength(s.Position); } } else { // This is a sparse disk extent, hopefully with embedded descriptor... HostedSparseExtentHeader hdr = HostedSparseExtentHeader.Read(header, 0); if (hdr.DescriptorOffset != 0) { Stream descriptorStream = new SubStream(s, hdr.DescriptorOffset * Sizes.Sector, hdr.DescriptorSize * Sizes.Sector); _descriptor = new DescriptorFile(descriptorStream); if (_access != FileAccess.Read) { _descriptor.ContentId = (uint)_rng.Next(); descriptorStream.Position = 0; _descriptor.Write(descriptorStream); byte[] blank = new byte[descriptorStream.Length - descriptorStream.Position]; descriptorStream.Write(blank, 0, blank.Length); } } } }