Add a new flag to dumpfs(8), -f, which causes dumpfs to list all free
fragments in the file system by fragment (block) number. This new mode does the necessary arithmetic to generate absolute fragment numbers rather than than the cg-relative numbers printed in the default mode. If -f is passed once, contiguous fragment ranges are collapsed into an X-Y format as free block lists are currently printed in regular dumpfs output, but if specified twice, all block numbers are printed individually, allowing both compact and more script-friendly representation. This proves quite handy when attempting to recover deleted data, as it allows exclusion of non-deleted data from blocks searched. MFC after: 1 week Discussed with: jeff, Richard Clayton <richard dot clayton at cl.cam.ac.uk> Sponsored by: Google, Inc.
This commit is contained in:
parent
c27cd4240a
commit
fd15d586ee
@ -36,15 +36,18 @@
|
||||
.Nd dump file system information
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl f
|
||||
.Op Fl m
|
||||
.Ar filesys | device
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
utility prints out the super block and cylinder group information
|
||||
for the file system or special device specified, unless
|
||||
for the file system or special device specified, unless the
|
||||
.Fl f
|
||||
or
|
||||
.Fl m
|
||||
is specified.
|
||||
flag is specified.
|
||||
The listing is very long and detailed.
|
||||
This
|
||||
command is useful mostly for finding out certain file system
|
||||
@ -52,6 +55,15 @@ information such as the file system block size and minimum
|
||||
free space percentage.
|
||||
.Pp
|
||||
If
|
||||
.Fl f
|
||||
is specified, a sorted list of all free fragments and free fragment ranges,
|
||||
as represented in cylinder group block free lists, is printed.
|
||||
If the flag is specified twice, contiguous free fragments are not collapsed
|
||||
into ranges and instead printed in a simple list.
|
||||
Fragment numbers may be converted to raw byte offsets by multiplying by the
|
||||
fragment size, which may be useful when recovering deleted data.
|
||||
.Pp
|
||||
If
|
||||
.Fl m
|
||||
is specified, a
|
||||
.Xr newfs 8
|
||||
|
@ -1,4 +1,10 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Robert N. M. Watson
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software was developed at the University of Cambridge Computer
|
||||
* Laboratory with support from a grant from Google, Inc.
|
||||
*
|
||||
* Copyright (c) 2002 Networks Associates Technology, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
@ -74,8 +80,11 @@ struct uufsd disk;
|
||||
|
||||
int dumpfs(const char *);
|
||||
int dumpcg(void);
|
||||
int dumpfreespace(const char *, int);
|
||||
void dumpfreespacecg(int);
|
||||
int marshal(const char *);
|
||||
void pbits(void *, int);
|
||||
void pblklist(void *, int, off_t, int);
|
||||
void ufserr(const char *);
|
||||
void usage(void) __dead2;
|
||||
|
||||
@ -83,12 +92,15 @@ int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
const char *name;
|
||||
int ch, domarshal, eval;
|
||||
int ch, dofreespace, domarshal, eval;
|
||||
|
||||
domarshal = eval = 0;
|
||||
dofreespace = domarshal = eval = 0;
|
||||
|
||||
while ((ch = getopt(argc, argv, "m")) != -1) {
|
||||
while ((ch = getopt(argc, argv, "fm")) != -1) {
|
||||
switch (ch) {
|
||||
case 'f':
|
||||
dofreespace++;
|
||||
break;
|
||||
case 'm':
|
||||
domarshal = 1;
|
||||
break;
|
||||
@ -102,6 +114,10 @@ main(int argc, char *argv[])
|
||||
|
||||
if (argc < 1)
|
||||
usage();
|
||||
if (dofreespace && domarshal)
|
||||
usage();
|
||||
if (dofreespace > 2)
|
||||
usage();
|
||||
|
||||
while ((name = *argv++) != NULL) {
|
||||
if (ufs_disk_fillout(&disk, name) == -1) {
|
||||
@ -109,7 +125,9 @@ main(int argc, char *argv[])
|
||||
eval |= 1;
|
||||
continue;
|
||||
}
|
||||
if (domarshal)
|
||||
if (dofreespace)
|
||||
eval |= dumpfreespace(name, dofreespace);
|
||||
else if (domarshal)
|
||||
eval |= marshal(name);
|
||||
else
|
||||
eval |= dumpfs(name);
|
||||
@ -332,6 +350,30 @@ dumpcg(void)
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
dumpfreespace(const char *name, int fflag)
|
||||
{
|
||||
int i;
|
||||
|
||||
while ((i = cgread(&disk)) != 0) {
|
||||
if (i == -1)
|
||||
goto err;
|
||||
dumpfreespacecg(fflag);
|
||||
}
|
||||
return (0);
|
||||
err:
|
||||
ufserr(name);
|
||||
return (1);
|
||||
}
|
||||
|
||||
void
|
||||
dumpfreespacecg(int fflag)
|
||||
{
|
||||
|
||||
pblklist(cg_blksfree(&acg), afs.fs_fpg, disk.d_lcg * afs.fs_fpg,
|
||||
fflag);
|
||||
}
|
||||
|
||||
int
|
||||
marshal(const char *name)
|
||||
{
|
||||
@ -400,6 +442,27 @@ pbits(void *vp, int max)
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void
|
||||
pblklist(void *vp, int max, off_t offset, int fflag)
|
||||
{
|
||||
int i, j;
|
||||
char *p;
|
||||
|
||||
for (i = 0, p = vp; i < max; i++) {
|
||||
if (isset(p, i)) {
|
||||
printf("%jd", (intmax_t)(i + offset));
|
||||
if (fflag < 2) {
|
||||
j = i;
|
||||
while ((i+1)<max && isset(p, i+1))
|
||||
i++;
|
||||
if (i != j)
|
||||
printf("-%lld", i + offset);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ufserr(const char *name)
|
||||
{
|
||||
@ -412,6 +475,6 @@ ufserr(const char *name)
|
||||
void
|
||||
usage(void)
|
||||
{
|
||||
(void)fprintf(stderr, "usage: dumpfs [-m] filesys | device\n");
|
||||
(void)fprintf(stderr, "usage: dumpfs [-fm] filesys | device\n");
|
||||
exit(1);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user