1/* 2 * Copyright 2005, Axel D��rfler, axeld@pinc-software.de. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7#include "bfs.h" 8 9#include <stdlib.h> 10#include <stdio.h> 11#include <string.h> 12#include <unistd.h> 13#include <fcntl.h> 14#include <errno.h> 15#include <ctype.h> 16 17 18extern const char *__progname; 19static const char *sProgramName = __progname; 20 21static bool sDumpBlocks = false; 22 23 24bool 25disk_super_block::IsValid() 26{ 27 if (Magic1() != (int32)SUPER_BLOCK_MAGIC1 28 || Magic2() != (int32)SUPER_BLOCK_MAGIC2 29 || Magic3() != (int32)SUPER_BLOCK_MAGIC3 30 || (int32)block_size != inode_size 31 || ByteOrder() != SUPER_BLOCK_FS_LENDIAN 32 || (1UL << BlockShift()) != BlockSize() 33 || AllocationGroups() < 1 34 || AllocationGroupShift() < 1 35 || BlocksPerAllocationGroup() < 1 36 || NumBlocks() < 10 37 || AllocationGroups() != divide_roundup(NumBlocks(), 38 1L << AllocationGroupShift())) 39 return false; 40 41 return true; 42} 43 44 45off_t 46toBlock(disk_super_block &superBlock, block_run run) 47{ 48 return ((((off_t)run.AllocationGroup()) << superBlock.AllocationGroupShift()) | (off_t)run.Start()); 49} 50 51 52off_t 53toOffset(disk_super_block &superBlock, block_run run) 54{ 55 return toBlock(superBlock, run) << superBlock.BlockShift(); 56} 57 58 59void 60dumpBlock(const char *buffer, int size) 61{ 62 const int blockSize = 16; 63 64 printf("\t"); 65 66 for (int i = 0; i < size;) { 67 int start = i; 68 69 for (; i < start + blockSize; i++) { 70 if (!(i % 4)) 71 printf(" "); 72 73 if (i >= size) 74 printf(" "); 75 else 76 printf("%02x", *(unsigned char *)(buffer+i)); 77 } 78 printf(" "); 79 80 for (i = start; i < start + blockSize; i++) { 81 if (i < size) { 82 char c = *(buffer+i); 83 84 if (c < 30) 85 printf("."); 86 else 87 printf("%c", c); 88 } 89 else 90 break; 91 } 92 93 if (i < size) 94 printf("\n\t"); 95 else 96 printf("\n"); 97 } 98} 99 100 101void 102dumpLogEntry(int device, disk_super_block &superBlock, int32 &start, uint8 *block) 103{ 104 int32 blockSize = superBlock.BlockSize(); 105 int32 entry = 0; 106 off_t count = 1; 107 int32 arrayBlocks = 1; 108 off_t blockStart = start; 109 bool first = true; 110 int32 indexOffset = -1; 111 int32 index = 0; 112 off_t dataStart = blockStart; 113 off_t bitmapSize = superBlock.AllocationGroups() * superBlock.BlocksPerAllocationGroup(); 114 115 uint8 *data = NULL; 116 if (sDumpBlocks) 117 data = (uint8 *)malloc(blockSize); 118 119 for (int32 i = 0; i < arrayBlocks; i++) { 120 off_t blockNumber = toBlock(superBlock, superBlock.log_blocks) 121 + blockStart++ % superBlock.log_blocks.Length(); 122 if (read_pos(device, blockNumber << superBlock.BlockShift(), 123 block, blockSize) != blockSize) { 124 fprintf(stderr, "%s: could not read block %lld.\n", sProgramName, blockNumber); 125 exit(-1); 126 } 127 128 off_t *array = (off_t *)block; 129 int32 arraySize = blockSize / sizeof(off_t); 130 131 if (first) { 132 count = array[0]; 133 arrayBlocks = ((count + 1) * sizeof(off_t) + blockSize - 1) / blockSize; 134 arraySize--; 135 dataStart += arrayBlocks; 136 137 start += arrayBlocks + count; 138 139 printf("Entry %ld contains %lld blocks (entry starts at block %lld):\n", entry, count, blockNumber); 140 first = false; 141 } else 142 indexOffset += arraySize; 143 144 for (; index < count; index++) { 145 int32 arrayIndex = index - indexOffset; 146 if (arrayIndex >= arraySize) 147 break; 148 149 off_t value = array[arrayIndex]; 150 printf("%7ld: %lld%s\n", index, value, value == 0 ? " (superblock)" : 151 value < bitmapSize + 1 ? " (bitmap block)" : ""); 152 153 if (data != NULL) { 154 off_t blockNumber = toBlock(superBlock, superBlock.log_blocks) 155 + ((dataStart + index) % superBlock.log_blocks.Length()); 156 if (read_pos(device, blockNumber << superBlock.BlockShift(), 157 data, blockSize) != blockSize) { 158 fprintf(stderr, "%s: could not read block %lld.\n", sProgramName, blockNumber); 159 } else 160 dumpBlock((char *)data, blockSize); 161 } 162 } 163 } 164 165 free(data); 166} 167 168 169void 170usage(void) 171{ 172 fprintf(stderr, "usage: %s [-d] bfs-volume\n" 173 " -d\tdump blocks in log\n", sProgramName); 174 exit(0); 175} 176 177 178int 179main(int argc, char **argv) 180{ 181 if (argc < 2 || !strcmp(argv[1], "--help")) 182 usage(); 183 184 while (*++argv) { 185 char *arg = *argv; 186 if (*arg == '-') { 187 while (*++arg && isalpha(*arg)) { 188 switch (*arg) { 189 case 'd': 190 sDumpBlocks = true; 191 break; 192 default: 193 usage(); 194 } 195 } 196 } 197 else 198 break; 199 } 200 201 char *devicePath = argv[0]; 202 int device = open(devicePath, O_RDONLY); 203 if (device < 0) { 204 fprintf(stderr, "%s: could not open device %s: %s\n", 205 sProgramName, devicePath, strerror(errno)); 206 return -1; 207 } 208 209 disk_super_block superBlock; 210 if (read_pos(device, 512, &superBlock, sizeof(disk_super_block)) < (ssize_t)sizeof(disk_super_block)) { 211 fprintf(stderr, "%s: could not read superblock.\n", sProgramName); 212 return -1; 213 } 214 215 if (!superBlock.IsValid()) { 216 fprintf(stderr, "%s: invalid superblock!\n", sProgramName); 217 return -1; 218 } 219 220 if (superBlock.Flags() == SUPER_BLOCK_DISK_CLEAN) { 221 printf("volume is clean; log is empty.\n"); 222 return 0; 223 } 224 225 off_t bitmapSize = superBlock.AllocationGroups() * superBlock.BlocksPerAllocationGroup(); 226 printf("Log area = (%lld - %lld), current start = %lld, end = %lld, %lld bitmap blocks\n", 227 toBlock(superBlock, superBlock.log_blocks), 228 toBlock(superBlock, superBlock.log_blocks) + superBlock.log_blocks.Length(), 229 superBlock.LogStart(), superBlock.LogEnd(), bitmapSize); 230 231 uint8 *block = (uint8 *)malloc(superBlock.BlockSize()); 232 if (block == NULL) { 233 fprintf(stderr, "%s: could not allocate block!\n", sProgramName); 234 return -1; 235 } 236 237 int32 start = superBlock.LogStart(); 238 int32 lastStart = -1; 239 240 while (true) { 241 if (start == superBlock.LogEnd()) 242 break; 243 if (start == lastStart) 244 break; 245 246 lastStart = start; 247 dumpLogEntry(device, superBlock, start, block); 248 } 249 250 close(device); 251 return 0; 252} 253 254