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