#define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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; }