1 /*
2  * Copyright (C) 2016 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 <sys/types.h>
29 #include <inttypes.h>
30 
31 #include "MFSCommunication.h"
32 #include "datapack.h"
33 
34 #define STR_AUX(x) #x
35 #define STR(x) STR_AUX(x)
36 const char id[]="@(#) version: " VERSSTR ", written by Jakub Kruszona-Zawadzki";
37 
38 #define MAX_INDEX 0x7FFFFFFF
39 #define MAX_CHUNKS_PER_FILE (MAX_INDEX+1)
40 
dispchar(uint8_t c)41 static inline char dispchar(uint8_t c) {
42 	return (c>=32 && c<=126)?c:'.';
43 }
44 
makestrip(char strip[16],uint32_t ip)45 static inline void makestrip(char strip[16],uint32_t ip) {
46 	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);
47 	strip[15]=0;
48 }
49 
print_name(FILE * in,uint32_t nleng)50 void print_name(FILE *in,uint32_t nleng) {
51 	uint8_t buff[1024];
52 	uint32_t x,y,i;
53 	size_t happy;
54 	while (nleng>0) {
55 		y = (nleng>1024)?1024:nleng;
56 		x = fread(buff,1,y,in);
57 		for (i=0 ; i<x ; i++) {
58 			if (buff[i]<32 || buff[i]>127) {
59 				buff[i]='.';
60 			}
61 		}
62 		happy = fwrite(buff,1,x,stdout);
63 		(void)happy;
64 		if (x!=y) {
65 			return;
66 		}
67 		nleng -= x;
68 	}
69 }
70 
print_hex(FILE * in,uint32_t vleng)71 void print_hex(FILE *in,uint32_t vleng) {
72 	uint8_t buff[1024];
73 	uint32_t x,y,i;
74 	while (vleng>0) {
75 		y = (vleng>1024)?1024:vleng;
76 		x = fread(buff,1,y,in);
77 		for (i=0 ; i<x ; i++) {
78 			printf("%02"PRIX8,buff[i]);
79 		}
80 		if (x!=y) {
81 			return;
82 		}
83 		vleng -= x;
84 	}
85 }
86 
chunk_load(FILE * fd,uint8_t mver)87 int chunk_load(FILE *fd,uint8_t mver) {
88 	uint8_t hdr[8];
89 	uint8_t loadbuff[16];
90 	const uint8_t *ptr;
91 	int32_t r;
92 	uint64_t chunkid,nextchunkid;
93 	uint32_t version,lockedto;
94 
95 	(void)mver;
96 
97 	if (fread(hdr,1,8,fd)!=8) {
98 		return -1;
99 	}
100 	ptr = hdr;
101 	nextchunkid = get64bit(&ptr);
102 	printf("# nextchunkid: %016"PRIX64"\n",nextchunkid);
103 	for (;;) {
104 		r = fread(loadbuff,1,16,fd);
105 		(void)r;
106 		ptr = loadbuff;
107 		chunkid = get64bit(&ptr);
108 		version = get32bit(&ptr);
109 		lockedto = get32bit(&ptr);
110 		if (chunkid==0 && version==0 && lockedto==0) {
111 			return 0;
112 		}
113 		printf("*|i:%016"PRIX64"|v:%08"PRIX32"|t:%10"PRIu32"\n",chunkid,version,lockedto);
114 	}
115 }
116 
fs_loadedge(FILE * fd,uint8_t mver)117 int fs_loadedge(FILE *fd,uint8_t mver) {
118 	uint8_t uedgebuff[4+4+8+2];
119 	const uint8_t *ptr;
120 	uint32_t parent_id;
121 	uint32_t child_id;
122 	uint64_t edge_id;
123 	uint16_t nleng;
124 
125 	ptr = uedgebuff;
126 	if (mver<=0x10) {
127 		if (fread(uedgebuff,1,4+4+2,fd)!=4+4+2) {
128 			fprintf(stderr,"loading edge: read error\n");
129 			return -1;
130 		}
131 		parent_id = get32bit(&ptr);
132 		child_id = get32bit(&ptr);
133 		edge_id = 0;
134 		nleng = get16bit(&ptr);
135 	} else {
136 		if (fread(uedgebuff,1,4+4+8+2,fd)!=4+4+8+2) {
137 			fprintf(stderr,"loading edge: read error\n");
138 			return -1;
139 		}
140 		parent_id = get32bit(&ptr);
141 		child_id = get32bit(&ptr);
142 		edge_id = get64bit(&ptr);
143 		nleng = get16bit(&ptr);
144 	}
145 	if (parent_id==0 && child_id==0) {	// last edge
146 		return 1;
147 	}
148 
149 	if (parent_id==0) {
150 		printf("E|p:      NULL|c:%10"PRIu32"|i:%016"PRIX64"|n:",child_id,edge_id);
151 	} else {
152 		printf("E|p:%10"PRIu32"|c:%10"PRIu32"|i:%016"PRIX64"|n:",parent_id,child_id,edge_id);
153 	}
154 	print_name(fd,nleng);
155 	printf("\n");
156 	return 0;
157 }
158 
fsnodes_type_convert(uint8_t type)159 static inline uint8_t fsnodes_type_convert(uint8_t type) {
160 	switch (type) {
161 		case DISP_TYPE_FILE:
162 			return TYPE_FILE;
163 		case DISP_TYPE_DIRECTORY:
164 			return TYPE_DIRECTORY;
165 		case DISP_TYPE_SYMLINK:
166 			return TYPE_SYMLINK;
167 		case DISP_TYPE_FIFO:
168 			return TYPE_FIFO;
169 		case DISP_TYPE_BLOCKDEV:
170 			return TYPE_BLOCKDEV;
171 		case DISP_TYPE_CHARDEV:
172 			return TYPE_CHARDEV;
173 		case DISP_TYPE_SOCKET:
174 			return TYPE_SOCKET;
175 		case DISP_TYPE_TRASH:
176 			return TYPE_TRASH;
177 		case DISP_TYPE_SUSTAINED:
178 			return TYPE_SUSTAINED;
179 	}
180 	return 0;
181 }
182 
fs_loadnode(FILE * fd,uint8_t mver)183 int fs_loadnode(FILE *fd,uint8_t mver) {
184 	uint8_t unodebuff[4+1+1+2+4+4+4+4+4+4+8+4+2+8*65536+4*65536+4];
185 	const uint8_t *ptr,*chptr;
186 	uint8_t type,goal,flags;
187 	uint32_t nodeid,uid,gid,atimestamp,mtimestamp,ctimestamp,trashtime;
188 	uint16_t mode;
189 	uint32_t hdrsize;
190 	char c;
191 
192 	type = fgetc(fd);
193 	if (type==0) {	// last node
194 		return 1;
195 	}
196 	if (mver<=0x11) {
197 		hdrsize = 4+1+2+6*4;
198 	} else {
199 		hdrsize = 4+1+1+2+6*4;
200 		if (mver<=0x12) {
201 			type = fsnodes_type_convert(type);
202 		}
203 	}
204 	switch (type) {
205 	case TYPE_DIRECTORY:
206 	case TYPE_FIFO:
207 	case TYPE_SOCKET:
208 		if (fread(unodebuff,1,hdrsize,fd)!=hdrsize) {
209 			fprintf(stderr,"loading node: read error\n");
210 			return -1;
211 		}
212 		break;
213 	case TYPE_BLOCKDEV:
214 	case TYPE_CHARDEV:
215 	case TYPE_SYMLINK:
216 		if (fread(unodebuff,1,hdrsize+4,fd)!=hdrsize+4) {
217 			fprintf(stderr,"loading node: read error\n");
218 			return -1;
219 		}
220 		break;
221 	case TYPE_FILE:
222 	case TYPE_TRASH:
223 	case TYPE_SUSTAINED:
224 		if (fread(unodebuff,1,hdrsize+8+4+2,fd)!=hdrsize+8+4+2) {
225 			fprintf(stderr,"loading node: read error\n");
226 			return -1;
227 		}
228 		break;
229 	default:
230 		fprintf(stderr,"loading node: unrecognized node type: %c\n",type);
231 		return -1;
232 	}
233 	c='?';
234 	switch (type) {
235 	case TYPE_DIRECTORY:
236 		c='D';
237 		break;
238 	case TYPE_SOCKET:
239 		c='S';
240 		break;
241 	case TYPE_FIFO:
242 		c='F';
243 		break;
244 	case TYPE_BLOCKDEV:
245 		c='B';
246 		break;
247 	case TYPE_CHARDEV:
248 		c='C';
249 		break;
250 	case TYPE_SYMLINK:
251 		c='L';
252 		break;
253 	case TYPE_FILE:
254 		c='-';
255 		break;
256 	case TYPE_TRASH:
257 		c='T';
258 		break;
259 	case TYPE_SUSTAINED:
260 		c='R';
261 		break;
262 	}
263 	ptr = unodebuff;
264 	nodeid = get32bit(&ptr);
265 	goal = get8bit(&ptr);
266 	if (mver<=0x11) {
267 		uint16_t flagsmode = get16bit(&ptr);
268 		flags = flagsmode >> 12;
269 		mode = flagsmode & 0xFFF;
270 	} else {
271 		flags = get8bit(&ptr);
272 		mode = get16bit(&ptr);
273 	}
274 	uid = get32bit(&ptr);
275 	gid = get32bit(&ptr);
276 	atimestamp = get32bit(&ptr);
277 	mtimestamp = get32bit(&ptr);
278 	ctimestamp = get32bit(&ptr);
279 	trashtime = get32bit(&ptr);
280 
281 	printf("%c|i:%10"PRIu32"|#:%"PRIu8"|e:%1"PRIX8"|m:%04"PRIo16"|u:%10"PRIu32"|g:%10"PRIu32"|a:%10"PRIu32",m:%10"PRIu32",c:%10"PRIu32"|t:%10"PRIu32,c,nodeid,goal,flags,mode,uid,gid,atimestamp,mtimestamp,ctimestamp,trashtime);
282 
283 	if (type==TYPE_BLOCKDEV || type==TYPE_CHARDEV) {
284 		uint32_t rdev;
285 		rdev = get32bit(&ptr);
286 		printf("|d:%5"PRIu32",%5"PRIu32"\n",rdev>>16,rdev&0xFFFF);
287 	} else if (type==TYPE_SYMLINK) {
288 		uint32_t pleng;
289 		pleng = get32bit(&ptr);
290 		printf("|p:");
291 		print_name(fd,pleng);
292 		printf("\n");
293 	} else if (type==TYPE_FILE || type==TYPE_TRASH || type==TYPE_SUSTAINED) {
294 		uint64_t length,chunkid;
295 		uint32_t ci,ch,sessionid;
296 		uint16_t sessionids;
297 
298 		length = get64bit(&ptr);
299 		ch = get32bit(&ptr);
300 		sessionids = get16bit(&ptr);
301 
302 		printf("|l:%20"PRIu64"|c:(",length);
303 		while (ch>65536) {
304 			chptr = ptr;
305 			if (fread((uint8_t*)ptr,1,8*65536,fd)!=8*65536) {
306 				fprintf(stderr,"loading node: read error\n");
307 				return -1;
308 			}
309 			for (ci=0 ; ci<65536 ; ci++) {
310 				chunkid = get64bit(&chptr);
311 				if (chunkid>0) {
312 					printf("%016"PRIX64,chunkid);
313 				} else {
314 					printf("N");
315 				}
316 				printf(",");
317 			}
318 			ch-=65536;
319 		}
320 
321 		if (fread((uint8_t*)ptr,1,8*ch+4*sessionids,fd)!=8*ch+4*sessionids) {
322 			fprintf(stderr,"loading node: read error\n");
323 			return -1;
324 		}
325 
326 		while (ch>0) {
327 			chunkid = get64bit(&ptr);
328 			if (chunkid>0) {
329 				printf("%016"PRIX64,chunkid);
330 			} else {
331 				printf("N");
332 			}
333 			if (ch>1) {
334 				printf(",");
335 			}
336 			ch--;
337 		}
338 		printf(")|r:(");
339 		while (sessionids>0) {
340 			sessionid = get32bit(&ptr);
341 			printf("%"PRIu32,sessionid);
342 			if (sessionids>1) {
343 				printf(",");
344 			}
345 			sessionids--;
346 		}
347 		printf(")\n");
348 	} else {
349 		printf("\n");
350 	}
351 
352 	return 0;
353 }
354 
fs_loadnodes(FILE * fd,uint8_t fver,uint8_t mver)355 int fs_loadnodes(FILE *fd,uint8_t fver,uint8_t mver) {
356 	int s;
357 	uint8_t hdr[8];
358 	const uint8_t *ptr;
359 	uint32_t maxnodeid,hashelements;
360 	(void)fver;
361 	if (fver>=0x20) {
362 		if (mver<=0x10) {
363 			if (fread(hdr,1,4,fd)!=4) {
364 				fprintf(stderr,"loading node: read error\n");
365 				return -1;
366 			}
367 			ptr = hdr;
368 			maxnodeid = get32bit(&ptr);
369 			printf("# maxinode: %"PRIu32"\n",maxnodeid);
370 		} else {
371 			if (fread(hdr,1,8,fd)!=8) {
372 				fprintf(stderr,"loading node: read error\n");
373 				return -1;
374 			}
375 			ptr = hdr;
376 			maxnodeid = get32bit(&ptr);
377 			hashelements = get32bit(&ptr);
378 			printf("# maxinode: %"PRIu32" ; hashelements: %"PRIu32"\n",maxnodeid,hashelements);
379 		}
380 	}
381 	do {
382 		s = fs_loadnode(fd,mver);
383 		if (s<0) {
384 			return -1;
385 		}
386 	} while (s==0);
387 	return 0;
388 }
389 
fs_loadedges(FILE * fd,uint8_t mver)390 int fs_loadedges(FILE *fd,uint8_t mver) {
391 	uint8_t hdr[8];
392 	const uint8_t *ptr;
393 	uint64_t nextedgeid;
394 	int s;
395 	if (mver>0x10) {
396 		if (fread(hdr,1,8,fd)!=8) {
397 			fprintf(stderr,"loading edge: read error\n");
398 			return -1;
399 		}
400 		ptr = hdr;
401 		nextedgeid = get64bit(&ptr);
402 		printf("# nextedgeid: %016"PRIX64"\n",nextedgeid);
403 	}
404 	do {
405 		s = fs_loadedge(fd,mver);
406 		if (s<0) {
407 			return -1;
408 		}
409 	} while (s==0);
410 	return 0;
411 }
412 
fs_loadfree(FILE * fd,uint8_t mver)413 int fs_loadfree(FILE *fd,uint8_t mver) {
414 	uint8_t rbuff[8];
415 	const uint8_t *ptr;
416 	uint32_t t,nodeid,ftime;
417 	(void)mver;
418 	if (fread(rbuff,1,4,fd)!=4) {
419 		return -1;
420 	}
421 	ptr=rbuff;
422 	t = get32bit(&ptr);
423 	printf("# free nodes: %"PRIu32"\n",t);
424 	while (t>0) {
425 		if (fread(rbuff,1,8,fd)!=8) {
426 			return -1;
427 		}
428 		ptr = rbuff;
429 		nodeid = get32bit(&ptr);
430 		ftime = get32bit(&ptr);
431 		printf("I|i:%10"PRIu32"|f:%10"PRIu32"\n",nodeid,ftime);
432 		t--;
433 	}
434 	return 0;
435 }
436 
fs_loadquota(FILE * fd,uint8_t mver)437 int fs_loadquota(FILE *fd,uint8_t mver) {
438 	uint8_t rbuff[66];
439 	const uint8_t *ptr;
440 	uint8_t exceeded,flags;
441 	uint32_t t,nodeid,stimestamp,sinodes,hinodes;
442 	uint64_t slength,hlength,ssize,hsize,srealsize,hrealsize;
443 	(void)mver;
444 	if (fread(rbuff,1,4,fd)!=4) {
445 		return -1;
446 	}
447 	ptr=rbuff;
448 	t = get32bit(&ptr);
449 	printf("# quota nodes: %"PRIu32"\n",t);
450 	while (t>0) {
451 		if (fread(rbuff,1,66,fd)!=66) {
452 			return -1;
453 		}
454 		ptr = rbuff;
455 		nodeid = get32bit(&ptr);
456 		exceeded = get8bit(&ptr);
457 		flags = get8bit(&ptr);
458 		stimestamp = get32bit(&ptr);
459 		sinodes = get32bit(&ptr);
460 		hinodes = get32bit(&ptr);
461 		slength = get64bit(&ptr);
462 		hlength = get64bit(&ptr);
463 		ssize = get64bit(&ptr);
464 		hsize = get64bit(&ptr);
465 		srealsize = get64bit(&ptr);
466 		hrealsize = get64bit(&ptr);
467 		printf("Q|i:%10"PRIu32"|e:%c|f:%02"PRIX8"|s:%10"PRIu32,nodeid,(exceeded)?'1':'0',flags,stimestamp);
468 		if (flags&QUOTA_FLAG_SINODES) {
469 			printf("|si:%10"PRIu32,sinodes);
470 		} else {
471 			printf("|si:         -");
472 		}
473 		if (flags&QUOTA_FLAG_HINODES) {
474 			printf("|hi:%10"PRIu32,hinodes);
475 		} else {
476 			printf("|hi:         -");
477 		}
478 		if (flags&QUOTA_FLAG_SLENGTH) {
479 			printf("|sl:%20"PRIu64,slength);
480 		} else {
481 			printf("|sl:                   -");
482 		}
483 		if (flags&QUOTA_FLAG_HLENGTH) {
484 			printf("|hl:%20"PRIu64,hlength);
485 		} else {
486 			printf("|hl:                   -");
487 		}
488 		if (flags&QUOTA_FLAG_SSIZE) {
489 			printf("|ss:%20"PRIu64,ssize);
490 		} else {
491 			printf("|ss:                   -");
492 		}
493 		if (flags&QUOTA_FLAG_HSIZE) {
494 			printf("|hs:%20"PRIu64,hsize);
495 		} else {
496 			printf("|hs:                   -");
497 		}
498 		if (flags&QUOTA_FLAG_SREALSIZE) {
499 			printf("|sr:%20"PRIu64,srealsize);
500 		} else {
501 			printf("|sr:                   -");
502 		}
503 		if (flags&QUOTA_FLAG_HREALSIZE) {
504 			printf("|hr:%20"PRIu64,hrealsize);
505 		} else {
506 			printf("|hr:                   -");
507 		}
508 		printf("\n");
509 		t--;
510 	}
511 	return 0;
512 }
513 
xattr_load(FILE * fd,uint8_t mver)514 int xattr_load(FILE *fd,uint8_t mver) {
515 	uint8_t hdrbuff[4+1+4];
516 	const uint8_t *ptr;
517 	uint32_t inode;
518 	uint8_t anleng;
519 	uint32_t avleng;
520 
521 	(void)mver;
522 
523         while (1) {
524                 if (fread(hdrbuff,1,4+1+4,fd)!=4+1+4) {
525                         fprintf(stderr,"loading xattr: read error");
526                         return -1;
527                 }
528                 ptr = hdrbuff;
529                 inode = get32bit(&ptr);
530                 anleng = get8bit(&ptr);
531                 avleng = get32bit(&ptr);
532 		if (inode==0) {
533 			return 0;
534 		}
535 		if (anleng==0) {
536 			fprintf(stderr,"loading xattr: empty name");
537 			fseek(fd,anleng+avleng,SEEK_CUR);
538 			continue;
539 		}
540 		printf("X|i:%10"PRIu32"|n:",inode);
541 		print_name(fd,anleng);
542 		printf("|v:");
543 		print_hex(fd,avleng);
544 		printf("\n");
545 	}
546 }
547 
posix_acl_load(FILE * fd,uint8_t mver)548 int posix_acl_load(FILE *fd,uint8_t mver) {
549 	uint8_t hdrbuff[4+1+2*6];
550 	uint8_t aclbuff[6*100];
551 	const uint8_t *ptr;
552 	uint32_t inode;
553 	uint8_t acltype;
554 	uint16_t userperm;
555 	uint16_t groupperm;
556 	uint16_t otherperm;
557 	uint16_t mask;
558 	uint16_t namedusers;
559 	uint16_t namedgroups;
560 	uint32_t aclid;
561 	uint16_t aclperm;
562 	uint32_t acls,acbcnt;
563 
564 	(void)mver;
565 
566 	while (1) {
567                 if (fread(hdrbuff,1,4+1+2*6,fd)!=4+1+2*6) {
568                         fprintf(stderr,"loading posix_acl: read error");
569                         return -1;
570                 }
571                 ptr = hdrbuff;
572                 inode = get32bit(&ptr);
573 		if (inode==0) {
574 			return 0;
575 		}
576                 acltype = get8bit(&ptr);
577                 userperm = get16bit(&ptr);
578                 groupperm = get16bit(&ptr);
579                 otherperm = get16bit(&ptr);
580                 mask = get16bit(&ptr);
581                 namedusers = get16bit(&ptr);
582                 namedgroups = get16bit(&ptr);
583 		printf("A|i:%10"PRIu32"|t:%"PRIu8"|u:%"PRIo16"|g:%"PRIo16"|o:%"PRIo16"|m:%"PRIo16"|n:(",inode,acltype,userperm,groupperm,otherperm,mask);
584 		acls = namedusers+namedgroups;
585 		acbcnt = 0;
586 		while (acls>0) {
587 			if (acbcnt==0) {
588 				if (acls>100) {
589 					acbcnt=100;
590 				} else {
591 					acbcnt=acls;
592 				}
593 				if (fread(aclbuff,6,acbcnt,fd)!=acbcnt) {
594 					fprintf(stderr,"loading posix_acl: read error");
595 					return -1;
596 				}
597 				ptr = aclbuff;
598 			}
599 			aclid = get32bit(&ptr);
600 			aclperm = get16bit(&ptr);
601 			acls--;
602 			acbcnt--;
603 			if (acls>=namedgroups) {
604 				printf("u(%"PRIu32"):%"PRIo16,aclid,aclperm);
605 			} else {
606 				printf("g(%"PRIu32"):%"PRIo16,aclid,aclperm);
607 			}
608 			if (acls>0) {
609 				printf(",");
610 			}
611 		}
612 		printf(")\n");
613 	}
614 }
615 
sessions_load(FILE * fd,uint8_t mver)616 int sessions_load(FILE *fd,uint8_t mver) {
617 	uint8_t hdr[8];
618 	uint8_t *fsesrecord;
619 	const uint8_t *ptr;
620 	uint16_t dver,statsinfile;
621 	uint32_t recsize;
622 	uint32_t i,nextsessionid,sessionid;
623 	uint32_t ileng,peerip,rootinode,mintrashtime,maxtrashtime,rootuid,rootgid,mapalluid,mapallgid,disconnected;
624 	uint8_t sesflags,mingoal,maxgoal;
625 	char strip[16];
626 
627 	if (mver<=0x11) {
628 		if (fread(hdr,1,8,fd)!=8) {
629 			fprintf(stderr,"loading sessions: read error");
630 			return -1;
631 		}
632 
633 		ptr = hdr;
634 		dver = get16bit(&ptr);
635 		if (dver==1) {
636 			mver = 0x10;
637 		} else if (dver==2) {
638 			mver = 0x11;
639 		}
640 	} else {
641 		dver = 0; // makes old gcc happy
642 		if (fread(hdr,1,6,fd)!=6) {
643 			fprintf(stderr,"loading sessions: read error");
644 			return -1;
645 		}
646 		ptr = hdr;
647 	}
648 	nextsessionid = get32bit(&ptr);
649 	statsinfile = get16bit(&ptr);
650 
651 	if (mver<=0x11) {
652 		printf("# dver: %"PRIu16" ; nextsessionid: %"PRIu32" ; statscount: %"PRIu16"\n",dver,nextsessionid,statsinfile);
653 	} else {
654 		printf("# nextsessionid: %"PRIu32" ; statscount: %"PRIu16"\n",nextsessionid,statsinfile);
655 	}
656 	if (mver<0x11) {
657 		recsize = 43+statsinfile*8;
658 	} else {
659 		recsize = 47+statsinfile*8;
660 	}
661 	fsesrecord = malloc(recsize);
662 	if (fsesrecord==NULL) {
663 		fprintf(stderr,"loading sessions: out of memory\n");
664 		return -1;
665 	}
666 
667 	while (1) {
668 		if (fread(fsesrecord,1,recsize,fd)!=(size_t)(recsize)) {
669 			free(fsesrecord);
670 			fprintf(stderr,"loading sessions: read error\n");
671 			return -1;
672 		}
673 		ptr = fsesrecord;
674 		sessionid = get32bit(&ptr);
675 		if (sessionid==0) {
676 			free(fsesrecord);
677 			return 0;
678 		}
679 		ileng = get32bit(&ptr);
680 		peerip = get32bit(&ptr);
681 		rootinode = get32bit(&ptr);
682 		sesflags = get8bit(&ptr);
683 		mingoal = get8bit(&ptr);
684 		maxgoal = get8bit(&ptr);
685 		mintrashtime = get32bit(&ptr);
686 		maxtrashtime = get32bit(&ptr);
687 		rootuid = get32bit(&ptr);
688 		rootgid = get32bit(&ptr);
689 		mapalluid = get32bit(&ptr);
690 		mapallgid = get32bit(&ptr);
691 		makestrip(strip,peerip);
692 		if (mver>=0x11) {
693 			disconnected = get32bit(&ptr);
694 			printf("M|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);
695 		} else {
696 			printf("M|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);
697 		}
698 		for (i=0 ; i<statsinfile ; i++) {
699 			printf("%c%"PRIu32,(i==0)?'[':',',get32bit(&ptr));
700 		}
701 		printf("]|l:");
702 		for (i=0 ; i<statsinfile ; i++) {
703 			printf("%c%"PRIu32,(i==0)?'[':',',get32bit(&ptr));
704 		}
705 		printf("]|i:");
706 		print_name(fd,ileng);
707 		printf("\n");
708 	}
709 }
710 
csdb_load(FILE * fd,uint8_t mver)711 int csdb_load(FILE *fd,uint8_t mver) {
712 	uint8_t csdbbuff[9];
713 	const uint8_t *ptr;
714 	uint32_t t;
715 	uint32_t ip;
716 	uint16_t port;
717 	uint16_t csid;
718 	uint8_t maintenance;
719 	size_t bsize;
720 	char strip[16];
721 
722 	if (mver<=0x10) {
723 		bsize = 6;
724 	} else if (mver<=0x11) {
725 		bsize = 8;
726 	} else {
727 		bsize = 9;
728 	}
729 
730 	if (fread(csdbbuff,1,4,fd)!=4) {
731 		return -1;
732 	}
733 	ptr = csdbbuff;
734 	t = get32bit(&ptr);
735 	printf("# chunk servers: %"PRIu32"\n",t);
736 	while (t>0) {
737 		if (fread(csdbbuff,1,bsize,fd)!=bsize) {
738 			fprintf(stderr,"loading chunk servers: read error\n");
739 			return -1;
740 		}
741 		ptr = csdbbuff;
742 		if (mver<=0x10) {
743 			ip = get32bit(&ptr);
744 			port = get16bit(&ptr);
745 			makestrip(strip,ip);
746 			printf("Z|i:%s|p:%5"PRIu16"\n",strip,port);
747 		} else if (mver<=0x11) {
748 			ip = get32bit(&ptr);
749 			port = get16bit(&ptr);
750 			csid = get16bit(&ptr);
751 			makestrip(strip,ip);
752 			printf("Z|i:%s|p:%5"PRIu16"|#:%5"PRIu16"\n",strip,port,csid);
753 		} else {
754 			ip = get32bit(&ptr);
755 			port = get16bit(&ptr);
756 			csid = get16bit(&ptr);
757 			maintenance = get8bit(&ptr);
758 			makestrip(strip,ip);
759 			printf("Z|i:%s|p:%5"PRIu16"|#:%5"PRIu16"|m:%u\n",strip,port,csid,(maintenance)?1:0);
760 		}
761 		t--;
762 	}
763 	return 0;
764 }
765 
of_load(FILE * fd,uint8_t mver)766 int of_load(FILE *fd,uint8_t mver) {
767 	uint8_t loadbuff[8];
768 	const uint8_t *ptr;
769 	uint32_t sessionid,inode;
770 
771 	(void)mver;
772 
773 	for (;;) {
774 		if (fread(loadbuff,1,8,fd)!=8) {
775 			fprintf(stderr,"loading open files: read error\n");
776 			return -1;
777 		}
778 		ptr = loadbuff;
779 		sessionid = get32bit(&ptr);
780 		inode = get32bit(&ptr);
781 		if (sessionid>0 && inode>0) {
782 			printf("O|s:%10"PRIu32"|i:%10"PRIu32"\n",sessionid,inode);
783 		} else {
784 			return 0;
785 		}
786 	}
787 	return 0;       // unreachable
788 }
789 
hexdump(FILE * fd,uint64_t sleng)790 int hexdump(FILE *fd,uint64_t sleng) {
791 	uint8_t lbuff[32];
792 	uint32_t i;
793 	while (sleng>32) {
794 		if (fread(lbuff,1,32,fd)!=32) {
795 			return -1;
796 		}
797 		for (i=0 ; i<32 ; i++) {
798 			printf("%02"PRIX8" ",lbuff[i]);
799 		}
800 		printf(" |");
801 		for (i=0 ; i<32 ; i++) {
802 			printf("%c",dispchar(lbuff[i]));
803 		}
804 		printf("|\n");
805 		sleng-=32;
806 	}
807 	if (sleng>0) {
808 		if (fread(lbuff,1,sleng,fd)!=(size_t)sleng) {
809 			return -1;
810 		}
811 		for (i=0 ; i<32 ; i++) {
812 			if (i<sleng) {
813 				printf("%02"PRIX8" ",lbuff[i]);
814 			} else {
815 				printf("   ");
816 			}
817 		}
818 		printf(" |");
819 		for (i=0 ; i<32 ; i++) {
820 			if (i<sleng) {
821 				printf("%c",dispchar(lbuff[i]));
822 			} else {
823 				printf(" ");
824 			}
825 		}
826 		printf("|\n");
827 	}
828 	return 0;
829 }
830 
fs_load_pre17(FILE * fd)831 int fs_load_pre17(FILE *fd) {
832 	uint32_t maxnodeid,nextsessionid;
833 	uint64_t version;
834 	uint8_t hdr[16];
835 	const uint8_t *ptr;
836 	if (fread(hdr,1,16,fd)!=16) {
837 		return -1;
838 	}
839 	ptr = hdr;
840 	maxnodeid = get32bit(&ptr);
841 	version = get64bit(&ptr);
842 	nextsessionid = get32bit(&ptr);
843 
844 	printf("# maxnodeid: %"PRIu32" ; version: %"PRIu64" ; nextsessionid: %"PRIu32"\n",maxnodeid,version,nextsessionid);
845 
846 	printf("# -------------------------------------------------------------------\n");
847 	if (fs_loadnodes(fd,0x15,0x10)<0) {
848 		printf("error reading metadata (node)\n");
849 		return -1;
850 	}
851 	printf("# -------------------------------------------------------------------\n");
852 	if (fs_loadedges(fd,0x10)<0) {
853 		printf("error reading metadata (edge)\n");
854 		return -1;
855 	}
856 	printf("# -------------------------------------------------------------------\n");
857 	if (fs_loadfree(fd,0x10)<0) {
858 		printf("error reading metadata (free)\n");
859 		return -1;
860 	}
861 	printf("# -------------------------------------------------------------------\n");
862 	return 0;
863 }
864 
fs_load(FILE * fd,uint8_t fver)865 int fs_load(FILE *fd,uint8_t fver) {
866 	uint32_t maxnodeid,nextsessionid;
867 	uint64_t sleng;
868 	off_t offbegin;
869 	uint64_t version,fileid;
870 	uint8_t hdr[16];
871 	const uint8_t *ptr;
872 	uint8_t mver;
873 	if (fread(hdr,1,16,fd)!=16) {
874 		return -1;
875 	}
876 	ptr = hdr;
877 
878 	if (fver<0x20) {
879 		maxnodeid = get32bit(&ptr);
880 		version = get64bit(&ptr);
881 		nextsessionid = get32bit(&ptr);
882 
883 		printf("# maxnodeid: %"PRIu32" ; version: %"PRIu64" ; nextsessionid: %"PRIu32"\n",maxnodeid,version,nextsessionid);
884 	} else {
885 		version = get64bit(&ptr);
886 		fileid = get64bit(&ptr);
887 
888 		printf("# version: %"PRIu64" ; fileid: 0x%"PRIX64"\n",version,fileid);
889 	}
890 
891 	while (1) {
892 		if (fread(hdr,1,16,fd)!=16) {
893 			printf("can't read section header\n");
894 			return -1;
895 		}
896 		if (memcmp(hdr,"[MFS EOF MARKER]",16)==0) {
897 			printf("# -------------------------------------------------------------------\n");
898 			printf("# MFS END OF FILE MARKER\n");
899 			printf("# -------------------------------------------------------------------\n");
900 			return 0;
901 		}
902 		ptr = hdr+8;
903 		sleng = get64bit(&ptr);
904 		offbegin = ftello(fd);
905 		printf("# -------------------------------------------------------------------\n");
906 		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);
907 		mver = (((hdr[5]-'0')&0xF)<<4)+(hdr[7]&0xF);
908 		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);
909 		if (memcmp(hdr,"NODE",4)==0) {
910 			if (fs_loadnodes(fd,fver,mver)<0) {
911 				printf("error reading metadata (NODE)\n");
912 				return -1;
913 			}
914 		} else if (memcmp(hdr,"EDGE",4)==0) {
915 			if (fs_loadedges(fd,mver)<0) {
916 				printf("error reading metadata (EDGE)\n");
917 				return -1;
918 			}
919 		} else if (memcmp(hdr,"FREE",4)==0) {
920 			if (fs_loadfree(fd,mver)<0) {
921 				printf("error reading metadata (FREE)\n");
922 				return -1;
923 			}
924 		} else if (memcmp(hdr,"QUOT",4)==0) {
925 			if (fs_loadquota(fd,mver)<0) {
926 				printf("error reading metadata (QUOT)\n");
927 				return -1;
928 			}
929 		} else if (memcmp(hdr,"CHNK",4)==0) {
930 			if (chunk_load(fd,mver)<0) {
931 				printf("error reading metadata (CHNK)\n");
932 				return -1;
933 			}
934 		} else if (memcmp(hdr,"XATR",4)==0) {
935 			if (xattr_load(fd,mver)<0) {
936 				printf("error reading metadata (XATR)\n");
937 				return -1;
938 			}
939 		} else if (memcmp(hdr,"PACL",4)==0) {
940 			if (posix_acl_load(fd,mver)<0) {
941 				printf("error reading metadata (PACL)\n");
942 				return -1;
943 			}
944 		} else if (memcmp(hdr,"SESS",4)==0) {
945 			if (sessions_load(fd,mver)<0) {
946 				printf("error reading metadata (SESS)\n");
947 				return -1;
948 			}
949 		} else if (memcmp(hdr,"OPEN",4)==0) {
950 			if (of_load(fd,mver)<0) {
951 				printf("error reading metadata (OPEN)\n");
952 				return -1;
953 			}
954 		} else if (memcmp(hdr,"CSDB",4)==0) {
955 			if (csdb_load(fd,mver)<0) {
956 				printf("error reading metadata (CSDB)\n");
957 				return -1;
958 			}
959 		} else {
960 			printf("unknown file part\n");
961 			if (hexdump(fd,sleng)<0) {
962 				return -1;
963 			}
964 		}
965 		if ((off_t)(offbegin+sleng)!=ftello(fd)) {
966 			fprintf(stderr,"some data in this section have not been read - file corrupted\n");
967 			return -1;
968 		}
969 	}
970 	return 0;
971 }
972 
fs_loadall(const char * fname)973 int fs_loadall(const char *fname) {
974 	FILE *fd;
975 	uint8_t hdr[8];
976 	uint8_t fver;
977 
978 	fd = fopen(fname,"r");
979 
980 	if (fd==NULL) {
981 		printf("can't open metadata file\n");
982 		return -1;
983 	}
984 	if (fread(hdr,1,8,fd)!=8) {
985 		printf("can't read metadata header\n");
986 		fclose(fd);
987 		return -1;
988 	}
989 	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]);
990 	if (memcmp(hdr,"MFSM NEW",8)==0) {
991 		printf("empty file\n");
992 	} else if (memcmp(hdr,MFSSIGNATURE "M ",5)==0 && hdr[5]>='1' && hdr[5]<='9' && hdr[6]=='.' && hdr[7]>='0' && hdr[7]<='9') {
993 		fver = ((hdr[5]-'0')<<4)+(hdr[7]-'0');
994 		if (fver<0x17) {
995 			if (fs_load_pre17(fd)<0) {
996 				printf("error reading metadata (structure)\n");
997 				fclose(fd);
998 				return -1;
999 			}
1000 			if (chunk_load(fd,0x10)<0) {
1001 				printf("error reading metadata (chunks)\n");
1002 				fclose(fd);
1003 				return -1;
1004 			}
1005 		} else {
1006 			if (fs_load(fd,fver)<0) {
1007 				fclose(fd);
1008 				return -1;
1009 			}
1010 		}
1011 	} else {
1012 		printf("wrong metadata header (old version ?)\n");
1013 		fclose(fd);
1014 		return -1;
1015 	}
1016 	if (ferror(fd)!=0) {
1017 		printf("error reading metadata\n");
1018 		fclose(fd);
1019 		return -1;
1020 	}
1021 	fclose(fd);
1022 	return 0;
1023 }
1024 
main(int argc,char ** argv)1025 int main(int argc,char **argv) {
1026 	if (argc!=2) {
1027 		printf("usage: %s metadata_file\n",argv[0]);
1028 		return 1;
1029 	}
1030 	return (fs_loadall(argv[1])<0)?1:0;
1031 }
1032