From 52e2cb785496f4a677f36650b27ee413069c69a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andi=20P=C3=A4tzold?= Date: Sun, 19 Jul 2020 00:43:21 +0200 Subject: [PATCH] fix: implement usage maps type 1 --- src/Table.ts | 2 +- src/usage-map.ts | 42 +++++++++++++++++++++++++++++++++++------- 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/src/Table.ts b/src/Table.ts index d395e34b..23773344 100644 --- a/src/Table.ts +++ b/src/Table.ts @@ -74,7 +74,7 @@ export default class Table { const usageMapBuffer = this.db.findPageRow( this.definitionBuffer.readUInt32LE(this.db.constants.tableDefinitionPage.usageMapOffset) ); - this.dataPages = findMapPages(usageMapBuffer); + this.dataPages = findMapPages(usageMapBuffer, this.db); } /** diff --git a/src/usage-map.ts b/src/usage-map.ts index 108f72dc..aeb1cc1c 100644 --- a/src/usage-map.ts +++ b/src/usage-map.ts @@ -1,25 +1,57 @@ import { getBitmapValue } from "./util"; +import Database from './Database'; +import PageType, { assertPageType } from './PageType'; /** * @see https://github.com/brianb/mdbtools/blob/d6f5745d949f37db969d5f424e69b54f0da60b9b/HACKING#L556-L622 */ -export function findMapPages(buffer: Buffer): number[] { +export function findMapPages(buffer: Buffer, db: Database): number[] { switch (buffer[0]) { case 0x00: return findMapPages0(buffer); case 0x01: - return findMapPages1(buffer); + return findMapPages1(buffer, db); default: throw new Error("Unknown usage map type"); } } +/** + * @see https://github.com/brianb/mdbtools/blob/d6f5745d949f37db969d5f424e69b54f0da60b9b/src/libmdb/map.c#L25-L43 + */ function findMapPages0(buffer: Buffer): number[] { const pageStart = buffer.readUInt32LE(1); + const bitmap = buffer.slice(5); + return getPagesFromBitmap(bitmap, pageStart); +} + +/** + * @see https://github.com/brianb/mdbtools/blob/d6f5745d949f37db969d5f424e69b54f0da60b9b/src/libmdb/map.c#L44-L84 + */ +function findMapPages1(buffer: Buffer, db: Database): number[] { + const bitmapLength = (db.constants.pageSize - 4) * 8; + const mapCount = Math.floor((buffer.length - 1) / 4); + const pages: number[] = []; + for (let mapIndex = 0; mapIndex < mapCount; ++mapIndex) { + const page = buffer.readUInt32LE(1 + (mapIndex * 4)); + if (page === 0) { + continue; + } + + const pageBuffer = db.getPage(page); + assertPageType(pageBuffer, PageType.PageUsageBitmaps); + + const bitmap = pageBuffer.slice(4); + pages.push(...getPagesFromBitmap(bitmap, mapIndex * bitmapLength)); + } + + return pages; +} + +function getPagesFromBitmap(bitmap: Buffer, pageStart: number): number[] { const pages: number[] = []; - const bitmap = buffer.slice(5); for (let i = 0; i < bitmap.length * 8; i++) { if (getBitmapValue(bitmap, i)) { pages.push(pageStart + i); @@ -28,7 +60,3 @@ function findMapPages0(buffer: Buffer): number[] { return pages; } - -function findMapPages1(_buffer: Buffer): number[] { - throw new Error("Not implemented yet"); -}