Something i always wanted to see: add a function to print the list of

blocks allocated by some inode.  Indirect blocks are printed
recursively, so beware :), the list could become lengthy...
(We should probably add some output pager to fsdb.)

MFC after:	1 month
This commit is contained in:
Joerg Wunsch 2002-01-26 15:53:23 +00:00
parent b81ba372c5
commit 280a49ec4b
4 changed files with 164 additions and 19 deletions

View File

@ -109,6 +109,10 @@ This command is valid only if the starting inode is a directory.
.It Cm print .It Cm print
Print out the active inode. Print out the active inode.
.Pp .Pp
.It Cm blocks
Print out the block list of the active inode.
Note that the printout could become long for large files, since all
indirect block pointers will also be printed.
.It Cm uplink .It Cm uplink
Increment the active inode's link count. Increment the active inode's link count.
.Pp .Pp

View File

@ -125,6 +125,7 @@ main(argc, argv)
CMDFUNC(helpfn); CMDFUNC(helpfn);
CMDFUNC(focus); /* focus on inode */ CMDFUNC(focus); /* focus on inode */
CMDFUNC(active); /* print active inode */ CMDFUNC(active); /* print active inode */
CMDFUNC(blocks); /* print blocks for active inode */
CMDFUNC(focusname); /* focus by name */ CMDFUNC(focusname); /* focus by name */
CMDFUNC(zapi); /* clear inode */ CMDFUNC(zapi); /* clear inode */
CMDFUNC(uplink); /* incr link */ CMDFUNC(uplink); /* incr link */
@ -158,6 +159,7 @@ struct cmdtable cmds[] = {
{ "back", "Go to previous active inode", 1, 1, FL_RO, back }, { "back", "Go to previous active inode", 1, 1, FL_RO, back },
{ "active", "Print active inode", 1, 1, FL_RO, active }, { "active", "Print active inode", 1, 1, FL_RO, active },
{ "print", "Print active inode", 1, 1, FL_RO, active }, { "print", "Print active inode", 1, 1, FL_RO, active },
{ "blocks", "Print block numbers of active inode", 1, 1, FL_RO, blocks },
{ "uplink", "Increment link count", 1, 1, FL_WR, uplink }, { "uplink", "Increment link count", 1, 1, FL_WR, uplink },
{ "downlink", "Decrement link count", 1, 1, FL_WR, downlink }, { "downlink", "Decrement link count", 1, 1, FL_WR, downlink },
{ "linkcount", "Set link count to COUNT", 2, 2, FL_WR, linkcount }, { "linkcount", "Set link count to COUNT", 2, 2, FL_WR, linkcount },
@ -224,7 +226,7 @@ cmdloop()
curinode = ginode(ROOTINO); curinode = ginode(ROOTINO);
curinum = ROOTINO; curinum = ROOTINO;
printactive(); printactive(0);
hist = history_init(); hist = history_init();
history(hist, &he, H_EVENT, 100); /* 100 elt history buffer */ history(hist, &he, H_EVENT, 100); /* 100 elt history buffer */
@ -307,7 +309,7 @@ CMDFUNCSTART(focus)
curinode = ginode(inum); curinode = ginode(inum);
ocurrent = curinum; ocurrent = curinum;
curinum = inum; curinum = inum;
printactive(); printactive(0);
return 0; return 0;
} }
@ -315,7 +317,7 @@ CMDFUNCSTART(back)
{ {
curinum = ocurrent; curinum = ocurrent;
curinode = ginode(curinum); curinode = ginode(curinum);
printactive(); printactive(0);
return 0; return 0;
} }
@ -336,10 +338,15 @@ CMDFUNCSTART(zapi)
CMDFUNCSTART(active) CMDFUNCSTART(active)
{ {
printactive(); printactive(0);
return 0; return 0;
} }
CMDFUNCSTART(blocks)
{
printactive(1);
return 0;
}
CMDFUNCSTART(quit) CMDFUNCSTART(quit)
{ {
@ -431,7 +438,7 @@ dolookup(name)
if (ckinode(curinode, &idesc) & FOUND) { if (ckinode(curinode, &idesc) & FOUND) {
curinum = idesc.id_parent; curinum = idesc.id_parent;
curinode = ginode(curinum); curinode = ginode(curinum);
printactive(); printactive(0);
return 1; return 1;
} else { } else {
warnx("name `%s' not found in current inode directory", name); warnx("name `%s' not found in current inode directory", name);
@ -639,7 +646,7 @@ CMDFUNCSTART(newtype)
curinode->di_mode &= ~IFMT; curinode->di_mode &= ~IFMT;
curinode->di_mode |= type; curinode->di_mode |= type;
inodirty(); inodirty();
printactive(); printactive(0);
return 0; return 0;
} }
@ -660,7 +667,7 @@ CMDFUNCSTART(chlen)
curinode->di_size = len; curinode->di_size = len;
inodirty(); inodirty();
printactive(); printactive(0);
return rval; return rval;
} }
@ -682,7 +689,7 @@ CMDFUNCSTART(chmode)
curinode->di_mode &= ~07777; curinode->di_mode &= ~07777;
curinode->di_mode |= modebits; curinode->di_mode |= modebits;
inodirty(); inodirty();
printactive(); printactive(0);
return rval; return rval;
} }
@ -707,7 +714,7 @@ CMDFUNCSTART(chaflags)
} }
curinode->di_flags = flags; curinode->di_flags = flags;
inodirty(); inodirty();
printactive(); printactive(0);
return rval; return rval;
} }
@ -732,7 +739,7 @@ CMDFUNCSTART(chgen)
} }
curinode->di_gen = gen; curinode->di_gen = gen;
inodirty(); inodirty();
printactive(); printactive(0);
return rval; return rval;
} }
@ -757,7 +764,7 @@ CMDFUNCSTART(linkcount)
curinode->di_nlink = lcnt; curinode->di_nlink = lcnt;
inodirty(); inodirty();
printactive(); printactive(0);
return rval; return rval;
} }
@ -784,7 +791,7 @@ CMDFUNCSTART(chowner)
curinode->di_uid = uid; curinode->di_uid = uid;
inodirty(); inodirty();
printactive(); printactive(0);
return rval; return rval;
} }
@ -810,7 +817,7 @@ CMDFUNCSTART(chgroup)
curinode->di_gid = gid; curinode->di_gid = gid;
inodirty(); inodirty();
printactive(); printactive(0);
return rval; return rval;
} }
@ -876,7 +883,7 @@ CMDFUNCSTART(chmtime)
if (dotime(argv[1], &curinode->di_ctime)) if (dotime(argv[1], &curinode->di_ctime))
return 1; return 1;
inodirty(); inodirty();
printactive(); printactive(0);
return 0; return 0;
} }
@ -885,7 +892,7 @@ CMDFUNCSTART(chatime)
if (dotime(argv[1], &curinode->di_ctime)) if (dotime(argv[1], &curinode->di_ctime))
return 1; return 1;
inodirty(); inodirty();
printactive(); printactive(0);
return 0; return 0;
} }
@ -894,6 +901,6 @@ CMDFUNCSTART(chctime)
if (dotime(argv[1], &curinode->di_ctime)) if (dotime(argv[1], &curinode->di_ctime))
return 1; return 1;
inodirty(); inodirty();
printactive(); printactive(0);
return 0; return 0;
} }

