1647cff2eSAxel Dörfler /* 2647cff2eSAxel Dörfler * Copyright 2001-2010, pinc Software. All Rights Reserved. 3647cff2eSAxel Dörfler */ 4647cff2eSAxel Dörfler 5647cff2eSAxel Dörfler //! BFS structure dump and helper functions 6647cff2eSAxel Dörfler 7647cff2eSAxel Dörfler #include "BPlusTree.h" 8647cff2eSAxel Dörfler #include "Inode.h" 9647cff2eSAxel Dörfler #include "dump.h" 10647cff2eSAxel Dörfler 11647cff2eSAxel Dörfler #include <File.h> 12647cff2eSAxel Dörfler #include <Mime.h> 13647cff2eSAxel Dörfler 14647cff2eSAxel Dörfler #include <stdio.h> 15647cff2eSAxel Dörfler #include <string.h> 16647cff2eSAxel Dörfler 17647cff2eSAxel Dörfler #define Print printf 18647cff2eSAxel Dörfler 19647cff2eSAxel Dörfler 20647cff2eSAxel Dörfler char * 21647cff2eSAxel Dörfler get_tupel(uint32 id) 22647cff2eSAxel Dörfler { 23647cff2eSAxel Dörfler static unsigned char tupel[5]; 24647cff2eSAxel Dörfler 25647cff2eSAxel Dörfler tupel[0] = 0xff & (id >> 24); 26647cff2eSAxel Dörfler tupel[1] = 0xff & (id >> 16); 27647cff2eSAxel Dörfler tupel[2] = 0xff & (id >> 8); 28647cff2eSAxel Dörfler tupel[3] = 0xff & (id); 29647cff2eSAxel Dörfler tupel[4] = 0; 30647cff2eSAxel Dörfler for (int16 i = 0;i < 4;i++) 31647cff2eSAxel Dörfler if (tupel[i] < ' ' || tupel[i] > 128) 32647cff2eSAxel Dörfler tupel[i] = '.'; 33647cff2eSAxel Dörfler 34647cff2eSAxel Dörfler return (char *)tupel; 35647cff2eSAxel Dörfler } 36647cff2eSAxel Dörfler 37647cff2eSAxel Dörfler 38647cff2eSAxel Dörfler void 39647cff2eSAxel Dörfler dump_block_run(const char *prefix, const block_run &run, const char *postfix) 40647cff2eSAxel Dörfler { 412a8d81c2SJérôme Duval Print("%s(%" B_PRId32 ", %d, %d)%s\n", prefix, run.allocation_group, 42647cff2eSAxel Dörfler run.start, run.length, postfix); 43647cff2eSAxel Dörfler } 44647cff2eSAxel Dörfler 45647cff2eSAxel Dörfler 46647cff2eSAxel Dörfler void 47647cff2eSAxel Dörfler dump_super_block(const disk_super_block *superBlock) 48647cff2eSAxel Dörfler { 49647cff2eSAxel Dörfler Print("disk_super_block:\n"); 50647cff2eSAxel Dörfler Print(" name = %s\n", superBlock->name); 512a8d81c2SJérôme Duval Print(" magic1 = %#08" B_PRIx32 " (%s) %s\n", superBlock->magic1, 52647cff2eSAxel Dörfler get_tupel(superBlock->magic1), 53647cff2eSAxel Dörfler superBlock->magic1 == SUPER_BLOCK_MAGIC1 ? "valid" : "INVALID"); 542a8d81c2SJérôme Duval Print(" fs_byte_order = %#08" B_PRIx32 " (%s, %s endian)\n", 55647cff2eSAxel Dörfler superBlock->fs_byte_order, get_tupel(superBlock->fs_byte_order), 56647cff2eSAxel Dörfler superBlock->fs_byte_order == SUPER_BLOCK_FS_LENDIAN ? "little" : "big"); 572a8d81c2SJérôme Duval Print(" block_size = %" B_PRIu32 "\n", superBlock->block_size); 582a8d81c2SJérôme Duval Print(" block_shift = %" B_PRIu32 "\n", superBlock->block_shift); 592a8d81c2SJérôme Duval Print(" num_blocks = %" B_PRIdOFF "\n", superBlock->num_blocks); 602a8d81c2SJérôme Duval Print(" used_blocks = %" B_PRIdOFF "\n", superBlock->used_blocks); 612a8d81c2SJérôme Duval Print(" inode_size = %" B_PRId32 "\n", superBlock->inode_size); 622a8d81c2SJérôme Duval Print(" magic2 = %#08" B_PRIx32 " (%s) %s\n", superBlock->magic2, 63647cff2eSAxel Dörfler get_tupel(superBlock->magic2), 64647cff2eSAxel Dörfler superBlock->magic2 == (int)SUPER_BLOCK_MAGIC2 ? "valid" : "INVALID"); 652a8d81c2SJérôme Duval Print(" blocks_per_ag = %" B_PRId32 "\n", superBlock->blocks_per_ag); 662a8d81c2SJérôme Duval Print(" ag_shift = %" B_PRId32 "\n", superBlock->ag_shift); 672a8d81c2SJérôme Duval Print(" num_ags = %" B_PRId32 "\n", superBlock->num_ags); 682a8d81c2SJérôme Duval Print(" flags = %#08" B_PRIx32 " (%s)\n", superBlock->flags, 69647cff2eSAxel Dörfler get_tupel(superBlock->flags)); 70647cff2eSAxel Dörfler dump_block_run(" log_blocks = ", superBlock->log_blocks); 712a8d81c2SJérôme Duval Print(" log_start = %" B_PRIdOFF "\n", superBlock->log_start); 722a8d81c2SJérôme Duval Print(" log_end = %" B_PRIdOFF "\n", superBlock->log_end); 732a8d81c2SJérôme Duval Print(" magic3 = %#08" B_PRIx32 " (%s) %s\n", superBlock->magic3, 74647cff2eSAxel Dörfler get_tupel(superBlock->magic3), 75647cff2eSAxel Dörfler superBlock->magic3 == SUPER_BLOCK_MAGIC3 ? "valid" : "INVALID"); 76647cff2eSAxel Dörfler dump_block_run(" root_dir = ", superBlock->root_dir); 77647cff2eSAxel Dörfler dump_block_run(" indices = ", superBlock->indices); 78647cff2eSAxel Dörfler } 79647cff2eSAxel Dörfler 80647cff2eSAxel Dörfler 81647cff2eSAxel Dörfler void 82647cff2eSAxel Dörfler dump_data_stream(const bfs_inode *inode, const data_stream *stream, bool showOffsets) 83647cff2eSAxel Dörfler { 84647cff2eSAxel Dörfler Print("data_stream:\n"); 85647cff2eSAxel Dörfler 86647cff2eSAxel Dörfler off_t offset = 0; 87647cff2eSAxel Dörfler 88647cff2eSAxel Dörfler for (int i = 0; i < NUM_DIRECT_BLOCKS; i++) { 89647cff2eSAxel Dörfler if (!stream->direct[i].IsZero()) { 90647cff2eSAxel Dörfler Print(" direct[%02d] = ", i); 91647cff2eSAxel Dörfler 92647cff2eSAxel Dörfler char buffer[256]; 93647cff2eSAxel Dörfler if (showOffsets) 942a8d81c2SJérôme Duval snprintf(buffer, sizeof(buffer), " %16" B_PRIdOFF, offset); 95647cff2eSAxel Dörfler else 96647cff2eSAxel Dörfler buffer[0] = '\0'; 97647cff2eSAxel Dörfler 98647cff2eSAxel Dörfler dump_block_run("", stream->direct[i], buffer); 99647cff2eSAxel Dörfler 100647cff2eSAxel Dörfler offset += stream->direct[i].length * inode->inode_size; 101647cff2eSAxel Dörfler } 102647cff2eSAxel Dörfler } 1032a8d81c2SJérôme Duval Print(" max_direct_range = %" B_PRIdOFF "\n", 1042a8d81c2SJérôme Duval stream->max_direct_range); 105647cff2eSAxel Dörfler 106647cff2eSAxel Dörfler if (!stream->indirect.IsZero()) 107647cff2eSAxel Dörfler dump_block_run(" indirect = ", stream->indirect); 108647cff2eSAxel Dörfler 1092a8d81c2SJérôme Duval Print(" max_indirect_range = %" B_PRIdOFF "\n", 1102a8d81c2SJérôme Duval stream->max_indirect_range); 111647cff2eSAxel Dörfler 112647cff2eSAxel Dörfler if (!stream->double_indirect.IsZero()) { 113647cff2eSAxel Dörfler dump_block_run(" double_indirect = ", 114647cff2eSAxel Dörfler stream->double_indirect); 115647cff2eSAxel Dörfler } 116647cff2eSAxel Dörfler 1172a8d81c2SJérôme Duval Print(" max_double_indirect_range = %" B_PRIdOFF "\n", 118647cff2eSAxel Dörfler stream->max_double_indirect_range); 1192a8d81c2SJérôme Duval Print(" size = %" B_PRIdOFF "\n", stream->size); 120647cff2eSAxel Dörfler } 121647cff2eSAxel Dörfler 122647cff2eSAxel Dörfler 123647cff2eSAxel Dörfler void 124647cff2eSAxel Dörfler dump_inode(const Inode *nameNode, const bfs_inode *inode, bool showOffsets) 125647cff2eSAxel Dörfler { 126647cff2eSAxel Dörfler if (nameNode != NULL) 127647cff2eSAxel Dörfler Print("inode \"%s\":\n", nameNode->Name()); 128647cff2eSAxel Dörfler else 129647cff2eSAxel Dörfler Print("inode:\n"); 130647cff2eSAxel Dörfler 1312a8d81c2SJérôme Duval Print(" magic1 = %08" B_PRIx32 " (%s) %s\n",inode->magic1, 1322a8d81c2SJérôme Duval get_tupel(inode->magic1), 1332a8d81c2SJérôme Duval (inode->magic1 == INODE_MAGIC1 ? "valid" : "INVALID")); 134647cff2eSAxel Dörfler dump_block_run( " inode_num = ",inode->inode_num); 1352a8d81c2SJérôme Duval Print(" uid = %" B_PRIu32 "\n",inode->uid); 1362a8d81c2SJérôme Duval Print(" gid = %" B_PRIu32 "\n",inode->gid); 1372a8d81c2SJérôme Duval Print(" mode = %10" B_PRIo32 " (octal)\n",inode->mode); 1382a8d81c2SJérôme Duval Print(" flags = %08" B_PRIx32 "\n",inode->flags); 139647cff2eSAxel Dörfler 140647cff2eSAxel Dörfler time_t time; 141647cff2eSAxel Dörfler time = (time_t)(inode->create_time >> 16); 142647cff2eSAxel Dörfler Print(" create_time = %s",ctime(&time)); 143647cff2eSAxel Dörfler time = (time_t)(inode->last_modified_time >> 16); 144647cff2eSAxel Dörfler Print(" last_modified_time = %s",ctime(&time)); 145647cff2eSAxel Dörfler 146647cff2eSAxel Dörfler dump_block_run( " parent = ",inode->parent); 147647cff2eSAxel Dörfler dump_block_run( " attributes = ",inode->attributes); 1482a8d81c2SJérôme Duval Print(" type = %" B_PRIu32 "\n",inode->type); 1492a8d81c2SJérôme Duval Print(" inode_size = %" B_PRId32 "\n",inode->inode_size); 1502a8d81c2SJérôme Duval Print(" etc = %#08" B_PRIx32 "\n",inode->etc); 151647cff2eSAxel Dörfler Print(" short_symlink = %s\n", 152647cff2eSAxel Dörfler S_ISLNK(inode->mode) && (inode->flags & INODE_LONG_SYMLINK) == 0 153647cff2eSAxel Dörfler ? inode->short_symlink : "-"); 154647cff2eSAxel Dörfler 155647cff2eSAxel Dörfler dump_data_stream(inode, &inode->data, showOffsets); 156647cff2eSAxel Dörfler Print(" --\n"); 157647cff2eSAxel Dörfler #if 0 158647cff2eSAxel Dörfler Print(" --\n pad[0] = %08lx\n", inode->pad[0]); 159647cff2eSAxel Dörfler Print(" pad[1] = %08lx\n", inode->pad[1]); 160647cff2eSAxel Dörfler Print(" pad[2] = %08lx\n", inode->pad[2]); 161647cff2eSAxel Dörfler Print(" pad[3] = %08lx\n", inode->pad[3]); 162647cff2eSAxel Dörfler #endif 163647cff2eSAxel Dörfler } 164647cff2eSAxel Dörfler 165647cff2eSAxel Dörfler 166647cff2eSAxel Dörfler void 167647cff2eSAxel Dörfler dump_small_data(Inode *inode) 168647cff2eSAxel Dörfler { 169647cff2eSAxel Dörfler if (inode == NULL || inode->InodeBuffer() == NULL) 170647cff2eSAxel Dörfler return; 171647cff2eSAxel Dörfler 172647cff2eSAxel Dörfler small_data *item = NULL; 173647cff2eSAxel Dörfler 174647cff2eSAxel Dörfler printf("small data section (max. %ld bytes):\n", 175647cff2eSAxel Dörfler inode->InodeBuffer()->inode_size - sizeof(struct bfs_inode)); 176647cff2eSAxel Dörfler 177647cff2eSAxel Dörfler while (inode->GetNextSmallData(&item) == B_OK) { 1782a8d81c2SJérôme Duval printf("%#08" B_PRIx32 " (%s), name = \"%s\", ", item->type, 1792a8d81c2SJérôme Duval get_tupel(item->type), item->Name()); 180647cff2eSAxel Dörfler if (item->type == FILE_NAME_TYPE 181647cff2eSAxel Dörfler || item->type == B_STRING_TYPE 182647cff2eSAxel Dörfler || item->type == B_MIME_STRING_TYPE) 183647cff2eSAxel Dörfler printf("data = \"%s\", ", item->Data()); 184647cff2eSAxel Dörfler 185647cff2eSAxel Dörfler printf("%u bytes\n", item->data_size); 186647cff2eSAxel Dörfler } 187647cff2eSAxel Dörfler } 188647cff2eSAxel Dörfler 189647cff2eSAxel Dörfler 190647cff2eSAxel Dörfler void 191647cff2eSAxel Dörfler dump_bplustree_header(const bplustree_header* header) 192647cff2eSAxel Dörfler { 193647cff2eSAxel Dörfler printf("bplustree_header:\n"); 1942a8d81c2SJérôme Duval printf(" magic = %#08" B_PRIx32 " (%s) %s\n", 1952a8d81c2SJérôme Duval header->magic, get_tupel(header->magic), 196647cff2eSAxel Dörfler header->magic == BPLUSTREE_MAGIC ? "valid" : "INVALID"); 1972a8d81c2SJérôme Duval printf(" node_size = %" B_PRIu32 "\n", header->node_size); 1982a8d81c2SJérôme Duval printf(" max_number_of_levels = %" B_PRIu32 "\n", 1992a8d81c2SJérôme Duval header->max_number_of_levels); 2002a8d81c2SJérôme Duval printf(" data_type = %" B_PRIu32 "\n", header->data_type); 2012a8d81c2SJérôme Duval printf(" root_node_pointer = %" B_PRIdOFF "\n", 2022a8d81c2SJérôme Duval header->root_node_pointer); 2032a8d81c2SJérôme Duval printf(" free_node_pointer = %" B_PRIdOFF "\n", 2042a8d81c2SJérôme Duval header->free_node_pointer); 2052a8d81c2SJérôme Duval printf(" maximum_size = %" B_PRIdOFF "\n", 2062a8d81c2SJérôme Duval header->maximum_size); 207647cff2eSAxel Dörfler } 208647cff2eSAxel Dörfler 209647cff2eSAxel Dörfler 210647cff2eSAxel Dörfler void 211647cff2eSAxel Dörfler dump_bplustree_node(const bplustree_node* node, const bplustree_header* header, 212647cff2eSAxel Dörfler Disk* disk) 213647cff2eSAxel Dörfler { 214647cff2eSAxel Dörfler Print("bplustree_node (%s node):\n", 215647cff2eSAxel Dörfler node->overflow_link == BPLUSTREE_NULL ? "leaf" : "index"); 2162a8d81c2SJérôme Duval Print(" left_link = %" B_PRIdOFF "\n", node->left_link); 2172a8d81c2SJérôme Duval Print(" right_link = %" B_PRIdOFF "\n", node->right_link); 2182a8d81c2SJérôme Duval Print(" overflow_link = %" B_PRIdOFF "\n", node->overflow_link); 219647cff2eSAxel Dörfler Print(" all_key_count = %u\n", node->all_key_count); 220647cff2eSAxel Dörfler Print(" all_key_length = %u\n", node->all_key_length); 221647cff2eSAxel Dörfler 222647cff2eSAxel Dörfler if (header == NULL) 223647cff2eSAxel Dörfler return; 224647cff2eSAxel Dörfler 225647cff2eSAxel Dörfler if (node->all_key_count > node->all_key_length 226647cff2eSAxel Dörfler || uint32(node->all_key_count * 10) > (uint32)header->node_size) { 227647cff2eSAxel Dörfler Print("\n"); 228647cff2eSAxel Dörfler dump_block((char *)node, header->node_size, sizeof(off_t)); 229647cff2eSAxel Dörfler return; 230647cff2eSAxel Dörfler } 231647cff2eSAxel Dörfler 232647cff2eSAxel Dörfler Print("\n"); 233647cff2eSAxel Dörfler for (int32 i = 0;i < node->all_key_count;i++) { 234647cff2eSAxel Dörfler uint16 length; 235647cff2eSAxel Dörfler char* key = (char *)node->KeyAt(i, &length); 236*b27b3781SAxel Dörfler if (length > BPLUSTREE_MAX_KEY_LENGTH) { 2372a8d81c2SJérôme Duval Print(" %2" B_PRId32 ". Invalid length (%u)!!\n", i, length); 238647cff2eSAxel Dörfler dump_block((char *)node, header->node_size, sizeof(off_t)); 239647cff2eSAxel Dörfler break; 240647cff2eSAxel Dörfler } 241647cff2eSAxel Dörfler 242647cff2eSAxel Dörfler char buffer[256]; 243647cff2eSAxel Dörfler memcpy(buffer, key, length); 244647cff2eSAxel Dörfler buffer[length] = '\0'; 245647cff2eSAxel Dörfler 246647cff2eSAxel Dörfler off_t *value = node->Values() + i; 2472a8d81c2SJérôme Duval if ((addr_t)value < (addr_t)node 2482a8d81c2SJérôme Duval || (addr_t)value > (addr_t)node + header->node_size) { 2492a8d81c2SJérôme Duval Print(" %2" B_PRId32 ". Invalid Offset!!\n", i); 2502a8d81c2SJérôme Duval } else { 2512a8d81c2SJérôme Duval Print(" %2" B_PRId32 ". ",i); 252647cff2eSAxel Dörfler if (header->data_type == BPLUSTREE_STRING_TYPE) 253647cff2eSAxel Dörfler Print("\"%s\"",buffer); 254647cff2eSAxel Dörfler else if (header->data_type == BPLUSTREE_INT32_TYPE) { 2552a8d81c2SJérôme Duval Print("int32 = %" B_PRId32 " (0x%" B_PRIx32 ")", 2562a8d81c2SJérôme Duval *(int32 *)&buffer, *(int32 *)&buffer); 257647cff2eSAxel Dörfler } else if (header->data_type == BPLUSTREE_UINT32_TYPE) { 2582a8d81c2SJérôme Duval Print("uint32 = %" B_PRIu32 " (0x%" B_PRIx32 ")", 2592a8d81c2SJérôme Duval *(uint32 *)&buffer, *(uint32 *)&buffer); 260647cff2eSAxel Dörfler } else if (header->data_type == BPLUSTREE_INT64_TYPE) { 2612a8d81c2SJérôme Duval Print("int64 = %" B_PRId64 " (0x%" B_PRIx64 ")", 2622a8d81c2SJérôme Duval *(int64 *)&buffer, *(int64 *)&buffer); 263647cff2eSAxel Dörfler } else 264647cff2eSAxel Dörfler Print("???"); 265647cff2eSAxel Dörfler 266647cff2eSAxel Dörfler off_t offset = *value & 0x3fffffffffffffffLL; 2672a8d81c2SJérôme Duval Print(" (%d bytes) -> %" B_PRIdOFF,length,offset); 268647cff2eSAxel Dörfler if (disk != NULL) { 269647cff2eSAxel Dörfler block_run run = disk->ToBlockRun(offset); 2702a8d81c2SJérôme Duval Print(" (%" B_PRId32 ", %d)", run.allocation_group, run.start); 271647cff2eSAxel Dörfler } 272647cff2eSAxel Dörfler if (bplustree_node::LinkType(*value) 273647cff2eSAxel Dörfler == BPLUSTREE_DUPLICATE_FRAGMENT) { 2742a8d81c2SJérôme Duval Print(" (duplicate fragment %" B_PRIdOFF ")\n", 2752a8d81c2SJérôme Duval *value & 0x3ff); 276647cff2eSAxel Dörfler } else if (bplustree_node::LinkType(*value) 277647cff2eSAxel Dörfler == BPLUSTREE_DUPLICATE_NODE) { 278647cff2eSAxel Dörfler Print(" (duplicate node)\n"); 279647cff2eSAxel Dörfler } else 280647cff2eSAxel Dörfler Print("\n"); 281647cff2eSAxel Dörfler } 282647cff2eSAxel Dörfler } 283647cff2eSAxel Dörfler } 284647cff2eSAxel Dörfler 285647cff2eSAxel Dörfler 286647cff2eSAxel Dörfler void 287647cff2eSAxel Dörfler dump_block(const char *buffer, uint32 size, int8 valueSize) 288647cff2eSAxel Dörfler { 289647cff2eSAxel Dörfler const uint32 kBlockSize = 16; 290647cff2eSAxel Dörfler 291647cff2eSAxel Dörfler for (uint32 i = 0; i < size;) { 292647cff2eSAxel Dörfler uint32 start = i; 293647cff2eSAxel Dörfler 294647cff2eSAxel Dörfler for (; i < start + kBlockSize; i++) { 295647cff2eSAxel Dörfler if (!(i % 4)) 296647cff2eSAxel Dörfler Print(" "); 297647cff2eSAxel Dörfler 298647cff2eSAxel Dörfler if (i >= size) 299647cff2eSAxel Dörfler Print(" "); 300647cff2eSAxel Dörfler else 301647cff2eSAxel Dörfler Print("%02x", *(unsigned char *)(buffer + i)); 302647cff2eSAxel Dörfler } 303647cff2eSAxel Dörfler Print(" "); 304647cff2eSAxel Dörfler 305647cff2eSAxel Dörfler for (i = start; i < start + kBlockSize; i++) { 306647cff2eSAxel Dörfler if (i < size) { 307647cff2eSAxel Dörfler char c = *(buffer + i); 308647cff2eSAxel Dörfler 309647cff2eSAxel Dörfler if (c < 30) 310647cff2eSAxel Dörfler Print("."); 311647cff2eSAxel Dörfler else 312647cff2eSAxel Dörfler Print("%c",c); 313647cff2eSAxel Dörfler } 314647cff2eSAxel Dörfler else 315647cff2eSAxel Dörfler break; 316647cff2eSAxel Dörfler } 317647cff2eSAxel Dörfler 318647cff2eSAxel Dörfler if (valueSize > 0) { 319647cff2eSAxel Dörfler Print(" ("); 320647cff2eSAxel Dörfler for (uint32 offset = start; offset < start + kBlockSize; 321647cff2eSAxel Dörfler offset += valueSize) { 322647cff2eSAxel Dörfler if (valueSize == sizeof(off_t)) 3232a8d81c2SJérôme Duval Print("%s%" B_PRIdOFF, offset == start ? "" : ", ", 324647cff2eSAxel Dörfler *(off_t *)(buffer + offset)); 325647cff2eSAxel Dörfler } 326647cff2eSAxel Dörfler Print(")"); 327647cff2eSAxel Dörfler } 328647cff2eSAxel Dörfler 329647cff2eSAxel Dörfler Print("\n"); 330647cff2eSAxel Dörfler } 331647cff2eSAxel Dörfler } 332647cff2eSAxel Dörfler 333