From 4bb67ad318dcfb72cdb77cd4617f94bdafcd44e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Wed, 2 Mar 2005 17:26:01 +0000 Subject: [PATCH] Added small test tool to dump the contents of a BFS log. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@11538 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../add-ons/kernel/file_systems/bfs/Jamfile | 1 + .../kernel/file_systems/bfs/dump_log/Jamfile | 9 + .../file_systems/bfs/dump_log/dump_log.cpp | 253 ++++++++++++++++++ 3 files changed, 263 insertions(+) create mode 100644 src/tests/add-ons/kernel/file_systems/bfs/dump_log/Jamfile create mode 100644 src/tests/add-ons/kernel/file_systems/bfs/dump_log/dump_log.cpp diff --git a/src/tests/add-ons/kernel/file_systems/bfs/Jamfile b/src/tests/add-ons/kernel/file_systems/bfs/Jamfile index 86ef456506..396480869a 100644 --- a/src/tests/add-ons/kernel/file_systems/bfs/Jamfile +++ b/src/tests/add-ons/kernel/file_systems/bfs/Jamfile @@ -4,6 +4,7 @@ SubInclude OBOS_TOP src tests add-ons kernel file_systems bfs array ; SubInclude OBOS_TOP src tests add-ons kernel file_systems bfs bufferPool ; SubInclude OBOS_TOP src tests add-ons kernel file_systems bfs bfs_shell ; SubInclude OBOS_TOP src tests add-ons kernel file_systems bfs btree ; +SubInclude OBOS_TOP src tests add-ons kernel file_systems bfs dump_log ; SubInclude OBOS_TOP src tests add-ons kernel file_systems bfs mkbfs ; SubInclude OBOS_TOP src tests add-ons kernel file_systems bfs queries ; SubInclude OBOS_TOP src tests add-ons kernel file_systems bfs randomread ; diff --git a/src/tests/add-ons/kernel/file_systems/bfs/dump_log/Jamfile b/src/tests/add-ons/kernel/file_systems/bfs/dump_log/Jamfile new file mode 100644 index 0000000000..a171e804e1 --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/bfs/dump_log/Jamfile @@ -0,0 +1,9 @@ +SubDir OBOS_TOP src tests add-ons kernel file_systems bfs dump_log ; + +SubDirHdrs $(OBOS_TOP) src add-ons kernel file_systems bfs ; +UsePrivateHeaders [ FDirName kernel ] ; # For kernel_cpp.cpp + +SimpleTest dump_log : + dump_log.cpp + ; + diff --git a/src/tests/add-ons/kernel/file_systems/bfs/dump_log/dump_log.cpp b/src/tests/add-ons/kernel/file_systems/bfs/dump_log/dump_log.cpp new file mode 100644 index 0000000000..2bdfe1e72d --- /dev/null +++ b/src/tests/add-ons/kernel/file_systems/bfs/dump_log/dump_log.cpp @@ -0,0 +1,253 @@ +/* + * Copyright 2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved. + * Distributed under the terms of the MIT License. + */ + + +#include "bfs.h" + +#include +#include +#include +#include +#include +#include +#include + + +extern const char *__progname; +static const char *sProgramName = __progname; + +static bool sDumpBlocks = false; + + +bool +disk_super_block::IsValid() +{ + if (Magic1() != (int32)SUPER_BLOCK_MAGIC1 + || Magic2() != (int32)SUPER_BLOCK_MAGIC2 + || Magic3() != (int32)SUPER_BLOCK_MAGIC3 + || (int32)block_size != inode_size + || ByteOrder() != SUPER_BLOCK_FS_LENDIAN + || (1UL << BlockShift()) != BlockSize() + || AllocationGroups() < 1 + || AllocationGroupShift() < 1 + || BlocksPerAllocationGroup() < 1 + || NumBlocks() < 10 + || AllocationGroups() != divide_roundup(NumBlocks(), + 1L << AllocationGroupShift())) + return false; + + return true; +} + + +off_t +toBlock(disk_super_block &superBlock, block_run run) +{ + return ((((off_t)run.AllocationGroup()) << superBlock.AllocationGroupShift()) | (off_t)run.Start()); +} + + +off_t +toOffset(disk_super_block &superBlock, block_run run) +{ + return toBlock(superBlock, run) << superBlock.BlockShift(); +} + + +void +dumpBlock(const char *buffer, int size) +{ + const int blockSize = 16; + + printf("\t"); + + for (int i = 0; i < size;) { + int start = i; + + for (; i < start + blockSize; i++) { + if (!(i % 4)) + printf(" "); + + if (i >= size) + printf(" "); + else + printf("%02x", *(unsigned char *)(buffer+i)); + } + printf(" "); + + for (i = start; i < start + blockSize; i++) { + if (i < size) { + char c = *(buffer+i); + + if (c < 30) + printf("."); + else + printf("%c", c); + } + else + break; + } + + if (i < size) + printf("\n\t"); + else + printf("\n"); + } +} + + +void +dumpLogEntry(int device, disk_super_block &superBlock, int32 &start, uint8 *block) +{ + int32 blockSize = superBlock.BlockSize(); + int32 entry = 0; + off_t count = 1; + int32 arrayBlocks = 1; + off_t blockStart = start; + bool first = true; + int32 indexOffset = -1; + int32 index = 0; + off_t dataStart = blockStart; + off_t bitmapSize = superBlock.AllocationGroups() * superBlock.BlocksPerAllocationGroup(); + + uint8 *data = NULL; + if (sDumpBlocks) + data = (uint8 *)malloc(blockSize); + + for (int32 i = 0; i < arrayBlocks; i++) { + off_t blockNumber = toBlock(superBlock, superBlock.log_blocks) + + blockStart++ % superBlock.log_blocks.Length(); + if (read_pos(device, blockNumber << superBlock.BlockShift(), + block, blockSize) != blockSize) { + fprintf(stderr, "%s: could not read block %Ld.\n", sProgramName, blockNumber); + exit(-1); + } + + off_t *array = (off_t *)block; + int32 arraySize = blockSize / sizeof(off_t); + + if (first) { + count = array[0]; + arrayBlocks = ((count + 1) * sizeof(off_t) + blockSize - 1) / blockSize; + arraySize--; + dataStart += arrayBlocks; + + start += arrayBlocks + count; + + printf("Entry %ld contains %Ld blocks (entry starts at block %Ld):\n", entry, count, blockNumber); + first = false; + } else + indexOffset += arraySize; + + for (; index < count; index++) { + int32 arrayIndex = index - indexOffset; + if (arrayIndex >= arraySize) + break; + + off_t value = array[arrayIndex]; + printf("%7ld: %Ld%s\n", index, value, value == 0 ? " (super block)" : + value < bitmapSize + 1 ? " (bitmap block)" : ""); + + if (data != NULL) { + off_t blockNumber = toBlock(superBlock, superBlock.log_blocks) + + ((dataStart + index) % superBlock.log_blocks.Length()); + if (read_pos(device, blockNumber << superBlock.BlockShift(), + data, blockSize) != blockSize) { + fprintf(stderr, "%s: could not read block %Ld.\n", sProgramName, blockNumber); + } else + dumpBlock((char *)data, blockSize); + } + } + } + + free(data); +} + + +void +usage(void) +{ + fprintf(stderr, "usage: %s [-d] bfs-volume\n" + " -d\tdump blocks in log\n", sProgramName); + exit(0); +} + + +int +main(int argc, char **argv) +{ + if (argc < 2 || !strcmp(argv[1], "--help")) + usage(); + + while (*++argv) { + char *arg = *argv; + if (*arg == '-') { + while (*++arg && isalpha(*arg)) { + switch (*arg) { + case 'd': + sDumpBlocks = true; + break; + default: + usage(); + } + } + } + else + break; + } + + char *devicePath = argv[0]; + int device = open(devicePath, O_RDONLY); + if (device < 0) { + fprintf(stderr, "%s: could not open device %s: %s\n", + sProgramName, devicePath, strerror(errno)); + return -1; + } + + disk_super_block superBlock; + if (read_pos(device, 512, &superBlock, sizeof(disk_super_block)) < (ssize_t)sizeof(disk_super_block)) { + fprintf(stderr, "%s: could not read super block.\n", sProgramName); + return -1; + } + + if (!superBlock.IsValid()) { + fprintf(stderr, "%s: invalid super block!\n", sProgramName); + return -1; + } + + if (superBlock.Flags() == SUPER_BLOCK_DISK_CLEAN) { + printf("volume is clean; log is empty.\n"); + return 0; + } + + off_t bitmapSize = superBlock.AllocationGroups() * superBlock.BlocksPerAllocationGroup(); + printf("Log area = (%Ld - %Ld), current start = %Ld, end = %Ld, %Ld bitmap blocks\n", + toBlock(superBlock, superBlock.log_blocks), + toBlock(superBlock, superBlock.log_blocks) + superBlock.log_blocks.Length(), + superBlock.LogStart(), superBlock.LogEnd(), bitmapSize); + + uint8 *block = (uint8 *)malloc(superBlock.BlockSize()); + if (block == NULL) { + fprintf(stderr, "%s: could not allocate block!\n", sProgramName); + return -1; + } + + int32 start = superBlock.LogStart(); + int32 lastStart = -1; + + while (true) { + if (start == superBlock.LogEnd()) + break; + if (start == lastStart) + break; + + lastStart = start; + dumpLogEntry(device, superBlock, start, block); + } + + close(device); + return 0; +} +