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