UNPKG

9.78 kBSource Map (JSON)View Raw
1{"version":3,"file":"vmdk-read-table.js","names":["_util","require","SECTOR_SIZE","HEADER_SIZE","FOOTER_POSITION","DISK_CAPACITY_OFFSET","GRAIN_SIZE_OFFSET","NUM_GTE_PER_GT_OFFSET","GRAIN_ADDRESS_OFFSET","MANTISSA_BITS_IN_DOUBLE","getLongLong","buffer","offset","name","byteLength","Error","dataView","DataView","highBits","getUint32","Math","pow","res","readVmdkGrainTable","fileAccessor","readCapacityAndGrainTable","tablePromise","grabTables","grainDirectoryEntries","grainDir","grainTablePhysicalSize","cachedGrainTables","i","grainTableAddr","Uint32Array","headerBuffer","grainAddrBuffer","slice","Int8Array","every","val","grainDirPosBytes","capacity","readTable","grainSizeByte","grainCount","ceil","numGTEsPerGT","grainDirectoryPhysicalSize","extractedGrainTable","directoryEntry","floor","grainTable","undefined","grainAddr","push","sort","_i1","grainAddress1","_i2","grainAddress2","length","grainLogicalAddressList","ArrayBuffer","grainFileOffsetList","forEach","index","grainAddress","setUint32","suppressUnhandledRejection","capacityBytes"],"sources":["../src/vmdk-read-table.js"],"sourcesContent":["import { suppressUnhandledRejection } from './util'\n\nconst SECTOR_SIZE = 512\nconst HEADER_SIZE = 512\nconst FOOTER_POSITION = -1024\nconst DISK_CAPACITY_OFFSET = 12\nconst GRAIN_SIZE_OFFSET = 20\nconst NUM_GTE_PER_GT_OFFSET = 44\nconst GRAIN_ADDRESS_OFFSET = 56\n\nconst MANTISSA_BITS_IN_DOUBLE = 53\nconst getLongLong = (buffer, offset, name) => {\n if (buffer.byteLength < offset + 8) {\n throw new Error(`buffer ${name} is too short, expecting ${offset + 8} minimum, got ${buffer.byteLength}`)\n }\n\n const dataView = new DataView(buffer)\n\n const highBits = dataView.getUint32(offset + 4, true)\n if (highBits >= Math.pow(2, MANTISSA_BITS_IN_DOUBLE - 32)) {\n throw new Error('Unsupported file, high order bits are too high in field ' + name)\n }\n\n const res = dataView.getUint32(offset, true)\n return res + highBits * Math.pow(2, 32)\n}\n\n/**\n * the grain table is an object { grainLogicalAddressList: [number], grainFileOffsetList: [number] }\n * grainLogicalAddressList contains the logical addresses of the grains in the file, in the order they are stored in the VMDK\n * grainFileOffsetList contains the offsets of the grains in the VMDK file, in the order they are stored in the VMDK (so this array should be ascending)\n *\n * THIS CODE RUNS ON THE BROWSER\n */\nexport default async function readVmdkGrainTable(fileAccessor) {\n return (await readCapacityAndGrainTable(fileAccessor)).tablePromise\n}\n\n/**\n * reading a big chunk of the file to memory before parsing is useful when the vmdk is gzipped and random access is costly\n */\nasync function grabTables(grainDirectoryEntries, grainDir, grainTablePhysicalSize, fileAccessor) {\n const cachedGrainTables = []\n for (let i = 0; i < grainDirectoryEntries; i++) {\n const grainTableAddr = grainDir[i] * SECTOR_SIZE\n if (grainTableAddr !== 0) {\n cachedGrainTables[i] = new Uint32Array(\n await fileAccessor(grainTableAddr, grainTableAddr + grainTablePhysicalSize)\n )\n }\n }\n return cachedGrainTables\n}\n\n/***\n * the tables are encoded in uint32 LE\n * @param fileAccessor: (start, end) => ArrayBuffer\n * @returns {Promise<{capacityBytes: number, tablePromise: Promise<{ grainLogicalAddressList: ArrayBuffer, grainFileOffsetList: ArrayBuffer }>}>}\n */\nexport async function readCapacityAndGrainTable(fileAccessor) {\n let headerBuffer = await fileAccessor(0, HEADER_SIZE)\n let grainAddrBuffer = headerBuffer.slice(GRAIN_ADDRESS_OFFSET, GRAIN_ADDRESS_OFFSET + 8)\n if (new Int8Array(grainAddrBuffer).every(val => val === -1)) {\n headerBuffer = await fileAccessor(FOOTER_POSITION, FOOTER_POSITION + HEADER_SIZE)\n grainAddrBuffer = headerBuffer.slice(GRAIN_ADDRESS_OFFSET, GRAIN_ADDRESS_OFFSET + 8)\n }\n\n const grainDirPosBytes = getLongLong(grainAddrBuffer, 0, 'grain directory address') * SECTOR_SIZE\n const capacity = getLongLong(headerBuffer, DISK_CAPACITY_OFFSET, 'capacity') * SECTOR_SIZE\n\n async function readTable() {\n const grainSizeByte = getLongLong(headerBuffer, GRAIN_SIZE_OFFSET, 'grain size') * SECTOR_SIZE\n const grainCount = Math.ceil(capacity / grainSizeByte)\n const numGTEsPerGT = new DataView(headerBuffer).getUint32(NUM_GTE_PER_GT_OFFSET, true)\n const grainTablePhysicalSize = numGTEsPerGT * 4\n const grainDirectoryEntries = Math.ceil(grainCount / numGTEsPerGT)\n const grainDirectoryPhysicalSize = grainDirectoryEntries * 4\n const grainDir = new Uint32Array(\n await fileAccessor(grainDirPosBytes, grainDirPosBytes + grainDirectoryPhysicalSize)\n )\n const cachedGrainTables = await grabTables(grainDirectoryEntries, grainDir, grainTablePhysicalSize, fileAccessor)\n const extractedGrainTable = []\n for (let i = 0; i < grainCount; i++) {\n const directoryEntry = Math.floor(i / numGTEsPerGT)\n const grainTable = cachedGrainTables[directoryEntry]\n if (grainTable !== undefined) {\n const grainAddr = grainTable[i % numGTEsPerGT]\n if (grainAddr !== 0) {\n extractedGrainTable.push([i, grainAddr])\n }\n }\n }\n extractedGrainTable.sort(([_i1, grainAddress1], [_i2, grainAddress2]) => grainAddress1 - grainAddress2)\n\n const byteLength = 4 * extractedGrainTable.length\n const grainLogicalAddressList = new DataView(new ArrayBuffer(byteLength))\n const grainFileOffsetList = new DataView(new ArrayBuffer(byteLength))\n extractedGrainTable.forEach(([index, grainAddress], i) => {\n grainLogicalAddressList.setUint32(i * 4, index, true)\n grainFileOffsetList.setUint32(i * 4, grainAddress, true)\n })\n return {\n grainLogicalAddressList: grainLogicalAddressList.buffer,\n grainFileOffsetList: grainFileOffsetList.buffer,\n }\n }\n\n return {\n tablePromise: suppressUnhandledRejection(readTable()),\n capacityBytes: capacity,\n }\n}\n"],"mappings":"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"}
\No newline at end of file