2 * Copyright 2001-2010, pinc Software. All Rights Reserved.
3 * Released under the terms of the MIT license.
6 //! BFS structure dump and helper functions
24 static unsigned char tupel
[5];
26 tupel
[0] = 0xff & (id
>> 24);
27 tupel
[1] = 0xff & (id
>> 16);
28 tupel
[2] = 0xff & (id
>> 8);
29 tupel
[3] = 0xff & (id
);
31 for (int16 i
= 0;i
< 4;i
++)
32 if (tupel
[i
] < ' ' || tupel
[i
] > 128)
40 dump_block_run(const char *prefix
, const block_run
&run
, const char *postfix
)
42 Print("%s(%" B_PRId32
", %d, %d)%s\n", prefix
, run
.allocation_group
,
43 run
.start
, run
.length
, postfix
);
48 dump_super_block(const disk_super_block
*superBlock
)
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
);
83 dump_data_stream(const bfs_inode
*inode
, const data_stream
*stream
, bool showOffsets
)
85 Print("data_stream:\n");
89 for (int i
= 0; i
< NUM_DIRECT_BLOCKS
; i
++) {
90 if (!stream
->direct
[i
].IsZero()) {
91 Print(" direct[%02d] = ", i
);
95 snprintf(buffer
, sizeof(buffer
), " %16" B_PRIdOFF
, offset
);
99 dump_block_run("", stream
->direct
[i
], buffer
);
101 offset
+= stream
->direct
[i
].length
* inode
->inode_size
;
104 Print(" max_direct_range = %" B_PRIdOFF
"\n",
105 stream
->max_direct_range
);
107 if (!stream
->indirect
.IsZero())
108 dump_block_run(" indirect = ", stream
->indirect
);
110 Print(" max_indirect_range = %" B_PRIdOFF
"\n",
111 stream
->max_indirect_range
);
113 if (!stream
->double_indirect
.IsZero()) {
114 dump_block_run(" double_indirect = ",
115 stream
->double_indirect
);
118 Print(" max_double_indirect_range = %" B_PRIdOFF
"\n",
119 stream
->max_double_indirect_range
);
120 Print(" size = %" B_PRIdOFF
"\n", stream
->size
);
125 dump_inode(const Inode
*nameNode
, const bfs_inode
*inode
, bool showOffsets
)
127 if (nameNode
!= NULL
)
128 Print("inode \"%s\":\n", nameNode
->Name());
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
);
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
));
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
: "-");
156 dump_data_stream(inode
, &inode
->data
, showOffsets
);
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]);
168 dump_small_data(Inode
*inode
)
170 if (inode
== NULL
|| inode
->InodeBuffer() == NULL
)
173 small_data
*item
= NULL
;
175 printf("small data section (max. %ld bytes):\n",
176 inode
->InodeBuffer()->inode_size
- sizeof(struct bfs_inode
));
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());
186 printf("%u bytes\n", item
->data_size
);
192 dump_bplustree_header(const bplustree_header
* header
)
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
);
212 dump_bplustree_node(const bplustree_node
* node
, const bplustree_header
* header
,
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
);
226 if (node
->all_key_count
> node
->all_key_length
227 || uint32(node
->all_key_count
* 10) > (uint32
)header
->node_size
) {
229 dump_block((char *)node
, header
->node_size
, sizeof(off_t
));
234 for (int32 i
= 0;i
< node
->all_key_count
;i
++) {
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
));
244 memcpy(buffer
, key
, length
);
245 buffer
[length
] = '\0';
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
);
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
);
267 off_t offset
= *value
& 0x3fffffffffffffffLL
;
268 Print(" (%d bytes) -> %" B_PRIdOFF
,length
,offset
);
270 block_run run
= disk
->ToBlockRun(offset
);
271 Print(" (%" B_PRId32
", %d)", run
.allocation_group
, run
.start
);
273 if (bplustree_node::LinkType(*value
)
274 == BPLUSTREE_DUPLICATE_FRAGMENT
) {
275 Print(" (duplicate fragment %" B_PRIdOFF
")\n",
277 } else if (bplustree_node::LinkType(*value
)
278 == BPLUSTREE_DUPLICATE_NODE
) {
279 Print(" (duplicate node)\n");
288 dump_block(const char *buffer
, uint32 size
, int8 valueSize
)
290 const uint32 kBlockSize
= 16;
292 for (uint32 i
= 0; i
< size
;) {
295 for (; i
< start
+ kBlockSize
; i
++) {
302 Print("%02x", *(unsigned char *)(buffer
+ i
));
306 for (i
= start
; i
< start
+ kBlockSize
; i
++) {
308 char c
= *(buffer
+ i
);
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
));