dumplfs.c revision 1.57
1/* $NetBSD: dumplfs.c,v 1.57 2015/09/01 06:12:04 dholland Exp $ */ 2 3/*- 4 * Copyright (c) 1991, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32#include <sys/cdefs.h> 33 34#ifndef lint 35__COPYRIGHT("@(#) Copyright (c) 1991, 1993\ 36 The Regents of the University of California. All rights reserved."); 37#endif /* not lint */ 38 39#ifndef lint 40#if 0 41static char sccsid[] = "@(#)dumplfs.c 8.5 (Berkeley) 5/24/95"; 42#else 43__RCSID("$NetBSD: dumplfs.c,v 1.57 2015/09/01 06:12:04 dholland Exp $"); 44#endif 45#endif /* not lint */ 46 47#include <sys/param.h> 48#include <sys/ucred.h> 49#include <sys/mount.h> 50#include <sys/time.h> 51 52#include <ufs/lfs/lfs.h> 53#include <ufs/lfs/lfs_accessors.h> 54 55#include <err.h> 56#include <errno.h> 57#include <fcntl.h> 58#include <fstab.h> 59#include <stdlib.h> 60#include <stdio.h> 61#include <string.h> 62#include <unistd.h> 63#include "extern.h" 64 65static void addseg(char *); 66static void dump_cleaner_info(struct lfs *, void *); 67static void dump_dinode(struct lfs *, union lfs_dinode *); 68static void dump_ifile(int, struct lfs *, int, int, daddr_t); 69static int dump_ipage_ifile(struct lfs *, int, char *, int); 70static int dump_ipage_segusage(struct lfs *, int, char *, int); 71static void dump_segment(int, int, daddr_t, struct lfs *, int); 72static int dump_sum(int, struct lfs *, SEGSUM *, int, daddr_t); 73static void dump_super(struct lfs *); 74static void usage(void); 75 76extern uint32_t cksum(void *, size_t); 77 78typedef struct seglist SEGLIST; 79struct seglist { 80 SEGLIST *next; 81 int num; 82}; 83SEGLIST *seglist; 84 85char *special; 86 87/* Segment Usage formats */ 88#define print_suheader \ 89 (void)printf("segnum\tflags\tnbytes\tninos\tnsums\tlastmod\n") 90 91static inline void 92print_suentry(int i, SEGUSE *sp, struct lfs *fs) 93{ 94 time_t t; 95 char flags[4] = " "; 96 97 if (sp->su_flags & SEGUSE_ACTIVE) 98 flags[0] = 'A'; 99 if (sp->su_flags & SEGUSE_DIRTY) 100 flags[1] = 'D'; 101 else 102 flags[1] = 'C'; 103 if (sp->su_flags & SEGUSE_SUPERBLOCK) 104 flags[2] = 'S'; 105 106 t = (lfs_sb_getversion(fs) == 1 ? sp->su_olastmod : sp->su_lastmod); 107 108 printf("%d\t%s\t%d\t%d\t%d\t%s", i, flags, 109 sp->su_nbytes, sp->su_ninos, sp->su_nsums, 110 ctime(&t)); 111} 112 113/* Ifile formats */ 114#define print_iheader \ 115 (void)printf("inum\tstatus\tversion\tdaddr\t\tfreeptr\n") 116 117static inline void 118print_ientry(int i, struct lfs *lfsp, IFILE *ip) 119{ 120 uint32_t version; 121 daddr_t daddr; 122 ino_t nextfree; 123 124 version = lfs_if_getversion(lfsp, ip); 125 daddr = lfs_if_getdaddr(lfsp, ip); 126 nextfree = lfs_if_getnextfree(lfsp, ip); 127 128 if (daddr == LFS_UNUSED_DADDR) 129 printf("%d\tFREE\t%u\t \t\t%ju\n", i, version, 130 (uintmax_t)nextfree); 131 else 132 printf("%d\tINUSE\t%u\t%8jX\t%s\n", 133 i, version, (intmax_t)daddr, 134 nextfree == LFS_ORPHAN_NEXTFREE ? "FFFFFFFF" : "-"); 135} 136 137#define fsbtobyte(fs, b) lfs_fsbtob((fs), (off_t)((b))) 138 139int datasum_check = 0; 140 141int 142main(int argc, char **argv) 143{ 144 struct lfs lfs_sb1, lfs_sb2, *lfs_master; 145 daddr_t seg_addr, idaddr, sbdaddr; 146 int ch, do_allsb, do_ientries, do_segentries, fd, segnum; 147 void *sbuf; 148 149 do_allsb = 0; 150 do_ientries = 0; 151 do_segentries = 0; 152 idaddr = 0x0; 153 sbdaddr = 0x0; 154 while ((ch = getopt(argc, argv, "ab:diI:Ss:")) != -1) 155 switch(ch) { 156 case 'a': /* Dump all superblocks */ 157 do_allsb = 1; 158 break; 159 case 'b': /* Use this superblock */ 160 sbdaddr = strtol(optarg, NULL, 0); 161 break; 162 case 'd': 163 datasum_check = 1; 164 break; 165 case 'i': /* Dump ifile entries */ 166 do_ientries = !do_ientries; 167 break; 168 case 'I': /* Use this ifile inode */ 169 idaddr = strtol(optarg, NULL, 0); 170 break; 171 case 'S': 172 do_segentries = !do_segentries; 173 break; 174 case 's': /* Dump out these segments */ 175 addseg(optarg); 176 break; 177 default: 178 usage(); 179 } 180 argc -= optind; 181 argv += optind; 182 183 if (argc != 1) 184 usage(); 185 186 special = argv[0]; 187 if ((fd = open(special, O_RDONLY, 0)) < 0) 188 err(1, "%s", special); 189 190 sbuf = malloc(LFS_SBPAD); 191 if (sbuf == NULL) 192 err(1, "malloc"); 193 194 if (sbdaddr == 0x0) { 195 /* Read the proto-superblock */ 196 __CTASSERT(sizeof(struct dlfs) == sizeof(struct dlfs64)); 197 get(fd, LFS_LABELPAD, sbuf, LFS_SBPAD); 198 memcpy(&lfs_sb1.lfs_dlfs_u, sbuf, sizeof(struct dlfs)); 199 200 /* If that wasn't the real first sb, get the real first sb */ 201 if (lfs_sb_getversion(&lfs_sb1) > 1 && 202 lfs_sb_getsboff(&lfs_sb1, 0) > lfs_btofsb(&lfs_sb1, LFS_LABELPAD)) 203 get(fd, lfs_fsbtob(&lfs_sb1, lfs_sb_getsboff(&lfs_sb1, 0)), 204 &lfs_sb1.lfs_dlfs_u, sizeof(struct dlfs)); 205 206 /* 207 * Read the second superblock and figure out which check point is 208 * most up to date. 209 */ 210 get(fd, 211 fsbtobyte(&lfs_sb1, lfs_sb_getsboff(&lfs_sb1, 1)), 212 sbuf, LFS_SBPAD); 213 memcpy(&lfs_sb2.lfs_dlfs_u, sbuf, sizeof(struct dlfs)); 214 215 lfs_master = &lfs_sb1; 216 if (lfs_sb_getversion(&lfs_sb1) > 1) { 217 if (lfs_sb_getserial(&lfs_sb1) > lfs_sb_getserial(&lfs_sb2)) { 218 lfs_master = &lfs_sb2; 219 sbdaddr = lfs_sb_getsboff(&lfs_sb1, 1); 220 } else 221 sbdaddr = lfs_sb_getsboff(&lfs_sb1, 0); 222 } else { 223 if (lfs_sb_getotstamp(&lfs_sb1) > lfs_sb_getotstamp(&lfs_sb2)) { 224 lfs_master = &lfs_sb2; 225 sbdaddr = lfs_sb_getsboff(&lfs_sb1, 1); 226 } else 227 sbdaddr = lfs_sb_getsboff(&lfs_sb1, 0); 228 } 229 } else { 230 /* Read the first superblock */ 231 get(fd, dbtob((off_t)sbdaddr), sbuf, LFS_SBPAD); 232 memcpy(&lfs_sb1.lfs_dlfs_u, sbuf, sizeof(struct dlfs)); 233 lfs_master = &lfs_sb1; 234 } 235 236 free(sbuf); 237 238 /* Compatibility */ 239 if (lfs_sb_getversion(lfs_master) == 1) { 240 lfs_sb_setsumsize(lfs_master, LFS_V1_SUMMARY_SIZE); 241 lfs_sb_setibsize(lfs_master, lfs_sb_getbsize(lfs_master)); 242 lfs_sb_sets0addr(lfs_master, lfs_sb_getsboff(lfs_master, 0)); 243 lfs_sb_settstamp(lfs_master, lfs_sb_getotstamp(lfs_master)); 244 lfs_sb_setfsbtodb(lfs_master, 0); 245 } 246 247 (void)printf("Master Superblock at 0x%llx:\n", (long long)sbdaddr); 248 dump_super(lfs_master); 249 250 dump_ifile(fd, lfs_master, do_ientries, do_segentries, idaddr); 251 252 if (seglist != NULL) 253 for (; seglist != NULL; seglist = seglist->next) { 254 seg_addr = lfs_sntod(lfs_master, seglist->num); 255 dump_segment(fd, seglist->num, seg_addr, lfs_master, 256 do_allsb); 257 } 258 else 259 for (segnum = 0, seg_addr = lfs_sntod(lfs_master, 0); 260 segnum < lfs_sb_getnseg(lfs_master); 261 segnum++, seg_addr = lfs_sntod(lfs_master, segnum)) 262 dump_segment(fd, segnum, seg_addr, lfs_master, 263 do_allsb); 264 265 (void)close(fd); 266 exit(0); 267} 268 269/* 270 * We are reading all the blocks of an inode and dumping out the ifile table. 271 * This code could be tighter, but this is a first pass at getting the stuff 272 * printed out rather than making this code incredibly efficient. 273 */ 274static void 275dump_ifile(int fd, struct lfs *lfsp, int do_ientries, int do_segentries, daddr_t addr) 276{ 277 char *ipage; 278 char *dpage; 279 union lfs_dinode *dip = NULL; 280 /* XXX ondisk32 */ 281 int32_t *addrp, *dindir, *iaddrp, *indir; 282 daddr_t pdb; 283 int block_limit, i, inum, j, nblocks, psize; 284 285 psize = lfs_sb_getbsize(lfsp); 286 if (!addr) 287 addr = lfs_sb_getidaddr(lfsp); 288 289 if (!(dpage = malloc(psize))) 290 err(1, "malloc"); 291 get(fd, fsbtobyte(lfsp, addr), dpage, psize); 292 293 for (i = LFS_INOPB(lfsp); i-- > 0; ) { 294 dip = DINO_IN_BLOCK(lfsp, dpage, i); 295 if (lfs_dino_getinumber(lfsp, dip) == LFS_IFILE_INUM) 296 break; 297 } 298 299 if (lfs_dino_getinumber(lfsp, dip) != LFS_IFILE_INUM) { 300 warnx("unable to locate ifile inode at disk address 0x%jx", 301 (uintmax_t)addr); 302 return; 303 } 304 305 (void)printf("\nIFILE inode\n"); 306 dump_dinode(lfsp, dip); 307 308 (void)printf("\nIFILE contents\n"); 309 nblocks = lfs_dino_getsize(lfsp, dip) >> lfs_sb_getbshift(lfsp); 310 block_limit = MIN(nblocks, ULFS_NDADDR); 311 312 /* Get the direct block */ 313 if ((ipage = malloc(psize)) == NULL) 314 err(1, "malloc"); 315 for (inum = 0, i = 0; i < block_limit; i++) { 316 pdb = lfs_dino_getdb(lfsp, dip, i); 317 get(fd, fsbtobyte(lfsp, pdb), ipage, psize); 318 if (i < lfs_sb_getcleansz(lfsp)) { 319 dump_cleaner_info(lfsp, ipage); 320 if (do_segentries) 321 print_suheader; 322 continue; 323 } 324 325 if (i < (lfs_sb_getsegtabsz(lfsp) + lfs_sb_getcleansz(lfsp))) { 326 if (do_segentries) 327 inum = dump_ipage_segusage(lfsp, inum, ipage, 328 lfs_sb_getsepb(lfsp)); 329 else 330 inum = (i < lfs_sb_getsegtabsz(lfsp) + lfs_sb_getcleansz(lfsp) - 1); 331 if (!inum) { 332 if(!do_ientries) 333 goto e0; 334 else 335 print_iheader; 336 } 337 } else 338 inum = dump_ipage_ifile(lfsp, inum, ipage, lfs_sb_getifpb(lfsp)); 339 } 340 341 if (nblocks <= ULFS_NDADDR) 342 goto e0; 343 344 /* Dump out blocks off of single indirect block */ 345 if (!(indir = malloc(psize))) 346 err(1, "malloc"); 347 get(fd, fsbtobyte(lfsp, lfs_dino_getib(lfsp, dip, 0)), indir, psize); 348 block_limit = MIN(i + lfs_sb_getnindir(lfsp), nblocks); 349 for (addrp = indir; i < block_limit; i++, addrp++) { 350 if (*addrp == LFS_UNUSED_DADDR) 351 break; 352 get(fd, fsbtobyte(lfsp, *addrp), ipage, psize); 353 if (i < lfs_sb_getcleansz(lfsp)) { 354 dump_cleaner_info(lfsp, ipage); 355 continue; 356 } 357 358 if (i < lfs_sb_getsegtabsz(lfsp) + lfs_sb_getcleansz(lfsp)) { 359 if (do_segentries) 360 inum = dump_ipage_segusage(lfsp, inum, ipage, 361 lfs_sb_getsepb(lfsp)); 362 else 363 inum = (i < lfs_sb_getsegtabsz(lfsp) + lfs_sb_getcleansz(lfsp) - 1); 364 if (!inum) { 365 if(!do_ientries) 366 goto e1; 367 else 368 print_iheader; 369 } 370 } else 371 inum = dump_ipage_ifile(lfsp, inum, ipage, lfs_sb_getifpb(lfsp)); 372 } 373 374 if (nblocks <= ULFS_NDADDR + lfs_sb_getnindir(lfsp)) 375 goto e1; 376 377 /* Get the double indirect block */ 378 if (!(dindir = malloc(psize))) 379 err(1, "malloc"); 380 get(fd, fsbtobyte(lfsp, lfs_dino_getib(lfsp, dip, 1)), dindir, psize); 381 for (iaddrp = dindir, j = 0; j < lfs_sb_getnindir(lfsp); j++, iaddrp++) { 382 if (*iaddrp == LFS_UNUSED_DADDR) 383 break; 384 get(fd, fsbtobyte(lfsp, *iaddrp), indir, psize); 385 block_limit = MIN(i + lfs_sb_getnindir(lfsp), nblocks); 386 for (addrp = indir; i < block_limit; i++, addrp++) { 387 if (*addrp == LFS_UNUSED_DADDR) 388 break; 389 get(fd, fsbtobyte(lfsp, *addrp), ipage, psize); 390 if (i < lfs_sb_getcleansz(lfsp)) { 391 dump_cleaner_info(lfsp, ipage); 392 continue; 393 } 394 395 if (i < lfs_sb_getsegtabsz(lfsp) + lfs_sb_getcleansz(lfsp)) { 396 if (do_segentries) 397 inum = dump_ipage_segusage(lfsp, 398 inum, ipage, lfs_sb_getsepb(lfsp)); 399 else 400 inum = (i < lfs_sb_getsegtabsz(lfsp) + 401 lfs_sb_getcleansz(lfsp) - 1); 402 if (!inum) { 403 if(!do_ientries) 404 goto e2; 405 else 406 print_iheader; 407 } 408 } else 409 inum = dump_ipage_ifile(lfsp, inum, 410 ipage, lfs_sb_getifpb(lfsp)); 411 } 412 } 413e2: free(dindir); 414e1: free(indir); 415e0: free(dpage); 416 free(ipage); 417} 418 419static int 420dump_ipage_ifile(struct lfs *lfsp, int i, char *pp, int tot) 421{ 422 char *ip; 423 int cnt, max, entsize; 424 425 if (lfsp->lfs_is64) 426 entsize = sizeof(IFILE64); 427 if (lfs_sb_getversion(lfsp) > 1) 428 entsize = sizeof(IFILE32); 429 else 430 entsize = sizeof(IFILE_V1); 431 max = i + tot; 432 433 for (ip = pp, cnt = i; cnt < max; cnt++, ip += entsize) 434 print_ientry(cnt, lfsp, (IFILE *)ip); 435 return (max); 436} 437 438static int 439dump_ipage_segusage(struct lfs *lfsp, int i, char *pp, int tot) 440{ 441 SEGUSE *sp; 442 int cnt, max; 443 struct seglist *slp; 444 445 max = i + tot; 446 for (sp = (SEGUSE *)pp, cnt = i; 447 cnt < lfs_sb_getnseg(lfsp) && cnt < max; cnt++) { 448 if (seglist == NULL) 449 print_suentry(cnt, sp, lfsp); 450 else { 451 for (slp = seglist; slp != NULL; slp = slp->next) 452 if (cnt == slp->num) { 453 print_suentry(cnt, sp, lfsp); 454 break; 455 } 456 } 457 if (lfs_sb_getversion(lfsp) > 1) 458 ++sp; 459 else 460 sp = (SEGUSE *)((SEGUSE_V1 *)sp + 1); 461 } 462 if (max >= lfs_sb_getnseg(lfsp)) 463 return (0); 464 else 465 return (max); 466} 467 468static void 469dump_dinode(struct lfs *fs, union lfs_dinode *dip) 470{ 471 int i; 472 time_t at, mt, ct; 473 474 at = lfs_dino_getatime(fs, dip); 475 mt = lfs_dino_getmtime(fs, dip); 476 ct = lfs_dino_getctime(fs, dip); 477 478 (void)printf(" %so%o\t%s%d\t%s%d\t%s%d\t%s%ju\n", 479 "mode ", lfs_dino_getmode(fs, dip), 480 "nlink ", lfs_dino_getnlink(fs, dip), 481 "uid ", lfs_dino_getuid(fs, dip), 482 "gid ", lfs_dino_getgid(fs, dip), 483 "size ", (uintmax_t)lfs_dino_getsize(fs, dip)); 484 (void)printf(" %s%s", "atime ", ctime(&at)); 485 (void)printf(" %s%s", "mtime ", ctime(&mt)); 486 (void)printf(" %s%s", "ctime ", ctime(&ct)); 487 (void)printf(" inum %ju\n", 488 (uintmax_t)lfs_dino_getinumber(fs, dip)); 489 (void)printf(" Direct Addresses\n"); 490 for (i = 0; i < ULFS_NDADDR; i++) { 491 (void)printf("\t0x%jx", (intmax_t)lfs_dino_getdb(fs, dip, i)); 492 if ((i % 6) == 5) 493 (void)printf("\n"); 494 } 495 (void)printf(" Indirect Addresses\n"); 496 for (i = 0; i < ULFS_NIADDR; i++) 497 (void)printf("\t0x%jx", (intmax_t)lfs_dino_getib(fs, dip, i)); 498 (void)printf("\n"); 499} 500 501static int 502dump_sum(int fd, struct lfs *lfsp, SEGSUM *sp, int segnum, daddr_t addr) 503{ 504 FINFO *fp; 505 int32_t *dp, *idp; 506 union lfs_blocks fipblocks; 507 int i, j, acc; 508 int ck; 509 int numbytes, numblocks; 510 char *datap; 511 char *diblock; 512 union lfs_dinode *dip; 513 size_t el_size; 514 u_int32_t datasum; 515 u_int32_t ssflags; 516 time_t t; 517 char *buf; 518 size_t sumstart; 519 520 sumstart = lfs_ss_getsumstart(lfsp); 521 if (lfs_ss_getmagic(lfsp, sp) != SS_MAGIC || 522 lfs_ss_getsumsum(lfsp, sp) != (ck = cksum((char *)sp + sumstart, 523 lfs_sb_getsumsize(lfsp) - sumstart))) { 524 /* Don't print "corrupt" if we're just too close to the edge */ 525 if (lfs_dtosn(lfsp, addr + LFS_FSBTODB(lfsp, 1)) == 526 lfs_dtosn(lfsp, addr)) 527 (void)printf("dumplfs: %s %d address 0x%llx\n", 528 "corrupt summary block; segment", segnum, 529 (long long)addr); 530 return -1; 531 } 532 if (lfs_sb_getversion(lfsp) > 1 && lfs_ss_getident(lfsp, sp) != lfs_sb_getident(lfsp)) { 533 (void)printf("dumplfs: %s %d address 0x%llx\n", 534 "summary from a former life; segment", segnum, 535 (long long)addr); 536 return -1; 537 } 538 539 (void)printf("Segment Summary Info at 0x%llx\n", (long long)addr); 540 ssflags = lfs_ss_getflags(lfsp, sp); 541 (void)printf(" %s0x%jx\t%s%d\t%s%d\t%s%c%c%c%c\n %s0x%x\t%s0x%x", 542 "next ", (intmax_t)lfs_ss_getnext(lfsp, sp), 543 "nfinfo ", lfs_ss_getnfinfo(lfsp, sp), 544 "ninos ", lfs_ss_getninos(lfsp, sp), 545 "flags ", (ssflags & SS_DIROP) ? 'D' : '-', 546 (ssflags & SS_CONT) ? 'C' : '-', 547 (ssflags & SS_CLEAN) ? 'L' : '-', 548 (ssflags & SS_RFW) ? 'R' : '-', 549 "sumsum ", lfs_ss_getsumsum(lfsp, sp), 550 "datasum ", lfs_ss_getdatasum(lfsp, sp)); 551 if (lfs_sb_getversion(lfsp) == 1) { 552 t = lfs_ss_getocreate(lfsp, sp); 553 (void)printf("\tcreate %s\n", ctime(&t)); 554 } else { 555 t = lfs_ss_getcreate(lfsp, sp); 556 (void)printf("\tcreate %s", ctime(&t)); 557 (void)printf(" roll_id %-8x", lfs_ss_getident(lfsp, sp)); 558 (void)printf(" serial %lld\n", 559 (long long)lfs_ss_getserial(lfsp, sp)); 560 } 561 562 /* Dump out inode disk addresses */ 563 /* XXX ondisk32 */ 564 dp = (int32_t *)sp; 565 dp += lfs_sb_getsumsize(lfsp) / sizeof(int32_t); 566 diblock = malloc(lfs_sb_getbsize(lfsp)); 567 printf(" Inode addresses:"); 568 numbytes = 0; 569 numblocks = 0; 570 for (dp--, i = 0; i < lfs_ss_getninos(lfsp, sp); dp--) { 571 ++numblocks; 572 numbytes += lfs_sb_getibsize(lfsp); /* add bytes for inode block */ 573 printf("\t0x%x {", *dp); 574 get(fd, fsbtobyte(lfsp, *dp), diblock, lfs_sb_getibsize(lfsp)); 575 for (j = 0; i < lfs_ss_getninos(lfsp, sp) && j < LFS_INOPB(lfsp); j++, i++) { 576 if (j > 0) 577 (void)printf(", "); 578 dip = DINO_IN_BLOCK(lfsp, diblock, j); 579 (void)printf("%juv%d", lfs_dino_getinumber(lfsp, dip), 580 lfs_dino_getgen(lfsp, dip)); 581 } 582 (void)printf("}"); 583 if (((i/LFS_INOPB(lfsp)) % 4) == 3) 584 (void)printf("\n"); 585 } 586 free(diblock); 587 588 printf("\n"); 589 590 fp = SEGSUM_FINFOBASE(lfsp, sp); 591 for (i = 0; i < lfs_ss_getnfinfo(lfsp, sp); i++) { 592 (void)printf(" FINFO for inode: %ju version %u nblocks %u lastlength %u\n", 593 (uintmax_t)lfs_fi_getino(lfsp, fp), 594 lfs_fi_getversion(lfsp, fp), 595 lfs_fi_getnblocks(lfsp, fp), 596 lfs_fi_getlastlength(lfsp, fp)); 597 lfs_blocks_fromfinfo(lfsp, &fipblocks, fp); 598 numblocks += lfs_fi_getnblocks(lfsp, fp); 599 for (j = 0; j < lfs_fi_getnblocks(lfsp, fp); j++) { 600 (void)printf("\t%jd", 601 (intmax_t)lfs_blocks_get(lfsp, &fipblocks, j)); 602 if ((j % 8) == 7) 603 (void)printf("\n"); 604 if (j == lfs_fi_getnblocks(lfsp, fp) - 1) 605 numbytes += lfs_fi_getlastlength(lfsp, fp); 606 else 607 numbytes += lfs_sb_getbsize(lfsp); 608 } 609 if ((j % 8) != 0) 610 (void)printf("\n"); 611 fp = NEXT_FINFO(lfsp, fp); 612 } 613 614 if (datasum_check == 0) 615 return (numbytes); 616 617 /* 618 * Now that we know the number of blocks, run back through and 619 * compute the data checksum. (A bad data checksum is not enough 620 * to prevent us from continuing, but it odes merit a warning.) 621 */ 622 idp = (int32_t *)sp; 623 idp += lfs_sb_getsumsize(lfsp) / sizeof(int32_t); 624 --idp; 625 if (lfs_sb_getversion(lfsp) == 1) { 626 fp = (FINFO *)((SEGSUM_V1 *)sp + 1); 627 el_size = sizeof(unsigned long); 628 } else { 629 fp = (FINFO *)(sp + 1); 630 el_size = sizeof(u_int32_t); 631 } 632 datap = (char *)malloc(el_size * numblocks); 633 memset(datap, 0, el_size * numblocks); 634 acc = 0; 635 addr += lfs_btofsb(lfsp, lfs_sb_getsumsize(lfsp)); 636 buf = malloc(lfs_sb_getbsize(lfsp)); 637 for (i = 0; i < lfs_ss_getnfinfo(lfsp, sp); i++) { 638 while (addr == *idp) { 639 get(fd, fsbtobyte(lfsp, addr), buf, lfs_sb_getibsize(lfsp)); 640 memcpy(datap + acc * el_size, buf, el_size); 641 addr += lfs_btofsb(lfsp, lfs_sb_getibsize(lfsp)); 642 --idp; 643 ++acc; 644 } 645 for (j = 0; j < lfs_fi_getnblocks(lfsp, fp); j++) { 646 get(fd, fsbtobyte(lfsp, addr), buf, lfs_sb_getfsize(lfsp)); 647 memcpy(datap + acc * el_size, buf, el_size); 648 if (j == lfs_fi_getnblocks(lfsp, fp) - 1) 649 addr += lfs_btofsb(lfsp, lfs_fi_getlastlength(lfsp, fp)); 650 else 651 addr += lfs_btofsb(lfsp, lfs_sb_getbsize(lfsp)); 652 ++acc; 653 } 654 fp = NEXT_FINFO(lfsp, fp); 655 } 656 while (addr == *idp) { 657 get(fd, fsbtobyte(lfsp, addr), buf, lfs_sb_getibsize(lfsp)); 658 memcpy(datap + acc * el_size, buf, el_size); 659 addr += lfs_btofsb(lfsp, lfs_sb_getibsize(lfsp)); 660 --idp; 661 ++acc; 662 } 663 free(buf); 664 if (acc != numblocks) 665 printf("** counted %d blocks but should have been %d\n", 666 acc, numblocks); 667 datasum = cksum(datap, numblocks * el_size); 668 if (datasum != lfs_ss_getdatasum(lfsp, sp)) 669 printf("** computed datasum 0x%lx does not match given datasum 0x%lx\n", (unsigned long)datasum, (unsigned long)lfs_ss_getdatasum(lfsp, sp)); 670 free(datap); 671 672 return (numbytes); 673} 674 675static void 676dump_segment(int fd, int segnum, daddr_t addr, struct lfs *lfsp, int dump_sb) 677{ 678 struct lfs lfs_sb, *sbp; 679 SEGSUM *sump; 680 size_t sumstart; 681 char *sumblock; 682 int did_one, nbytes, sb; 683 off_t sum_offset; 684 daddr_t new_addr; 685 686 (void)printf("\nSEGMENT %lld (Disk Address 0x%llx)\n", 687 (long long)lfs_dtosn(lfsp, addr), (long long)addr); 688 sum_offset = fsbtobyte(lfsp, addr); 689 sumblock = malloc(lfs_sb_getsumsize(lfsp)); 690 691 if (lfs_sb_getversion(lfsp) > 1 && segnum == 0) { 692 if (lfs_fsbtob(lfsp, lfs_sb_gets0addr(lfsp)) < LFS_LABELPAD) { 693 /* First segment eats the disklabel */ 694 sum_offset += lfs_fragroundup(lfsp, LFS_LABELPAD) - 695 lfs_fsbtob(lfsp, lfs_sb_gets0addr(lfsp)); 696 addr += lfs_btofsb(lfsp, lfs_fragroundup(lfsp, LFS_LABELPAD)) - 697 lfs_sb_gets0addr(lfsp); 698 printf("Disklabel at 0x0\n"); 699 } 700 } 701 702 sb = 0; 703 did_one = 0; 704 do { 705 get(fd, sum_offset, sumblock, lfs_sb_getsumsize(lfsp)); 706 sump = (SEGSUM *)sumblock; 707 sumstart = lfs_ss_getsumstart(lfsp); 708 if ((lfs_sb_getversion(lfsp) > 1 && 709 lfs_ss_getident(lfsp, sump) != lfs_sb_getident(lfsp)) || 710 lfs_ss_getsumsum(lfsp, sump) != 711 cksum((char *)sump + sumstart, 712 lfs_sb_getsumsize(lfsp) - sumstart)) { 713 sbp = (struct lfs *)sump; 714 if ((sb = (sbp->lfs_dlfs_u.u_32.dlfs_magic == LFS_MAGIC))) { 715 printf("Superblock at 0x%x\n", 716 (unsigned)lfs_btofsb(lfsp, sum_offset)); 717 if (dump_sb) { 718 __CTASSERT(sizeof(struct dlfs) == 719 sizeof(struct dlfs64)); 720 get(fd, sum_offset, &(lfs_sb.lfs_dlfs_u), 721 sizeof(struct dlfs)); 722 dump_super(&lfs_sb); 723 } 724 if (lfs_sb_getversion(lfsp) > 1) 725 sum_offset += lfs_fragroundup(lfsp, LFS_SBPAD); 726 else 727 sum_offset += LFS_SBPAD; 728 } else if (did_one) 729 break; 730 else { 731 printf("Segment at 0x%llx empty or corrupt\n", 732 (long long)addr); 733 break; 734 } 735 } else { 736 nbytes = dump_sum(fd, lfsp, sump, segnum, 737 lfs_btofsb(lfsp, sum_offset)); 738 if (nbytes >= 0) 739 sum_offset += lfs_sb_getsumsize(lfsp) + nbytes; 740 else 741 sum_offset = 0; 742 did_one = 1; 743 } 744 /* If the segment ends right on a boundary, it still ends */ 745 new_addr = lfs_btofsb(lfsp, sum_offset); 746 /* printf("end daddr = 0x%lx\n", (long)new_addr); */ 747 if (lfs_dtosn(lfsp, new_addr) != lfs_dtosn(lfsp, addr)) 748 break; 749 } while (sum_offset); 750 751 free(sumblock); 752} 753 754static void 755dump_super(struct lfs *lfsp) 756{ 757 time_t stamp; 758 int i; 759 760 (void)printf(" %s0x%-8x %s0x%-8x %s%-10ju\n", 761 "magic ", lfsp->lfs_dlfs_u.u_32.dlfs_magic, 762 "version ", lfs_sb_getversion(lfsp), 763 "size ", (uintmax_t)lfs_sb_getsize(lfsp)); 764 (void)printf(" %s%-10d %s%-10ju %s%-10d\n", 765 "ssize ", lfs_sb_getssize(lfsp), 766 "dsize ", (uintmax_t)lfs_sb_getdsize(lfsp), 767 "bsize ", lfs_sb_getbsize(lfsp)); 768 (void)printf(" %s%-10d %s%-10d %s%-10d\n", 769 "fsize ", lfs_sb_getfsize(lfsp), 770 "frag ", lfs_sb_getfrag(lfsp), 771 "minfree ", lfs_sb_getminfree(lfsp)); 772 (void)printf(" %s%-10d %s%-10d %s%-10d\n", 773 "inopb ", lfs_sb_getinopb(lfsp), 774 "ifpb ", lfs_sb_getifpb(lfsp), 775 "nindir ", lfs_sb_getnindir(lfsp)); 776 (void)printf(" %s%-10d %s%-10d %s%-10d\n", 777 "nseg ", lfs_sb_getnseg(lfsp), 778 "sepb ", lfs_sb_getsepb(lfsp), 779 "cleansz ", lfs_sb_getcleansz(lfsp)); 780 (void)printf(" %s%-10d %s0x%-8x %s%-10d\n", 781 "segtabsz ", lfs_sb_getsegtabsz(lfsp), 782 "segmask ", lfs_sb_getsegmask(lfsp), 783 "segshift ", lfs_sb_getsegshift(lfsp)); 784 (void)printf(" %s0x%-8jx %s%-10d %s0x%-8jX\n", 785 "bmask ", (uintmax_t)lfs_sb_getbmask(lfsp), 786 "bshift ", lfs_sb_getbshift(lfsp), 787 "ffmask ", (uintmax_t)lfs_sb_getffmask(lfsp)); 788 (void)printf(" %s%-10d %s0x%-8jx %s%u\n", 789 "ffshift ", lfs_sb_getffshift(lfsp), 790 "fbmask ", (uintmax_t)lfs_sb_getfbmask(lfsp), 791 "fbshift ", lfs_sb_getfbshift(lfsp)); 792 793 (void)printf(" %s%-10d %s%-10d %s0x%-8x\n", 794 "sushift ", lfs_sb_getsushift(lfsp), 795 "fsbtodb ", lfs_sb_getfsbtodb(lfsp), 796 "cksum ", lfs_sb_getcksum(lfsp)); 797 (void)printf(" %s%-10d %s%-10d %s%-10d\n", 798 "nclean ", lfs_sb_getnclean(lfsp), 799 "dmeta ", lfs_sb_getdmeta(lfsp), 800 "minfreeseg ", lfs_sb_getminfreeseg(lfsp)); 801 (void)printf(" %s0x%-8x %s%-9d %s%-10d\n", 802 "roll_id ", lfs_sb_getident(lfsp), 803 "interleave ", lfs_sb_getinterleave(lfsp), 804 "sumsize ", lfs_sb_getsumsize(lfsp)); 805 (void)printf(" %s%-10jd %s0x%-8jx\n", 806 "seg0addr ", (intmax_t)lfs_sb_gets0addr(lfsp), 807 "maxfilesize ", (uintmax_t)lfs_sb_getmaxfilesize(lfsp)); 808 809 810 (void)printf(" Superblock disk addresses:\n "); 811 for (i = 0; i < LFS_MAXNUMSB; i++) { 812 (void)printf(" 0x%-8jx", (intmax_t)lfs_sb_getsboff(lfsp, i)); 813 if (i == (LFS_MAXNUMSB >> 1)) 814 (void)printf("\n "); 815 } 816 (void)printf("\n"); 817 818 (void)printf(" Checkpoint Info\n"); 819 (void)printf(" %s%-10ju %s0x%-8jx\n", 820 "freehd ", (uintmax_t)lfs_sb_getfreehd(lfsp), 821 "idaddr ", (intmax_t)lfs_sb_getidaddr(lfsp)); 822 (void)printf(" %s%-10d %s%-10jd %s%-10jd\n", 823 "uinodes ", lfs_sb_getuinodes(lfsp), 824 "bfree ", (intmax_t)lfs_sb_getbfree(lfsp), 825 "avail ", (intmax_t)lfs_sb_getavail(lfsp)); 826 (void)printf(" %s%-10ju %s0x%-8jx %s0x%-8jx\n", 827 "nfiles ", (uintmax_t)lfs_sb_getnfiles(lfsp), 828 "lastseg ", (uintmax_t)lfs_sb_getlastseg(lfsp), 829 "nextseg ", (uintmax_t)lfs_sb_getnextseg(lfsp)); 830 (void)printf(" %s0x%-8jx %s0x%-8jx %s%-10ju\n", 831 "curseg ", (uintmax_t)lfs_sb_getcurseg(lfsp), 832 "offset ", (uintmax_t)lfs_sb_getoffset(lfsp), 833 "serial ", (uintmax_t)lfs_sb_getserial(lfsp)); 834 stamp = lfs_sb_gettstamp(lfsp); 835 (void)printf(" tstamp %s", ctime(&stamp)); 836 837 if (!lfsp->lfs_is64) { 838 (void)printf(" 32-bit only derived or constant fields\n"); 839 (void)printf(" %s%-10u\n", 840 "ifile ", lfs_sb_getifile(lfsp)); 841 } 842} 843 844static void 845addseg(char *arg) 846{ 847 SEGLIST *p; 848 849 if ((p = malloc(sizeof(SEGLIST))) == NULL) 850 err(1, "malloc"); 851 p->next = seglist; 852 p->num = atoi(arg); 853 seglist = p; 854} 855 856static void 857dump_cleaner_info(struct lfs *lfsp, void *ipage) 858{ 859 CLEANERINFO *cip; 860 861 cip = (CLEANERINFO *)ipage; 862 if (lfs_sb_getversion(lfsp) > 1) { 863 (void)printf("free_head %ju\n", 864 (uintmax_t)lfs_ci_getfree_head(lfsp, cip)); 865 (void)printf("free_tail %ju\n", 866 (uintmax_t)lfs_ci_getfree_tail(lfsp, cip)); 867 } 868 (void)printf("clean\t%u\tdirty\t%u\n", 869 lfs_ci_getclean(lfsp, cip), lfs_ci_getdirty(lfsp, cip)); 870 (void)printf("bfree\t%jd\tavail\t%jd\n\n", 871 (intmax_t)lfs_ci_getbfree(lfsp, cip), 872 (intmax_t)lfs_ci_getavail(lfsp, cip)); 873} 874 875static void 876usage(void) 877{ 878 (void)fprintf(stderr, "usage: dumplfs [-adiS] [-b blkno] [-I blkno] [-s segno] filesys|device\n"); 879 exit(1); 880} 881