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