UNPKG

xo-vmdk-to-vhd

Version:
118 lines (117 loc) 5.06 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.compressionNone = exports.compressionDeflate = exports.SECTOR_SIZE = exports.MARKER_GT = exports.MARKER_GD = exports.MARKER_FOOTER = exports.MARKER_EOS = void 0; exports.createStreamOptimizedHeader = createStreamOptimizedHeader; exports.parseFlags = parseFlags; exports.parseU64b = parseU64b; exports.unpackHeader = unpackHeader; const SECTOR_SIZE = exports.SECTOR_SIZE = 512; const compressionDeflate = exports.compressionDeflate = 'COMPRESSION_DEFLATE'; const compressionNone = exports.compressionNone = 'COMPRESSION_NONE'; const MARKER_EOS = exports.MARKER_EOS = 0; const MARKER_GT = exports.MARKER_GT = 1; const MARKER_GD = exports.MARKER_GD = 2; const MARKER_FOOTER = exports.MARKER_FOOTER = 3; const compressionMap = [compressionNone, compressionDeflate]; function parseFlags(flagBuffer) { const number = flagBuffer.readUInt32LE(0); return { newLineTest: !!(number & 1 << 0), useSecondaryGrain: !!(number & 1 << 1), useZeroedGrainTable: !!(number & 1 << 2), compressedGrains: !!(number & 1 << 16), hasMarkers: !!(number & 1 << 17) }; } function parseS64b(buffer, offset, valueName) { const extraBits = buffer.readIntLE(offset + 6, 2); const value = buffer.readIntLE(offset, 6); const hadValueInHighBytes = !(extraBits === 0 || extraBits === -1); const readWrongSign = Math.sign(value) * Math.sign(extraBits) < 0; if (hadValueInHighBytes || readWrongSign) { throw new Error('Unsupported VMDK, ' + valueName + ' is too big'); } return value; } function parseU64b(buffer, offset, valueName) { const extraBits = buffer.readUIntLE(offset + 6, 2); const value = buffer.readUIntLE(offset, 6); if (extraBits > 0) { throw new Error('Unsupported VMDK, ' + valueName + ' is too big'); } return value; } function unpackHeader(buffer) { const magicString = buffer.slice(0, 4).toString('ascii'); if (magicString !== 'KDMV') { throw new Error('not a VMDK file'); } const version = buffer.readUInt32LE(4); if (version !== 1 && version !== 3) { throw new Error('unsupported VMDK version ' + version + ', only version 1 and 3 are supported'); } const flags = parseFlags(buffer.slice(8, 12)); const capacitySectors = parseU64b(buffer, 12, 'capacitySectors'); const grainSizeSectors = parseU64b(buffer, 20, 'grainSizeSectors'); const descriptorOffsetSectors = parseU64b(buffer, 28, 'descriptorOffsetSectors'); const descriptorSizeSectors = parseU64b(buffer, 36, 'descriptorSizeSectors'); const numGTEsPerGT = buffer.readUInt32LE(44); const rGrainDirectoryOffsetSectors = parseS64b(buffer, 48, 'rGrainDirectoryOffsetSectors'); const grainDirectoryOffsetSectors = parseS64b(buffer, 56, 'grainDirectoryOffsetSectors'); const overheadSectors = parseS64b(buffer, 64, 'overheadSectors'); const compressionMethod = compressionMap[buffer.readUInt16LE(77)]; const l1EntrySectors = numGTEsPerGT * grainSizeSectors; return { magicString, version, flags, compressionMethod, grainSizeSectors, overheadSectors, capacitySectors, descriptorOffsetSectors, descriptorSizeSectors, grainDirectoryOffsetSectors, rGrainDirectoryOffsetSectors, l1EntrySectors, numGTEsPerGT }; } function createStreamOptimizedHeader(capacitySectors, descriptorSizeSectors, grainDirectoryOffsetSectors = -1, rGrainDirectoryOffsetSectors = 0) { const headerBuffer = Buffer.alloc(SECTOR_SIZE); Buffer.from('KDMV', 'ascii').copy(headerBuffer, 0); headerBuffer.writeUInt32LE(3, 4); const flags = 1 | 1 << 1 | 1 << 16 | 1 << 17; headerBuffer.writeUInt32LE(flags, 8); headerBuffer.writeBigUInt64LE(BigInt(capacitySectors), 12); const grainSizeSectors = 128; headerBuffer.writeBigUInt64LE(BigInt(grainSizeSectors), 20); const descriptorOffsetSectors = 1; headerBuffer.writeBigUInt64LE(BigInt(descriptorOffsetSectors), 28); headerBuffer.writeBigUInt64LE(BigInt(descriptorSizeSectors), 36); const numGTEsPerGT = 512; headerBuffer.writeUInt32LE(numGTEsPerGT, 44); headerBuffer.writeBigInt64LE(BigInt(rGrainDirectoryOffsetSectors), 48); 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); let overheadSectors = 1 + descriptorSizeSectors; if (grainDirectoryOffsetSectors > 0) { overheadSectors += grainDirectorySizeSectors + grainTableSizeSectors; } headerBuffer.writeBigInt64LE(BigInt(overheadSectors), 64); headerBuffer.write('\n \r\n', 73, 4, 'ascii'); headerBuffer.writeUInt16LE(1, 77); return { buffer: headerBuffer, grainDirectorySizeSectors, grainTableSizeSectors, grainDirectoryEntries, grainTableEntries }; } //# sourceMappingURL=definitions.js.map