btrfs: Attempt to fix GCC2 build.
[haiku.git] / src / bin / bfs_tools / lib / dump.cpp
blob523e50cd5c1692d5de26480a94ee7154fe2862d4
1 /*
2 * Copyright 2001-2010, pinc Software. All Rights Reserved.
3 * Released under the terms of the MIT license.
4 */
6 //! BFS structure dump and helper functions
8 #include "BPlusTree.h"
9 #include "Inode.h"
10 #include "dump.h"
12 #include <File.h>
13 #include <Mime.h>
15 #include <stdio.h>
16 #include <string.h>
18 #define Print printf
21 char *
22 get_tupel(uint32 id)
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);
30 tupel[4] = 0;
31 for (int16 i = 0;i < 4;i++)
32 if (tupel[i] < ' ' || tupel[i] > 128)
33 tupel[i] = '.';
35 return (char *)tupel;
39 void
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);
47 void
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);
82 void
83 dump_data_stream(const bfs_inode *inode, const data_stream *stream, bool showOffsets)
85 Print("data_stream:\n");
87 off_t offset = 0;
89 for (int i = 0; i < NUM_DIRECT_BLOCKS; i++) {
90 if (!stream->direct[i].IsZero()) {
91 Print(" direct[%02d] = ", i);
93 char buffer[256];
94 if (showOffsets)
95 snprintf(buffer, sizeof(buffer), " %16" B_PRIdOFF, offset);
96 else
97 buffer[0] = '\0';
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);
124 void
125 dump_inode(const Inode *nameNode, const bfs_inode *inode, bool showOffsets)
127 if (nameNode != NULL)
128 Print("inode \"%s\":\n", nameNode->Name());
129 else
130 Print("inode:\n");
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);
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));
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);
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
167 void
168 dump_small_data(Inode *inode)
170 if (inode == NULL || inode->InodeBuffer() == NULL)
171 return;
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);
191 void
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);
211 void
212 dump_bplustree_node(const bplustree_node* node, const bplustree_header* header,
213 Disk* disk)
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);
223 if (header == NULL)
224 return;
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;
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;
243 char buffer[256];
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);
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("???");
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);
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");
287 void
288 dump_block(const char *buffer, uint32 size, int8 valueSize)
290 const uint32 kBlockSize = 16;
292 for (uint32 i = 0; i < size;) {
293 uint32 start = i;
295 for (; i < start + kBlockSize; i++) {
296 if (!(i % 4))
297 Print(" ");
299 if (i >= size)
300 Print(" ");
301 else
302 Print("%02x", *(unsigned char *)(buffer + i));
304 Print(" ");
306 for (i = start; i < start + kBlockSize; i++) {
307 if (i < size) {
308 char c = *(buffer + i);
310 if (c < 30)
311 Print(".");
312 else
313 Print("%c",c);
315 else
316 break;
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));
327 Print(")");
330 Print("\n");