xref: /haiku/src/bin/bfs_tools/lib/dump.cpp (revision ed24eb5ff12640d052171c6a7feba37fab8a75d1)
1 /*
2  * Copyright 2001-2010, pinc Software. All Rights Reserved.
3  * Released under the terms of the MIT license.
4  */
5 
6 //!	BFS structure dump and helper functions
7 
8 #include "BPlusTree.h"
9 #include "Inode.h"
10 #include "dump.h"
11 
12 #include <File.h>
13 #include <Mime.h>
14 
15 #include <stdio.h>
16 #include <string.h>
17 
18 #define Print printf
19 
20 
21 char *
22 get_tupel(uint32 id)
23 {
24 	static unsigned char tupel[5];
25 
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] = '.';
34 
35 	return (char *)tupel;
36 }
37 
38 
39 void
40 dump_block_run(const char *prefix, const block_run &run, const char *postfix)
41 {
42 	Print("%s(%" B_PRId32 ", %d, %d)%s\n", prefix, run.allocation_group,
43 		run.start, run.length, postfix);
44 }
45 
46 
47 void
48 dump_super_block(const disk_super_block *superBlock)
49 {
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);
79 }
80 
81 
82 void
83 dump_data_stream(const bfs_inode *inode, const data_stream *stream, bool showOffsets)
84 {
85 	Print("data_stream:\n");
86 
87 	off_t offset = 0;
88 
89 	for (int i = 0; i < NUM_DIRECT_BLOCKS; i++) {
90 		if (!stream->direct[i].IsZero()) {
91 			Print("  direct[%02d]                = ", i);
92 
93 			char buffer[256];
94 			if (showOffsets)
95 				snprintf(buffer, sizeof(buffer), " %16" B_PRIdOFF, offset);
96 			else
97 				buffer[0] = '\0';
98 
99 			dump_block_run("", stream->direct[i], buffer);
100 
101 			offset += stream->direct[i].length * inode->inode_size;
102 		}
103 	}
104 	Print("  max_direct_range          = %" B_PRIdOFF "\n",
105 		stream->max_direct_range);
106 
107 	if (!stream->indirect.IsZero())
108 		dump_block_run("  indirect                  = ", stream->indirect);
109 
110 	Print("  max_indirect_range        = %" B_PRIdOFF "\n",
111 		stream->max_indirect_range);
112 
113 	if (!stream->double_indirect.IsZero()) {
114 		dump_block_run("  double_indirect           = ",
115 			stream->double_indirect);
116 	}
117 
118 	Print("  max_double_indirect_range = %" B_PRIdOFF "\n",
119 		stream->max_double_indirect_range);
120 	Print("  size                      = %" B_PRIdOFF "\n", stream->size);
121 }
122 
123 
124 void
125 dump_inode(const Inode *nameNode, const bfs_inode *inode, bool showOffsets)
126 {
127 	if (nameNode != NULL)
128 		Print("inode \"%s\":\n", nameNode->Name());
129 	else
130 		Print("inode:\n");
131 
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);
140 
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));
146 
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 : "-");
155 
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
164 }
165 
166 
167 void
168 dump_small_data(Inode *inode)
169 {
170 	if (inode == NULL || inode->InodeBuffer() == NULL)
171 		return;
172 
173 	small_data *item = NULL;
174 
175 	printf("small data section (max. %ld bytes):\n",
176 		inode->InodeBuffer()->inode_size - sizeof(struct bfs_inode));
177 
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());
185 
186 		printf("%u bytes\n", item->data_size);
187 	}
188 }
189 
190 
191 void
192 dump_bplustree_header(const bplustree_header* header)
193 {
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);
208 }
209 
210 
211 void
212 dump_bplustree_node(const bplustree_node* node, const bplustree_header* header,
213 	Disk* disk)
214 {
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);
222 
223 	if (header == NULL)
224 		return;
225 
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;
231 	}
232 
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;
241 		}
242 
243 		char buffer[BPLUSTREE_MAX_KEY_LENGTH + 1];
244 		memcpy(buffer, key, length);
245 		buffer[length] = '\0';
246 
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("???");
266 
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);
272 			}
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");
282 		}
283 	}
284 }
285 
286 
287 void
288 dump_block(const char *buffer, uint32 size, int8 valueSize)
289 {
290 	const uint32 kBlockSize = 16;
291 
292 	for (uint32 i = 0; i < size;) {
293 		uint32 start = i;
294 
295 		for (; i < start + kBlockSize; i++) {
296 			if (!(i % 4))
297 				Print(" ");
298 
299 			if (i >= size)
300 				Print("  ");
301 			else
302 				Print("%02x", *(unsigned char *)(buffer + i));
303 		}
304 		Print("  ");
305 
306 		for (i = start; i < start + kBlockSize; i++) {
307 			if (i < size) {
308 				char c = *(buffer + i);
309 
310 				if (c < 30)
311 					Print(".");
312 				else
313 					Print("%c",c);
314 			}
315 			else
316 				break;
317 		}
318 
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));
326 			}
327 			Print(")");
328 		}
329 
330 		Print("\n");
331 	}
332 }
333 
334