xref: /haiku/src/bin/bfs_tools/lib/dump.cpp (revision b617a7b410c05275effb95f4b2f5608359d9b7b9)
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(%" B_PRId32 ", %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         = %#08" B_PRIx32 " (%s) %s\n", superBlock->magic1,
52 		get_tupel(superBlock->magic1),
53 		superBlock->magic1 == SUPER_BLOCK_MAGIC1 ? "valid" : "INVALID");
54 	Print("  fs_byte_order  = %#08" B_PRIx32 " (%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     = %" B_PRIu32 "\n", superBlock->block_size);
58 	Print("  block_shift    = %" B_PRIu32 "\n", superBlock->block_shift);
59 	Print("  num_blocks     = %" B_PRIdOFF "\n", superBlock->num_blocks);
60 	Print("  used_blocks    = %" B_PRIdOFF "\n", superBlock->used_blocks);
61 	Print("  inode_size     = %" B_PRId32 "\n", superBlock->inode_size);
62 	Print("  magic2         = %#08" B_PRIx32 " (%s) %s\n", superBlock->magic2,
63 		get_tupel(superBlock->magic2),
64 		superBlock->magic2 == (int)SUPER_BLOCK_MAGIC2 ? "valid" : "INVALID");
65 	Print("  blocks_per_ag  = %" B_PRId32 "\n", superBlock->blocks_per_ag);
66 	Print("  ag_shift       = %" B_PRId32 "\n", superBlock->ag_shift);
67 	Print("  num_ags        = %" B_PRId32 "\n", superBlock->num_ags);
68 	Print("  flags          = %#08" B_PRIx32 " (%s)\n", superBlock->flags,
69 		get_tupel(superBlock->flags));
70 	dump_block_run("  log_blocks     = ", superBlock->log_blocks);
71 	Print("  log_start      = %" B_PRIdOFF "\n", superBlock->log_start);
72 	Print("  log_end        = %" B_PRIdOFF "\n", superBlock->log_end);
73 	Print("  magic3         = %#08" B_PRIx32 " (%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), " %16" B_PRIdOFF, 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          = %" B_PRIdOFF "\n",
104 		stream->max_direct_range);
105 
106 	if (!stream->indirect.IsZero())
107 		dump_block_run("  indirect                  = ", stream->indirect);
108 
109 	Print("  max_indirect_range        = %" B_PRIdOFF "\n",
110 		stream->max_indirect_range);
111 
112 	if (!stream->double_indirect.IsZero()) {
113 		dump_block_run("  double_indirect           = ",
114 			stream->double_indirect);
115 	}
116 
117 	Print("  max_double_indirect_range = %" B_PRIdOFF "\n",
118 		stream->max_double_indirect_range);
119 	Print("  size                      = %" B_PRIdOFF "\n", stream->size);
120 }
121 
122 
123 void
124 dump_inode(const Inode *nameNode, const bfs_inode *inode, bool showOffsets)
125 {
126 	if (nameNode != NULL)
127 		Print("inode \"%s\":\n", nameNode->Name());
128 	else
129 		Print("inode:\n");
130 
131 	Print("  magic1             = %08" B_PRIx32 " (%s) %s\n",inode->magic1,
132 		get_tupel(inode->magic1),
133 		(inode->magic1 == INODE_MAGIC1 ? "valid" : "INVALID"));
134 	dump_block_run(	"  inode_num          = ",inode->inode_num);
135 	Print("  uid                = %" B_PRIu32 "\n",inode->uid);
136 	Print("  gid                = %" B_PRIu32 "\n",inode->gid);
137 	Print("  mode               = %10" B_PRIo32 " (octal)\n",inode->mode);
138 	Print("  flags              = %08" B_PRIx32 "\n",inode->flags);
139 
140 	time_t time;
141 	time = (time_t)(inode->create_time >> 16);
142 	Print("  create_time        = %s",ctime(&time));
143 	time = (time_t)(inode->last_modified_time >> 16);
144 	Print("  last_modified_time = %s",ctime(&time));
145 
146 	dump_block_run(	"  parent             = ",inode->parent);
147 	dump_block_run(	"  attributes         = ",inode->attributes);
148 	Print("  type               = %" B_PRIu32 "\n",inode->type);
149 	Print("  inode_size         = %" B_PRId32 "\n",inode->inode_size);
150 	Print("  etc                = %#08" B_PRIx32 "\n",inode->etc);
151 	Print("  short_symlink      = %s\n",
152 		S_ISLNK(inode->mode) && (inode->flags & INODE_LONG_SYMLINK) == 0
153 			? inode->short_symlink : "-");
154 
155 	dump_data_stream(inode, &inode->data, showOffsets);
156 	Print("  --\n");
157 #if 0
158 	Print("  --\n  pad[0]             = %08lx\n", inode->pad[0]);
159 	Print("  pad[1]             = %08lx\n", inode->pad[1]);
160 	Print("  pad[2]             = %08lx\n", inode->pad[2]);
161 	Print("  pad[3]             = %08lx\n", inode->pad[3]);
162 #endif
163 }
164 
165 
166 void
167 dump_small_data(Inode *inode)
168 {
169 	if (inode == NULL || inode->InodeBuffer() == NULL)
170 		return;
171 
172 	small_data *item = NULL;
173 
174 	printf("small data section (max. %ld bytes):\n",
175 		inode->InodeBuffer()->inode_size - sizeof(struct bfs_inode));
176 
177 	while (inode->GetNextSmallData(&item) == B_OK) {
178 		printf("%#08" B_PRIx32 " (%s), name = \"%s\", ", item->type,
179 			get_tupel(item->type), item->Name());
180 		if (item->type == FILE_NAME_TYPE
181 			|| item->type == B_STRING_TYPE
182 			|| item->type == B_MIME_STRING_TYPE)
183 			printf("data = \"%s\", ", item->Data());
184 
185 		printf("%u bytes\n", item->data_size);
186 	}
187 }
188 
189 
190 void
191 dump_bplustree_header(const bplustree_header* header)
192 {
193 	printf("bplustree_header:\n");
194 	printf("  magic                = %#08" B_PRIx32 " (%s) %s\n",
195 		header->magic, get_tupel(header->magic),
196 		header->magic == BPLUSTREE_MAGIC ? "valid" : "INVALID");
197 	printf("  node_size            = %" B_PRIu32 "\n", header->node_size);
198 	printf("  max_number_of_levels = %" B_PRIu32 "\n",
199 		header->max_number_of_levels);
200 	printf("  data_type            = %" B_PRIu32 "\n", header->data_type);
201 	printf("  root_node_pointer    = %" B_PRIdOFF "\n",
202 		header->root_node_pointer);
203 	printf("  free_node_pointer    = %" B_PRIdOFF "\n",
204 		header->free_node_pointer);
205 	printf("  maximum_size         = %" B_PRIdOFF "\n",
206 		header->maximum_size);
207 }
208 
209 
210 void
211 dump_bplustree_node(const bplustree_node* node, const bplustree_header* header,
212 	Disk* disk)
213 {
214 	Print("bplustree_node (%s node):\n",
215 		node->overflow_link == BPLUSTREE_NULL ? "leaf" : "index");
216 	Print("  left_link      = %" B_PRIdOFF "\n", node->left_link);
217 	Print("  right_link     = %" B_PRIdOFF "\n", node->right_link);
218 	Print("  overflow_link  = %" B_PRIdOFF "\n", node->overflow_link);
219 	Print("  all_key_count  = %u\n", node->all_key_count);
220 	Print("  all_key_length = %u\n", node->all_key_length);
221 
222 	if (header == NULL)
223 		return;
224 
225 	if (node->all_key_count > node->all_key_length
226 		|| uint32(node->all_key_count * 10) > (uint32)header->node_size) {
227 		Print("\n");
228 		dump_block((char *)node, header->node_size, sizeof(off_t));
229 		return;
230 	}
231 
232 	Print("\n");
233 	for (int32 i = 0;i < node->all_key_count;i++) {
234 		uint16 length;
235 		char* key = (char *)node->KeyAt(i, &length);
236 		if (length > 255) {
237 			Print("  %2" B_PRId32 ". Invalid length (%u)!!\n", i, length);
238 			dump_block((char *)node, header->node_size, sizeof(off_t));
239 			break;
240 		}
241 
242 		char buffer[256];
243 		memcpy(buffer, key, length);
244 		buffer[length] = '\0';
245 
246 		off_t *value = node->Values() + i;
247 		if ((addr_t)value < (addr_t)node
248 			|| (addr_t)value > (addr_t)node + header->node_size) {
249 			Print("  %2" B_PRId32 ". Invalid Offset!!\n", i);
250 		} else {
251 			Print("  %2" B_PRId32 ". ",i);
252 			if (header->data_type == BPLUSTREE_STRING_TYPE)
253 				Print("\"%s\"",buffer);
254 			else if (header->data_type == BPLUSTREE_INT32_TYPE) {
255 				Print("int32 = %" B_PRId32 " (0x%" B_PRIx32 ")",
256 					*(int32 *)&buffer, *(int32 *)&buffer);
257 			} else if (header->data_type == BPLUSTREE_UINT32_TYPE) {
258 				Print("uint32 = %" B_PRIu32 " (0x%" B_PRIx32 ")",
259 					*(uint32 *)&buffer, *(uint32 *)&buffer);
260 			} else if (header->data_type == BPLUSTREE_INT64_TYPE) {
261 				Print("int64 = %" B_PRId64 " (0x%" B_PRIx64 ")",
262 					*(int64 *)&buffer, *(int64 *)&buffer);
263 			} else
264 				Print("???");
265 
266 			off_t offset = *value & 0x3fffffffffffffffLL;
267 			Print(" (%d bytes) -> %" B_PRIdOFF,length,offset);
268 			if (disk != NULL) {
269 				block_run run = disk->ToBlockRun(offset);
270 				Print(" (%" B_PRId32 ", %d)", run.allocation_group, run.start);
271 			}
272 			if (bplustree_node::LinkType(*value)
273 					== BPLUSTREE_DUPLICATE_FRAGMENT) {
274 				Print(" (duplicate fragment %" B_PRIdOFF ")\n",
275 					*value & 0x3ff);
276 			} else if (bplustree_node::LinkType(*value)
277 					== BPLUSTREE_DUPLICATE_NODE) {
278 				Print(" (duplicate node)\n");
279 			} else
280 				Print("\n");
281 		}
282 	}
283 }
284 
285 
286 void
287 dump_block(const char *buffer, uint32 size, int8 valueSize)
288 {
289 	const uint32 kBlockSize = 16;
290 
291 	for (uint32 i = 0; i < size;) {
292 		uint32 start = i;
293 
294 		for (; i < start + kBlockSize; i++) {
295 			if (!(i % 4))
296 				Print(" ");
297 
298 			if (i >= size)
299 				Print("  ");
300 			else
301 				Print("%02x", *(unsigned char *)(buffer + i));
302 		}
303 		Print("  ");
304 
305 		for (i = start; i < start + kBlockSize; i++) {
306 			if (i < size) {
307 				char c = *(buffer + i);
308 
309 				if (c < 30)
310 					Print(".");
311 				else
312 					Print("%c",c);
313 			}
314 			else
315 				break;
316 		}
317 
318 		if (valueSize > 0) {
319 			Print("  (");
320 			for (uint32 offset = start; offset < start + kBlockSize;
321 					offset += valueSize) {
322 				if (valueSize == sizeof(off_t))
323 					Print("%s%" B_PRIdOFF, offset == start ? "" : ", ",
324 						*(off_t *)(buffer + offset));
325 			}
326 			Print(")");
327 		}
328 
329 		Print("\n");
330 	}
331 }
332 
333