199 lines
5.0 KiB
C
199 lines
5.0 KiB
C
#define _GNU_SOURCE
|
|
|
|
#include <assert.h>
|
|
#include <errno.h>
|
|
#include <fcntl.h>
|
|
#include <getopt.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <time.h>
|
|
|
|
#include <asm/types.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/resource.h>
|
|
#include <sys/vfs.h>
|
|
|
|
#include "io.h"
|
|
#include "misc.h"
|
|
#include "reiserfs_lib.h"
|
|
|
|
enum {
|
|
USED_BLOCKS,
|
|
ALL_BLOCKS,
|
|
EXTERN_BITMAP
|
|
};
|
|
|
|
typedef struct corrupter_options {
|
|
int bitmap_kind;
|
|
char * bm_name;
|
|
reiserfs_bitmap_t * bm;
|
|
int block_size;
|
|
int offset;
|
|
} corrupter_options_t;
|
|
|
|
#define print_usage_and_exit() {\
|
|
printf ("\nUsage: %s [options] device\n"\
|
|
"Options:\n"\
|
|
" -b bitmap\t\tscan blocks marked in bitmap\n"\
|
|
" -S\t\t\tscan-whole-partition\n"\
|
|
" -s blocksize\t\tfs blocksize\n"\
|
|
" -o bitmap\t\tskip offset blocks\n\n"\
|
|
, argv[0]);\
|
|
exit (16);\
|
|
}
|
|
|
|
static char * parse_options (corrupter_options_t * options, int argc, char * argv [])
|
|
{
|
|
int c;
|
|
options->bitmap_kind = USED_BLOCKS;
|
|
options->block_size = 4096;
|
|
options->offset = 0;
|
|
options->bm_name = NULL;
|
|
options->bm = NULL;
|
|
|
|
while (1) {
|
|
int option_index;
|
|
|
|
c = getopt_long (argc, argv, "Sb:s:o:",
|
|
NULL, &option_index);
|
|
if (c == -1)
|
|
break;
|
|
|
|
switch (c) {
|
|
case 0:
|
|
/* long-only options */
|
|
|
|
break;
|
|
|
|
case 'b': /* --scan-marked-in-bitmap */
|
|
options->bitmap_kind = EXTERN_BITMAP;
|
|
options->bm_name = optarg;
|
|
break;
|
|
|
|
case 'S': /* --scan-whole-partition */
|
|
options->bitmap_kind = ALL_BLOCKS;
|
|
break;
|
|
|
|
case 'o': /* --scan-marked-in-bitmap */
|
|
options->offset = atoi (optarg);
|
|
break;
|
|
|
|
case 's': /* --scan-marked-in-bitmap */
|
|
options->block_size = atoi (optarg);
|
|
break;
|
|
|
|
default:
|
|
print_usage_and_exit();
|
|
}
|
|
}
|
|
|
|
if (optind != argc - 1)
|
|
print_usage_and_exit();
|
|
|
|
return argv[optind];
|
|
}
|
|
|
|
void load_bitmap_from_file (corrupter_options_t * options) {
|
|
FILE * fd;
|
|
|
|
fd = fopen (options->bm_name, "r");
|
|
|
|
if (!fd)
|
|
reiserfs_panic ("%s: could not load bitmap: %s\n", __FUNCTION__, strerror(errno));
|
|
|
|
options->bm = reiserfs_bitmap_load (fd);
|
|
|
|
if (!options->bm)
|
|
reiserfs_panic ("could not load fitmap from \"%s\"", options->bm_name);
|
|
|
|
fclose (fd);
|
|
}
|
|
|
|
void warn_what_will_be_done (corrupter_options_t * options, char * file_name, int bl_count) {
|
|
printf ("====================\n");
|
|
printf ("\tprogram will corrupt %s\n", file_name);
|
|
printf ("\tblock size is %d\n", options->block_size);
|
|
printf ("\toffset is %d blocks\n", options->offset);
|
|
|
|
if (options->bitmap_kind == ALL_BLOCKS) {
|
|
printf ("\tall formatted blocks, bitmap and journal blocks will be corrupted\n");
|
|
} else if (options->bitmap_kind == USED_BLOCKS) {
|
|
printf ("\tall formatted blocks, bitmap and journal blocks which are used in fs bitmap will be corrupted\n");
|
|
} else if (options->bitmap_kind == EXTERN_BITMAP) {
|
|
printf ("\tall formatted blocks, bitmap and journal blocks from bitmap %s will be corrupted\n", options->bm_name);
|
|
}
|
|
|
|
printf ("\tblocks count %d\n", bl_count);
|
|
printf ("====================\n");
|
|
}
|
|
|
|
int main (int argc, char * argv []) {
|
|
corrupter_options_t options;
|
|
char * file_name;
|
|
unsigned int block_count, i;
|
|
reiserfs_filsys_t * fs;
|
|
|
|
file_name = parse_options (&options, argc, argv);
|
|
|
|
fs = reiserfs_open (file_name, O_RDONLY, 0, &options, 1);
|
|
|
|
if (no_reiserfs_found (fs))
|
|
die ("could not open filesystem on \"%s\"", file_name);
|
|
|
|
/* keep SB to separate memory */
|
|
fs->fs_ondisk_sb = getmem(fs->fs_blocksize);
|
|
memcpy (fs->fs_ondisk_sb, fs->fs_super_bh->b_data, fs->fs_blocksize);
|
|
|
|
block_count = get_sb_block_count (fs->fs_ondisk_sb);
|
|
|
|
if (options.bm_name) {
|
|
load_bitmap_from_file (&options);
|
|
} else {
|
|
if (reiserfs_open_ondisk_bitmap (fs))
|
|
die ("could not open bitmap\n");
|
|
|
|
options.bm = reiserfs_create_bitmap (fs->fs_bitmap2->bm_bit_size);
|
|
reiserfs_bitmap_copy (options.bm, fs->fs_bitmap2);
|
|
}
|
|
|
|
if (options.bm && block_count > options.bm->bm_bit_size) {
|
|
printf ("fs is larger (%d blocks) then bitmap (%ld blocks), work with %ld blocks only\n",
|
|
block_count, options.bm->bm_bit_size, options.bm->bm_bit_size);
|
|
block_count = options.bm->bm_bit_size;
|
|
}
|
|
|
|
warn_what_will_be_done (&options, file_name, block_count);
|
|
|
|
for (i = options.offset; i < block_count; i++) {
|
|
int who;
|
|
struct buffer_head * bh;
|
|
/* read every block and corrupt all formatted blocks */
|
|
if (!reiserfs_bitmap_test_bit (options.bm, i))
|
|
continue;
|
|
|
|
bh = bread (fs->fs_dev, i, fs->fs_blocksize);
|
|
|
|
who = who_is_this (bh->b_data, bh->b_size);
|
|
|
|
/*
|
|
if (block of bitmap || block of journal || leaf || internal)
|
|
take N random bytes and write them into N random place
|
|
within the block
|
|
*/
|
|
if (who != THE_SUPER && who != THE_LEAF && who != THE_INTERNAL && who != THE_JDESC &&
|
|
!block_of_bitmap (fs, i) && !block_of_journal (fs, i))
|
|
continue;
|
|
|
|
printf ("\ncorrupt %d ", i);
|
|
}
|
|
|
|
freemem(fs->fs_ondisk_sb);
|
|
|
|
reiserfs_close (fs);
|
|
printf ("\nDone\n");
|
|
return 0;
|
|
}
|