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

244 lines
5.3 KiB
C

#ident "$Revision: 1.4 $"
/**************************************************************************
* *
* Copyright (C) 1992-1994 Silicon Graphics, Inc. *
* *
* These coded instructions, statements, and computer programs contain *
* unpublished proprietary information of Silicon Graphics, Inc., and *
* are protected by Federal copyright law. They may not be disclosed *
* to third parties or copied or duplicated in any form, in whole or *
* in part, without the prior written consent of Silicon Graphics, Inc. *
* *
**************************************************************************/
/*
* Find a block in the filesystem. Print out where its being used, if
* its being used. Used to discover what files are affected by a bad spot.
*/
#include "efs.h"
int fs_fd;
struct efs *fs;
union {
struct efs fs;
char data[BBTOB(BTOBB(sizeof(struct efs)))];
} sblock;
char *progname;
efs_daddr_t bn;
int err;
efs_ino_t inum;
int found;
static void find_file(void);
static void find_inode(void);
static void outofmem(void);
static void search_extents(struct efs_dinode *di);
int
main(int argc, char **argv)
{
int tblock;
progname = argv[0];
if (argc != 3) {
fprintf(stderr, "usage: %s special bn\n", progname);
exit(-1);
}
if ((fs_fd = open(argv[1], O_RDONLY)) < 0) {
fprintf(stderr, "%s: can't open %s\n", progname, argv[1]);
exit(-1);
}
fs = &sblock.fs;
if (efs_mount()) {
fprintf(stderr, "%s: %s is not an extent filesystem\n",
progname, argv[1]);
exit(-1);
}
bn = strtol(argv[2], (char **)0, 0);
if ((bn < 0) || (bn >= fs->fs_size)) {
fprintf(stderr, "%s: block number %d is not valid\n",
progname, bn);
exit(-1);
}
/*
* First figure out if block is being used by the first few blocks.
*/
if (bn == 0) {
printf("Block %d is the unused boot block\n", bn);
exit(0);
}
if (bn == EFS_SUPERBB) {
printf("Block %d is the super block\n", bn);
found++;
}
if (bn == fs->fs_replsb) {
printf("Block %d is the replicated super block\n", bn);
found++;
}
tblock = fs->fs_bmblock ? fs->fs_bmblock : EFS_BITMAPBB;
if ((bn >= tblock) &&
(bn < tblock + BTOBB(fs->fs_bmsize))) {
printf("Block %d is in the bitmap\n", bn);
found++;
}
if (bn > EFS_SUPERBB && bn < fs->fs_firstcg &&
!(bn >= tblock && bn < tblock + BTOBB(fs->fs_bmsize))) {
printf("Block %d is in the unused region between\n", bn);
if (tblock == EFS_BITMAPBB)
printf("the bitmap and the first cylinder group\n");
else
printf("the superblock and the first cylinder group\n");
found++;
}
find_inode();
/*
* See if the block is used within a file.
*/
find_file();
if (!err && !found)
printf("Block %d is an unused free block\n", bn);
if (found > 1)
printf("Block %d was multiply used - filesystem is dirty\n",
bn);
exit(0);
/* NOTREACHED */
}
/*
* See if block is an inode block.
*/
static void
find_inode(void)
{
int i;
efs_daddr_t cgbn;
cgbn = fs->fs_firstcg;
for (i = 0; i < fs->fs_ncg; i++) {
if ((cgbn <= bn) && (bn < cgbn + fs->fs_cgisize)) {
inum = ((bn - cgbn) + i * fs->fs_cgisize) * EFS_INOPBB;
printf("Block %d is used by inodes %d-%d\n",
bn, inum, inum + EFS_INOPBB - 1);
found++;
}
cgbn += fs->fs_cgfsize;
}
}
/*
* Read inode list in, and indirect extents if needed to find where a block
* is being used.
*/
static void
find_file(void)
{
int i;
int j;
struct efs_dinode *di, *ilist;
int ilist_size;
ilist_size = BBTOB(fs->fs_cgisize);
ilist = (struct efs_dinode *) malloc(ilist_size);
if (!ilist)
outofmem();
inum = 0;
for (i = 0; i < fs->fs_ncg; i++) {
di = ilist;
lseek(fs_fd, (long) BBTOB(EFS_CGIMIN(fs, i)), 0);
if (read(fs_fd, (char *) ilist, ilist_size) != ilist_size) {
fprintf(stderr, "%s: read error on cg %d's ilist\n",
progname, i);
/* try to keep going */
err++;
continue;
}
for (j = fs->fs_cgisize * EFS_INOPBB; --j >= 0; di++, inum++) {
if (inum == 0)
continue;
if ((di->di_mode == 0) ||
(di->di_numextents <= 0) ||
(di->di_numextents > EFS_MAXEXTENTS))
continue;
if (((di->di_mode & IFMT) == IFREG) ||
((di->di_mode & IFMT) == IFDIR) ||
((di->di_mode & IFMT) == IFLNK))
search_extents(di);
}
}
free(ilist);
}
static void
search_extents(struct efs_dinode *di)
{
int i;
extent *ex, *exsave;
/*
* Search extents
*/
ex = efs_getextents(di);
exsave = ex;
if (exsave) {
i = di->di_numextents;
while (--i >= 0) {
if ((ex->ex_bn <= bn) &&
(bn < ex->ex_bn + ex->ex_length)) {
printf("Block %d is being used by inode %d\n",
bn, inum);
found++;
}
ex++;
}
free(exsave);
}
/*
* efs_getextents() only returns the extents that map file blocks.
* Look at indirect blocks iff file blocks are indirect.
*/
if (di->di_numextents > EFS_DIRECTEXTENTS) {
ex = &di->di_u.di_extents[0];
i = ex->ex_offset;
while (--i >= 0) {
if ((ex->ex_bn <= bn) &&
(bn < ex->ex_bn + ex->ex_length)) {
printf("Block %d is being used by inode %d as an indirect extent list\n",
bn, inum);
found++;
}
ex++;
}
}
}
void
error(void)
{
int old_errno;
old_errno = errno;
fprintf(stderr, "%s: i/o error\n", progname);
errno = old_errno;
perror(progname);
err++;
}
static void
outofmem(void)
{
fprintf(stderr, "%s: out of memory\n", progname);
exit(1);
}