dumplfs.c revision 1.15
1/* $NetBSD: dumplfs.c,v 1.15 2000/06/25 21:36:16 perseant 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. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by the University of 18 * California, Berkeley and its contributors. 19 * 4. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36#include <sys/cdefs.h> 37 38#ifndef lint 39__COPYRIGHT( 40"@(#) Copyright (c) 1991, 1993\n\ 41 The Regents of the University of California. All rights reserved.\n"); 42#endif /* not lint */ 43 44#ifndef lint 45#if 0 46static char sccsid[] = "@(#)dumplfs.c 8.5 (Berkeley) 5/24/95"; 47#else 48__RCSID("$NetBSD: dumplfs.c,v 1.15 2000/06/25 21:36:16 perseant Exp $"); 49#endif 50#endif /* not lint */ 51 52#include <sys/param.h> 53#include <sys/ucred.h> 54#include <sys/mount.h> 55#include <sys/time.h> 56 57#include <ufs/ufs/dinode.h> 58#include <ufs/lfs/lfs.h> 59 60#include <err.h> 61#include <errno.h> 62#include <fcntl.h> 63#include <fstab.h> 64#include <stdlib.h> 65#include <stdio.h> 66#include <string.h> 67#include <unistd.h> 68#include "extern.h" 69 70static void addseg __P((char *)); 71static void dump_cleaner_info __P((struct lfs *, void *)); 72static void dump_dinode __P((struct dinode *)); 73static void dump_ifile __P((int, struct lfs *, int, int)); 74static int dump_ipage_ifile __P((int, IFILE *, int)); 75static int dump_ipage_segusage __P((struct lfs *, int, IFILE *, int)); 76static void dump_segment __P((int, int, daddr_t, struct lfs *, int)); 77static int dump_sum __P((int, struct lfs *, SEGSUM *, int, daddr_t)); 78static void dump_super __P((struct lfs *)); 79static void usage __P((void)); 80 81int main __P((int, char *[])); 82 83extern u_long cksum __P((void *, size_t)); 84 85typedef struct seglist SEGLIST; 86struct seglist { 87 SEGLIST *next; 88 int num; 89}; 90SEGLIST *seglist; 91 92int daddr_shift; 93char *special; 94 95/* Segment Usage formats */ 96#define print_suheader \ 97 (void)printf("segnum\tflags\tnbytes\tninos\tnsums\tlastmod\n") 98 99#define print_suentry(i, sp) \ 100 (void)printf("%d\t%c%c%c\t%d\t%d\t%d\t%s", i, \ 101 (((sp)->su_flags & SEGUSE_ACTIVE) ? 'A' : ' '), \ 102 (((sp)->su_flags & SEGUSE_DIRTY) ? 'D' : 'C'), \ 103 (((sp)->su_flags & SEGUSE_SUPERBLOCK) ? 'S' : ' '), \ 104 (sp)->su_nbytes, (sp)->su_ninos, (sp)->su_nsums, \ 105 ctime((time_t *)&(sp)->su_lastmod)) 106 107/* Ifile formats */ 108#define print_iheader \ 109 (void)printf("inum\tstatus\tversion\tdaddr\t\tfreeptr\n") 110#define print_ientry(i, ip) \ 111 if (ip->if_daddr == LFS_UNUSED_DADDR) \ 112 (void)printf("%d\tFREE\t%d\t \t\t%d\n", \ 113 i, ip->if_version, ip->if_nextfree); \ 114 else \ 115 (void)printf("%d\tINUSE\t%d\t%8X \n", \ 116 i, ip->if_version, ip->if_daddr) 117 118int 119main(argc, argv) 120 int argc; 121 char *argv[]; 122{ 123 struct lfs lfs_sb1, lfs_sb2, *lfs_master; 124 daddr_t seg_addr, idaddr, sbdaddr; 125 int ch, do_allsb, do_ientries, fd, segnum; 126 127 do_allsb = 0; 128 do_ientries = 0; 129 idaddr = 0x0; 130 sbdaddr = 0x0; 131 while ((ch = getopt(argc, argv, "ab:iI:s:")) != -1) 132 switch(ch) { 133 case 'a': /* Dump all superblocks */ 134 do_allsb = 1; 135 break; 136 case 'b': /* Use this superblock */ 137 sbdaddr = strtol(optarg, NULL, 0); 138 break; 139 case 'i': /* Dump ifile entries */ 140 do_ientries = 1; 141 break; 142 case 'I': /* Use this ifile inode */ 143 idaddr = strtol(optarg, NULL, 0); 144 break; 145 case 's': /* Dump out these segments */ 146 addseg(optarg); 147 break; 148 default: 149 usage(); 150 } 151 argc -= optind; 152 argv += optind; 153 154 if (argc != 1) 155 usage(); 156 157 special = argv[0]; 158 if ((fd = open(special, O_RDONLY, 0)) < 0) 159 err(1, "%s", special); 160 161 if (sbdaddr == 0x0) { 162 /* Read the first superblock */ 163 get(fd, LFS_LABELPAD, &(lfs_sb1.lfs_dlfs), sizeof(struct dlfs)); 164 daddr_shift = lfs_sb1.lfs_bshift - lfs_sb1.lfs_fsbtodb; 165 166 /* 167 * Read the second superblock and figure out which check point is 168 * most up to date. 169 */ 170 get(fd, 171 lfs_sb1.lfs_sboffs[1] << daddr_shift, &(lfs_sb2.lfs_dlfs), sizeof(struct dlfs)); 172 173 lfs_master = &lfs_sb1; 174 if (lfs_sb1.lfs_tstamp > lfs_sb2.lfs_tstamp) { 175 lfs_master = &lfs_sb2; 176 sbdaddr = lfs_sb1.lfs_sboffs[1] << daddr_shift; 177 } else 178 sbdaddr = btodb(LFS_LABELPAD); 179 } else { 180 /* Read the first superblock */ 181 get(fd, dbtob(sbdaddr), &(lfs_sb1.lfs_dlfs), sizeof(struct dlfs)); 182 daddr_shift = lfs_sb1.lfs_bshift - lfs_sb1.lfs_fsbtodb; 183 lfs_master = &lfs_sb1; 184 } 185 186 (void)printf("Master Superblock at 0x%x:\n", sbdaddr); 187 dump_super(lfs_master); 188 189 dump_ifile(fd, lfs_master, do_ientries, idaddr); 190 191 if (seglist != NULL) 192 for (; seglist != NULL; seglist = seglist->next) { 193 seg_addr = lfs_master->lfs_sboffs[0] + seglist->num * 194 (lfs_master->lfs_ssize << lfs_master->lfs_fsbtodb); 195 dump_segment(fd, 196 seglist->num, seg_addr, lfs_master, do_allsb); 197 } 198 else 199 for (segnum = 0, seg_addr = lfs_master->lfs_sboffs[0]; 200 segnum < lfs_master->lfs_nseg; segnum++, seg_addr += 201 lfs_master->lfs_ssize << lfs_master->lfs_fsbtodb) 202 dump_segment(fd, 203 segnum, seg_addr, lfs_master, do_allsb); 204 205 (void)close(fd); 206 exit(0); 207} 208 209/* 210 * We are reading all the blocks of an inode and dumping out the ifile table. 211 * This code could be tighter, but this is a first pass at getting the stuff 212 * printed out rather than making this code incredibly efficient. 213 */ 214static void 215dump_ifile(fd, lfsp, do_ientries, addr) 216 int fd; 217 struct lfs *lfsp; 218 int do_ientries; 219 daddr_t addr; 220{ 221 IFILE *ipage; 222 struct dinode *dip, *dpage; 223 daddr_t *addrp, *dindir, *iaddrp, *indir; 224 int block_limit, i, inum, j, nblocks, psize; 225 226 psize = lfsp->lfs_bsize; 227 if (!addr) 228 addr = lfsp->lfs_idaddr; 229 230 if (!(dpage = malloc(psize))) 231 err(1, "malloc"); 232 get(fd, addr << daddr_shift, dpage, psize); 233 234 for (dip = dpage + INOPB(lfsp) - 1; dip >= dpage; --dip) 235 if (dip->di_inumber == LFS_IFILE_INUM) 236 break; 237 238 if (dip < dpage) 239 errx(1, "unable to locate ifile inode at disk address 0x%x", 240 addr); 241 242 (void)printf("\nIFILE inode\n"); 243 dump_dinode(dip); 244 245 (void)printf("\nIFILE contents\n"); 246 nblocks = dip->di_size >> lfsp->lfs_bshift; 247 block_limit = MIN(nblocks, NDADDR); 248 249 /* Get the direct block */ 250 if ((ipage = malloc(psize)) == NULL) 251 err(1, "malloc"); 252 for (inum = 0, addrp = dip->di_db, i = 0; i < block_limit; 253 i++, addrp++) { 254 get(fd, *addrp << daddr_shift, ipage, psize); 255 if (i < lfsp->lfs_cleansz) { 256 dump_cleaner_info(lfsp, ipage); 257 print_suheader; 258 continue; 259 } 260 261 if (i < (lfsp->lfs_segtabsz + lfsp->lfs_cleansz)) { 262 inum = dump_ipage_segusage(lfsp, inum, ipage, 263 lfsp->lfs_sepb); 264 if (!inum) { 265 if(!do_ientries) 266 goto e0; 267 else 268 print_iheader; 269 } 270 } else 271 inum = dump_ipage_ifile(inum, ipage, lfsp->lfs_ifpb); 272 273 } 274 275 if (nblocks <= NDADDR) 276 goto e0; 277 278 /* Dump out blocks off of single indirect block */ 279 if (!(indir = malloc(psize))) 280 err(1, "malloc"); 281 get(fd, dip->di_ib[0] << daddr_shift, indir, psize); 282 block_limit = MIN(i + lfsp->lfs_nindir, nblocks); 283 for (addrp = indir; i < block_limit; i++, addrp++) { 284 if (*addrp == LFS_UNUSED_DADDR) 285 break; 286 get(fd, *addrp << daddr_shift,ipage, psize); 287 if (i < lfsp->lfs_cleansz) { 288 dump_cleaner_info(lfsp, ipage); 289 continue; 290 } else 291 i -= lfsp->lfs_cleansz; 292 293 if (i < lfsp->lfs_segtabsz) { 294 inum = dump_ipage_segusage(lfsp, inum, ipage, 295 lfsp->lfs_sepb); 296 if (!inum) { 297 if(!do_ientries) 298 goto e1; 299 else 300 print_iheader; 301 } 302 } else 303 inum = dump_ipage_ifile(inum, ipage, lfsp->lfs_ifpb); 304 } 305 306 if (nblocks <= lfsp->lfs_nindir * lfsp->lfs_ifpb) 307 goto e1; 308 309 /* Get the double indirect block */ 310 if (!(dindir = malloc(psize))) 311 err(1, "malloc"); 312 get(fd, dip->di_ib[1] << daddr_shift, dindir, psize); 313 for (iaddrp = dindir, j = 0; j < lfsp->lfs_nindir; j++, iaddrp++) { 314 if (*iaddrp == LFS_UNUSED_DADDR) 315 break; 316 get(fd, *iaddrp << daddr_shift, indir, psize); 317 block_limit = MIN(i + lfsp->lfs_nindir, nblocks); 318 for (addrp = indir; i < block_limit; i++, addrp++) { 319 if (*addrp == LFS_UNUSED_DADDR) 320 break; 321 get(fd, *addrp << daddr_shift, ipage, psize); 322 if (i < lfsp->lfs_cleansz) { 323 dump_cleaner_info(lfsp, ipage); 324 continue; 325 } else 326 i -= lfsp->lfs_cleansz; 327 328 if (i < lfsp->lfs_segtabsz) { 329 inum = dump_ipage_segusage(lfsp, 330 inum, ipage, lfsp->lfs_sepb); 331 if (!inum) { 332 if(!do_ientries) 333 goto e2; 334 else 335 print_iheader; 336 } 337 } else 338 inum = dump_ipage_ifile(inum, 339 ipage, lfsp->lfs_ifpb); 340 } 341 } 342e2: free(dindir); 343e1: free(indir); 344e0: free(dpage); 345 free(ipage); 346} 347 348static int 349dump_ipage_ifile(i, pp, tot) 350 int i; 351 IFILE *pp; 352 int tot; 353{ 354 IFILE *ip; 355 int cnt, max; 356 357 max = i + tot; 358 359 for (ip = pp, cnt = i; cnt < max; cnt++, ip++) 360 print_ientry(cnt, ip); 361 return (max); 362} 363 364static int 365dump_ipage_segusage(lfsp, i, pp, tot) 366 struct lfs *lfsp; 367 int i; 368 IFILE *pp; 369 int tot; 370{ 371 SEGUSE *sp; 372 int cnt, max; 373 struct seglist *slp; 374 375 max = i + tot; 376 for (sp = (SEGUSE *)pp, cnt = i; 377 cnt < lfsp->lfs_nseg && cnt < max; cnt++, sp++) { 378 if (seglist == NULL) 379 print_suentry(cnt, sp); 380 else { 381 for (slp = seglist; slp != NULL; slp = slp->next) 382 if (cnt == slp->num) { 383 print_suentry(cnt, sp); 384 break; 385 } 386 } 387 } 388 if (max >= lfsp->lfs_nseg) 389 return (0); 390 else 391 return (max); 392} 393 394static void 395dump_dinode(dip) 396 struct dinode *dip; 397{ 398 int i; 399 time_t at, mt, ct; 400 401 at = dip->di_atime; 402 mt = dip->di_mtime; 403 ct = dip->di_ctime; 404 405 (void)printf("%s%d\t%s%d\t%s%d\t%s%d\t%s%qu\n", 406 "mode ", dip->di_mode, 407 "nlink ", dip->di_nlink, 408 "uid ", dip->di_uid, 409 "gid ", dip->di_gid, 410 "size ", (long long)dip->di_size); 411 (void)printf("%s%s%s%s%s%s", 412 "atime ", ctime(&at), 413 "mtime ", ctime(&mt), 414 "ctime ", ctime(&ct)); 415 (void)printf("inum %d\n", dip->di_inumber); 416 (void)printf("Direct Addresses\n"); 417 for (i = 0; i < NDADDR; i++) { 418 (void)printf("\t0x%x", dip->di_db[i]); 419 if ((i % 6) == 5) 420 (void)printf("\n"); 421 } 422 for (i = 0; i < NIADDR; i++) 423 (void)printf("\t0x%x", dip->di_ib[i]); 424 (void)printf("\n"); 425} 426 427static int 428dump_sum(fd, lfsp, sp, segnum, addr) 429 struct lfs *lfsp; 430 SEGSUM *sp; 431 int fd, segnum; 432 daddr_t addr; 433{ 434 FINFO *fp; 435 daddr_t *dp; 436 int i, j; 437 int ck; 438 int numbytes; 439 struct dinode *inop; 440 441 if (sp->ss_magic != SS_MAGIC || 442 sp->ss_sumsum != (ck = cksum(&sp->ss_datasum, 443 LFS_SUMMARY_SIZE - sizeof(sp->ss_sumsum)))) { 444 /* Don't print "corrupt" if we're just too close to the edge */ 445 if (datosn(lfsp, addr + fsbtodb(lfsp, lfsp->lfs_bsize)) == 446 datosn(lfsp, addr)) 447 (void)printf("dumplfs: %s %d address 0x%x\n", 448 "corrupt summary block; segment", segnum, 449 addr); 450 return(0); 451 } 452 453 (void)printf("Segment Summary Info at 0x%x\n", addr); 454 (void)printf(" %s0x%x\t%s%d\t%s%d\t%s%c%c\n %s0x%x\t%s0x%x", 455 "next ", sp->ss_next, 456 "nfinfo ", sp->ss_nfinfo, 457 "ninos ", sp->ss_ninos, 458 "flags ", (sp->ss_flags & SS_DIROP) ? 'D' : '-', 459 (sp->ss_flags & SS_CONT) ? 'C' : '-', 460 "sumsum ", sp->ss_sumsum, 461 "datasum ", sp->ss_datasum ); 462 (void)printf("\tcreate %s", ctime((time_t *)&sp->ss_create)); 463 464 /* Dump out inode disk addresses */ 465 dp = (daddr_t *)sp; 466 dp += LFS_SUMMARY_SIZE / sizeof(daddr_t); 467 inop = malloc(1 << lfsp->lfs_bshift); 468 printf(" Inode addresses:"); 469 numbytes = 0; 470 for (dp--, i = 0; i < sp->ss_ninos; dp--) { 471 numbytes += lfsp->lfs_bsize; /* add bytes for inode block */ 472 printf("\t0x%x {", *dp); 473 get(fd, *dp << (lfsp->lfs_bshift - lfsp->lfs_fsbtodb), inop, 474 (1 << lfsp->lfs_bshift)); 475 for (j = 0; i < sp->ss_ninos && j < INOPB(lfsp); j++, i++) { 476 if (j > 0) 477 (void)printf(", "); 478 (void)printf("%d", inop[j].di_inumber); 479 } 480 (void)printf("}"); 481 if (((i/INOPB(lfsp)) % 4) == 3) 482 (void)printf("\n"); 483 } 484 free(inop); 485 486 printf("\n"); 487 for (fp = (FINFO *)(sp + 1), i = 0; i < sp->ss_nfinfo; i++) { 488 (void)printf(" FINFO for inode: %d version %d nblocks %d lastlength %d\n", 489 fp->fi_ino, fp->fi_version, fp->fi_nblocks, 490 fp->fi_lastlength); 491 dp = &(fp->fi_blocks[0]); 492 for (j = 0; j < fp->fi_nblocks; j++, dp++) { 493 (void)printf("\t%d", *dp); 494 if ((j % 8) == 7) 495 (void)printf("\n"); 496 if (j == fp->fi_nblocks - 1) 497 numbytes += fp->fi_lastlength; 498 else 499 numbytes += lfsp->lfs_bsize; 500 } 501 if ((j % 8) != 0) 502 (void)printf("\n"); 503 fp = (FINFO *)dp; 504 } 505 return (numbytes); 506} 507 508static void 509dump_segment(fd, segnum, addr, lfsp, dump_sb) 510 int fd, segnum; 511 daddr_t addr; 512 struct lfs *lfsp; 513 int dump_sb; 514{ 515 struct lfs lfs_sb, *sbp; 516 SEGSUM *sump; 517 char sumblock[LFS_SUMMARY_SIZE]; 518 int did_one, nbytes, sb; 519 off_t sum_offset; 520 daddr_t new_addr; 521 522 (void)printf("\nSEGMENT %d (Disk Address 0x%x)\n", 523 /* addr >> (lfsp->lfs_segshift - daddr_shift), */ 524 datosn(lfsp, addr), 525 addr); 526 sum_offset = (addr << (lfsp->lfs_bshift - lfsp->lfs_fsbtodb)); 527 528 sb = 0; 529 did_one = 0; 530 do { 531 get(fd, sum_offset, sumblock, LFS_SUMMARY_SIZE); 532 sump = (SEGSUM *)sumblock; 533 if (sump->ss_sumsum != cksum (&sump->ss_datasum, 534 LFS_SUMMARY_SIZE - sizeof(sump->ss_sumsum))) { 535 sbp = (struct lfs *)sump; 536 if ((sb = (sbp->lfs_magic == LFS_MAGIC))) { 537 if (dump_sb) { 538 get(fd, sum_offset, &(lfs_sb.lfs_dlfs), 539 sizeof(struct dlfs)); 540 (void)printf("\nSuperblock at 0x%x:\n", 541 (unsigned)btodb(sum_offset)); 542 dump_super(&lfs_sb); 543 (void)printf("%s","\n"); 544 } 545 sum_offset += LFS_SBPAD; 546 } else if (did_one) 547 break; 548 else { 549 printf("Segment at 0x%x corrupt\n", addr); 550 break; 551 } 552 } else { 553 nbytes = dump_sum(fd, lfsp, sump, segnum, sum_offset >> 554 (lfsp->lfs_bshift - lfsp->lfs_fsbtodb)); 555 if (nbytes) 556 sum_offset += LFS_SUMMARY_SIZE + nbytes; 557 else 558 sum_offset = 0; 559 did_one = 1; 560 } 561 /* If the segment ends right on a boundary, it still ends */ 562 new_addr = sum_offset >> (lfsp->lfs_bshift - lfsp->lfs_fsbtodb); 563 if (datosn(lfsp, new_addr) != datosn(lfsp, addr)) 564 break; 565 } while (sum_offset); 566 567 return; 568} 569 570static void 571dump_super(lfsp) 572 struct lfs *lfsp; 573{ 574 int i; 575 576 (void)printf("%s0x%x\t%s0x%x\t%s%d\t%s%d\n", 577 "magic ", lfsp->lfs_magic, 578 "version ", lfsp->lfs_version, 579 "size ", lfsp->lfs_size, 580 "ssize ", lfsp->lfs_ssize); 581 (void)printf("%s%d\t\t%s%d\t%s%d\t%s%d\n", 582 "dsize ", lfsp->lfs_dsize, 583 "bsize ", lfsp->lfs_bsize, 584 "fsize ", lfsp->lfs_fsize, 585 "frag ", lfsp->lfs_frag); 586 587 (void)printf("%s%d\t\t%s%d\t%s%d\t%s%d\n", 588 "minfree ", lfsp->lfs_minfree, 589 "inopb ", lfsp->lfs_inopb, 590 "ifpb ", lfsp->lfs_ifpb, 591 "nindir ", lfsp->lfs_nindir); 592 593 (void)printf("%s%d\t\t%s%d\t%s%d\t%s%d\n", 594 "nseg ", lfsp->lfs_nseg, 595 "nspf ", lfsp->lfs_nspf, 596 "cleansz ", lfsp->lfs_cleansz, 597 "segtabsz ", lfsp->lfs_segtabsz); 598 599 (void)printf("%s0x%x\t%s%d\t%s0x%qX\t%s%d\n", 600 "segmask ", lfsp->lfs_segmask, 601 "segshift ", lfsp->lfs_segshift, 602 "bmask ", (long long)lfsp->lfs_bmask, 603 "bshift ", lfsp->lfs_bshift); 604 605 (void)printf("%s0x%qX\t\t%s%d\t%s0x%qX\t%s%u\n", 606 "ffmask ", (long long)lfsp->lfs_ffmask, 607 "ffshift ", lfsp->lfs_ffshift, 608 "fbmask ", (long long)lfsp->lfs_fbmask, 609 "fbshift ", lfsp->lfs_fbshift); 610 611 (void)printf("%s%d\t%s%d\t%s0x%x\t%s0x%qx\n", 612 "sushift ", lfsp->lfs_sushift, 613 "fsbtodb ", lfsp->lfs_fsbtodb, 614 "cksum ", lfsp->lfs_cksum, 615 "maxfilesize ", (long long)lfsp->lfs_maxfilesize); 616 617 (void)printf("Superblock disk addresses:\t"); 618 for (i = 0; i < LFS_MAXNUMSB; i++) { 619 (void)printf(" 0x%x", lfsp->lfs_sboffs[i]); 620 if ( i == (LFS_MAXNUMSB >> 1)) 621 (void)printf("\n\t\t\t\t"); 622 } 623 (void)printf("\n"); 624 625 (void)printf("Checkpoint Info\n"); 626 (void)printf("%s%d\t%s0x%x\t%s%d\n", 627 "free ", lfsp->lfs_free, 628 "idaddr ", lfsp->lfs_idaddr, 629 "ifile ", lfsp->lfs_ifile); 630 (void)printf("%s%d\t%s%d\t%s%d\n", 631 "bfree ", lfsp->lfs_bfree, 632 "avail ", lfsp->lfs_avail, 633 "uinodes ", lfsp->lfs_uinodes); 634 (void)printf("%s%d\t%s0x%x\t%s0x%x\n%s0x%x\t%s0x%x\t", 635 "nfiles ", lfsp->lfs_nfiles, 636 "lastseg ", lfsp->lfs_lastseg, 637 "nextseg ", lfsp->lfs_nextseg, 638 "curseg ", lfsp->lfs_curseg, 639 "offset ", lfsp->lfs_offset); 640 (void)printf("tstamp %s", ctime((time_t *)&lfsp->lfs_tstamp)); 641#if 0 /* This is no longer stored on disk! --ks */ 642 (void)printf("\nIn-Memory Information\n"); 643 (void)printf("%s%d\t%s0x%x\t%s%d%s%d\t%s%d\n", 644 "seglock ", lfsp->lfs_seglock, 645 "iocount ", lfsp->lfs_iocount, 646 "writer ", lfsp->lfs_writer, 647 "dirops ", lfsp->lfs_dirops, 648 "doifile ", lfsp->lfs_doifile); 649 (void)printf("%s%d\t%s%d\t%s0x%x\t%s%d\n", 650 "nactive ", lfsp->lfs_nactive, 651 "fmod ", lfsp->lfs_fmod, 652 "clean ", lfsp->lfs_clean, 653 "ronly ", lfsp->lfs_ronly); 654#endif 655} 656 657static void 658addseg(arg) 659 char *arg; 660{ 661 SEGLIST *p; 662 663 if ((p = malloc(sizeof(SEGLIST))) == NULL) 664 err(1, "malloc"); 665 p->next = seglist; 666 p->num = atoi(arg); 667 seglist = p; 668} 669 670static void 671dump_cleaner_info(lfsp, ipage) 672 struct lfs *lfsp; 673 void *ipage; 674{ 675 CLEANERINFO *cip; 676 677 cip = (CLEANERINFO *)ipage; 678 (void)printf("segments clean\t%d\tsegments dirty\t%d\n\n", 679 cip->clean, cip->dirty); 680} 681 682static void 683usage() 684{ 685 (void)fprintf(stderr, "usage: dumplfs [-ai] [-s segnum] file\n"); 686 exit(1); 687} 688