private static long CalcSize(SparseStream content, ServerSparseExtentHeader header) { long numDataGrains = StreamExtent.BlockCount(content.Extents, header.GrainSize * Sizes.Sector); long grainTableSectors = Utilities.Ceil(header.NumGTEsPerGT * 4, Sizes.Sector); return((grainTableSectors + (numDataGrains * header.GrainSize)) * Sizes.Sector); }
internal override List <BuilderExtent> FixExtents(out long totalLength) { List <BuilderExtent> extents = new List <BuilderExtent>(); ServerSparseExtentHeader header = DiskImageFile.CreateServerSparseExtentHeader(_content.Length); GlobalDirectoryExtent gdExtent = new GlobalDirectoryExtent(header); long grainTableStart = (header.GdOffset * Sizes.Sector) + gdExtent.Length; long grainTableCoverage = header.NumGTEsPerGT * header.GrainSize * Sizes.Sector; foreach (var grainTableRange in StreamExtent.Blocks(_content.Extents, grainTableCoverage)) { for (int i = 0; i < grainTableRange.Count; ++i) { long grainTable = grainTableRange.Offset + i; long dataStart = grainTable * grainTableCoverage; GrainTableExtent gtExtent = new GrainTableExtent(grainTableStart, new SubStream(_content, dataStart, Math.Min(grainTableCoverage, _content.Length - dataStart)), header); extents.Add(gtExtent); gdExtent.SetEntry((int)grainTable, (uint)(grainTableStart / Sizes.Sector)); grainTableStart += gtExtent.Length; } } extents.Insert(0, gdExtent); header.FreeSector = (uint)(grainTableStart / Sizes.Sector); byte[] buffer = header.GetBytes(); extents.Insert(0, new BuilderBufferExtent(0, buffer)); totalLength = grainTableStart; return(extents); }
private static void CreateExtent(Stream extentStream, long size, ExtentType type, long descriptorLength, out long descriptorStart) { if (type == ExtentType.Flat || type == ExtentType.Vmfs) { extentStream.SetLength(size); descriptorStart = 0; return; } if (type == ExtentType.Sparse) { CreateSparseExtent(extentStream, size, descriptorLength, out descriptorStart); return; } else if (type == ExtentType.VmfsSparse) { ServerSparseExtentHeader header = CreateServerSparseExtentHeader(size); extentStream.Position = 0; extentStream.Write(header.GetBytes(), 0, 4 * Sizes.Sector); byte[] blankGlobalDirectory = new byte[header.NumGdEntries * 4]; extentStream.Write(blankGlobalDirectory, 0, blankGlobalDirectory.Length); descriptorStart = 0; return; } else { throw new NotImplementedException("Extent type not implemented"); } }
internal static ServerSparseExtentHeader CreateServerSparseExtentHeader(long size) { uint numSectors = (uint)Utilities.Ceil(size, Sizes.Sector); uint numGDEntries = (uint)Utilities.Ceil(numSectors * (long)Sizes.Sector, 2 * Sizes.OneMiB); ServerSparseExtentHeader header = new ServerSparseExtentHeader(); header.Capacity = numSectors; header.GrainSize = 1; header.GdOffset = 4; header.NumGdEntries = numGDEntries; header.FreeSector = (uint)(header.GdOffset + Utilities.Ceil(numGDEntries * 4, Sizes.Sector)); return(header); }
public ServerSparseExtentStream(Stream file, Ownership ownsFile, long diskOffset, SparseStream parentDiskStream, Ownership ownsParentDiskStream) { _fileStream = file; _ownsFileStream = ownsFile; _diskOffset = diskOffset; _parentDiskStream = parentDiskStream; _ownsParentDiskStream = ownsParentDiskStream; file.Position = 0; byte[] firstSectors = Utilities.ReadFully(file, Sizes.Sector * 4); _serverHeader = ServerSparseExtentHeader.Read(firstSectors, 0); _header = _serverHeader; _gtCoverage = _header.NumGTEsPerGT * (long)_header.GrainSize * Sizes.Sector; LoadGlobalDirectory(); }
public static ServerSparseExtentHeader Read(byte[] buffer, int offset) { ServerSparseExtentHeader hdr = new ServerSparseExtentHeader(); hdr.MagicNumber = Utilities.ToUInt32LittleEndian(buffer, offset + 0x00); hdr.Version = Utilities.ToUInt32LittleEndian(buffer, offset + 0x04); hdr.Flags = Utilities.ToUInt32LittleEndian(buffer, offset + 0x08); hdr.Capacity = Utilities.ToUInt32LittleEndian(buffer, offset + 0x0C); hdr.GrainSize = Utilities.ToUInt32LittleEndian(buffer, offset + 0x10); hdr.GdOffset = Utilities.ToUInt32LittleEndian(buffer, offset + 0x14); hdr.NumGdEntries = Utilities.ToUInt32LittleEndian(buffer, offset + 0x18); hdr.FreeSector = Utilities.ToUInt32LittleEndian(buffer, offset + 0x1C); hdr.SavedGeneration = Utilities.ToUInt32LittleEndian(buffer, offset + 0x660); hdr.UncleanShutdown = Utilities.ToUInt32LittleEndian(buffer, offset + 0x66C); hdr.NumGTEsPerGT = 4096; return(hdr); }
public GlobalDirectoryExtent(ServerSparseExtentHeader header) : base(header.GdOffset * Sizes.Sector, Utilities.RoundUp(header.NumGdEntries * 4, Sizes.Sector)) { _buffer = new byte[Length]; }
public GrainTableExtent(long outputStart, SparseStream content, ServerSparseExtentHeader header) : base(outputStart, CalcSize(content, header)) { _content = content; _header = header; }