1
0
Files
irix-657m-src/eoe/cmd/efs/tools/prino.c
2022-09-29 17:59:04 +03:00

290 lines
7.0 KiB
C

/*
* Dump an inode out. This is not meant as a complete diagnostic tool, just
* something handy to look at inodes.
*
* Written by: Kipp Hickman
*
* $Source: /proj/irix6.5.7m/isms/eoe/cmd/efs/tools/RCS/prino.c,v $
* $Revision: 1.4 $
* $Date: 1997/06/03 20:58:11 $
*/
/* unlike dino, this program wants a filename, so it only works
on mounted filesystems, which is what I was ususally using
dino for anyway. This saves doing an ls -i on the file to
get its inum, and remembering which drive it is on.
By default, this one checks for contiguous blocks, not
'aligned' blocks, which are pretty much meaningless on
SCSI drives.
*/
#include "efs.h"
#include <sys/stat.h>
#include <sys/dir.h>
#include <strings.h>
char *progname;
int fs_fd;
struct efs *fs;
union {
struct efs fs;
char data[BBTOB(BTOBB(sizeof(struct efs)))];
} sblock;
int aligned_extents = 0, contig_extents = 0;
int docontig = 1;
main(argc, argv)
int argc;
char *argv[];
{
efs_ino_t inum;
register struct efs_dinode *di;
register extent *ex, *exb = NULL;
register int i;
efs_daddr_t nextbn = 0;
int contigext = -1, ext_len;
struct stat sbuf;
char *dname;
progname = argv[0];
if(argc == 3 && *argv[1] == '-' && argv[1][1] == 'a') {
docontig = 0;
argc--, argv++;
}
if (argc != 2) {
fprintf(stderr, "usage: %s [-a] filename\n", progname);
exit(-1);
}
if(stat(argv[1], &sbuf) == 0)
inum = sbuf.st_ino;
else {
fprintf(stderr, "%s can't stat ", progname);
perror(argv[1]);
exit(1);
}
opendisk(sbuf.st_dev);
if ((inum < EFS_ROOTINO) ||
(inum > fs->fs_ipcg * fs->fs_ncg)) {
fprintf(stderr, "%s: inode number %d is not valid\n",
progname, inum);
exit(-1);
}
di = efs_iget(inum);
printf("inode %d at disk block %d offset %d\n",
inum, EFS_ITOBB(fs, inum),
EFS_ITOO(fs, inum) * sizeof(struct efs_dinode));
printf("mode=%07o nlink=%d uid=%d gid=%d size=%d\n",
di->di_mode, di->di_nlink, di->di_uid,
di->di_gid, di->di_size);
printf("atime=%s", ctime(&di->di_atime));
printf("mtime=%s", ctime(&di->di_mtime));
printf("ctime=%s", ctime(&di->di_ctime));
printf("gen=%d numextents=%d vers=%d dev=%x\n",
di->di_gen, di->di_numextents, di->di_version,
di->di_u.di_dev);
if (di->di_numextents > EFS_DIRECTEXTENTS)
dumpindir(di);
else if (di->di_numextents) {
printf("Extent Magic # Disk Block Length Offset Cg\n");
ex = &di->di_u.di_extents[0];
for (i = 0; i < di->di_numextents; i++, ex++) {
if(ex->ex_bn == nextbn) {
contig_extents++;
nextbn += ex->ex_length;
if(docontig) {
if(!exb) {
exb = ex - 1;
contigext = i-1;
ext_len = exb->ex_length;
}
ext_len += ex->ex_length;
continue;
}
}
nextbn = ex->ex_bn + ex->ex_length;
if(i == 0)
continue; /* catch next time or at end of loop */
if(exb) {
prextent(contigext, exb, ext_len);
ext_len = 0;
exb = NULL;
}
else /* print the previous one, since this one might be the
start of a contiguous chunk */
prextent(i-1, ex-1, 0);
}
/* print the last line, which may be a contigous block, or a
single extent */
if(exb)
prextent(contigext, exb, ext_len);
else /* print the previous one, since this one might be the
start of a contiguous chunk */
prextent(i-1, ex-1, 0);
}
if(docontig)
printf("Total of %d contigous extents out of %d\n",
contig_extents, di->di_numextents);
else
printf("Total of %5.2f aligned extents (%d out of %d), %d contigous extents\n",
(float) aligned_extents / (float) di->di_numextents,
aligned_extents, di->di_numextents, contig_extents);
}
/*
* Print out indirect extent information
*/
dumpindir(di)
register struct efs_dinode *di;
{
register extent *ex, *exb = NULL;
register int i, j, k;
char buf[BBSIZE];
int left;
char header = 0;
long bn;
efs_daddr_t nextbn = 0;
int contigext = -1, ext_len, base_ext;
left = di->di_numextents;
for (i = 0; i < di->di_u.di_extents[0].ex_offset; i++) {
printf("Indirect extent #%d: bn=%d len=%d\n",
i, di->di_u.di_extents[i].ex_bn,
di->di_u.di_extents[i].ex_length);
}
for (i = 0; i < di->di_u.di_extents[0].ex_offset && left; i++) {
bn = di->di_u.di_extents[i].ex_bn;
for (j = 0; j < di->di_u.di_extents[i].ex_length && left; j++, bn++) {
lseek(fs_fd, BBTOB(bn), 0);
if (read(fs_fd, buf, BBSIZE) != BBSIZE)
error();
ex = (extent *) buf;
exb = NULL;
nextbn = 0;
base_ext = (j * BBSIZE / sizeof(extent));
for (k = 0; k < BBSIZE / sizeof(extent) && left--; k++, ex++) {
if (!header) {
printf("Extent Magic # Disk Block Length Offset Cg\n");
header = 1;
}
if(ex->ex_bn == nextbn) {
contig_extents++;
nextbn += ex->ex_length;
if(docontig) {
if(!exb) {
exb = ex - 1;
contigext = base_ext + k - 1;
ext_len = exb->ex_length;
}
ext_len += ex->ex_length;
continue;
}
}
nextbn = ex->ex_bn + ex->ex_length;
if(ex == (extent *)buf)
continue; /* catch next time or at end of loop */
if(exb) {
prextent(contigext, exb, ext_len);
ext_len = 0;
exb = NULL;
}
else /* print the previous one, since this one might be the
start of a contiguous chunk */
prextent(base_ext + k-1, ex-1, 0);
}
if(exb) { /* don't do across indirect extents, for now */
prextent(contigext, exb, ext_len);
ext_len = 0;
exb = NULL;
}
else { /* print the previous one, since this one might be the
start of a contiguous chunk */
prextent(base_ext + k-1, ex-1, 0);
}
}
}
}
error()
{
int old_errno;
old_errno = errno;
fprintf(stderr, "%s: i/o error\n", progname);
errno = old_errno;
perror(progname);
exit(-1);
}
prextent(extno, ex, contiglen)
register struct extent *ex;
int extno, contiglen;
{
printf("%6d %6d %12d %6d %6d %4d\n",
extno, ex->ex_magic, ex->ex_bn,
contiglen,
ex->ex_offset,
EFS_BBTOCG(fs, ex->ex_bn));
}
char *
finddev(char *dname, dev_t dnum, unsigned type)
{
DIR *dirp;
struct direct *dp;
struct stat sb;
char path[MAXPATHLEN], *devnam;
dirp = opendir((const char *)dname);
if (dirp == NULL)
return NULL;
strcpy(path, dname);
strcat(path, "/");
devnam = path + strlen(path);
while((dp = readdir(dirp)) != NULL) {
strcpy(devnam, dp->d_name);
if(stat(path, &sb) == 0 && sb.st_rdev == dnum &&
(sb.st_mode & S_IFMT) == type) {
devnam = strdup(path);
if(!devnam)
fprintf(stderr, "couldn't allocate space for pathname %s\n", path);
closedir(dirp);
return devnam;
}
}
closedir(dirp);
return NULL;
}
/* find the disk drive partition and open it. Assumes the device
will be found in /dev/dsk, since we are dealing with mounted
filesystems
*/
opendisk(devnum)
{
char *dname = finddev("/dev/dsk", devnum, S_IFBLK);
if(dname == NULL) {
fprintf(stderr, "%s: can't find device for filesystem\n", progname);
exit(-1);
}
if ((fs_fd = open(dname, O_RDONLY)) < 0) {
fprintf(stderr, "%s: can't open %s\n", progname, dname);
exit(-1);
}
fs = &sblock.fs;
if (efs_mount()) {
fprintf(stderr, "%s: %s is not an extent filesystem\n",
progname, dname);
exit(-1);
}
}