UNPKG

4.14 kBJavaScriptView Raw
1"use strict";
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6exports.default = readVmdkGrainTable;
7exports.readCapacityAndGrainTable = readCapacityAndGrainTable;
8var _util = require("./util");
9const SECTOR_SIZE = 512;
10const HEADER_SIZE = 512;
11const FOOTER_POSITION = -1024;
12const DISK_CAPACITY_OFFSET = 12;
13const GRAIN_SIZE_OFFSET = 20;
14const NUM_GTE_PER_GT_OFFSET = 44;
15const GRAIN_ADDRESS_OFFSET = 56;
16const MANTISSA_BITS_IN_DOUBLE = 53;
17const getLongLong = (buffer, offset, name) => {
18 if (buffer.byteLength < offset + 8) {
19 throw new Error(`buffer ${name} is too short, expecting ${offset + 8} minimum, got ${buffer.byteLength}`);
20 }
21 const dataView = new DataView(buffer);
22 const highBits = dataView.getUint32(offset + 4, true);
23 if (highBits >= Math.pow(2, MANTISSA_BITS_IN_DOUBLE - 32)) {
24 throw new Error('Unsupported file, high order bits are too high in field ' + name);
25 }
26 const res = dataView.getUint32(offset, true);
27 return res + highBits * Math.pow(2, 32);
28};
29async function readVmdkGrainTable(fileAccessor) {
30 return (await readCapacityAndGrainTable(fileAccessor)).tablePromise;
31}
32async function grabTables(grainDirectoryEntries, grainDir, grainTablePhysicalSize, fileAccessor) {
33 const cachedGrainTables = [];
34 for (let i = 0; i < grainDirectoryEntries; i++) {
35 const grainTableAddr = grainDir[i] * SECTOR_SIZE;
36 if (grainTableAddr !== 0) {
37 cachedGrainTables[i] = new Uint32Array(await fileAccessor(grainTableAddr, grainTableAddr + grainTablePhysicalSize));
38 }
39 }
40 return cachedGrainTables;
41}
42async function readCapacityAndGrainTable(fileAccessor) {
43 let headerBuffer = await fileAccessor(0, HEADER_SIZE);
44 let grainAddrBuffer = headerBuffer.slice(GRAIN_ADDRESS_OFFSET, GRAIN_ADDRESS_OFFSET + 8);
45 if (new Int8Array(grainAddrBuffer).every(val => val === -1)) {
46 headerBuffer = await fileAccessor(FOOTER_POSITION, FOOTER_POSITION + HEADER_SIZE);
47 grainAddrBuffer = headerBuffer.slice(GRAIN_ADDRESS_OFFSET, GRAIN_ADDRESS_OFFSET + 8);
48 }
49 const grainDirPosBytes = getLongLong(grainAddrBuffer, 0, 'grain directory address') * SECTOR_SIZE;
50 const capacity = getLongLong(headerBuffer, DISK_CAPACITY_OFFSET, 'capacity') * SECTOR_SIZE;
51 async function readTable() {
52 const grainSizeByte = getLongLong(headerBuffer, GRAIN_SIZE_OFFSET, 'grain size') * SECTOR_SIZE;
53 const grainCount = Math.ceil(capacity / grainSizeByte);
54 const numGTEsPerGT = new DataView(headerBuffer).getUint32(NUM_GTE_PER_GT_OFFSET, true);
55 const grainTablePhysicalSize = numGTEsPerGT * 4;
56 const grainDirectoryEntries = Math.ceil(grainCount / numGTEsPerGT);
57 const grainDirectoryPhysicalSize = grainDirectoryEntries * 4;
58 const grainDir = new Uint32Array(await fileAccessor(grainDirPosBytes, grainDirPosBytes + grainDirectoryPhysicalSize));
59 const cachedGrainTables = await grabTables(grainDirectoryEntries, grainDir, grainTablePhysicalSize, fileAccessor);
60 const extractedGrainTable = [];
61 for (let i = 0; i < grainCount; i++) {
62 const directoryEntry = Math.floor(i / numGTEsPerGT);
63 const grainTable = cachedGrainTables[directoryEntry];
64 if (grainTable !== undefined) {
65 const grainAddr = grainTable[i % numGTEsPerGT];
66 if (grainAddr !== 0) {
67 extractedGrainTable.push([i, grainAddr]);
68 }
69 }
70 }
71 extractedGrainTable.sort(([_i1, grainAddress1], [_i2, grainAddress2]) => grainAddress1 - grainAddress2);
72 const byteLength = 4 * extractedGrainTable.length;
73 const grainLogicalAddressList = new DataView(new ArrayBuffer(byteLength));
74 const grainFileOffsetList = new DataView(new ArrayBuffer(byteLength));
75 extractedGrainTable.forEach(([index, grainAddress], i) => {
76 grainLogicalAddressList.setUint32(i * 4, index, true);
77 grainFileOffsetList.setUint32(i * 4, grainAddress, true);
78 });
79 return {
80 grainLogicalAddressList: grainLogicalAddressList.buffer,
81 grainFileOffsetList: grainFileOffsetList.buffer
82 };
83 }
84 return {
85 tablePromise: (0, _util.suppressUnhandledRejection)(readTable()),
86 capacityBytes: capacity
87 };
88}
89//# sourceMappingURL=vmdk-read-table.js.map
\No newline at end of file