40 lines
1.3 KiB
JavaScript
40 lines
1.3 KiB
JavaScript
import { fromCallback } from 'promise-toolbox'
|
|
import { readChunkStrict } from '@vates/read-chunk'
|
|
import { XXHash64 } from 'xxhash'
|
|
|
|
async function writeBlock(pack, data, name) {
|
|
await fromCallback.call(pack, pack.entry, { name }, data)
|
|
const hasher = new XXHash64(0)
|
|
hasher.update(data)
|
|
// weirdly, ocaml and xxhash return the bytes in reverse order to each other
|
|
const hash = hasher.digest().reverse().toString('hex').toUpperCase()
|
|
await fromCallback.call(pack, pack.entry, { name: `${name}.xxhash` }, Buffer.from(hash, 'utf8'))
|
|
}
|
|
export default async function addDisk(pack, vhd, basePath) {
|
|
let counter = 0
|
|
let written
|
|
const chunk_length = 1024 * 1024
|
|
const empty = Buffer.alloc(chunk_length, 0)
|
|
const stream = await vhd.rawContent()
|
|
let lastBlockLength
|
|
const diskSize = vhd.footer.currentSize
|
|
let remaining = diskSize
|
|
while (remaining > 0) {
|
|
const data = await readChunkStrict(stream, Math.min(chunk_length, remaining))
|
|
lastBlockLength = data.length
|
|
remaining -= lastBlockLength
|
|
|
|
if (counter === 0 || !data.equals(empty)) {
|
|
written = true
|
|
await writeBlock(pack, data, `${basePath}/${('' + counter).padStart(8, '0')}`)
|
|
} else {
|
|
written = false
|
|
}
|
|
counter++
|
|
}
|
|
if (!written) {
|
|
// last block must be present
|
|
writeBlock(pack, empty.slice(0, lastBlockLength), `${basePath}/${counter}`)
|
|
}
|
|
}
|