1 | {"version":3,"sources":["../src/vmdk-read.js"],"names":[],"mappings":"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","file":"vmdk-read.js","sourcesContent":["'use strict'\n\nimport zlib from 'zlib'\nimport {VirtualBuffer} from './virtual-buffer'\n\nconst sectorSize = 512\nconst compressionDeflate = 'COMPRESSION_DEFLATE'\nconst compressionNone = 'COMPRESSION_NONE'\nconst compressionMap = [compressionNone, compressionDeflate]\n\nfunction parseS64b (buffer, offset, valueName) {\n const low = buffer.readInt32LE(offset)\n const high = buffer.readInt32LE(offset + 4)\n // here there might be a surprise because we are reading 64 integers into double floats (53 bits mantissa)\n const value = low | high << 32\n if ((value & (Math.pow(2, 32) - 1)) !== low) {\n throw new Error('Unsupported VMDK, ' + valueName + ' is too big')\n }\n return value\n}\n\nfunction parseU64b (buffer, offset, valueName) {\n const low = buffer.readUInt32LE(offset)\n const high = buffer.readUInt32LE(offset + 4)\n // here there might be a surprise because we are reading 64 integers into double floats (53 bits mantissa)\n const value = low | high << 32\n if ((value & (Math.pow(2, 32) - 1)) !== low) {\n throw new Error('Unsupported VMDK, ' + valueName + ' is too big')\n }\n return value\n}\n\nfunction parseDescriptor (descriptorSlice) {\n const descriptorText = descriptorSlice.toString('ascii').replace(/\\x00+$/, '')\n const descriptorDict = {}\n const extentList = []\n const lines = descriptorText.split(/\\r?\\n/).filter((line) => {\n return line.trim().length > 0 && line[0] !== '#'\n })\n for (let line of lines) {\n let defLine = line.split('=')\n // the wonky quote test is to avoid having an equal sign in the name of an extent\n if (defLine.length === 2 && defLine[0].indexOf('\"') === -1) {\n descriptorDict[defLine[0]] = defLine[1].replace(/['\"]+/g, '')\n } else {\n const items = line.split(' ')\n extentList.push({\n access: items[0],\n sizeSectors: items[1],\n type: items[2],\n name: items[3],\n offset: items.length > 4 ? items[4] : 0\n })\n }\n }\n return {descriptor: descriptorDict, extents: extentList}\n}\n\nfunction parseFlags (flagBuffer) {\n const number = flagBuffer.readUInt32LE(0)\n return {\n newLineTest: !!(number & (1 << 0)),\n useSecondaryGrain: !!(number & (1 << 1)),\n useZeroedGrainTable: !!(number & (1 << 2)),\n compressedGrains: !!(number & (1 << 16)),\n hasMarkers: !!(number & (1 << 17))\n }\n}\n\nfunction parseHeader (buffer) {\n const magicString = buffer.slice(0, 4).toString('ascii')\n if (magicString !== 'KDMV') {\n throw new Error('not a VMDK file')\n }\n const version = buffer.readUInt32LE(4)\n if (version !== 1 && version !== 3) {\n throw new Error('unsupported VMDK version ' + version + ', only version 1 and 3 are supported')\n }\n const flags = parseFlags(buffer.slice(8, 12))\n const capacitySectors = parseU64b(buffer, 12, 'capacitySectors')\n const grainSizeSectors = parseU64b(buffer, 20, 'grainSizeSectors')\n const descriptorOffsetSectors = parseU64b(buffer, 28, 'descriptorOffsetSectors')\n const descriptorSizeSectors = parseU64b(buffer, 36, 'descriptorSizeSectors')\n const numGTEsPerGT = buffer.readUInt32LE(44)\n const rGrainDirectoryOffsetSectors = parseS64b(buffer, 48, 'rGrainDirectoryOffsetSectors')\n const grainDirectoryOffsetSectors = parseS64b(buffer, 56, 'grainDirectoryOffsetSectors')\n const overheadSectors = parseS64b(buffer, 64, 'overheadSectors')\n const compressionMethod = compressionMap[buffer.readUInt16LE(77)]\n const l1EntrySectors = numGTEsPerGT * grainSizeSectors\n return {\n flags,\n compressionMethod,\n grainSizeSectors,\n overheadSectors,\n capacitySectors,\n descriptorOffsetSectors,\n descriptorSizeSectors,\n grainDirectoryOffsetSectors,\n rGrainDirectoryOffsetSectors,\n l1EntrySectors,\n numGTEsPerGT\n }\n}\nasync function readGrain (offsetSectors, buffer, compressed) {\n const offset = offsetSectors * sectorSize\n const size = buffer.readUInt32LE(offset + 8)\n const grainBuffer = buffer.slice(offset + 12, offset + 12 + size)\n const grainContent = compressed ? await zlib.inflateSync(grainBuffer) : grainBuffer\n const lba = parseU64b(buffer, offset, 'l2Lba')\n return {\n offsetSectors: offsetSectors,\n offset,\n lba,\n lbaBytes: lba * sectorSize,\n size,\n buffer: grainBuffer,\n grain: grainContent,\n grainSize: grainContent.byteLength\n }\n}\n\nfunction tryToParseMarker (buffer) {\n const value = buffer.readUInt32LE(0)\n const size = buffer.readUInt32LE(8)\n const type = buffer.readUInt32LE(12)\n return {value, size, type}\n}\n\nfunction alignSectors (number) {\n return Math.ceil(number / sectorSize) * sectorSize\n}\n\nexport class VMDKDirectParser {\n constructor (readStream) {\n this.virtualBuffer = new VirtualBuffer(readStream)\n this.header = null\n }\n\n // I found a VMDK file whose L1 and L2 table did not have a marker, but they were at the top\n // I detect this case and eat those tables first then let the normal loop go over the grains.\n async _readL1 () {\n const position = this.virtualBuffer.position\n const l1entries = Math.floor((this.header.capacitySectors + this.header.l1EntrySectors - 1) / this.header.l1EntrySectors)\n const sectorAlignedL1Bytes = alignSectors(l1entries * 4)\n const l1Buffer = await this.virtualBuffer.readChunk(sectorAlignedL1Bytes, 'L1 table ' + position)\n let l2Start = 0\n let l2IsContiguous = true\n for (let i = 0; i < l1entries; i++) {\n const l1Entry = l1Buffer.readUInt32LE(i * 4)\n if (i > 0) {\n const previousL1Entry = l1Buffer.readUInt32LE((i - 1) * 4)\n l2IsContiguous = l2IsContiguous && ((l1Entry - previousL1Entry) === 4)\n } else {\n l2IsContiguous = (l1Entry * sectorSize === this.virtualBuffer.position) || (l1Entry * sectorSize === this.virtualBuffer.position + 512)\n l2Start = l1Entry * sectorSize\n }\n }\n if (!l2IsContiguous) {\n return null\n }\n const l1L2FreeSpace = l2Start - this.virtualBuffer.position\n if (l1L2FreeSpace > 0) {\n await this.virtualBuffer.readChunk(l1L2FreeSpace, 'freeSpace between L1 and L2')\n }\n const l2entries = Math.ceil(this.header.capacitySectors / this.header.grainSizeSectors)\n const l2ByteSize = alignSectors(l1entries * this.header.numGTEsPerGT * 4)\n const l2Buffer = await this.virtualBuffer.readChunk(l2ByteSize, 'L2 table ' + position)\n let grainsAreInAscendingOrder = true\n let previousL2Entry = 0\n let firstGrain = null\n for (let i = 0; i < l2entries; i++) {\n const l2Entry = l2Buffer.readUInt32LE(i * 4)\n if (i > 0 && previousL2Entry !== 0 && l2Entry !== 0) {\n grainsAreInAscendingOrder = grainsAreInAscendingOrder && (previousL2Entry < l2Entry)\n }\n previousL2Entry = l2Entry\n if (firstGrain === null) {\n firstGrain = l2Entry\n }\n }\n if (!grainsAreInAscendingOrder) {\n // TODO: here we could transform the file to a sparse VHD on the fly because we have the complete table\n throw new Error('Unsupported file format')\n }\n const freeSpace = firstGrain * sectorSize - this.virtualBuffer.position\n if (freeSpace > 0) {\n await this.virtualBuffer.readChunk(freeSpace, 'freeSpace after L2')\n }\n }\n\n async readHeader () {\n const headerBuffer = await this.virtualBuffer.readChunk(512, 'readHeader')\n const magicString = headerBuffer.slice(0, 4).toString('ascii')\n if (magicString !== 'KDMV') {\n throw new Error('not a VMDK file')\n }\n const version = headerBuffer.readUInt32LE(4)\n if (version !== 1 && version !== 3) {\n throw new Error('unsupported VMDK version ' + version + ', only version 1 and 3 are supported')\n }\n this.header = parseHeader(headerBuffer)\n // I think the multiplications are OK, because the descriptor is always at the beginning of the file\n const descriptorLength = this.header.descriptorSizeSectors * sectorSize\n const descriptorBuffer = await this.virtualBuffer.readChunk(descriptorLength, 'descriptor')\n this.descriptor = parseDescriptor(descriptorBuffer)\n let l1PositionBytes = null\n if (this.header.grainDirectoryOffsetSectors !== -1 && this.header.grainDirectoryOffsetSectors !== 0) {\n l1PositionBytes = this.header.grainDirectoryOffsetSectors * sectorSize\n }\n const endOfDescriptor = this.virtualBuffer.position\n if (l1PositionBytes !== null && (l1PositionBytes === endOfDescriptor || l1PositionBytes === endOfDescriptor + sectorSize)) {\n if (l1PositionBytes === endOfDescriptor + sectorSize) {\n await this.virtualBuffer.readChunk(sectorSize, 'skipping L1 marker')\n }\n await this._readL1()\n }\n return this.header\n }\n\n async next () {\n while (!this.virtualBuffer.isDepleted) {\n const position = this.virtualBuffer.position\n const sector = await this.virtualBuffer.readChunk(512, 'marker start ' + position)\n if (sector.length === 0) {\n break\n }\n const marker = tryToParseMarker(sector)\n if (marker.size === 0) {\n if (marker.value !== 0) {\n await this.virtualBuffer.readChunk(marker.value * sectorSize, 'other marker value ' + this.virtualBuffer.position)\n }\n } else if (marker.size > 10) {\n const grainDiskSize = marker.size + 12\n const alignedGrainDiskSize = alignSectors(grainDiskSize)\n const remainOfBufferSize = alignedGrainDiskSize - sectorSize\n const remainderOfGrainBuffer = await this.virtualBuffer.readChunk(remainOfBufferSize, 'grain remainder ' + this.virtualBuffer.position)\n const grainBuffer = Buffer.concat([sector, remainderOfGrainBuffer])\n return readGrain(0, grainBuffer, this.header.compressionMethod === compressionDeflate && this.header.flags.compressedGrains)\n }\n }\n return new Promise((resolve) => resolve(null))\n }\n}\n\nexport async function readRawContent (readStream) {\n const virtualBuffer = new VirtualBuffer(readStream)\n const headerBuffer = await virtualBuffer.readChunk(512, 'header')\n let header = parseHeader(headerBuffer)\n\n // I think the multiplications are OK, because the descriptor is always at the beginning of the file\n const descriptorLength = header.descriptorSizeSectors * sectorSize\n const descriptorBuffer = await virtualBuffer.readChunk(descriptorLength, 'descriptor')\n const descriptor = parseDescriptor(descriptorBuffer)\n\n // TODO: we concat them back for now so that the indices match, we'll have to introduce a bias later\n const remainingBuffer = await virtualBuffer.readChunk(-1, 'remainder')\n const buffer = Buffer.concat([headerBuffer, descriptorBuffer, remainingBuffer])\n if (header.grainDirectoryOffsetSectors === -1) {\n header = parseHeader(buffer.slice(-1024, -1024 + sectorSize))\n }\n const rawOutputBuffer = new Buffer(header.capacitySectors * sectorSize)\n rawOutputBuffer.fill(0)\n const l1Size = Math.floor((header.capacitySectors + header.l1EntrySectors - 1) / header.l1EntrySectors)\n const l2Size = header.numGTEsPerGT\n const l1 = []\n for (let i = 0; i < l1Size; i++) {\n const l1Entry = buffer.readUInt32LE(header.grainDirectoryOffsetSectors * sectorSize + 4 * i)\n if (l1Entry !== 0) {\n l1.push(l1Entry)\n const l2 = []\n for (let j = 0; j < l2Size; j++) {\n const l2Entry = buffer.readUInt32LE(l1Entry * sectorSize + 4 * j)\n if (l2Entry !== 0 && l2Entry !== 1) {\n const grain = await readGrain(l2Entry, buffer, header['flags']['compressedGrains'])\n grain.grain.copy(rawOutputBuffer, grain.lba * sectorSize)\n l2[j] = grain\n }\n }\n }\n }\n const vmdkType = descriptor['descriptor']['createType']\n if (!vmdkType || vmdkType.toLowerCase() !== 'streamOptimized'.toLowerCase()) {\n throw new Error('unsupported VMDK type \"' + vmdkType + '\", only streamOptimized is supported')\n }\n return {descriptor: descriptor.descriptor, extents: descriptor.extents, rawFile: rawOutputBuffer}\n}\n"]} |