UNPKG

5.06 kBJavaScriptView Raw
1"use strict";
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6exports.compressionNone = exports.compressionDeflate = exports.SECTOR_SIZE = exports.MARKER_GT = exports.MARKER_GD = exports.MARKER_FOOTER = exports.MARKER_EOS = void 0;
7exports.createStreamOptimizedHeader = createStreamOptimizedHeader;
8exports.parseFlags = parseFlags;
9exports.parseU64b = parseU64b;
10exports.unpackHeader = unpackHeader;
11const SECTOR_SIZE = exports.SECTOR_SIZE = 512;
12const compressionDeflate = exports.compressionDeflate = 'COMPRESSION_DEFLATE';
13const compressionNone = exports.compressionNone = 'COMPRESSION_NONE';
14const MARKER_EOS = exports.MARKER_EOS = 0;
15const MARKER_GT = exports.MARKER_GT = 1;
16const MARKER_GD = exports.MARKER_GD = 2;
17const MARKER_FOOTER = exports.MARKER_FOOTER = 3;
18const compressionMap = [compressionNone, compressionDeflate];
19function parseFlags(flagBuffer) {
20 const number = flagBuffer.readUInt32LE(0);
21 return {
22 newLineTest: !!(number & 1 << 0),
23 useSecondaryGrain: !!(number & 1 << 1),
24 useZeroedGrainTable: !!(number & 1 << 2),
25 compressedGrains: !!(number & 1 << 16),
26 hasMarkers: !!(number & 1 << 17)
27 };
28}
29function parseS64b(buffer, offset, valueName) {
30 const extraBits = buffer.readIntLE(offset + 6, 2);
31 const value = buffer.readIntLE(offset, 6);
32 const hadValueInHighBytes = !(extraBits === 0 || extraBits === -1);
33 const readWrongSign = Math.sign(value) * Math.sign(extraBits) < 0;
34 if (hadValueInHighBytes || readWrongSign) {
35 throw new Error('Unsupported VMDK, ' + valueName + ' is too big');
36 }
37 return value;
38}
39function parseU64b(buffer, offset, valueName) {
40 const extraBits = buffer.readUIntLE(offset + 6, 2);
41 const value = buffer.readUIntLE(offset, 6);
42 if (extraBits > 0) {
43 throw new Error('Unsupported VMDK, ' + valueName + ' is too big');
44 }
45 return value;
46}
47function unpackHeader(buffer) {
48 const magicString = buffer.slice(0, 4).toString('ascii');
49 if (magicString !== 'KDMV') {
50 throw new Error('not a VMDK file');
51 }
52 const version = buffer.readUInt32LE(4);
53 if (version !== 1 && version !== 3) {
54 throw new Error('unsupported VMDK version ' + version + ', only version 1 and 3 are supported');
55 }
56 const flags = parseFlags(buffer.slice(8, 12));
57 const capacitySectors = parseU64b(buffer, 12, 'capacitySectors');
58 const grainSizeSectors = parseU64b(buffer, 20, 'grainSizeSectors');
59 const descriptorOffsetSectors = parseU64b(buffer, 28, 'descriptorOffsetSectors');
60 const descriptorSizeSectors = parseU64b(buffer, 36, 'descriptorSizeSectors');
61 const numGTEsPerGT = buffer.readUInt32LE(44);
62 const rGrainDirectoryOffsetSectors = parseS64b(buffer, 48, 'rGrainDirectoryOffsetSectors');
63 const grainDirectoryOffsetSectors = parseS64b(buffer, 56, 'grainDirectoryOffsetSectors');
64 const overheadSectors = parseS64b(buffer, 64, 'overheadSectors');
65 const compressionMethod = compressionMap[buffer.readUInt16LE(77)];
66 const l1EntrySectors = numGTEsPerGT * grainSizeSectors;
67 return {
68 magicString,
69 version,
70 flags,
71 compressionMethod,
72 grainSizeSectors,
73 overheadSectors,
74 capacitySectors,
75 descriptorOffsetSectors,
76 descriptorSizeSectors,
77 grainDirectoryOffsetSectors,
78 rGrainDirectoryOffsetSectors,
79 l1EntrySectors,
80 numGTEsPerGT
81 };
82}
83function createStreamOptimizedHeader(capacitySectors, descriptorSizeSectors, grainDirectoryOffsetSectors = -1, rGrainDirectoryOffsetSectors = 0) {
84 const headerBuffer = Buffer.alloc(SECTOR_SIZE);
85 Buffer.from('KDMV', 'ascii').copy(headerBuffer, 0);
86 headerBuffer.writeUInt32LE(3, 4);
87 const flags = 1 | 1 << 1 | 1 << 16 | 1 << 17;
88 headerBuffer.writeUInt32LE(flags, 8);
89 headerBuffer.writeBigUInt64LE(BigInt(capacitySectors), 12);
90 const grainSizeSectors = 128;
91 headerBuffer.writeBigUInt64LE(BigInt(grainSizeSectors), 20);
92 const descriptorOffsetSectors = 1;
93 headerBuffer.writeBigUInt64LE(BigInt(descriptorOffsetSectors), 28);
94 headerBuffer.writeBigUInt64LE(BigInt(descriptorSizeSectors), 36);
95 const numGTEsPerGT = 512;
96 headerBuffer.writeUInt32LE(numGTEsPerGT, 44);
97 headerBuffer.writeBigInt64LE(BigInt(rGrainDirectoryOffsetSectors), 48);
98 headerBuffer.writeBigInt64LE(BigInt(grainDirectoryOffsetSectors), 56);
99 const grainDirectoryEntries = Math.ceil(Math.ceil(capacitySectors / grainSizeSectors) / numGTEsPerGT);
100 const grainTableEntries = grainDirectoryEntries * numGTEsPerGT;
101 const grainDirectorySizeSectors = Math.ceil(grainDirectoryEntries * 4 / SECTOR_SIZE);
102 const grainTableSizeSectors = Math.ceil(grainTableEntries * 4 / SECTOR_SIZE);
103 let overheadSectors = 1 + descriptorSizeSectors;
104 if (grainDirectoryOffsetSectors > 0) {
105 overheadSectors += grainDirectorySizeSectors + grainTableSizeSectors;
106 }
107 headerBuffer.writeBigInt64LE(BigInt(overheadSectors), 64);
108 headerBuffer.write('\n \r\n', 73, 4, 'ascii');
109 headerBuffer.writeUInt16LE(1, 77);
110 return {
111 buffer: headerBuffer,
112 grainDirectorySizeSectors,
113 grainTableSizeSectors,
114 grainDirectoryEntries,
115 grainTableEntries
116 };
117}
118//# sourceMappingURL=definitions.js.map
\No newline at end of file