fix(xo-vmdk-to-vhd): ensure secondary grain table is present (#6167)
This commit is contained in:
parent
915e4b66a3
commit
e142bacb67
@ -79,33 +79,58 @@ export function unpackHeader(buffer) {
|
||||
}
|
||||
}
|
||||
|
||||
export function createStreamOptimizedHeader(capacitySectors, descriptorSizeSectors, grainDirectoryOffsetSectors = -1) {
|
||||
export function createStreamOptimizedHeader(
|
||||
capacitySectors,
|
||||
descriptorSizeSectors,
|
||||
grainDirectoryOffsetSectors = -1,
|
||||
rGrainDirectoryOffsetSectors = 0
|
||||
) {
|
||||
const headerBuffer = Buffer.alloc(SECTOR_SIZE)
|
||||
Buffer.from('KDMV', 'ascii').copy(headerBuffer, 0)
|
||||
// version
|
||||
headerBuffer.writeUInt32LE(3, 4)
|
||||
// newline, compression, markers
|
||||
const flags = 1 | (1 << 16) | (1 << 17)
|
||||
// newline, secondary grain directory , compression, markers
|
||||
const flags = 1 | (1 << 1) | (1 << 16) | (1 << 17)
|
||||
headerBuffer.writeUInt32LE(flags, 8)
|
||||
|
||||
// number of sectors of the full disk
|
||||
headerBuffer.writeBigUInt64LE(BigInt(capacitySectors), 12)
|
||||
|
||||
// number of sectors in the data of a grain (uncompressed)
|
||||
const grainSizeSectors = 128
|
||||
headerBuffer.writeBigUInt64LE(BigInt(grainSizeSectors), 20)
|
||||
|
||||
// offset of the descriptor(should be directly after header which is 1 sector long)
|
||||
const descriptorOffsetSectors = 1
|
||||
headerBuffer.writeBigUInt64LE(BigInt(descriptorOffsetSectors), 28)
|
||||
// size of the descriptor in sectors
|
||||
headerBuffer.writeBigUInt64LE(BigInt(descriptorSizeSectors), 36)
|
||||
const numGTEsPerGT = 512
|
||||
// number of entries in a grain table
|
||||
headerBuffer.writeUInt32LE(numGTEsPerGT, 44)
|
||||
// The rgdOffset should be ignored because bit 1 of the flags field is not set.
|
||||
|
||||
// redundant grain directory offset
|
||||
headerBuffer.writeBigInt64LE(BigInt(rGrainDirectoryOffsetSectors), 48)
|
||||
|
||||
// grain directory offset in sector
|
||||
headerBuffer.writeBigInt64LE(BigInt(grainDirectoryOffsetSectors), 56)
|
||||
const grainDirectoryEntries = Math.ceil(Math.ceil(capacitySectors / grainSizeSectors) / numGTEsPerGT)
|
||||
const grainTableEntries = grainDirectoryEntries * numGTEsPerGT
|
||||
const grainDirectorySizeSectors = Math.ceil((grainDirectoryEntries * 4) / SECTOR_SIZE)
|
||||
const grainTableSizeSectors = Math.ceil((grainTableEntries * 4) / SECTOR_SIZE)
|
||||
const overheadSectors = 1 + descriptorSizeSectors + grainDirectorySizeSectors + grainTableSizeSectors
|
||||
let overheadSectors = 1 + descriptorSizeSectors
|
||||
// only grow the header if there really is a grain directory
|
||||
if (grainDirectoryOffsetSectors > 0) {
|
||||
overheadSectors += grainDirectorySizeSectors + grainTableSizeSectors
|
||||
}
|
||||
|
||||
// first offset available for data
|
||||
headerBuffer.writeBigInt64LE(BigInt(overheadSectors), 64)
|
||||
|
||||
// newline mangling detector
|
||||
headerBuffer.write('\n \r\n', 73, 4, 'ascii')
|
||||
// use DEFLATE
|
||||
|
||||
// use DEFLATE compression algorithm
|
||||
headerBuffer.writeUInt16LE(1, 77)
|
||||
return {
|
||||
buffer: headerBuffer,
|
||||
|
@ -155,15 +155,28 @@ ddb.geometry.cylinders = "${geometry.cylinders}"
|
||||
yield track(descriptorBuffer)
|
||||
yield* emitBlocks(grainSizeBytes, blockGenerator)
|
||||
yield track(createEmptyMarker(MARKER_GT))
|
||||
const tableOffset = streamPosition
|
||||
let tableOffset = streamPosition
|
||||
// grain tables
|
||||
yield track(tableBuffer)
|
||||
// redundant grain directory
|
||||
// virtual box and esxi seems to prefer having both
|
||||
yield track(createEmptyMarker(MARKER_GD))
|
||||
yield track(createDirectoryBuffer(headerData.grainDirectoryEntries, tableOffset))
|
||||
const rDirectoryOffset = directoryOffset
|
||||
|
||||
// grain tables (again)
|
||||
yield track(createEmptyMarker(MARKER_GT))
|
||||
tableOffset = streamPosition
|
||||
yield track(tableBuffer)
|
||||
// main grain directory (same data)
|
||||
yield track(createEmptyMarker(MARKER_GD))
|
||||
yield track(createDirectoryBuffer(headerData.grainDirectoryEntries, tableOffset))
|
||||
yield track(createEmptyMarker(MARKER_FOOTER))
|
||||
const footer = createStreamOptimizedHeader(
|
||||
diskCapacitySectors,
|
||||
descriptorSizeSectors,
|
||||
directoryOffset / SECTOR_SIZE
|
||||
directoryOffset / SECTOR_SIZE,
|
||||
rDirectoryOffset / SECTOR_SIZE
|
||||
)
|
||||
yield track(footer.buffer)
|
||||
yield track(createEmptyMarker(MARKER_EOS))
|
||||
|
Loading…
Reference in New Issue
Block a user