1 | {"version":3,"sources":["../src/vhd-write.js"],"names":[],"mappings":"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","file":"vhd-write.js","sourcesContent":["'use strict'\nimport {open, write} from 'fs-promise'\nimport stream from 'stream'\nimport {VMDKDirectParser} from './vmdk-read'\n\nconst footerCookie = 'conectix'\nconst creatorApp = 'xo '\n// it looks like everybody is using Wi2k\nconst osString = 'Wi2k'\nconst headerCookie = 'cxsparse'\nconst fixedHardDiskType = 2\nconst dynamicHardDiskType = 3\n\nconst sectorSize = 512\n\nexport function computeChecksum (buffer) {\n let sum = 0\n for (let i = 0; i < buffer.length; i++) {\n sum += buffer[i]\n }\n // http://stackoverflow.com/a/1908655/72637 the >>> prevents the number from going negative\n return (~sum) >>> 0\n}\n\nclass Block {\n constructor (blockSize) {\n const bitmapSize = blockSize / sectorSize / 8\n const bufferSize = Math.ceil((blockSize + bitmapSize) / sectorSize) * sectorSize\n this.buffer = new Buffer(bufferSize)\n this.buffer.fill(0)\n this.bitmapBuffer = this.buffer.slice(0, bitmapSize)\n this.dataBuffer = this.buffer.slice(bitmapSize)\n this.bitmapBuffer.fill(0xff)\n }\n\n writeData (buffer, offset = 0) {\n buffer.copy(this.dataBuffer, offset)\n }\n\n async writeOnFile (file) {\n await write(file, this.buffer, 0, this.buffer.length)\n }\n}\n\nclass SparseExtent {\n constructor (dataSize, blockSize, startOffset) {\n this.table = createEmptyTable(dataSize, blockSize)\n this.blockSize = blockSize\n this.startOffset = (startOffset + this.table.buffer.length) / sectorSize\n }\n\n get entryCount () {\n return this.table.entryCount\n }\n\n _writeBlock (blockBuffer, tableIndex, offset) {\n if (blockBuffer.length + offset > this.blockSize) {\n throw new Error('invalid block geometry')\n }\n let entry = this.table.entries[tableIndex]\n if (entry === undefined) {\n entry = new Block(this.blockSize)\n this.table.entries[tableIndex] = entry\n }\n entry.writeData(blockBuffer, offset)\n }\n\n writeBuffer (buffer, offset = 0) {\n const startBlock = Math.floor(offset / this.blockSize)\n const endBlock = Math.ceil((offset + buffer.length) / this.blockSize)\n for (let i = startBlock; i < endBlock; i++) {\n const blockDelta = offset - (i * this.blockSize)\n let blockBuffer, blockOffset\n if (blockDelta > 0) {\n blockBuffer = buffer.slice(0, (i + 1) * this.blockSize - offset)\n blockOffset = blockDelta\n } else {\n blockBuffer = buffer.slice(-blockDelta, (i + 1) * this.blockSize - offset)\n blockOffset = 0\n }\n this._writeBlock(blockBuffer, i, blockOffset)\n }\n }\n\n async writeOnFile (file) {\n let currentOffset = this.startOffset\n for (let i = 0; i < this.table.entryCount; i++) {\n const block = this.table.entries[i]\n if (block !== undefined) {\n this.table.buffer.writeUInt32BE(currentOffset, i * 4)\n currentOffset += block.buffer.length / sectorSize\n }\n }\n await write(file, this.table.buffer, 0, this.table.buffer.length)\n for (let i = 0; i < this.table.entryCount; i++) {\n const block = this.table.entries[i]\n if (block !== undefined) {\n await block.writeOnFile(file)\n }\n }\n }\n}\n\nexport class VHDFile {\n constructor (virtualSize, timestamp) {\n this.geomtry = computeGeometryForSize(virtualSize)\n this.timestamp = timestamp\n this.blockSize = 0x00200000\n this.sparseFile = new SparseExtent(this.geomtry.actualSize, this.blockSize, sectorSize * 3)\n }\n\n writeBuffer (buffer, offset = 0) {\n this.sparseFile.writeBuffer(buffer, offset)\n }\n\n async writeFile (fileName) {\n const fileFooter = createFooter(this.geomtry.actualSize, this.timestamp, this.geomtry, dynamicHardDiskType, 512, 0)\n const diskHeader = createDynamicDiskHeader(this.sparseFile.entryCount, this.blockSize)\n const file = await open(fileName, 'w')\n await write(file, fileFooter, 0, fileFooter.length)\n await write(file, diskHeader, 0, diskHeader.length)\n await this.sparseFile.writeOnFile(file)\n await write(file, fileFooter, 0, fileFooter.length)\n }\n}\n\nexport function computeGeometryForSize (size) {\n let totalSectors = Math.ceil(size / 512)\n let sectorsPerTrack\n let heads\n let cylinderTimesHeads\n if (totalSectors > 65535 * 16 * 255) {\n throw Error('disk is too big')\n }\n // straight copypasta from the file spec appendix on CHS Calculation\n if (totalSectors >= 65535 * 16 * 63) {\n sectorsPerTrack = 255\n heads = 16\n cylinderTimesHeads = totalSectors / sectorsPerTrack\n } else {\n sectorsPerTrack = 17\n cylinderTimesHeads = totalSectors / sectorsPerTrack\n heads = Math.floor((cylinderTimesHeads + 1023) / 1024)\n if (heads < 4) {\n heads = 4\n }\n if (cylinderTimesHeads >= (heads * 1024) || heads > 16) {\n sectorsPerTrack = 31\n heads = 16\n cylinderTimesHeads = totalSectors / sectorsPerTrack\n }\n if (cylinderTimesHeads >= (heads * 1024)) {\n sectorsPerTrack = 63\n heads = 16\n cylinderTimesHeads = totalSectors / sectorsPerTrack\n }\n }\n let cylinders = Math.floor(cylinderTimesHeads / heads)\n let actualSize = cylinders * heads * sectorsPerTrack * sectorSize\n return {cylinders, heads, sectorsPerTrack, actualSize}\n}\n\nexport function createFooter (size, timestamp, geometry, diskType, dataOffsetLow = 0xFFFFFFFF, dataOffsetHigh = 0xFFFFFFFF) {\n let footer = new Buffer(512)\n footer.fill(0)\n new Buffer(footerCookie, 'ascii').copy(footer)\n footer.writeUInt32BE(2, 8)\n footer.writeUInt32BE(0x00010000, 12)\n footer.writeUInt32BE(dataOffsetHigh, 16)\n footer.writeUInt32BE(dataOffsetLow, 20)\n footer.writeUInt32BE(timestamp, 24)\n new Buffer(creatorApp, 'ascii').copy(footer, 28)\n new Buffer(osString, 'ascii').copy(footer, 36)\n // do not use & 0xFFFFFFFF to extract lower bits, that would propagate a negative sign if the 2^31 bit is one\n const sizeHigh = Math.floor(size / Math.pow(2, 32)) % Math.pow(2, 32)\n const sizeLow = size % Math.pow(2, 32)\n footer.writeUInt32BE(sizeHigh, 40)\n footer.writeUInt32BE(sizeLow, 44)\n footer.writeUInt32BE(sizeHigh, 48)\n footer.writeUInt32BE(sizeLow, 52)\n footer.writeUInt16BE(geometry['cylinders'], 56)\n footer.writeUInt8(geometry['heads'], 58)\n footer.writeUInt8(geometry['sectorsPerTrack'], 59)\n footer.writeUInt32BE(diskType, 60)\n let checksum = computeChecksum(footer)\n footer.writeUInt32BE(checksum, 64)\n return footer\n}\n\nexport function createDynamicDiskHeader (tableEntries, blockSize) {\n let header = new Buffer(1024)\n header.fill(0)\n new Buffer(headerCookie, 'ascii').copy(header)\n // hard code no next data\n header.writeUInt32BE(0xFFFFFFFF, 8)\n header.writeUInt32BE(0xFFFFFFFF, 12)\n // hard code table offset\n header.writeUInt32BE(0, 16)\n header.writeUInt32BE(sectorSize * 3, 20)\n header.writeUInt32BE(0x00010000, 24)\n header.writeUInt32BE(tableEntries, 28)\n header.writeUInt32BE(blockSize, 32)\n let checksum = computeChecksum(header)\n header.writeUInt32BE(checksum, 36)\n return header\n}\n\nexport function createEmptyTable (dataSize, blockSize) {\n const blockCount = Math.ceil(dataSize / blockSize)\n const tableSizeSectors = Math.ceil(blockCount * 4 / sectorSize)\n const buffer = new Buffer(tableSizeSectors * sectorSize)\n buffer.fill(0xff)\n return {entryCount: blockCount, buffer: buffer, entries: []}\n}\n\nexport class ReadableRawVHDStream extends stream.Readable {\n constructor (size, vmdkParser) {\n super()\n this.size = size\n var geometry = computeGeometryForSize(size)\n this.footer = createFooter(size, Math.floor(Date.now() / 1000), geometry, fixedHardDiskType)\n this.position = 0\n this.vmdkParser = vmdkParser\n this.done = false\n this.busy = false\n this.currentFile = []\n }\n\n filePadding (paddingLength) {\n if (paddingLength !== 0) {\n const chunkSize = 1024 * 1024 // 1Mo\n const chunkCount = Math.floor(paddingLength / chunkSize)\n for (let i = 0; i < chunkCount; i++) {\n this.currentFile.push(() => {\n const paddingBuffer = new Buffer(chunkSize)\n paddingBuffer.fill(0)\n return paddingBuffer\n })\n }\n this.currentFile.push(() => {\n const paddingBuffer = new Buffer(paddingLength % chunkSize)\n paddingBuffer.fill(0)\n return paddingBuffer\n })\n }\n }\n\n async pushNextBlock () {\n const next = await this.vmdkParser.next()\n if (next === null) {\n const paddingLength = this.size - this.position\n this.filePadding(paddingLength)\n this.currentFile.push(() => this.footer)\n this.currentFile.push(() => {\n this.done = true\n return null\n })\n } else {\n const offset = next.lbaBytes\n const buffer = next.grain\n const paddingLength = offset - this.position\n if (paddingLength < 0) {\n process.nextTick(() => this.emit('error', 'This VMDK file does not have its blocks in the correct order'))\n }\n this.filePadding(paddingLength)\n this.currentFile.push(() => buffer)\n this.position = offset + buffer.length\n }\n return this.pushFileUntilFull()\n }\n\n // returns true if the file is empty\n pushFileUntilFull () {\n while (true) {\n if (this.currentFile.length === 0) {\n break\n }\n const result = this.push(this.currentFile.shift()())\n if (!result) {\n break\n }\n }\n return this.currentFile.length === 0\n }\n\n async pushNextUntilFull () {\n while (!this.done && await this.pushNextBlock()) {\n }\n }\n\n _read () {\n if (this.busy || this.done) {\n return\n }\n if (this.pushFileUntilFull()) {\n this.busy = true\n this.pushNextUntilFull().then(() => {\n this.busy = false\n }).catch((error) => {\n process.nextTick(() => this.emit('error', error))\n })\n }\n }\n}\n\nexport async function convertFromVMDK (vmdkReadStream) {\n const parser = new VMDKDirectParser(vmdkReadStream)\n const header = await parser.readHeader()\n return new ReadableRawVHDStream(header.capacitySectors * sectorSize, parser)\n}\n"]} |