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

352 lines
6.8 KiB
C

/*
* Filesystem corrupter for testing fsck.
*
* Written by: Kipp Hickman
*
* $Source: /proj/irix6.5.7m/isms/eoe/cmd/efs/tools/RCS/corrupt.c,v $
* $Revision: 1.2 $
* $Date: 1997/06/03 20:58:03 $
*/
#include "efs.h"
char *progname;
int fs_fd;
struct efs *fs;
char *bitmap;
union {
struct efs fs;
char data[BBTOB(BTOBB(sizeof(struct efs)))];
} sblock;
efs_daddr_t dirbn;
struct efs_dirblk dirblk;
efs_ino_t inum;
int badDirSize();
int badDirMagic();
int badDirSlotCount();
int badDirSlotOffset();
int badDirSlotOverlap();
int badDirName();
int badDirDot();
int badDirDotDot();
struct hows {
char *test;
char *file;
int type;
int (*func)();
} hows[] = {
{ "directory size", "test-dir-1", IFDIR, badDirSize },
{ "directory magic", "test-dir-2", IFDIR, badDirMagic, },
{ "directory slot count", "test-dir-3", IFDIR, badDirSlotCount, },
{ "directory slot offset", "test-dir-4", IFDIR, badDirSlotOffset, },
{ "directory slot overlap", "test-dir-5", IFDIR, badDirSlotOverlap, },
{ "directory name", "test-dir-6", IFDIR, badDirName, },
{ "directory dot", "test-dir-7", IFDIR, badDirDot, },
{ "directory dot dot", "test-dir-8", IFDIR, badDirDotDot, },
};
#define NHOWS (sizeof(hows) / sizeof(struct hows))
struct hows *current;
void verify();
struct efs_dinode *namei();
main(argc, argv)
int argc;
char *argv[];
{
int i;
struct efs_dinode *di;
progname = argv[0];
if (argc != 2) {
fprintf(stderr, "usage: %s device\n", progname);
exit(-1);
}
if ((fs_fd = open(argv[1], O_RDWR)) < 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);
}
current = &hows[0];
for (i = 0; i < NHOWS; i++, current++) {
di = namei(current->file);
printf("%s: test \"corrupt %s\" is messing up inode %u\n",
progname, current->test, inum);
verify(current->type, di);
(*current->func)(di);
}
exit(0);
}
/*
* Make sure the given inode is of the correct type
*/
void
verify(format, di)
int format;
struct efs_dinode *di;
{
if ((di->di_mode & IFMT) != format) {
fprintf(stderr, "%s: file %s should have format %x\n",
progname, current->file, format);
exit(-1);
}
}
/*
* Read in a directory block
*/
void
getDirBlock(di, offset)
struct efs_dinode *di;
off_t offset;
{
dirbn = efs_bmap(di, offset, EFS_DIRBSIZE);
lseek(fs_fd, BBTOB(dirbn), 0);
if (read(fs_fd, (char *) &dirblk, sizeof(dirblk)) != sizeof(dirblk))
error();
}
void
putDirBlock()
{
lseek(fs_fd, BBTOB(dirbn), 0);
if (write(fs_fd, &dirblk, sizeof(dirblk)) != sizeof(dirblk))
error();
}
/*
* Translate a name into an inode pointer. This only searches "/" in the
* filesystem.
*/
struct efs_dinode *
namei(name)
char *name;
{
struct efs_dinode *root;
off_t offset;
struct efs_dirblk *db;
struct efs_dent *dep;
int slot;
int namelen;
root = efs_iget(EFS_ROOTINO);
verify(IFDIR, root);
namelen = strlen(name);
/*
* Search root directory
*/
db = &dirblk;
for (offset = 0; offset < root->di_size; offset += EFS_DIRBSIZE) {
getDirBlock(root, offset);
for (slot = 0; slot < db->slots; slot++) {
if (EFS_SLOTAT(db, slot) == 0)
continue;
dep = EFS_SLOTOFF_TO_DEP(db, EFS_SLOTAT(db, slot));
if ((dep->d_namelen == namelen) &&
(strncmp(dep->d_name, name, namelen) == 0)) {
inum = EFS_GET_INUM(dep);
return efs_iget(inum);
}
}
}
fprintf(stderr, "%s: file \"%s\" not found in filesystem\n",
progname, name);
exit(-1);
}
/*
* Mangle a directories size
*/
badDirSize(di)
struct efs_dinode *di;
{
di->di_size = di->di_size | 1;
efs_iput(di, inum);
}
/*
* Mess up a directories magic number in the first directory block.
*/
badDirMagic(di)
struct efs_dinode *di;
{
getDirBlock(di, 0);
dirblk.magic = 0;
putDirBlock();
}
/*
* Mess up count of directory slots
*/
badDirSlotCount(di)
struct efs_dinode *di;
{
getDirBlock(di, 0);
dirblk.slots = EFS_MAXENTS + 1;
putDirBlock();
}
/*
* Mess up a valid slot offset - push into free space/slot array
*/
badDirSlotOffset(di)
struct efs_dinode *di;
{
int slot;
int slotoff;
getDirBlock(di, 0);
for (slot = 0; slot < dirblk.slots; slot++) {
slotoff = EFS_SLOTAT(&dirblk, slot);
if (slotoff == 0)
continue;
EFS_SET_SLOT(&dirblk, slot, 1);
putDirBlock();
return;
}
fprintf(stderr, "%s: no valid names in directory block for file %s\n",
progname, current->file);
exit(-1);
}
/*
* Make two slots overlap
*/
badDirSlotOverlap(di)
struct efs_dinode *di;
{
int slot, slot1, slot2;
int slotoff;
getDirBlock(di, 0);
slot1 = slot2 = 0;
for (slot = 0; slot < dirblk.slots; slot++) {
slotoff = EFS_SLOTAT(&dirblk, slot);
if (slotoff == 0)
continue;
if (slot1) {
slot2 = slot;
break;
}
slot1 = slot;
}
if ((slot1 == 0) || (slot2 == 0)) {
fprintf(stderr,
"%s: no valid names in directory block for file %s\n",
progname, current->file);
exit(-1);
}
EFS_SET_SLOT(&dirblk, slot1,
EFS_COMPACT(EFS_SLOTAT(&dirblk, slot2) + 2));
putDirBlock();
}
/*
* Put some slashes and null's into a directory name
*/
badDirName(di)
struct efs_dinode *di;
{
int slot;
int slotoff;
struct efs_dent *dep;
getDirBlock(di, 0);
for (slot = 0; slot < dirblk.slots; slot++) {
slotoff = EFS_SLOTAT(&dirblk, slot);
if (slotoff == 0)
continue;
dep = EFS_SLOTOFF_TO_DEP(&dirblk, slotoff);
if (dep->d_namelen < 2)
continue;
dep->d_name[0] = '/';
dep->d_name[1] = 0;
putDirBlock();
return;
}
fprintf(stderr, "%s: no valid names in directory block for file %s\n",
progname, current->file);
exit(-1);
}
/*
* Mess up the directory name "."
*/
badDirDot(di)
struct efs_dinode *di;
{
int slot;
int slotoff;
struct efs_dent *dep;
getDirBlock(di, 0);
for (slot = 0; slot < dirblk.slots; slot++) {
slotoff = EFS_SLOTAT(&dirblk, slot);
if (slotoff == 0)
continue;
dep = EFS_SLOTOFF_TO_DEP(&dirblk, slotoff);
if ((dep->d_namelen != 1) ||
(dep->d_name[0] != '.'))
continue;
dep->d_name[0] = 'Z';
putDirBlock();
return;
}
fprintf(stderr, "%s: no valid \".\" in directory block for file %s\n",
progname, current->file);
exit(-1);
}
/*
* Mess up the directory name "."
*/
badDirDotDot(di)
struct efs_dinode *di;
{
int slot;
int slotoff;
struct efs_dent *dep;
getDirBlock(di, 0);
for (slot = 0; slot < dirblk.slots; slot++) {
slotoff = EFS_SLOTAT(&dirblk, slot);
if (slotoff == 0)
continue;
dep = EFS_SLOTOFF_TO_DEP(&dirblk, slotoff);
if ((dep->d_namelen != 2) ||
(dep->d_name[0] != '.') ||
(dep->d_name[1] != '.'))
continue;
dep->d_name[0] = 'Z';
dep->d_name[1] = 'Z';
putDirBlock();
return;
}
fprintf(stderr, "%s: no valid \"..\" in directory block for file %s\n",
progname, current->file);
exit(-1);
}
error()
{
int old_errno;
extern int errno;
old_errno = errno;
fprintf(stderr, "%s: i/o error\n", progname);
errno = old_errno;
perror(current->test);
exit(-1);
}