View File

@ -57,6 +57,6 @@ int argcount __P((struct cmdtable *cmdp, int argc, char *argv[]));
char **crack __P((char *line, int *argc)); char **crack __P((char *line, int *argc));
char **recrack __P((char *line, int *argc, int argc_max)); char **recrack __P((char *line, int *argc, int argc_max));
void printstat __P((const char *cp, ino_t inum, struct dinode *dp)); void printstat __P((const char *cp, ino_t inum, struct dinode *dp));
int printactive __P((void)); int printactive __P((int doblocks));
int checkactive __P((void)); int checkactive __P((void));
int checkactivedir __P((void)); int checkactivedir __P((void));

View File

@ -44,9 +44,15 @@ static const char rcsid[] =
#include <ufs/ufs/dinode.h> #include <ufs/ufs/dinode.h>
#include <ufs/ffs/fs.h> #include <ufs/ffs/fs.h>
#include <sys/ioctl.h>
#include "fsdb.h" #include "fsdb.h"
#include "fsck.h" #include "fsck.h"
static int charsperline __P((void));
static int printindir __P((ufs_daddr_t blk, int level, char *bufp));
static void printblocks __P((ino_t inum, struct dinode *dp));
char ** char **
crack(line, argc) crack(line, argc)
char *line; char *line;
@ -176,6 +182,130 @@ printstat(cp, inum, dp)
dp->di_blocks, dp->di_gen); dp->di_blocks, dp->di_gen);
} }
/*
* Determine the number of characters in a
* single line.
*/
static int
charsperline()
{
int columns;
char *cp;
struct winsize ws;
columns = 0;
if (ioctl(0, TIOCGWINSZ, &ws) != -1)
columns = ws.ws_col;
if (columns == 0 && (cp = getenv("COLUMNS")))
columns = atoi(cp);
if (columns == 0)
columns = 80; /* last resort */
return (columns);
}
/*
* Recursively print a list of indirect blocks.
*/
static int
printindir(blk, level, bufp)
ufs_daddr_t blk;
int level;
char *bufp;
{
struct bufarea buf, *bp;
char tempbuf[32]; /* enough to print an ufs_daddr_t */
int i, j, cpl, charssofar;
ufs_daddr_t blkno;
if (level == 0) {
/* for the final indirect level, don't use the cache */
bp = &buf;
bp->b_un.b_buf = bufp;
bp->b_prev = bp->b_next = bp;
initbarea(bp);
getblk(bp, blk, sblock.fs_bsize);
} else
bp = getdatablk(blk, sblock.fs_bsize);
cpl = charsperline();
for (i = charssofar = 0; i < NINDIR(&sblock); i++) {
blkno = bp->b_un.b_indir[i];
if (blkno == 0) {
if (level == 0)
putchar('\n');
return 0;
}
j = sprintf(tempbuf, "%d", blkno);
if (level == 0) {
charssofar += j;
if (charssofar >= cpl - 2) {
putchar('\n');
charssofar = j;
}
}
fputs(tempbuf, stdout);
if (level == 0) {
printf(", ");
charssofar += 2;
} else {
printf(" =>\n");
if (printindir(blkno, level - 1, bufp) == 0)
return 0;
}
}
if (level == 0)
putchar('\n');
return 1;
}
/*
* Print the block pointers for one inode.
*/
static void
printblocks(inum, dp)
ino_t inum;
struct dinode *dp;
{
char *bufp;
int i, j, nfrags;
long ndb, offset;
printf("Blocks for inode %d:\n", inum);
printf("Direct blocks:\n");
ndb = howmany(dp->di_size, sblock.fs_bsize);
for (i = 0; i < NDADDR; i++) {
if (dp->di_db[i] == 0) {
putchar('\n');
return;
}
if (i > 0)
printf(", ");
printf("%d", dp->di_db[i]);
if (--ndb == 0 && (offset = blkoff(&sblock, dp->di_size)) != 0) {
nfrags = numfrags(&sblock, fragroundup(&sblock, offset));
printf(" (%d frag%s)", nfrags, nfrags > 1? "s": "");
}
}
putchar('\n');
if (dp->di_ib[0] == 0)
return;
bufp = malloc((unsigned int)sblock.fs_bsize);
if (bufp == 0)
errx(EEXIT, "cannot allocate indirect block buffer");
printf("Indirect blocks:\n");
for (i = 0; i < NIADDR; i++)
if (printindir(dp->di_ib[i], i, bufp) == 0)
break;
free(bufp);
}
int int
checkactive() checkactive()
{ {
@ -201,7 +331,8 @@ checkactivedir()
} }
int int
printactive() printactive(doblocks)
int doblocks;
{ {
if (!checkactive()) if (!checkactive())
return 1; return 1;
@ -213,7 +344,10 @@ printactive()
case IFLNK: case IFLNK:
case IFSOCK: case IFSOCK:
case IFIFO: case IFIFO:
printstat("current inode", curinum, curinode); if (doblocks)
printblocks(curinum, curinode);
else
printstat("current inode", curinum, curinode);
break; break;
case 0: case 0:
printf("current inode %d: unallocated inode\n", curinum); printf("current inode %d: unallocated inode\n", curinum);