* Copyright (c) 1991 The Regents of the University of California.
* %sccs.include.redist.c%
"@(#) Copyright (c) 1991 The Regents of the University of California.\n\
static char sccsid
[] = "@(#)dumplfs.c 5.5 (Berkeley) %G%";
#include <ufs/ufs/dinode.h>
static void addseg
__P((char *));
static void dump_cleaner_info
__P((struct lfs
*, void *));
static void dump_dinode
__P((struct dinode
*));
static void dump_ifile
__P((int, struct lfs
*, int));
static int dump_ipage_ifile
__P((int, IFILE
*, int));
static int dump_ipage_segusage
__P((struct lfs
*, int, IFILE
*, int));
static void dump_segment
__P((int, int, daddr_t
, struct lfs
*, int));
static int dump_sum
__P((struct lfs
*, SEGSUM
*, int, daddr_t
));
static void dump_super
__P((struct lfs
*));
static void usage
__P((void));
typedef struct seglist SEGLIST
;
/* Segment Usage formats */
(void)printf("segnum\tstatus\tnbytes\t\tlastmod\n")
#define print_suentry(i, sp) \
(void)printf("%d\t%c%c%c\t%d\t%s", i, \
(((sp)->su_flags & SEGUSE_ACTIVE) ? 'A' : ' '), \
(((sp)->su_flags & SEGUSE_DIRTY) ? 'D' : 'C'), \
(((sp)->su_flags & SEGUSE_SUPERBLOCK) ? 'S' : ' '), \
(sp)->su_nbytes, ctime((time_t *)&(sp)->su_lastmod))
(void)printf("inum\tstatus\tversion\tdaddr\t\tatime\tfreeptr\n")
#define print_ientry(i, ip) \
if (ip->if_daddr == LFS_UNUSED_DADDR) \
(void)printf("%d\tFREE\t%d\t \t\t \t%d\n", \
i, ip->if_version, ip->if_nextfree); \
(void)printf("%d\tINUSE\t%d\t%8X \t%s\n", \
i, ip->if_version, ip->if_daddr, \
ctime((time_t *)&ip->if_st_atime))
struct lfs lfs_sb1
, lfs_sb2
, *lfs_master
;
int ch
, do_allsb
, do_ientries
, fd
, segnum
;
while ((ch
= getopt(argc
, argv
, "ais:")) != EOF
)
case 'a': /* Dump all superblocks */
case 'i': /* Dump ifile entries */
case 's': /* Dump out these segments */
if ((fd
= open(special
, O_RDONLY
, 0)) < 0)
err("%s: %s", special
, strerror(errno
));
/* Read the first superblock */
get(fd
, LFS_LABELPAD
, &lfs_sb1
, sizeof(struct lfs
));
daddr_shift
= lfs_sb1
.lfs_bshift
- lfs_sb1
.lfs_fsbtodb
;
* Read the second superblock and figure out which check point is
lfs_sb1
.lfs_sboffs
[1] << daddr_shift
, &lfs_sb2
, sizeof(struct lfs
));
if (lfs_sb1
.lfs_tstamp
< lfs_sb2
.lfs_tstamp
)
(void)printf("Master Superblock:\n");
dump_ifile(fd
, lfs_master
, do_ientries
);
for (; seglist
!= NULL
; seglist
= seglist
->next
) {
seg_addr
= lfs_master
->lfs_sboffs
[0] + seglist
->num
*
(lfs_master
->lfs_ssize
<< lfs_master
->lfs_fsbtodb
);
seglist
->num
, seg_addr
, lfs_master
, do_allsb
);
for (segnum
= 0, seg_addr
= lfs_master
->lfs_sboffs
[0];
segnum
< lfs_master
->lfs_nseg
; segnum
++, seg_addr
+=
lfs_master
->lfs_ssize
<< lfs_master
->lfs_fsbtodb
)
segnum
, seg_addr
, lfs_master
, do_allsb
);
* We are reading all the blocks of an inode and dumping out the ifile table.
* This code could be tighter, but this is a first pass at getting the stuff
* printed out rather than making this code incredibly efficient.
dump_ifile(fd
, lfsp
, do_ientries
)
struct dinode
*dip
, *dpage
;
daddr_t addr
, *addrp
, *dindir
, *iaddrp
, *indir
;
int block_limit
, i
, inum
, j
, nblocks
, nsupb
, psize
;
if (!(dip
= dpage
= malloc(psize
)))
err("%s", strerror(errno
));
get(fd
, addr
<< daddr_shift
, dip
, psize
);
for (i
= 0; i
< lfsp
->lfs_inopb
; i
++, dip
++)
if (dip
->di_inum
== LFS_IFILE_INUM
)
if (i
>= lfsp
->lfs_inopb
)
err("unable to locate ifile inode");
(void)printf("\nIFILE inode\n");
(void)printf("\nIFILE contents\n");
nblocks
= dip
->di_size
>> lfsp
->lfs_bshift
;
block_limit
= MIN(nblocks
, NDADDR
);
/* Get the direct block */
if ((ipage
= malloc(psize
)) == NULL
)
err("%s", strerror(errno
));
for (inum
= 0, addrp
= dip
->di_db
, i
= 0; i
< block_limit
;
get(fd
, *addrp
<< daddr_shift
, ipage
, psize
);
if (i
< lfsp
->lfs_cleansz
) {
dump_cleaner_info(lfsp
, ipage
);
if (i
< lfsp
->lfs_segtabsz
) {
inum
= dump_ipage_segusage(lfsp
, inum
, ipage
,
inum
= dump_ipage_ifile(inum
, ipage
, lfsp
->lfs_ifpb
);
/* Dump out blocks off of single indirect block */
if (!(indir
= malloc(psize
)))
err("%s", strerror(errno
));
get(fd
, dip
->di_ib
[0] << daddr_shift
, indir
, psize
);
block_limit
= MIN(i
+ lfsp
->lfs_nindir
, nblocks
);
for (addrp
= indir
; i
< block_limit
; i
++, addrp
++) {
if (*addrp
== LFS_UNUSED_DADDR
)
get(fd
, *addrp
<< daddr_shift
,ipage
, psize
);
if (i
< lfsp
->lfs_cleansz
) {
dump_cleaner_info(lfsp
, ipage
);
if (i
< lfsp
->lfs_segtabsz
) {
inum
= dump_ipage_segusage(lfsp
, inum
, ipage
,
inum
= dump_ipage_ifile(inum
, ipage
, lfsp
->lfs_ifpb
);
if (nblocks
<= lfsp
->lfs_nindir
* lfsp
->lfs_ifpb
)
/* Get the double indirect block */
if (!(dindir
= malloc(psize
)))
err("%s", strerror(errno
));
get(fd
, dip
->di_ib
[1] << daddr_shift
, dindir
, psize
);
for (iaddrp
= dindir
, j
= 0; j
< lfsp
->lfs_nindir
; j
++, iaddrp
++) {
if (*iaddrp
== LFS_UNUSED_DADDR
)
get(fd
, *iaddrp
<< daddr_shift
, indir
, psize
);
block_limit
= MIN(i
+ lfsp
->lfs_nindir
, nblocks
);
for (addrp
= indir
; i
< block_limit
; i
++, addrp
++) {
if (*addrp
== LFS_UNUSED_DADDR
)
get(fd
, *addrp
<< daddr_shift
, ipage
, psize
);
if (i
< lfsp
->lfs_cleansz
) {
dump_cleaner_info(lfsp
, ipage
);
if (i
< lfsp
->lfs_segtabsz
) {
inum
= dump_ipage_segusage(lfsp
,
inum
, ipage
, lfsp
->lfs_sepb
);
inum
= dump_ipage_ifile(inum
,
dump_ipage_ifile(i
, pp
, tot
)
for (ip
= pp
, cnt
= i
; cnt
< max
; cnt
++, ip
++)
dump_ipage_segusage(lfsp
, i
, pp
, tot
)
for (sp
= (SEGUSE
*)pp
, cnt
= i
;
cnt
< lfsp
->lfs_nseg
&& cnt
< max
; cnt
++, sp
++)
if (max
>= lfsp
->lfs_nseg
)
(void)printf("%s%d\t%s%d\t%s%d\t%s%d\t%s%d\n",
(void)printf("%s%s%s%s%s%s",
"atime ", ctime(&dip
->di_atime
),
"mtime ", ctime(&dip
->di_mtime
),
"ctime ", ctime(&dip
->di_ctime
));
(void)printf("inum %d\n", dip
->di_inum
);
(void)printf("Direct Addresses\n");
for (i
= 0; i
< NDADDR
; i
++) {
(void)printf("\t%X", dip
->di_db
[i
]);
for (i
= 0; i
< NIADDR
; i
++)
(void)printf("\t%X", dip
->di_ib
[i
]);
dump_sum(lfsp
, sp
, segnum
, addr
)
if (sp
->ss_sumsum
!= (ck
= cksum(&sp
->ss_datasum
,
LFS_SUMMARY_SIZE
- sizeof(sp
->ss_sumsum
))))
(void)printf("dumplfs: %s %d address %lx\n",
"corrupt summary block; segment", segnum
, addr
);
(void)printf("Segment Summary Info\n");
(void)printf("\t%s%X\t%s%d\t%s%d\t%s%X\t%s%X\n",
"nfinfo ", sp
->ss_nfinfo
,
"sumsum ", sp
->ss_sumsum
,
"datasum ", sp
->ss_datasum
);
(void)printf("\tcreate %s", ctime((time_t *)&sp
->ss_create
));
numblocks
= (sp
->ss_ninos
+ INOPB(lfsp
) - 1) / INOPB(lfsp
);
/* Dump out inode disk addresses */
dp
+= LFS_SUMMARY_SIZE
/ sizeof(daddr_t
);
printf("\tInode addresses:");
for (dp
--, i
= 0; i
< numblocks
; i
+= INOPB(lfsp
))
for (fp
= (FINFO
*)(sp
+ 1), i
= 0; i
< sp
->ss_nfinfo
; i
++) {
numblocks
+= fp
->fi_nblocks
;
(void)printf("File Info for file: %d version %d nblocks %d\n",
fp
->fi_ino
, fp
->fi_version
, fp
->fi_nblocks
);
dp
= &(fp
->fi_blocks
[0]);
for (j
= 0; j
< fp
->fi_nblocks
; j
++, dp
++) {
(void)printf("\t%d", *dp
);
dump_segment(fd
, segnum
, addr
, lfsp
, dump_sb
)
char sumblock
[LFS_SUMMARY_SIZE
];
int did_one
, nblocks
, sb
;
off_t sum_offset
, super_off
;
(void)printf("\nSegment Number %d (Disk Address %X)\n",
addr
>> (lfsp
->lfs_segshift
- daddr_shift
), addr
);
sum_offset
= (addr
<< (lfsp
->lfs_bshift
- lfsp
->lfs_fsbtodb
));
get(fd
, sum_offset
, sumblock
, LFS_SUMMARY_SIZE
);
sump
= (SEGSUM
*)sumblock
;
if (sump
->ss_sumsum
!= cksum (&sump
->ss_datasum
,
LFS_SUMMARY_SIZE
- sizeof(sump
->ss_sumsum
))) {
sbp
= (struct lfs
*)sump
;
if (sb
= (sbp
->lfs_magic
== LFS_MAGIC
)) {
printf("Segment at %X corrupt\n", addr
);
nblocks
= dump_sum(lfsp
, sump
, segnum
, addr
);
sum_offset
+= (nblocks
<< lfsp
->lfs_bshift
);
get(fd
, super_off
, &lfs_sb
, sizeof(struct lfs
));
(void)printf("%s%X\t%s%X\t%s%d\t%s%d\n",
"magic ", lfsp
->lfs_magic
,
"version ", lfsp
->lfs_version
,
"ssize ", lfsp
->lfs_ssize
);
(void)printf("%s%d\t%s%d\t%s%d\t%s%d\n",
"dsize ", lfsp
->lfs_dsize
,
"bsize ", lfsp
->lfs_bsize
,
"fsize ", lfsp
->lfs_fsize
,
"frag ", lfsp
->lfs_frag
);
(void)printf("%s%d\t%s%d\t%s%d\t%s%d\n",
"minfree ", lfsp
->lfs_minfree
,
"inopb ", lfsp
->lfs_inopb
,
"nindir ", lfsp
->lfs_nindir
);
(void)printf("%s%d\t%s%d\t%s%d\t%s%d\n",
"cleansz ", lfsp
->lfs_cleansz
,
"segtabsz ", lfsp
->lfs_segtabsz
);
(void)printf("%s%X\t%s%d\t%s%X\t%s%d\n",
"segmask ", lfsp
->lfs_segmask
,
"segshift ", lfsp
->lfs_segshift
,
"bmask ", lfsp
->lfs_bmask
,
"bshift ", lfsp
->lfs_bshift
);
(void)printf("%s%X\t%s%d\t%s%X\t%s%d\n",
"ffmask ", lfsp
->lfs_ffmask
,
"ffshift ", lfsp
->lfs_ffshift
,
"fbmask ", lfsp
->lfs_fbmask
,
"fbshift ", lfsp
->lfs_fbshift
);
(void)printf("%s%d\t%s%X\n",
"fsbtodb ", lfsp
->lfs_fsbtodb
,
"cksum ", lfsp
->lfs_cksum
);
(void)printf("Superblock disk addresses:");
for (i
= 0; i
< LFS_MAXNUMSB
; i
++)
(void)printf(" %X", lfsp
->lfs_sboffs
[i
]);
(void)printf("Checkpoint Info\n");
(void)printf("%s%d\t%s%X\t%s%d\n",
"idaddr ", lfsp
->lfs_idaddr
,
"ifile ", lfsp
->lfs_ifile
);
(void)printf("%s%X\t%s%d\t%s%X\t%s%X\t%s%X\t%s%X\n",
"bfree ", lfsp
->lfs_bfree
,
"nfiles ", lfsp
->lfs_nfiles
,
"lastseg ", lfsp
->lfs_lastseg
,
"nextseg ", lfsp
->lfs_nextseg
,
"curseg ", lfsp
->lfs_curseg
,
"offset ", lfsp
->lfs_offset
);
(void)printf("tstamp %s", ctime((time_t *)&lfsp
->lfs_tstamp
));
if ((p
= malloc(sizeof(SEGLIST
))) == NULL
)
err("%s", strerror(errno
));
dump_cleaner_info(lfsp
, ipage
)
cip
= (CLEANERINFO
*)ipage
;
(void)printf("Cleaner Info\nclean\t%d\tdirty\t%d\n",
(void)fprintf(stderr
, "usage: dumplfs [-ai] [-s segnum] file\n");