1 /*
2  * Copyright (C) 2021 Jakub Kruszona-Zawadzki, Core Technology Sp. z o.o.
3  *
4  * This file is part of MooseFS.
5  *
6  * MooseFS is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, version 2 (only).
9  *
10  * MooseFS is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with MooseFS; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02111-1301, USA
18  * or visit http://www.gnu.org/licenses/gpl-2.0.html
19  */
20 
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24 
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <unistd.h>
29 #include <sys/types.h>
30 #include <inttypes.h>
31 
32 #include "MFSCommunication.h"
33 #include "datapack.h"
34 #include "idstr.h"
35 
36 #define MAX_INDEX 0x7FFFFFFF
37 #define MAX_CHUNKS_PER_FILE (MAX_INDEX+1)
38 
39 #define MAXSCLASSNLENG 256
40 
41 static int hide_nonprintable = 0;
42 
dispchar(uint8_t c)43 static inline char dispchar(uint8_t c) {
44 	if (hide_nonprintable) {
45 		return (c>=32 && c<=126)?c:'.';
46 	} else {
47 		return c;
48 	}
49 }
50 
makestrip(char strip[16],uint32_t ip)51 static inline void makestrip(char strip[16],uint32_t ip) {
52 	snprintf(strip,16,"%03"PRIu8".%03"PRIu8".%03"PRIu8".%03"PRIu8,(uint8_t)(ip>>24),(uint8_t)(ip>>16),(uint8_t)(ip>>8),(uint8_t)ip);
53 	strip[15]=0;
54 }
55 
print_name(FILE * in,uint32_t nleng)56 void print_name(FILE *in,uint32_t nleng) {
57 	uint8_t buff[1024];
58 	uint32_t x,y,i;
59 	size_t happy;
60 	while (nleng>0) {
61 		y = (nleng>1024)?1024:nleng;
62 		x = fread(buff,1,y,in);
63 		if (hide_nonprintable) {
64 			for (i=0 ; i<x ; i++) {
65 				if (buff[i]<32 || buff[i]>127) {
66 					buff[i]='.';
67 				}
68 			}
69 		}
70 		happy = fwrite(buff,1,x,stdout);
71 		(void)happy;
72 		if (x!=y) {
73 			return;
74 		}
75 		nleng -= x;
76 	}
77 }
78 
print_hex(FILE * in,uint32_t vleng)79 void print_hex(FILE *in,uint32_t vleng) {
80 	uint8_t buff[1024];
81 	uint32_t x,y,i;
82 	while (vleng>0) {
83 		y = (vleng>1024)?1024:vleng;
84 		x = fread(buff,1,y,in);
85 		for (i=0 ; i<x ; i++) {
86 			printf("%02"PRIX8,buff[i]);
87 		}
88 		if (x!=y) {
89 			return;
90 		}
91 		vleng -= x;
92 	}
93 }
94 
chunk_load(FILE * fd,uint8_t mver)95 int chunk_load(FILE *fd,uint8_t mver) {
96 	uint8_t hdr[8];
97 	uint8_t loadbuff[17];
98 	const uint8_t *ptr;
99 	int32_t r,recsize;
100 	uint64_t chunkid,nextchunkid;
101 	uint32_t version,lockedto;
102 	uint8_t archflag;
103 
104 	if (mver>0x11) {
105 		fprintf(stderr,"loading chunks: unsupported format\n");
106 		return -1;
107 	}
108 
109 	if (fread(hdr,1,8,fd)!=8) {
110 		return -1;
111 	}
112 	ptr = hdr;
113 	nextchunkid = get64bit(&ptr);
114 	recsize = (mver==0x10)?16:17;
115 	printf("# nextchunkid: %016"PRIX64"\n",nextchunkid);
116 	for (;;) {
117 		r = fread(loadbuff,1,recsize,fd);
118 		(void)r;
119 		ptr = loadbuff;
120 		chunkid = get64bit(&ptr);
121 		version = get32bit(&ptr);
122 		lockedto = get32bit(&ptr);
123 		if (mver==0x10) {
124 			archflag = 0;
125 		} else {
126 			archflag = get8bit(&ptr);
127 		}
128 		if (chunkid==0 && version==0 && lockedto==0) {
129 			return 0;
130 		}
131 		printf("CHUNK|i:0x%016"PRIX64"|v:0x%08"PRIX32"|t:%10"PRIu32"|a:%"PRIu8"\n",chunkid,version,lockedto,archflag);
132 	}
133 }
134 
fs_loadedge(FILE * fd,uint8_t mver)135 int fs_loadedge(FILE *fd,uint8_t mver) {
136 	uint8_t uedgebuff[4+4+8+2];
137 	const uint8_t *ptr;
138 	uint32_t parent_id;
139 	uint32_t child_id;
140 	uint64_t edge_id;
141 	uint16_t nleng;
142 
143 	ptr = uedgebuff;
144 	if (mver<=0x10) {
145 		if (fread(uedgebuff,1,4+4+2,fd)!=4+4+2) {
146 			fprintf(stderr,"loading edge: read error\n");
147 			return -1;
148 		}
149 		parent_id = get32bit(&ptr);
150 		child_id = get32bit(&ptr);
151 		edge_id = 0;
152 		nleng = get16bit(&ptr);
153 	} else {
154 		if (fread(uedgebuff,1,4+4+8+2,fd)!=4+4+8+2) {
155 			fprintf(stderr,"loading edge: read error\n");
156 			return -1;
157 		}
158 		parent_id = get32bit(&ptr);
159 		child_id = get32bit(&ptr);
160 		edge_id = get64bit(&ptr);
161 		nleng = get16bit(&ptr);
162 	}
163 	if (parent_id==0 && child_id==0) {	// last edge
164 		return 1;
165 	}
166 
167 	if (parent_id==0) {
168 		printf("EDGE|p:      NULL|c:%10"PRIu32"|i:0x%016"PRIX64"|n:",child_id,edge_id);
169 	} else {
170 		printf("EDGE|p:%10"PRIu32"|c:%10"PRIu32"|i:0x%016"PRIX64"|n:",parent_id,child_id,edge_id);
171 	}
172 	print_name(fd,nleng);
173 	printf("\n");
174 	return 0;
175 }
176 
fsnodes_type_convert(uint8_t type)177 static inline uint8_t fsnodes_type_convert(uint8_t type) {
178 	switch (type) {
179 		case DISP_TYPE_FILE:
180 			return TYPE_FILE;
181 		case DISP_TYPE_DIRECTORY:
182 			return TYPE_DIRECTORY;
183 		case DISP_TYPE_SYMLINK:
184 			return TYPE_SYMLINK;
185 		case DISP_TYPE_FIFO:
186 			return TYPE_FIFO;
187 		case DISP_TYPE_BLOCKDEV:
188 			return TYPE_BLOCKDEV;
189 		case DISP_TYPE_CHARDEV:
190 			return TYPE_CHARDEV;
191 		case DISP_TYPE_SOCKET:
192 			return TYPE_SOCKET;
193 		case DISP_TYPE_TRASH:
194 			return TYPE_TRASH;
195 		case DISP_TYPE_SUSTAINED:
196 			return TYPE_SUSTAINED;
197 	}
198 	return 0;
199 }
200 
fs_loadnode(FILE * fd,uint8_t mver)201 int fs_loadnode(FILE *fd,uint8_t mver) {
202 	uint8_t unodebuff[4+1+1+1+2+4+4+4+4+4+4+8+4+2+8*65536+4*65536+4];
203 	const uint8_t *ptr,*chptr;
204 	uint8_t type,goal,flags,winattr;
205 	uint32_t nodeid,uid,gid,atimestamp,mtimestamp,ctimestamp,trashtime;
206 	uint16_t mode;
207 	uint32_t hdrsize;
208 	char c;
209 
210 	type = fgetc(fd);
211 	if (type==0) {	// last node
212 		return 1;
213 	}
214 	if (mver<=0x11) {
215 		hdrsize = 4+1+2+6*4;
216 	} else if (mver<=0x13) {
217 		hdrsize = 4+1+1+2+6*4;
218 	} else {
219 		hdrsize = 4+1+1+1+2+5*4+2;
220 	}
221 	if (mver<=0x12) {
222 		type = fsnodes_type_convert(type);
223 	}
224 	switch (type) {
225 	case TYPE_DIRECTORY:
226 	case TYPE_FIFO:
227 	case TYPE_SOCKET:
228 		if (fread(unodebuff,1,hdrsize,fd)!=hdrsize) {
229 			fprintf(stderr,"loading node: read error\n");
230 			return -1;
231 		}
232 		break;
233 	case TYPE_BLOCKDEV:
234 	case TYPE_CHARDEV:
235 	case TYPE_SYMLINK:
236 		if (fread(unodebuff,1,hdrsize+4,fd)!=hdrsize+4) {
237 			fprintf(stderr,"loading node: read error\n");
238 			return -1;
239 		}
240 		break;
241 	case TYPE_FILE:
242 	case TYPE_TRASH:
243 	case TYPE_SUSTAINED:
244 		if (mver<=0x13) {
245 			if (fread(unodebuff,1,hdrsize+8+4+2,fd)!=hdrsize+8+4+2) {
246 				fprintf(stderr,"loading node: read error\n");
247 				return -1;
248 			}
249 		} else {
250 			if (fread(unodebuff,1,hdrsize+8+4,fd)!=hdrsize+8+4) {
251 				fprintf(stderr,"loading node: read error\n");
252 				return -1;
253 			}
254 		}
255 		break;
256 	default:
257 		fprintf(stderr,"loading node: unrecognized node type: %c\n",type);
258 		return -1;
259 	}
260 	c='?';
261 	switch (type) {
262 	case TYPE_DIRECTORY:
263 		c='D';
264 		break;
265 	case TYPE_SOCKET:
266 		c='S';
267 		break;
268 	case TYPE_FIFO:
269 		c='F';
270 		break;
271 	case TYPE_BLOCKDEV:
272 		c='B';
273 		break;
274 	case TYPE_CHARDEV:
275 		c='C';
276 		break;
277 	case TYPE_SYMLINK:
278 		c='L';
279 		break;
280 	case TYPE_FILE:
281 		c='-';
282 		break;
283 	case TYPE_TRASH:
284 		c='T';
285 		break;
286 	case TYPE_SUSTAINED:
287 		c='R';
288 		break;
289 	}
290 	ptr = unodebuff;
291 	nodeid = get32bit(&ptr);
292 	goal = get8bit(&ptr);
293 	if (mver<=0x11) {
294 		uint16_t flagsmode = get16bit(&ptr);
295 		flags = flagsmode >> 12;
296 		mode = flagsmode & 0xFFF;
297 		winattr = 0;
298 	} else {
299 		flags = get8bit(&ptr);
300 		if (mver>=0x14) {
301 			winattr = get8bit(&ptr);
302 		} else {
303 			winattr = 0;
304 		}
305 		mode = get16bit(&ptr);
306 	}
307 	uid = get32bit(&ptr);
308 	gid = get32bit(&ptr);
309 	atimestamp = get32bit(&ptr);
310 	mtimestamp = get32bit(&ptr);
311 	ctimestamp = get32bit(&ptr);
312 	if (mver>=0x14) {
313 		trashtime = get16bit(&ptr);
314 		printf("NODE|k:%c|i:%10"PRIu32"|#:%"PRIu8"|e:0x%02"PRIX8"|w:0x%1"PRIX8"|m:0%04"PRIo16"|u:%10"PRIu32"|g:%10"PRIu32"|a:%10"PRIu32",m:%10"PRIu32",c:%10"PRIu32"|t:%5"PRIu32"h",c,nodeid,goal,flags,winattr,mode,uid,gid,atimestamp,mtimestamp,ctimestamp,trashtime);
315 	} else {
316 		trashtime = get32bit(&ptr);
317 		printf("NODE|k:%c|i:%10"PRIu32"|#:%"PRIu8"|e:0x%02"PRIX8"|m:0%04"PRIo16"|u:%10"PRIu32"|g:%10"PRIu32"|a:%10"PRIu32",m:%10"PRIu32",c:%10"PRIu32"|t:%10"PRIu32"s",c,nodeid,goal,flags,mode,uid,gid,atimestamp,mtimestamp,ctimestamp,trashtime);
318 	}
319 
320 	if (type==TYPE_BLOCKDEV || type==TYPE_CHARDEV) {
321 		uint32_t rdev;
322 		rdev = get32bit(&ptr);
323 		printf("|d:%5"PRIu32",%5"PRIu32"\n",rdev>>16,rdev&0xFFFF);
324 	} else if (type==TYPE_SYMLINK) {
325 		uint32_t pleng;
326 		pleng = get32bit(&ptr);
327 		printf("|p:");
328 		print_name(fd,pleng);
329 		printf("\n");
330 	} else if (type==TYPE_FILE || type==TYPE_TRASH || type==TYPE_SUSTAINED) {
331 		uint64_t length,chunkid;
332 		uint32_t ci,ch,sessionid;
333 		uint16_t sessionids;
334 
335 		length = get64bit(&ptr);
336 		ch = get32bit(&ptr);
337 		if (mver<=0x13) {
338 			sessionids = get16bit(&ptr);
339 		} else {
340 			sessionids = 0;
341 		}
342 
343 		printf("|l:%20"PRIu64"|c:(",length);
344 		while (ch>65536) {
345 			chptr = ptr;
346 			if (fread((uint8_t*)ptr,1,8*65536,fd)!=8*65536) {
347 				fprintf(stderr,"loading node: read error\n");
348 				return -1;
349 			}
350 			for (ci=0 ; ci<65536 ; ci++) {
351 				chunkid = get64bit(&chptr);
352 				if (chunkid>0) {
353 					printf("%016"PRIX64,chunkid);
354 				} else {
355 					printf("N");
356 				}
357 				printf(",");
358 			}
359 			ch-=65536;
360 		}
361 
362 		if (fread((uint8_t*)ptr,1,8*ch+4*sessionids,fd)!=8*ch+4*sessionids) {
363 			fprintf(stderr,"loading node: read error\n");
364 			return -1;
365 		}
366 
367 		while (ch>0) {
368 			chunkid = get64bit(&ptr);
369 			if (chunkid>0) {
370 				printf("%016"PRIX64,chunkid);
371 			} else {
372 				printf("N");
373 			}
374 			if (ch>1) {
375 				printf(",");
376 			}
377 			ch--;
378 		}
379 		if (mver<=0x13) {
380 			printf(")|r:(");
381 			while (sessionids>0) {
382 				sessionid = get32bit(&ptr);
383 				printf("%"PRIu32,sessionid);
384 				if (sessionids>1) {
385 					printf(",");
386 				}
387 				sessionids--;
388 			}
389 		}
390 		printf(")\n");
391 	} else {
392 		printf("\n");
393 	}
394 
395 	return 0;
396 }
397 
fs_loadnodes(FILE * fd,uint8_t fver,uint8_t mver)398 int fs_loadnodes(FILE *fd,uint8_t fver,uint8_t mver) {
399 	int s;
400 	uint8_t hdr[8];
401 	const uint8_t *ptr;
402 	uint32_t maxnodeid,hashelements;
403 	(void)fver;
404 	if (fver>=0x20) {
405 		if (mver>0x14) {
406 			fprintf(stderr,"loading node: unsupported format\n");
407 			return -1;
408 		}
409 		if (mver<=0x10) {
410 			if (fread(hdr,1,4,fd)!=4) {
411 				fprintf(stderr,"loading node: read error\n");
412 				return -1;
413 			}
414 			ptr = hdr;
415 			maxnodeid = get32bit(&ptr);
416 			printf("# maxinode: %"PRIu32"\n",maxnodeid);
417 		} else {
418 			if (fread(hdr,1,8,fd)!=8) {
419 				fprintf(stderr,"loading node: read error\n");
420 				return -1;
421 			}
422 			ptr = hdr;
423 			maxnodeid = get32bit(&ptr);
424 			hashelements = get32bit(&ptr);
425 			printf("# maxinode: %"PRIu32" ; hashelements: %"PRIu32"\n",maxnodeid,hashelements);
426 		}
427 	}
428 	do {
429 		s = fs_loadnode(fd,mver);
430 		if (s<0) {
431 			return -1;
432 		}
433 	} while (s==0);
434 	return 0;
435 }
436 
fs_loadedges(FILE * fd,uint8_t mver)437 int fs_loadedges(FILE *fd,uint8_t mver) {
438 	uint8_t hdr[8];
439 	const uint8_t *ptr;
440 	uint64_t nextedgeid;
441 	int s;
442 	if (mver>0x11) {
443 		fprintf(stderr,"loading edge: unsupported format\n");
444 		return -1;
445 	}
446 	if (mver>0x10) {
447 		if (fread(hdr,1,8,fd)!=8) {
448 			fprintf(stderr,"loading edge: read error\n");
449 			return -1;
450 		}
451 		ptr = hdr;
452 		nextedgeid = get64bit(&ptr);
453 		printf("# nextedgeid: %016"PRIX64"\n",nextedgeid);
454 	}
455 	do {
456 		s = fs_loadedge(fd,mver);
457 		if (s<0) {
458 			return -1;
459 		}
460 	} while (s==0);
461 	return 0;
462 }
463 
fs_loadfree(FILE * fd,uint8_t mver)464 int fs_loadfree(FILE *fd,uint8_t mver) {
465 	uint8_t rbuff[8];
466 	const uint8_t *ptr;
467 	uint32_t t,nodeid,ftime;
468 	if (mver>0x10) {
469 		fprintf(stderr,"loading free nodes: unsupported format\n");
470 		return -1;
471 	}
472 	if (fread(rbuff,1,4,fd)!=4) {
473 		return -1;
474 	}
475 	ptr=rbuff;
476 	t = get32bit(&ptr);
477 	printf("# free nodes: %"PRIu32"\n",t);
478 	while (t>0) {
479 		if (fread(rbuff,1,8,fd)!=8) {
480 			return -1;
481 		}
482 		ptr = rbuff;
483 		nodeid = get32bit(&ptr);
484 		ftime = get32bit(&ptr);
485 		printf("FREEID|i:%10"PRIu32"|f:%10"PRIu32"\n",nodeid,ftime);
486 		t--;
487 	}
488 	return 0;
489 }
490 
fs_loadquota(FILE * fd,uint8_t mver)491 int fs_loadquota(FILE *fd,uint8_t mver) {
492 	uint8_t rbuff[70];
493 	const uint8_t *ptr;
494 	uint8_t exceeded,flags;
495 	uint32_t t,graceperiod,nodeid,stimestamp,sinodes,hinodes;
496 	uint64_t slength,hlength,ssize,hsize,srealsize,hrealsize;
497 	size_t rsize;
498 
499 	if (mver>0x11) {
500 		fprintf(stderr,"loading quota: unsupported format\n");
501 		return -1;
502 	}
503 	rsize = (mver==0x10)?66:70;
504 	if (fread(rbuff,1,4,fd)!=4) {
505 		return -1;
506 	}
507 	ptr=rbuff;
508 	t = get32bit(&ptr);
509 	printf("# quota nodes: %"PRIu32"\n",t);
510 	while (t>0) {
511 		if (fread(rbuff,1,rsize,fd)!=rsize) {
512 			return -1;
513 		}
514 		ptr = rbuff;
515 		nodeid = get32bit(&ptr);
516 		if (mver>=0x11) {
517 			graceperiod = get32bit(&ptr);
518 		} else {
519 			graceperiod = 7*86400;
520 		}
521 		exceeded = get8bit(&ptr);
522 		flags = get8bit(&ptr);
523 		stimestamp = get32bit(&ptr);
524 		sinodes = get32bit(&ptr);
525 		hinodes = get32bit(&ptr);
526 		slength = get64bit(&ptr);
527 		hlength = get64bit(&ptr);
528 		ssize = get64bit(&ptr);
529 		hsize = get64bit(&ptr);
530 		srealsize = get64bit(&ptr);
531 		hrealsize = get64bit(&ptr);
532 		printf("QUOTA|i:%10"PRIu32"|g:%"PRIu32"|e:%c|f:0x%02"PRIX8"|s:%10"PRIu32,nodeid,graceperiod,(exceeded)?'1':'0',flags,stimestamp);
533 		if (flags&QUOTA_FLAG_SINODES) {
534 			printf("|si:%10"PRIu32,sinodes);
535 		} else {
536 			printf("|si:         -");
537 		}
538 		if (flags&QUOTA_FLAG_HINODES) {
539 			printf("|hi:%10"PRIu32,hinodes);
540 		} else {
541 			printf("|hi:         -");
542 		}
543 		if (flags&QUOTA_FLAG_SLENGTH) {
544 			printf("|sl:%20"PRIu64,slength);
545 		} else {
546 			printf("|sl:                   -");
547 		}
548 		if (flags&QUOTA_FLAG_HLENGTH) {
549 			printf("|hl:%20"PRIu64,hlength);
550 		} else {
551 			printf("|hl:                   -");
552 		}
553 		if (flags&QUOTA_FLAG_SSIZE) {
554 			printf("|ss:%20"PRIu64,ssize);
555 		} else {
556 			printf("|ss:                   -");
557 		}
558 		if (flags&QUOTA_FLAG_HSIZE) {
559 			printf("|hs:%20"PRIu64,hsize);
560 		} else {
561 			printf("|hs:                   -");
562 		}
563 		if (flags&QUOTA_FLAG_SREALSIZE) {
564 			printf("|sr:%20"PRIu64,srealsize);
565 		} else {
566 			printf("|sr:                   -");
567 		}
568 		if (flags&QUOTA_FLAG_HREALSIZE) {
569 			printf("|hr:%20"PRIu64,hrealsize);
570 		} else {
571 			printf("|hr:                   -");
572 		}
573 		printf("\n");
574 		t--;
575 	}
576 	return 0;
577 }
578 
xattr_load(FILE * fd,uint8_t mver)579 int xattr_load(FILE *fd,uint8_t mver) {
580 	uint8_t hdrbuff[4+1+4];
581 	const uint8_t *ptr;
582 	uint32_t inode;
583 	uint8_t anleng;
584 	uint32_t avleng;
585 
586 	if (mver>0x10) {
587 		fprintf(stderr,"loading xattr: unsupported format\n");
588 		return -1;
589 	}
590 
591 	while (1) {
592 		if (fread(hdrbuff,1,4+1+4,fd)!=4+1+4) {
593 			fprintf(stderr,"loading xattr: read error");
594 			return -1;
595 		}
596 		ptr = hdrbuff;
597 		inode = get32bit(&ptr);
598 		anleng = get8bit(&ptr);
599 		avleng = get32bit(&ptr);
600 		if (inode==0) {
601 			return 0;
602 		}
603 		if (anleng==0) {
604 			fprintf(stderr,"loading xattr: empty name");
605 			fseek(fd,anleng+avleng,SEEK_CUR);
606 			continue;
607 		}
608 		printf("XATTR|i:%10"PRIu32"|n:",inode);
609 		print_name(fd,anleng);
610 		printf("|v:");
611 		print_hex(fd,avleng);
612 		printf("\n");
613 	}
614 }
615 
posix_acl_load(FILE * fd,uint8_t mver)616 int posix_acl_load(FILE *fd,uint8_t mver) {
617 	uint8_t hdrbuff[4+1+2*6];
618 	uint8_t aclbuff[6*100];
619 	const uint8_t *ptr;
620 	uint32_t inode;
621 	uint8_t acltype;
622 	uint16_t userperm;
623 	uint16_t groupperm;
624 	uint16_t otherperm;
625 	uint16_t mask;
626 	uint16_t namedusers;
627 	uint16_t namedgroups;
628 	uint32_t aclid;
629 	uint16_t aclperm;
630 	uint32_t acls,acbcnt;
631 
632 	if (mver>0x11) {
633 		fprintf(stderr,"loading posix_acl: unsupported format\n");
634 		return -1;
635 	}
636 
637 	while (1) {
638 		if (fread(hdrbuff,1,4+1+2*6,fd)!=4+1+2*6) {
639 			fprintf(stderr,"loading posix_acl: read error");
640 			return -1;
641 		}
642 		ptr = hdrbuff;
643 		inode = get32bit(&ptr);
644 		if (inode==0) {
645 			return 0;
646 		}
647 		acltype = get8bit(&ptr);
648 		userperm = get16bit(&ptr);
649 		groupperm = get16bit(&ptr);
650 		otherperm = get16bit(&ptr);
651 		mask = get16bit(&ptr);
652 		namedusers = get16bit(&ptr);
653 		namedgroups = get16bit(&ptr);
654 		printf("POSIXACL|i:%10"PRIu32"|t:%"PRIu8"|u:0%05"PRIo16"|g:0%05"PRIo16"|o:0%05"PRIo16"|m:0%05"PRIo16"|n:(",inode,acltype,userperm,groupperm,otherperm,mask);
655 		acls = namedusers+namedgroups;
656 		acbcnt = 0;
657 		while (acls>0) {
658 			if (acbcnt==0) {
659 				if (acls>100) {
660 					acbcnt=100;
661 				} else {
662 					acbcnt=acls;
663 				}
664 				if (fread(aclbuff,6,acbcnt,fd)!=acbcnt) {
665 					fprintf(stderr,"loading posix_acl: read error");
666 					return -1;
667 				}
668 				ptr = aclbuff;
669 			}
670 			aclid = get32bit(&ptr);
671 			aclperm = get16bit(&ptr);
672 			acls--;
673 			acbcnt--;
674 			if (acls>=namedgroups) {
675 				printf("u(%"PRIu32"):0%05"PRIo16,aclid,aclperm);
676 			} else {
677 				printf("g(%"PRIu32"):0%05"PRIo16,aclid,aclperm);
678 			}
679 			if (acls>0) {
680 				printf(",");
681 			}
682 		}
683 		printf(")\n");
684 	}
685 }
686 
sessions_load(FILE * fd,uint8_t mver)687 int sessions_load(FILE *fd,uint8_t mver) {
688 	uint8_t hdr[8];
689 	uint8_t *fsesrecord;
690 	const uint8_t *ptr;
691 	uint16_t dver,statsinfile;
692 	uint32_t recsize;
693 	uint32_t i,nextsessionid,sessionid;
694 	uint32_t ileng,peerip,rootinode,mintrashtime,maxtrashtime,rootuid,rootgid,mapalluid,mapallgid,disconnected;
695 	uint32_t disables;
696 	uint16_t umaskval;
697 	uint64_t exportscsum;
698 	uint8_t sesflags,mingoal,maxgoal;
699 	char strip[16];
700 
701 	if (mver>0x15) {
702 		fprintf(stderr,"loading sessions: unsupported format\n");
703 		return -1;
704 	}
705 
706 	if (mver<=0x11) {
707 		if (fread(hdr,1,8,fd)!=8) {
708 			fprintf(stderr,"loading sessions: read error");
709 			return -1;
710 		}
711 
712 		ptr = hdr;
713 		dver = get16bit(&ptr);
714 		if (dver==1) {
715 			mver = 0x10;
716 		} else if (dver==2) {
717 			mver = 0x11;
718 		}
719 	} else {
720 		dver = 0; // makes old gcc happy
721 		if (fread(hdr,1,6,fd)!=6) {
722 			fprintf(stderr,"loading sessions: read error");
723 			return -1;
724 		}
725 		ptr = hdr;
726 	}
727 	nextsessionid = get32bit(&ptr);
728 	statsinfile = get16bit(&ptr);
729 
730 	if (mver<=0x11) {
731 		printf("# dver: %"PRIu16" ; nextsessionid: %"PRIu32" ; statscount: %"PRIu16"\n",dver,nextsessionid,statsinfile);
732 	} else {
733 		printf("# nextsessionid: %"PRIu32" ; statscount: %"PRIu16"\n",nextsessionid,statsinfile);
734 	}
735 	if (mver<0x11) {
736 		recsize = 43+statsinfile*8;
737 	} else if (mver<0x13) {
738 		recsize = 47+statsinfile*8;
739 	} else if (mver<0x14) {
740 		recsize = 55+statsinfile*8;
741 	} else if (mver<0x15) {
742 		recsize = 57+statsinfile*8;
743 	} else {
744 		recsize = 61+statsinfile*8;
745 	}
746 	fsesrecord = malloc(recsize);
747 	if (fsesrecord==NULL) {
748 		fprintf(stderr,"loading sessions: out of memory\n");
749 		return -1;
750 	}
751 
752 	while (1) {
753 		if (fread(fsesrecord,1,recsize,fd)!=(size_t)(recsize)) {
754 			free(fsesrecord);
755 			fprintf(stderr,"loading sessions: read error\n");
756 			return -1;
757 		}
758 		ptr = fsesrecord;
759 		sessionid = get32bit(&ptr);
760 		if (sessionid==0) {
761 			free(fsesrecord);
762 			return 0;
763 		}
764 		if (mver>=0x13) {
765 			exportscsum = get64bit(&ptr);
766 		} else {
767 			exportscsum = 0;
768 		}
769 		ileng = get32bit(&ptr);
770 		peerip = get32bit(&ptr);
771 		rootinode = get32bit(&ptr);
772 		sesflags = get8bit(&ptr);
773 		if (mver>=0x14) {
774 			umaskval = get16bit(&ptr);
775 		} else {
776 			umaskval = 0;
777 		}
778 		mingoal = get8bit(&ptr);
779 		maxgoal = get8bit(&ptr);
780 		mintrashtime = get32bit(&ptr);
781 		maxtrashtime = get32bit(&ptr);
782 		rootuid = get32bit(&ptr);
783 		rootgid = get32bit(&ptr);
784 		mapalluid = get32bit(&ptr);
785 		mapallgid = get32bit(&ptr);
786 		if (mver>=0x15) {
787 			disables = get32bit(&ptr);
788 		} else {
789 			disables = 0;
790 		}
791 		makestrip(strip,peerip);
792 		if (mver>=0x11) {
793 			disconnected = get32bit(&ptr);
794 		} else {
795 			disconnected = 0;
796 		}
797 		if (mver>=0x15) {
798 			printf("SESSION|s:%10"PRIu32"|e:#%"PRIu64"|p:%s|r:%10"PRIu32"|f:0x%02"PRIX8"|u:0%03"PRIo16"|g:%"PRIu8"-%"PRIu8"|t:%10"PRIu32"-%10"PRIu32"|m:%10"PRIu32",%10"PRIu32",%10"PRIu32",%10"PRIu32"|x:0x%08"PRIX32"|d:%10"PRIu32"|c:",sessionid,exportscsum,strip,rootinode,sesflags,umaskval,mingoal,maxgoal,mintrashtime,maxtrashtime,rootuid,rootgid,mapalluid,mapallgid,disables,disconnected);
799 		} else if (mver>=0x14) {
800 			printf("SESSION|s:%10"PRIu32"|e:#%"PRIu64"|p:%s|r:%10"PRIu32"|f:0x%02"PRIX8"|u:0%03"PRIo16"|g:%"PRIu8"-%"PRIu8"|t:%10"PRIu32"-%10"PRIu32"|m:%10"PRIu32",%10"PRIu32",%10"PRIu32",%10"PRIu32"|d:%10"PRIu32"|c:",sessionid,exportscsum,strip,rootinode,sesflags,umaskval,mingoal,maxgoal,mintrashtime,maxtrashtime,rootuid,rootgid,mapalluid,mapallgid,disconnected);
801 		} else if (mver>=0x13) {
802 			printf("SESSION|s:%10"PRIu32"|e:#%"PRIu64"|p:%s|r:%10"PRIu32"|f:%02"PRIX8"|g:%"PRIu8"-%"PRIu8"|t:%10"PRIu32"-%10"PRIu32"|m:%10"PRIu32",%10"PRIu32",%10"PRIu32",%10"PRIu32"|d:%10"PRIu32"|c:",sessionid,exportscsum,strip,rootinode,sesflags,mingoal,maxgoal,mintrashtime,maxtrashtime,rootuid,rootgid,mapalluid,mapallgid,disconnected);
803 		} else if (mver>=0x11) {
804 			printf("SESSION|s:%10"PRIu32"|p:%s|r:%10"PRIu32"|f:%02"PRIX8"|g:%"PRIu8"-%"PRIu8"|t:%10"PRIu32"-%10"PRIu32"|m:%10"PRIu32",%10"PRIu32",%10"PRIu32",%10"PRIu32"|d:%10"PRIu32"|c:",sessionid,strip,rootinode,sesflags,mingoal,maxgoal,mintrashtime,maxtrashtime,rootuid,rootgid,mapalluid,mapallgid,disconnected);
805 		} else {
806 			printf("SESSION|s:%10"PRIu32"|p:%s|r:%10"PRIu32"|f:%02"PRIX8"|g:%"PRIu8"-%"PRIu8"|t:%10"PRIu32"-%10"PRIu32"|m:%10"PRIu32",%10"PRIu32",%10"PRIu32",%10"PRIu32"|c:",sessionid,strip,rootinode,sesflags,mingoal,maxgoal,mintrashtime,maxtrashtime,rootuid,rootgid,mapalluid,mapallgid);
807 		}
808 		if (statsinfile==0) {
809 			printf("[]|l:[]|i:");
810 		} else {
811 			for (i=0 ; i<statsinfile ; i++) {
812 				printf("%c%"PRIu32,(i==0)?'[':',',get32bit(&ptr));
813 			}
814 			printf("]|l:");
815 			for (i=0 ; i<statsinfile ; i++) {
816 				printf("%c%"PRIu32,(i==0)?'[':',',get32bit(&ptr));
817 			}
818 			printf("]|i:");
819 		}
820 		print_name(fd,ileng);
821 		printf("\n");
822 	}
823 }
824 
csdb_load(FILE * fd,uint8_t mver)825 int csdb_load(FILE *fd,uint8_t mver) {
826 	uint8_t csdbbuff[13];
827 	const uint8_t *ptr;
828 	uint32_t t;
829 	uint32_t ip;
830 	uint16_t port;
831 	uint16_t csid;
832 	uint8_t maintenance;
833 	uint32_t maintenance_to;
834 	size_t bsize;
835 	char strip[16];
836 
837 	if (mver>0x13) {
838 		fprintf(stderr,"loading chunk servers: unsupported format\n");
839 		return -1;
840 	}
841 	if (mver<=0x10) {
842 		bsize = 6;
843 	} else if (mver<=0x11) {
844 		bsize = 8;
845 	} else if (mver<=0x12) {
846 		bsize = 9;
847 	} else {
848 		bsize = 13;
849 	}
850 
851 	if (fread(csdbbuff,1,4,fd)!=4) {
852 		return -1;
853 	}
854 	ptr = csdbbuff;
855 	t = get32bit(&ptr);
856 	printf("# chunk servers: %"PRIu32"\n",t);
857 	while (t>0) {
858 		if (fread(csdbbuff,1,bsize,fd)!=bsize) {
859 			fprintf(stderr,"loading chunk servers: read error\n");
860 			return -1;
861 		}
862 		ptr = csdbbuff;
863 		if (mver<=0x10) {
864 			ip = get32bit(&ptr);
865 			port = get16bit(&ptr);
866 			makestrip(strip,ip);
867 			printf("CHUNKSERVER|i:%s|p:%5"PRIu16"\n",strip,port);
868 		} else if (mver<=0x11) {
869 			ip = get32bit(&ptr);
870 			port = get16bit(&ptr);
871 			csid = get16bit(&ptr);
872 			makestrip(strip,ip);
873 			printf("CHUNKSERVER|i:%s|p:%5"PRIu16"|#:%5"PRIu16"\n",strip,port,csid);
874 		} else if (mver<=0x12) {
875 			ip = get32bit(&ptr);
876 			port = get16bit(&ptr);
877 			csid = get16bit(&ptr);
878 			maintenance = get8bit(&ptr);
879 			makestrip(strip,ip);
880 			printf("CHUNKSERVER|i:%s|p:%5"PRIu16"|#:%5"PRIu16"|m:%u\n",strip,port,csid,(maintenance)?1:0);
881 		} else {
882 			ip = get32bit(&ptr);
883 			port = get16bit(&ptr);
884 			csid = get16bit(&ptr);
885 			maintenance = get8bit(&ptr);
886 			maintenance_to = get32bit(&ptr);
887 			makestrip(strip,ip);
888 			printf("CHUNKSERVER|i:%s|p:%5"PRIu16"|#:%5"PRIu16"|m:%4s|t:%10"PRIu32"\n",strip,port,csid,(maintenance==0)?"off":(maintenance==1)?"on":(maintenance==2)?"temp":"???",maintenance_to);
889 		}
890 		t--;
891 	}
892 	return 0;
893 }
894 
of_load(FILE * fd,uint8_t mver)895 int of_load(FILE *fd,uint8_t mver) {
896 	uint8_t loadbuff[8];
897 	const uint8_t *ptr;
898 	uint32_t sessionid,inode;
899 
900 	if (mver>0x10) {
901 		fprintf(stderr,"loading open files: unsupported format\n");
902 		return -1;
903 	}
904 
905 	for (;;) {
906 		if (fread(loadbuff,1,8,fd)!=8) {
907 			fprintf(stderr,"loading open files: read error\n");
908 			return -1;
909 		}
910 		ptr = loadbuff;
911 		sessionid = get32bit(&ptr);
912 		inode = get32bit(&ptr);
913 		if (sessionid>0 && inode>0) {
914 			printf("OPENFILE|s:%10"PRIu32"|i:%10"PRIu32"\n",sessionid,inode);
915 		} else {
916 			return 0;
917 		}
918 	}
919 	return 0; // unreachable
920 }
921 
flock_load(FILE * fd,uint8_t mver)922 int flock_load(FILE *fd,uint8_t mver) {
923 	uint8_t loadbuff[17];
924 	const uint8_t *ptr;
925 	uint32_t sessionid,inode;
926 	uint64_t owner;
927 	uint8_t ltype;
928 
929 	if (mver>0x10) {
930 		fprintf(stderr,"loading flock locks: unsupported format\n");
931 		return -1;
932 	}
933 
934 	for (;;) {
935 		if (fread(loadbuff,1,17,fd)!=17) {
936 			fprintf(stderr,"loading flock locks: read error\n");
937 			return -1;
938 		}
939 		ptr = loadbuff;
940 		inode = get32bit(&ptr);
941 		sessionid = get32bit(&ptr);
942 		owner = get64bit(&ptr);
943 		ltype = get8bit(&ptr);
944 		if (inode==0 && owner==0 && sessionid==0) {
945 			return 0;
946 		}
947 		printf("FLOCK|i:%10"PRIu32"|s:%10"PRIu32"|o:%016"PRIX64"|t:%c\n",inode,sessionid,owner,ltype?'W':'R');
948 	}
949 	return 0;	// unreachable
950 }
951 
posix_lock_load(FILE * fd,uint8_t mver)952 int posix_lock_load(FILE *fd,uint8_t mver) {
953 	uint8_t loadbuff[37];
954 	const uint8_t *ptr;
955 	uint32_t sessionid,inode,pid;
956 	uint64_t owner,start,end;
957 	uint8_t type;
958 
959 	if (mver>0x10) {
960 		fprintf(stderr,"loading posix locks: unsupported format\n");
961 		return -1;
962 	}
963 
964 	for (;;) {
965 		if (fread(loadbuff,1,37,fd)!=37) {
966 			fprintf(stderr,"loading posix locks: read error\n");
967 			return -1;
968 		}
969 		ptr = loadbuff;
970 		inode = get32bit(&ptr);
971 		owner = get64bit(&ptr);
972 		sessionid = get32bit(&ptr);
973 		pid = get32bit(&ptr);
974 		start = get64bit(&ptr);
975 		end = get64bit(&ptr);
976 		type = get8bit(&ptr);
977 		if (inode==0 && owner==0 && sessionid==0) {
978 			return 0;
979 		}
980 		printf("POSIXLOCK|i:%10"PRIu32"|s:%10"PRIu32"|o:0x%016"PRIX64"|p:%10"PRIu32"|r:<%20"PRIu64",%20"PRIu64")|t:%c\n",inode,sessionid,owner,pid,start,end,(type==POSIX_LOCK_RDLCK)?'R':(type==POSIX_LOCK_WRLCK)?'W':'?');
981 	}
982 	return 0;	// unreachable
983 }
984 
print_labels(const uint8_t ** rptr,uint8_t cnt,uint8_t orgroup)985 static void print_labels(const uint8_t **rptr,uint8_t cnt,uint8_t orgroup) {
986 	uint8_t i,j,k;
987 	uint8_t p;
988 	uint32_t mask;
989 	for (i=0 ; i<cnt ; i++) {
990 		if (i>0) {
991 			printf(":");
992 		}
993 		p = 1;
994 		for (j=0 ; j<orgroup ; j++) {
995 			mask = get32bit(rptr);
996 			if (j==0 && mask==0) {
997 				printf("*");
998 			}
999 			if (mask==0) {
1000 				p = 0;
1001 			}
1002 			if (p) {
1003 				if (j>0) {
1004 					printf("+");
1005 				}
1006 				for (k=0 ; k<26 ; k++) {
1007 					if (mask & (1<<k)) {
1008 						printf("%c",'A'+k);
1009 					}
1010 				}
1011 			}
1012 		}
1013 	}
1014 }
1015 
labelset_load(FILE * fd,uint8_t mver)1016 int labelset_load(FILE *fd,uint8_t mver) {
1017 	uint8_t *databuff = NULL;
1018 	const uint8_t *ptr;
1019 	uint32_t chunkcount;
1020 	uint16_t sclassid;
1021 	uint16_t arch_delay;
1022 	uint8_t mode;
1023 	uint8_t admin_only;
1024 	uint8_t nleng;
1025 	uint8_t name[MAXSCLASSNLENG];
1026 	uint8_t create_labelscnt;
1027 	uint8_t keep_labelscnt;
1028 	uint8_t arch_labelscnt;
1029 	uint8_t descrleng;
1030 	uint8_t i;
1031 	uint8_t orgroup;
1032 	uint8_t hdrleng;
1033 
1034 	if (mver>0x16) {
1035 		fprintf(stderr,"loading labelset: unsupported format\n");
1036 		return -1;
1037 	}
1038 
1039 	if (mver<0x15) {
1040 		for (i=0 ; i<26 ; i++) {
1041 			if (fread(&descrleng,1,1,fd)!=1) {
1042 				fprintf(stderr,"loading labelset: read error\n");
1043 				return -1;
1044 			}
1045 			if (descrleng>128) {
1046 				fprintf(stderr,"loading labelset: description too long\n");
1047 				return -1;
1048 			}
1049 			printf("LABELDESC|l:%c|n:",i+'A');
1050 			print_name(fd,descrleng);
1051 			printf("\n");
1052 		}
1053 	}
1054 
1055 	if (mver==0x10) {
1056 		orgroup = 1;
1057 	} else {
1058 		if (fread(&orgroup,1,1,fd)!=1) {
1059 			fprintf(stderr,"loading labelset: read error\n");
1060 			return -1;
1061 		}
1062 	}
1063 	if (orgroup<1) {
1064 		fprintf(stderr,"loading labelset: zero or-groups !!!\n");
1065 		return -1;
1066 	}
1067 	databuff = malloc(3U*9U*4U*(uint32_t)orgroup);
1068 	hdrleng = (mver==0x12)?11:(mver<=0x13)?3:(mver<=0x14)?5:(mver<=0x15)?8:10;
1069 
1070 	while (1) {
1071 		if (fread(databuff,1,hdrleng,fd)!=hdrleng) {
1072 			fprintf(stderr,"loading labelset: read error\n");
1073 			return -1;
1074 		}
1075 		ptr = databuff;
1076 		sclassid = get16bit(&ptr);
1077 		if (mver>0x15) {
1078 			nleng = get8bit(&ptr);
1079 			admin_only = get8bit(&ptr);
1080 			mode = get8bit(&ptr);
1081 			arch_delay = get16bit(&ptr);
1082 			create_labelscnt = get8bit(&ptr);
1083 			keep_labelscnt = get8bit(&ptr);
1084 			arch_labelscnt = get8bit(&ptr);
1085 			chunkcount = 0;
1086 		} else if (mver>0x14) {
1087 			nleng = 0;
1088 			admin_only = 0;
1089 			mode = get8bit(&ptr);
1090 			arch_delay = get16bit(&ptr);
1091 			create_labelscnt = get8bit(&ptr);
1092 			keep_labelscnt = get8bit(&ptr);
1093 			arch_labelscnt = get8bit(&ptr);
1094 			chunkcount = 0;
1095 		} else if (mver>0x13) {
1096 			nleng = 0;
1097 			admin_only = 0;
1098 			mode = get8bit(&ptr);
1099 			create_labelscnt = get8bit(&ptr);
1100 			keep_labelscnt = get8bit(&ptr);
1101 			arch_labelscnt = keep_labelscnt;
1102 			arch_delay = 0;
1103 			chunkcount = 0;
1104 		} else {
1105 			nleng = 0;
1106 			admin_only = 0;
1107 			create_labelscnt = get8bit(&ptr);
1108 			keep_labelscnt = create_labelscnt;
1109 			arch_labelscnt = create_labelscnt;
1110 			mode = SCLASS_MODE_STD;
1111 			arch_delay = 0;
1112 			if (mver==0x12) {
1113 				chunkcount = get32bit(&ptr);
1114 				ptr+=4;
1115 			} else {
1116 				chunkcount = 0;
1117 			}
1118 		}
1119 		if (nleng>0) {
1120 			if (fread(name,1,nleng,fd)!=nleng) {
1121 				fprintf(stderr,"loading labelset: read error\n");
1122 				return -1;
1123 			}
1124 		}
1125 		name[nleng] = 0;
1126 		if (sclassid==0 && create_labelscnt==0 && keep_labelscnt==0 && arch_labelscnt==0 && chunkcount==0 && arch_delay==0) {
1127 			break;
1128 		}
1129 		if (create_labelscnt==0 || create_labelscnt>9 || keep_labelscnt==0 || keep_labelscnt>9 || arch_labelscnt==0 || arch_labelscnt>9) {
1130 			fprintf(stderr,"loading labelset: data format error (sclassid: %"PRIu16" ; mode: %"PRIu8" ; create_labelscnt: %"PRIu8" ; keep_labelscnt: %"PRIu8" ; arch_labelscnt: %"PRIu8" ; arch_delay: %"PRIu16")\n",sclassid,mode,create_labelscnt,keep_labelscnt,arch_labelscnt,arch_delay);
1131 			free(databuff);
1132 			databuff=NULL;
1133 			return -1;
1134 		}
1135 		if (mver>0x14) {
1136 			if (fread(databuff,1,(create_labelscnt+keep_labelscnt+arch_labelscnt)*4*orgroup,fd)!=(size_t)((create_labelscnt+keep_labelscnt+arch_labelscnt)*4*orgroup)) {
1137 				fprintf(stderr,"loading labelset: read error\n");
1138 				free(databuff);
1139 				databuff=NULL;
1140 				return -1;
1141 			}
1142 		} else if (mver>0x13) {
1143 			if (fread(databuff,1,(create_labelscnt+keep_labelscnt)*4*orgroup,fd)!=(size_t)((create_labelscnt+keep_labelscnt)*4*orgroup)) {
1144 				fprintf(stderr,"loading labelset: read error\n");
1145 				free(databuff);
1146 				databuff=NULL;
1147 				return -1;
1148 			}
1149 		} else {
1150 			if (fread(databuff,1,create_labelscnt*4*orgroup,fd)!=(size_t)(create_labelscnt*4*orgroup)) {
1151 				fprintf(stderr,"loading labelset: read error\n");
1152 				free(databuff);
1153 				databuff=NULL;
1154 				return -1;
1155 			}
1156 		}
1157 		if (chunkcount>0) {
1158 			fseek(fd,chunkcount*8,SEEK_CUR);
1159 		}
1160 		ptr = databuff;
1161 		printf("SCLASS|#:%5"PRIu16"|x:%u|m:%u|d:%5"PRIu16,sclassid,admin_only,mode,arch_delay);
1162 		if (mver<=0x13) {
1163 			printf("|c+k+a: ");
1164 		} else {
1165 			printf("|c: ");
1166 		}
1167 		print_labels(&ptr,create_labelscnt,orgroup);
1168 		if (mver>0x13) {
1169 			if (mver<=0x14) {
1170 				printf(" |k+a: ");
1171 			} else {
1172 				printf(" |k: ");
1173 			}
1174 			print_labels(&ptr,keep_labelscnt,orgroup);
1175 			if (mver>0x14) {
1176 				printf(" |a: ");
1177 				print_labels(&ptr,arch_labelscnt,orgroup);
1178 			}
1179 		}
1180 		if (nleng>0) {
1181 			printf(" |n:%s",name);
1182 		}
1183 		printf("\n");
1184 	}
1185 	free(databuff);
1186 	databuff=NULL;
1187 	return 0;
1188 }
1189 
hexdump(FILE * fd,uint64_t sleng)1190 int hexdump(FILE *fd,uint64_t sleng) {
1191 	uint8_t lbuff[32];
1192 	uint32_t i;
1193 	while (sleng>32) {
1194 		if (fread(lbuff,1,32,fd)!=32) {
1195 			return -1;
1196 		}
1197 		for (i=0 ; i<32 ; i++) {
1198 			printf("%02"PRIX8" ",lbuff[i]);
1199 		}
1200 		printf(" |");
1201 		for (i=0 ; i<32 ; i++) {
1202 			printf("%c",dispchar(lbuff[i]));
1203 		}
1204 		printf("|\n");
1205 		sleng-=32;
1206 	}
1207 	if (sleng>0) {
1208 		if (fread(lbuff,1,sleng,fd)!=(size_t)sleng) {
1209 			return -1;
1210 		}
1211 		for (i=0 ; i<32 ; i++) {
1212 			if (i<sleng) {
1213 				printf("%02"PRIX8" ",lbuff[i]);
1214 			} else {
1215 				printf("   ");
1216 			}
1217 		}
1218 		printf(" |");
1219 		for (i=0 ; i<32 ; i++) {
1220 			if (i<sleng) {
1221 				printf("%c",dispchar(lbuff[i]));
1222 			} else {
1223 				printf(" ");
1224 			}
1225 		}
1226 		printf("|\n");
1227 	}
1228 	return 0;
1229 }
1230 
fs_load_pre17(FILE * fd)1231 int fs_load_pre17(FILE *fd) {
1232 	uint32_t maxnodeid,nextsessionid;
1233 	uint64_t version;
1234 	uint8_t hdr[16];
1235 	const uint8_t *ptr;
1236 	if (fread(hdr,1,16,fd)!=16) {
1237 		return -1;
1238 	}
1239 	ptr = hdr;
1240 	maxnodeid = get32bit(&ptr);
1241 	version = get64bit(&ptr);
1242 	nextsessionid = get32bit(&ptr);
1243 
1244 	printf("# maxnodeid: %"PRIu32" ; version: %"PRIu64" ; nextsessionid: %"PRIu32"\n",maxnodeid,version,nextsessionid);
1245 
1246 	printf("# -------------------------------------------------------------------\n");
1247 	if (fs_loadnodes(fd,0x15,0x10)<0) {
1248 		printf("error reading metadata (node)\n");
1249 		return -1;
1250 	}
1251 	printf("# -------------------------------------------------------------------\n");
1252 	if (fs_loadedges(fd,0x10)<0) {
1253 		printf("error reading metadata (edge)\n");
1254 		return -1;
1255 	}
1256 	printf("# -------------------------------------------------------------------\n");
1257 	if (fs_loadfree(fd,0x10)<0) {
1258 		printf("error reading metadata (free)\n");
1259 		return -1;
1260 	}
1261 	printf("# -------------------------------------------------------------------\n");
1262 	return 0;
1263 }
1264 
fs_load(FILE * fd,uint8_t fver,const char section[4])1265 int fs_load(FILE *fd,uint8_t fver,const char section[4]) {
1266 	uint32_t maxnodeid,nextsessionid;
1267 	uint64_t sleng;
1268 	off_t offbegin;
1269 	uint64_t version,fileid;
1270 	uint8_t hdr[16];
1271 	const uint8_t *ptr;
1272 	uint8_t mver;
1273 	if (fread(hdr,1,16,fd)!=16) {
1274 		return -1;
1275 	}
1276 	ptr = hdr;
1277 
1278 	if (fver<0x20) {
1279 		maxnodeid = get32bit(&ptr);
1280 		version = get64bit(&ptr);
1281 		nextsessionid = get32bit(&ptr);
1282 
1283 		if (section[0]==0 || memcmp(section,"HEAD",4)==0) {
1284 			printf("# maxnodeid: %"PRIu32" ; version: %"PRIu64" ; nextsessionid: %"PRIu32"\n",maxnodeid,version,nextsessionid);
1285 		}
1286 	} else {
1287 		version = get64bit(&ptr);
1288 		fileid = get64bit(&ptr);
1289 
1290 		if (section[0]==0 || memcmp(section,"HEAD",4)==0) {
1291 			printf("# version: %"PRIu64" ; fileid: 0x%"PRIX64"\n",version,fileid);
1292 		}
1293 	}
1294 
1295 	while (1) {
1296 		if (fread(hdr,1,16,fd)!=16) {
1297 			printf("can't read section header\n");
1298 			return -1;
1299 		}
1300 		if (memcmp(hdr,"[MFS EOF MARKER]",16)==0) {
1301 			if (section[0]==0) {
1302 				printf("# -------------------------------------------------------------------\n");
1303 				printf("# MFS END OF FILE MARKER\n");
1304 				printf("# -------------------------------------------------------------------\n");
1305 			}
1306 			return 0;
1307 		}
1308 		ptr = hdr+8;
1309 		sleng = get64bit(&ptr);
1310 		offbegin = ftello(fd);
1311 		if (section[0]==0 || memcmp(hdr,section,4)==0) {
1312 			printf("# -------------------------------------------------------------------\n");
1313 			printf("# section header: %c%c%c%c%c%c%c%c (%02X%02X%02X%02X%02X%02X%02X%02X) ; length: %"PRIu64"\n",dispchar(hdr[0]),dispchar(hdr[1]),dispchar(hdr[2]),dispchar(hdr[3]),dispchar(hdr[4]),dispchar(hdr[5]),dispchar(hdr[6]),dispchar(hdr[7]),hdr[0],hdr[1],hdr[2],hdr[3],hdr[4],hdr[5],hdr[6],hdr[7],sleng);
1314 			mver = (((hdr[5]-'0')&0xF)<<4)+(hdr[7]&0xF);
1315 			printf("# section type: %c%c%c%c ; version: 0x%02"PRIX8"\n",dispchar(hdr[0]),dispchar(hdr[1]),dispchar(hdr[2]),dispchar(hdr[3]),mver);
1316 			if (memcmp(hdr,"SESS",4)==0) {
1317 				if (sessions_load(fd,mver)<0) {
1318 					printf("error reading metadata (SESS)\n");
1319 					return -1;
1320 				}
1321 			} else if (memcmp(hdr,"LABS",4)==0) {
1322 				if (labelset_load(fd,mver)<0) {
1323 					printf("error reading metadata (LABS)\n");
1324 					return -1;
1325 				}
1326 			} else if (memcmp(hdr,"SCLA",4)==0) {
1327 				if (labelset_load(fd,mver)<0) {
1328 					printf("error reading metadata (SCLA)\n");
1329 					return -1;
1330 				}
1331 			} else if (memcmp(hdr,"NODE",4)==0) {
1332 				if (fs_loadnodes(fd,fver,mver)<0) {
1333 					printf("error reading metadata (NODE)\n");
1334 					return -1;
1335 				}
1336 			} else if (memcmp(hdr,"EDGE",4)==0) {
1337 				if (fs_loadedges(fd,mver)<0) {
1338 					printf("error reading metadata (EDGE)\n");
1339 					return -1;
1340 				}
1341 			} else if (memcmp(hdr,"FREE",4)==0) {
1342 				if (fs_loadfree(fd,mver)<0) {
1343 					printf("error reading metadata (FREE)\n");
1344 					return -1;
1345 				}
1346 			} else if (memcmp(hdr,"QUOT",4)==0) {
1347 				if (fs_loadquota(fd,mver)<0) {
1348 					printf("error reading metadata (QUOT)\n");
1349 					return -1;
1350 				}
1351 			} else if (memcmp(hdr,"XATR",4)==0) {
1352 				if (xattr_load(fd,mver)<0) {
1353 					printf("error reading metadata (XATR)\n");
1354 					return -1;
1355 				}
1356 			} else if (memcmp(hdr,"PACL",4)==0) {
1357 				if (posix_acl_load(fd,mver)<0) {
1358 					printf("error reading metadata (PACL)\n");
1359 					return -1;
1360 				}
1361 			} else if (memcmp(hdr,"FLCK",4)==0) {
1362 				if (flock_load(fd,mver)<0) {
1363 					printf("error reading metadata (FLCK)\n");
1364 					return -1;
1365 				}
1366 			} else if (memcmp(hdr,"PLCK",4)==0) {
1367 				if (posix_lock_load(fd,mver)<0) {
1368 					printf("error reading metadata (PLCK)\n");
1369 					return -1;
1370 				}
1371 			} else if (memcmp(hdr,"OPEN",4)==0) {
1372 				if (of_load(fd,mver)<0) {
1373 					printf("error reading metadata (OPEN)\n");
1374 					return -1;
1375 				}
1376 			} else if (memcmp(hdr,"CSDB",4)==0) {
1377 				if (csdb_load(fd,mver)<0) {
1378 					printf("error reading metadata (CSDB)\n");
1379 					return -1;
1380 				}
1381 			} else if (memcmp(hdr,"CHNK",4)==0) {
1382 				if (chunk_load(fd,mver)<0) {
1383 					printf("error reading metadata (CHNK)\n");
1384 					return -1;
1385 				}
1386 			} else {
1387 				printf("unknown file part\n");
1388 				if (hexdump(fd,sleng)<0) {
1389 					return -1;
1390 				}
1391 			}
1392 			if ((off_t)(offbegin+sleng)!=ftello(fd)) {
1393 				fprintf(stderr,"some data in this section have not been read - file corrupted\n");
1394 				return -1;
1395 			}
1396 		} else {
1397 			fseeko(fd,sleng,SEEK_CUR);
1398 		}
1399 	}
1400 	return 0;
1401 }
1402 
fs_loadall(const char * fname,const char section[4])1403 int fs_loadall(const char *fname,const char section[4]) {
1404 	FILE *fd;
1405 	uint8_t hdr[8];
1406 	uint8_t fver;
1407 
1408 	fd = fopen(fname,"r");
1409 
1410 	if (fd==NULL) {
1411 		printf("can't open metadata file\n");
1412 		return -1;
1413 	}
1414 	if (fread(hdr,1,8,fd)!=8) {
1415 		printf("can't read metadata header\n");
1416 		fclose(fd);
1417 		return -1;
1418 	}
1419 	if (memcmp(section,"HEAD",4)==0 || section[0]==0) {
1420 		printf("# header: %c%c%c%c%c%c%c%c (%02X%02X%02X%02X%02X%02X%02X%02X)\n",dispchar(hdr[0]),dispchar(hdr[1]),dispchar(hdr[2]),dispchar(hdr[3]),dispchar(hdr[4]),dispchar(hdr[5]),dispchar(hdr[6]),dispchar(hdr[7]),hdr[0],hdr[1],hdr[2],hdr[3],hdr[4],hdr[5],hdr[6],hdr[7]);
1421 	}
1422 	if (memcmp(hdr,"MFSM NEW",8)==0) {
1423 		printf("empty file\n");
1424 	} else if (memcmp(hdr,MFSSIGNATURE "M ",5)==0 && hdr[5]>='1' && hdr[5]<='9' && hdr[6]=='.' && hdr[7]>='0' && hdr[7]<='9') {
1425 		fver = ((hdr[5]-'0')<<4)+(hdr[7]-'0');
1426 		if (fver<0x17) {
1427 			if (section[0]!=0) {
1428 				printf("old format detected - can't dump sections separatelly");
1429 				fclose(fd);
1430 				return -1;
1431 			}
1432 			if (fs_load_pre17(fd)<0) {
1433 				printf("error reading metadata (structure)\n");
1434 				fclose(fd);
1435 				return -1;
1436 			}
1437 			if (chunk_load(fd,0x10)<0) {
1438 				printf("error reading metadata (chunks)\n");
1439 				fclose(fd);
1440 				return -1;
1441 			}
1442 		} else {
1443 			if (fs_load(fd,fver,section)<0) {
1444 				fclose(fd);
1445 				return -1;
1446 			}
1447 		}
1448 	} else {
1449 		printf("wrong metadata header (old version ?)\n");
1450 		fclose(fd);
1451 		return -1;
1452 	}
1453 	if (ferror(fd)!=0) {
1454 		printf("error reading metadata\n");
1455 		fclose(fd);
1456 		return -1;
1457 	}
1458 	fclose(fd);
1459 	return 0;
1460 }
1461 
usage(const char * appname)1462 void usage(const char *appname) {
1463 //	printf("usage: %s [-f J|C[separator]] [-o outputfile] [-a sum_name] metadata.mfs PATH ...\n",appname);
1464 	printf("usage: %s [-d] [-s section to dump] metadata.mfs\n",appname);
1465 	printf("options:\n");
1466 	printf("\td: print dot instead of non printable characters\n");
1467 	printf("\ts: dump only given section\n");
1468 	printf("section names:\n");
1469 	printf("\tHEAD - header info\n");
1470 	printf("\tSESS - client sessions\n");
1471 	printf("\tLABS - labels (not used)\n");
1472 	printf("\tSCLA - storage classes\n");
1473 	printf("\tNODE - tree nodes (i-nodes)\n");
1474 	printf("\tEDGE - tree edges (file names)\n");
1475 	printf("\tFREE - free nodes (deleted i-nodes)\n");
1476 	printf("\tQUOT - quota definitions\n");
1477 	printf("\tXATR - xattr data\n");
1478 	printf("\tPACL - posix acl data\n");
1479 	printf("\tOPEN - open files\n");
1480 	printf("\tFLCK - flock data\n");
1481 	printf("\tPLCK - posix locks (lockf,ioctl) data\n");
1482 	printf("\tCSDB - active chunkservers\n");
1483 	printf("\tCHNK - chunks\n");
1484 	exit(1);
1485 }
1486 
main(int argc,char * argv[])1487 int main(int argc,char *argv[]) {
1488 	int ch;
1489 	char *appname;
1490 	char section[4];
1491 
1492 	appname = argv[0];
1493 	memset(section,0,4);
1494 
1495 	while ((ch=getopt(argc,argv,"s:d"))>=0) {
1496 		switch(ch) {
1497 			case 's':
1498 				if (strlen(optarg)!=4) {
1499 					printf("wrong section name\n");
1500 					usage(appname);
1501 				}
1502 				memcpy(section,optarg,4);
1503 				break;
1504 			case 'd':
1505 				hide_nonprintable = 1;
1506 				break;
1507 			default:
1508 				usage(appname);
1509 				return 1;
1510 		}
1511 	}
1512 	argc -= optind;
1513 	argv += optind;
1514 
1515 	if (argc<1) {
1516 		usage(appname);
1517 		return 1;
1518 	}
1519 
1520 //	if (argc!=2) {
1521 //		printf("usage: %s metadata_file\n",argv[0]);
1522 //		return 1;
1523 //	}
1524 	return (fs_loadall(argv[0],section)<0)?1:0;
1525 }
1526