1 /* 2 * Copyright 2001-2010, pinc Software. All Rights Reserved. 3 * Released under the terms of the MIT license. 4 */ 5 6 //! BFS structure dump and helper functions 7 8 #include "BPlusTree.h" 9 #include "Inode.h" 10 #include "dump.h" 11 12 #include <File.h> 13 #include <Mime.h> 14 15 #include <stdio.h> 16 #include <string.h> 17 18 #define Print printf 19 20 21 char * 22 get_tupel(uint32 id) 23 { 24 static unsigned char tupel[5]; 25 26 tupel[0] = 0xff & (id >> 24); 27 tupel[1] = 0xff & (id >> 16); 28 tupel[2] = 0xff & (id >> 8); 29 tupel[3] = 0xff & (id); 30 tupel[4] = 0; 31 for (int16 i = 0;i < 4;i++) 32 if (tupel[i] < ' ' || tupel[i] > 128) 33 tupel[i] = '.'; 34 35 return (char *)tupel; 36 } 37 38 39 void 40 dump_block_run(const char *prefix, const block_run &run, const char *postfix) 41 { 42 Print("%s(%" B_PRId32 ", %d, %d)%s\n", prefix, run.allocation_group, 43 run.start, run.length, postfix); 44 } 45 46 47 void 48 dump_super_block(const disk_super_block *superBlock) 49 { 50 Print("disk_super_block:\n"); 51 Print(" name = %s\n", superBlock->name); 52 Print(" magic1 = %#08" B_PRIx32 " (%s) %s\n", superBlock->magic1, 53 get_tupel(superBlock->magic1), 54 superBlock->magic1 == SUPER_BLOCK_MAGIC1 ? "valid" : "INVALID"); 55 Print(" fs_byte_order = %#08" B_PRIx32 " (%s, %s endian)\n", 56 superBlock->fs_byte_order, get_tupel(superBlock->fs_byte_order), 57 superBlock->fs_byte_order == SUPER_BLOCK_FS_LENDIAN ? "little" : "big"); 58 Print(" block_size = %" B_PRIu32 "\n", superBlock->block_size); 59 Print(" block_shift = %" B_PRIu32 "\n", superBlock->block_shift); 60 Print(" num_blocks = %" B_PRIdOFF "\n", superBlock->num_blocks); 61 Print(" used_blocks = %" B_PRIdOFF "\n", superBlock->used_blocks); 62 Print(" inode_size = %" B_PRId32 "\n", superBlock->inode_size); 63 Print(" magic2 = %#08" B_PRIx32 " (%s) %s\n", superBlock->magic2, 64 get_tupel(superBlock->magic2), 65 superBlock->magic2 == (int)SUPER_BLOCK_MAGIC2 ? "valid" : "INVALID"); 66 Print(" blocks_per_ag = %" B_PRId32 "\n", superBlock->blocks_per_ag); 67 Print(" ag_shift = %" B_PRId32 "\n", superBlock->ag_shift); 68 Print(" num_ags = %" B_PRId32 "\n", superBlock->num_ags); 69 Print(" flags = %#08" B_PRIx32 " (%s)\n", superBlock->flags, 70 get_tupel(superBlock->flags)); 71 dump_block_run(" log_blocks = ", superBlock->log_blocks); 72 Print(" log_start = %" B_PRIdOFF "\n", superBlock->log_start); 73 Print(" log_end = %" B_PRIdOFF "\n", superBlock->log_end); 74 Print(" magic3 = %#08" B_PRIx32 " (%s) %s\n", superBlock->magic3, 75 get_tupel(superBlock->magic3), 76 superBlock->magic3 == SUPER_BLOCK_MAGIC3 ? "valid" : "INVALID"); 77 dump_block_run(" root_dir = ", superBlock->root_dir); 78 dump_block_run(" indices = ", superBlock->indices); 79 } 80 81 82 void 83 dump_data_stream(const bfs_inode *inode, const data_stream *stream, bool showOffsets) 84 { 85 Print("data_stream:\n"); 86 87 off_t offset = 0; 88 89 for (int i = 0; i < NUM_DIRECT_BLOCKS; i++) { 90 if (!stream->direct[i].IsZero()) { 91 Print(" direct[%02d] = ", i); 92 93 char buffer[256]; 94 if (showOffsets) 95 snprintf(buffer, sizeof(buffer), " %16" B_PRIdOFF, offset); 96 else 97 buffer[0] = '\0'; 98 99 dump_block_run("", stream->direct[i], buffer); 100 101 offset += stream->direct[i].length * inode->inode_size; 102 } 103 } 104 Print(" max_direct_range = %" B_PRIdOFF "\n", 105 stream->max_direct_range); 106 107 if (!stream->indirect.IsZero()) 108 dump_block_run(" indirect = ", stream->indirect); 109 110 Print(" max_indirect_range = %" B_PRIdOFF "\n", 111 stream->max_indirect_range); 112 113 if (!stream->double_indirect.IsZero()) { 114 dump_block_run(" double_indirect = ", 115 stream->double_indirect); 116 } 117 118 Print(" max_double_indirect_range = %" B_PRIdOFF "\n", 119 stream->max_double_indirect_range); 120 Print(" size = %" B_PRIdOFF "\n", stream->size); 121 } 122 123 124 void 125 dump_inode(const Inode *nameNode, const bfs_inode *inode, bool showOffsets) 126 { 127 if (nameNode != NULL) 128 Print("inode \"%s\":\n", nameNode->Name()); 129 else 130 Print("inode:\n"); 131 132 Print(" magic1 = %08" B_PRIx32 " (%s) %s\n",inode->magic1, 133 get_tupel(inode->magic1), 134 (inode->magic1 == INODE_MAGIC1 ? "valid" : "INVALID")); 135 dump_block_run( " inode_num = ",inode->inode_num); 136 Print(" uid = %" B_PRIu32 "\n",inode->uid); 137 Print(" gid = %" B_PRIu32 "\n",inode->gid); 138 Print(" mode = %10" B_PRIo32 " (octal)\n",inode->mode); 139 Print(" flags = %08" B_PRIx32 "\n",inode->flags); 140 141 time_t time; 142 time = (time_t)(inode->create_time >> 16); 143 Print(" create_time = %s",ctime(&time)); 144 time = (time_t)(inode->last_modified_time >> 16); 145 Print(" last_modified_time = %s",ctime(&time)); 146 147 dump_block_run( " parent = ",inode->parent); 148 dump_block_run( " attributes = ",inode->attributes); 149 Print(" type = %" B_PRIu32 "\n",inode->type); 150 Print(" inode_size = %" B_PRId32 "\n",inode->inode_size); 151 Print(" etc = %#08" B_PRIx32 "\n",inode->etc); 152 Print(" short_symlink = %s\n", 153 S_ISLNK(inode->mode) && (inode->flags & INODE_LONG_SYMLINK) == 0 154 ? inode->short_symlink : "-"); 155 156 dump_data_stream(inode, &inode->data, showOffsets); 157 Print(" --\n"); 158 #if 0 159 Print(" --\n pad[0] = %08lx\n", inode->pad[0]); 160 Print(" pad[1] = %08lx\n", inode->pad[1]); 161 Print(" pad[2] = %08lx\n", inode->pad[2]); 162 Print(" pad[3] = %08lx\n", inode->pad[3]); 163 #endif 164 } 165 166 167 void 168 dump_small_data(Inode *inode) 169 { 170 if (inode == NULL || inode->InodeBuffer() == NULL) 171 return; 172 173 small_data *item = NULL; 174 175 printf("small data section (max. %ld bytes):\n", 176 inode->InodeBuffer()->inode_size - sizeof(struct bfs_inode)); 177 178 while (inode->GetNextSmallData(&item) == B_OK) { 179 printf("%#08" B_PRIx32 " (%s), name = \"%s\", ", item->type, 180 get_tupel(item->type), item->Name()); 181 if (item->type == FILE_NAME_TYPE 182 || item->type == B_STRING_TYPE 183 || item->type == B_MIME_STRING_TYPE) 184 printf("data = \"%s\", ", item->Data()); 185 186 printf("%u bytes\n", item->data_size); 187 } 188 } 189 190 191 void 192 dump_bplustree_header(const bplustree_header* header) 193 { 194 printf("bplustree_header:\n"); 195 printf(" magic = %#08" B_PRIx32 " (%s) %s\n", 196 header->magic, get_tupel(header->magic), 197 header->magic == BPLUSTREE_MAGIC ? "valid" : "INVALID"); 198 printf(" node_size = %" B_PRIu32 "\n", header->node_size); 199 printf(" max_number_of_levels = %" B_PRIu32 "\n", 200 header->max_number_of_levels); 201 printf(" data_type = %" B_PRIu32 "\n", header->data_type); 202 printf(" root_node_pointer = %" B_PRIdOFF "\n", 203 header->root_node_pointer); 204 printf(" free_node_pointer = %" B_PRIdOFF "\n", 205 header->free_node_pointer); 206 printf(" maximum_size = %" B_PRIdOFF "\n", 207 header->maximum_size); 208 } 209 210 211 void 212 dump_bplustree_node(const bplustree_node* node, const bplustree_header* header, 213 Disk* disk) 214 { 215 Print("bplustree_node (%s node):\n", 216 node->overflow_link == BPLUSTREE_NULL ? "leaf" : "index"); 217 Print(" left_link = %" B_PRIdOFF "\n", node->left_link); 218 Print(" right_link = %" B_PRIdOFF "\n", node->right_link); 219 Print(" overflow_link = %" B_PRIdOFF "\n", node->overflow_link); 220 Print(" all_key_count = %u\n", node->all_key_count); 221 Print(" all_key_length = %u\n", node->all_key_length); 222 223 if (header == NULL) 224 return; 225 226 if (node->all_key_count > node->all_key_length 227 || uint32(node->all_key_count * 10) > (uint32)header->node_size) { 228 Print("\n"); 229 dump_block((char *)node, header->node_size, sizeof(off_t)); 230 return; 231 } 232 233 Print("\n"); 234 for (int32 i = 0;i < node->all_key_count;i++) { 235 uint16 length; 236 char* key = (char *)node->KeyAt(i, &length); 237 if (length > BPLUSTREE_MAX_KEY_LENGTH) { 238 Print(" %2" B_PRId32 ". Invalid length (%u)!!\n", i, length); 239 dump_block((char *)node, header->node_size, sizeof(off_t)); 240 break; 241 } 242 243 char buffer[BPLUSTREE_MAX_KEY_LENGTH + 1]; 244 memcpy(buffer, key, length); 245 buffer[length] = '\0'; 246 247 off_t *value = node->Values() + i; 248 if ((addr_t)value < (addr_t)node 249 || (addr_t)value > (addr_t)node + header->node_size) { 250 Print(" %2" B_PRId32 ". Invalid Offset!!\n", i); 251 } else { 252 Print(" %2" B_PRId32 ". ",i); 253 if (header->data_type == BPLUSTREE_STRING_TYPE) 254 Print("\"%s\"",buffer); 255 else if (header->data_type == BPLUSTREE_INT32_TYPE) { 256 Print("int32 = %" B_PRId32 " (0x%" B_PRIx32 ")", 257 *(int32 *)&buffer, *(int32 *)&buffer); 258 } else if (header->data_type == BPLUSTREE_UINT32_TYPE) { 259 Print("uint32 = %" B_PRIu32 " (0x%" B_PRIx32 ")", 260 *(uint32 *)&buffer, *(uint32 *)&buffer); 261 } else if (header->data_type == BPLUSTREE_INT64_TYPE) { 262 Print("int64 = %" B_PRId64 " (0x%" B_PRIx64 ")", 263 *(int64 *)&buffer, *(int64 *)&buffer); 264 } else 265 Print("???"); 266 267 off_t offset = *value & 0x3fffffffffffffffLL; 268 Print(" (%d bytes) -> %" B_PRIdOFF,length,offset); 269 if (disk != NULL) { 270 block_run run = disk->ToBlockRun(offset); 271 Print(" (%" B_PRId32 ", %d)", run.allocation_group, run.start); 272 } 273 if (bplustree_node::LinkType(*value) 274 == BPLUSTREE_DUPLICATE_FRAGMENT) { 275 Print(" (duplicate fragment %" B_PRIdOFF ")\n", 276 *value & 0x3ff); 277 } else if (bplustree_node::LinkType(*value) 278 == BPLUSTREE_DUPLICATE_NODE) { 279 Print(" (duplicate node)\n"); 280 } else 281 Print("\n"); 282 } 283 } 284 } 285 286 287 void 288 dump_block(const char *buffer, uint32 size, int8 valueSize) 289 { 290 const uint32 kBlockSize = 16; 291 292 for (uint32 i = 0; i < size;) { 293 uint32 start = i; 294 295 for (; i < start + kBlockSize; i++) { 296 if (!(i % 4)) 297 Print(" "); 298 299 if (i >= size) 300 Print(" "); 301 else 302 Print("%02x", *(unsigned char *)(buffer + i)); 303 } 304 Print(" "); 305 306 for (i = start; i < start + kBlockSize; i++) { 307 if (i < size) { 308 char c = *(buffer + i); 309 310 if (c < 30) 311 Print("."); 312 else 313 Print("%c",c); 314 } 315 else 316 break; 317 } 318 319 if (valueSize > 0) { 320 Print(" ("); 321 for (uint32 offset = start; offset < start + kBlockSize; 322 offset += valueSize) { 323 if (valueSize == sizeof(off_t)) 324 Print("%s%" B_PRIdOFF, offset == start ? "" : ", ", 325 *(off_t *)(buffer + offset)); 326 } 327 Print(")"); 328 } 329 330 Print("\n"); 331 } 332 } 333 334