This patch just removes trailing whitespace. Signed-off-by: Jeff Mahoney <jeffm@suse.com>
786 lines
18 KiB
C
786 lines
18 KiB
C
/*
|
|
* Copyright 2000-2004 by Hans Reiser, licensing governed by
|
|
* reiserfsprogs/README
|
|
*/
|
|
|
|
#include "debugreiserfs.h"
|
|
|
|
reiserfs_filsys_t *fs;
|
|
|
|
#define print_usage_and_exit() {\
|
|
fprintf (stderr, "Usage: %s [options] device\n\n\
|
|
Options:\n\
|
|
-d\t\tprint blocks details of the internal tree\n\
|
|
-D\t\tprint blocks details of all used blocks\n\
|
|
-B file\textract list of badblocks\n\
|
|
-m\t\tprint bitmap blocks\n\
|
|
-o\t\tprint objectid map\n\n\
|
|
-J\t\tprint journal header\n\
|
|
-j filename\n\t\tprint journal located on the device 'filename'\n\
|
|
\t\tstores the journal in the specified file 'filename.\n\
|
|
-p\t\tsend filesystem metadata to stdout\n\
|
|
-u\t\tread stdin and unpack the metadata\n\
|
|
-S\t\thandle all blocks, not only used\n\
|
|
-1 block\tblock to print\n\
|
|
-q\t\tno speed info\n\
|
|
-V\t\tprint version and exit\n\n", argv[0]);\
|
|
exit (16);\
|
|
}
|
|
|
|
/*
|
|
|
|
Undocumented options:
|
|
-a map_file\n\tstore to the file the map of file. Is used with -n, -N, -r, -f\n
|
|
-f \tprints the file map specified by -a.\n
|
|
-n name\n\stcan device for specific name in reiserfs directories\n\
|
|
-N \tscan tree for specific key in reiserfs directories\n\
|
|
-k \tscan device either for specific key or for any metadata\n\
|
|
-r name\n\trecovers the file spacified by -a to the 'name' file.\n\
|
|
|
|
-S\t\tgo through whole device when running -p, -k or -n\n\
|
|
-U\t\tgo through unused blocks only when running -p, -k or -n\n\
|
|
-D\t\tprint blocks details scanning the device, not the tree as -d does\n\
|
|
-b bitmap_file\n\t\trunning -p, -k or -n read blocks marked in this bitmap only\n\
|
|
-C\tallow to change reiserfs metadata\n\
|
|
-J\tsearch block numbers in the journal\n\
|
|
-t\tstat the device\n\
|
|
-v\tverboes unpack, prints the block number of every block being unpacked\n\
|
|
-Z\tzero all data.
|
|
|
|
To build a map of a file blocks by name:
|
|
debugreiserfs device -a mapfile -n filename
|
|
|
|
To build a map of a file blocks by key:
|
|
debugreiserfs device -a mapfile -k
|
|
|
|
To extract some:
|
|
debugreiserfs device -a mapfile -r filename > backup
|
|
*/
|
|
|
|
#if 1
|
|
struct reiserfs_fsstat {
|
|
unsigned int nr_internals;
|
|
unsigned int nr_leaves;
|
|
unsigned int nr_files;
|
|
unsigned int nr_directories;
|
|
unsigned int nr_unformatted;
|
|
} g_stat_info;
|
|
#endif
|
|
|
|
static void print_disk_tree(reiserfs_filsys_t *fs, unsigned long block_nr)
|
|
{
|
|
struct buffer_head *bh;
|
|
int i, j, count;
|
|
static int level = -1;
|
|
|
|
if (level == -1)
|
|
level = get_sb_tree_height(fs->fs_ondisk_sb);
|
|
|
|
bh = bread(fs->fs_dev, block_nr, fs->fs_blocksize);
|
|
if (!bh) {
|
|
die("Could not read block %lu\n", block_nr);
|
|
}
|
|
level--;
|
|
|
|
if (level < 1)
|
|
die("level too small");
|
|
|
|
if (level != get_blkh_level(B_BLK_HEAD(bh))) {
|
|
printf("%d expected, %d found in %lu\n", level,
|
|
get_blkh_level(B_BLK_HEAD(bh)), bh->b_blocknr);
|
|
}
|
|
|
|
if (is_internal_node(bh)) {
|
|
struct disk_child *dc;
|
|
|
|
g_stat_info.nr_internals++;
|
|
print_block(stdout, fs, bh,
|
|
data(fs)->options & PRINT_TREE_DETAILS, -1, -1);
|
|
|
|
dc = B_N_CHILD(bh, 0);
|
|
count = B_NR_ITEMS(bh);
|
|
for (i = 0; i <= count; i++, dc++)
|
|
print_disk_tree(fs, get_dc_child_blocknr(dc));
|
|
} else if (is_leaf_node(bh)) {
|
|
struct item_head *ih;
|
|
|
|
g_stat_info.nr_leaves++;
|
|
print_block(stdout, fs, bh,
|
|
data(fs)->options & PRINT_TREE_DETAILS, -1, -1);
|
|
|
|
ih = B_N_PITEM_HEAD(bh, 0);
|
|
count = leaf_item_number_estimate(bh);
|
|
for (i = 0; i < count; i++, ih++) {
|
|
if (is_indirect_ih(ih)) {
|
|
__u32 *ind_item = (__u32 *) B_I_PITEM(bh, ih);
|
|
|
|
for (j = 0; j < (int)I_UNFM_NUM(ih); j++) {
|
|
if (d32_get(ind_item, j)) {
|
|
g_stat_info.nr_unformatted += 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
print_block(stdout, fs, bh,
|
|
data(fs)->options & PRINT_TREE_DETAILS, -1, -1);
|
|
|
|
reiserfs_warning(stdout, "print_disk_tree: bad block "
|
|
"type (%b)\n", bh);
|
|
}
|
|
brelse(bh);
|
|
level++;
|
|
}
|
|
|
|
static void print_disk_blocks(reiserfs_filsys_t *fs)
|
|
{
|
|
int type;
|
|
unsigned long done = 0, total;
|
|
struct buffer_head *bh;
|
|
unsigned int j;
|
|
|
|
total = reiserfs_bitmap_ones(input_bitmap(fs));
|
|
|
|
for (j = 0; j < get_sb_block_count(fs->fs_ondisk_sb); j++) {
|
|
if (!reiserfs_bitmap_test_bit(input_bitmap(fs), j))
|
|
continue;
|
|
|
|
print_how_far(stderr, &done, total, 1, be_quiet(fs));
|
|
|
|
bh = bread(fs->fs_dev, j, fs->fs_blocksize);
|
|
if (!bh) {
|
|
reiserfs_warning(stderr, "could not read block %lu\n",
|
|
j);
|
|
continue;
|
|
}
|
|
|
|
type = who_is_this(bh->b_data, bh->b_size);
|
|
if (type != THE_UNKNOWN) {
|
|
print_block(stdout, fs, bh,
|
|
PRINT_TREE_DETAILS | PRINT_DIRECT_ITEMS,
|
|
-1, -1);
|
|
}
|
|
|
|
if (type == THE_INTERNAL)
|
|
g_stat_info.nr_internals++;
|
|
else if (type == THE_LEAF || type == HAS_IH_ARRAY)
|
|
g_stat_info.nr_leaves++;
|
|
|
|
brelse(bh);
|
|
}
|
|
fprintf(stderr, "\n");
|
|
}
|
|
|
|
void pack_one_block(reiserfs_filsys_t *fs, unsigned long block);
|
|
static void print_one_block(reiserfs_filsys_t *fs, unsigned long block)
|
|
{
|
|
struct buffer_head *bh;
|
|
|
|
if (!fs->fs_bitmap2) {
|
|
struct buffer_head *bm_bh;
|
|
unsigned long bm_block;
|
|
|
|
if (spread_bitmaps(fs))
|
|
bm_block =
|
|
(block / (fs->fs_blocksize * 8)) ?
|
|
(block / (fs->fs_blocksize * 8)) *
|
|
(fs->fs_blocksize * 8) :
|
|
fs->fs_super_bh->b_blocknr + 1;
|
|
else
|
|
bm_block = fs->fs_super_bh->b_blocknr + 1 +
|
|
(block / (fs->fs_blocksize * 8));
|
|
|
|
bm_bh = bread(fs->fs_dev, bm_block, fs->fs_blocksize);
|
|
if (bm_bh) {
|
|
if (misc_test_bit((block % (fs->fs_blocksize * 8)),
|
|
bm_bh->b_data)) {
|
|
fprintf(stderr, "%lu is used in "
|
|
"ondisk bitmap\n", block);
|
|
} else {
|
|
fprintf(stderr, "%lu is free in "
|
|
"ondisk bitmap\n", block);
|
|
}
|
|
|
|
brelse(bm_bh);
|
|
}
|
|
} else {
|
|
if (reiserfs_bitmap_test_bit(fs->fs_bitmap2, block))
|
|
fprintf(stderr, "%lu is used in ondisk bitmap\n",
|
|
block);
|
|
else
|
|
fprintf(stderr, "%lu is free in ondisk bitmap\n",
|
|
block);
|
|
}
|
|
|
|
bh = bread(fs->fs_dev, block, fs->fs_blocksize);
|
|
if (!bh) {
|
|
printf("print_one_block: bread failed\n");
|
|
return;
|
|
}
|
|
|
|
if (debug_mode(fs) == DO_PACK) {
|
|
pack_one_block(fs, bh->b_blocknr);
|
|
brelse(bh);
|
|
return;
|
|
}
|
|
|
|
if (who_is_this(bh->b_data, bh->b_size) != THE_UNKNOWN)
|
|
print_block(stdout, fs, bh, PRINT_TREE_DETAILS, -1, -1);
|
|
else
|
|
printf("Looks like unformatted\n");
|
|
brelse(bh);
|
|
return;
|
|
}
|
|
|
|
/* debugreiserfs -p or -P compresses reiserfs meta data: super block, journal,
|
|
bitmap blocks and blocks looking like leaves. It may save "bitmap" of
|
|
blocks they packed in the file of special format. Reiserfsck can then load
|
|
"bitmap" saved in that file and build the tree of blocks marked used in
|
|
that "bitmap"
|
|
*/
|
|
char *where_to_save;
|
|
char *badblocks_file;
|
|
char *corruption_list_file;
|
|
char *program_name;
|
|
|
|
static char *parse_options(struct debugreiserfs_data *data,
|
|
int argc, char *argv[])
|
|
{
|
|
int c;
|
|
char *tmp;
|
|
|
|
data->scan_area = USED_BLOCKS;
|
|
data->mode = DO_DUMP;
|
|
|
|
program_name = strrchr(argv[0], '/');
|
|
|
|
if (program_name)
|
|
program_name++;
|
|
else
|
|
program_name = argv[0];
|
|
|
|
while ((c =
|
|
getopt(argc, argv, "a:b:C:F:SU1:pkn:Nfr:dDomj:JqtZl:LVB:uv"))
|
|
!= EOF) {
|
|
switch (c) {
|
|
case 'a': /* -r will read this, -n and -N will write to it */
|
|
asprintf(&data->map_file, "%s", optarg);
|
|
break;
|
|
|
|
case 'b':
|
|
/* will load bitmap from a file and read only blocks
|
|
marked in it. This is for -p and -k */
|
|
asprintf(&data->input_bitmap, "%s", optarg);
|
|
data->scan_area = EXTERN_BITMAP;
|
|
break;
|
|
|
|
case 'S':
|
|
/* have debugreiserfs -p or -k to read all the device */
|
|
data->scan_area = ALL_BLOCKS;
|
|
break;
|
|
|
|
case 'U':
|
|
/* have debugreiserfs -p or -k to read unused blocks only */
|
|
data->scan_area = UNUSED_BLOCKS;
|
|
break;
|
|
|
|
case '1': /* print a single node */
|
|
data->block = strtol(optarg, &tmp, 0);
|
|
if (*tmp)
|
|
die("parse_options: bad block number");
|
|
break;
|
|
|
|
case 'C':
|
|
data->mode = DO_CORRUPT_ONE;
|
|
data->block = strtol(optarg, &tmp, 0);
|
|
if (*tmp) {
|
|
die("parse_options: bad block number");
|
|
}
|
|
break;
|
|
|
|
case 'F':
|
|
data->mode = DO_CORRUPT_FILE;
|
|
if (asprintf(&corruption_list_file, "%s", optarg) == -1) {
|
|
die("parse_options: bad list corruption file");
|
|
}
|
|
break;
|
|
|
|
case 'p':
|
|
data->mode = DO_PACK;
|
|
break;
|
|
|
|
case 'u':
|
|
data->mode = DO_UNPACK;
|
|
break;
|
|
|
|
case 't':
|
|
data->mode = DO_STAT;
|
|
break;
|
|
|
|
case 'k':
|
|
/* read the device and print reiserfs blocks which contain
|
|
defined key */
|
|
data->mode = DO_SCAN;
|
|
break;
|
|
|
|
case 'n': /* scan for names matching a specified pattern */
|
|
data->mode = DO_SCAN_FOR_NAME;
|
|
data->pattern = optarg;
|
|
/*asprintf (&data->pattern, "%s", optarg); */
|
|
break;
|
|
|
|
case 'N': /* search name in the tree */
|
|
data->mode = DO_LOOK_FOR_NAME;
|
|
break;
|
|
|
|
case 'f':
|
|
data->mode = DO_FILE_MAP;
|
|
break;
|
|
|
|
case 'r':
|
|
asprintf(&data->recovery_file, "%s", optarg);
|
|
data->mode = DO_RECOVER;
|
|
break;
|
|
|
|
case 'd':
|
|
/* print leaf details from internal tree */
|
|
data->options |= PRINT_TREE_DETAILS;
|
|
break;
|
|
|
|
case 'D':
|
|
/* print leaf details accordingly the bitmap - can be used
|
|
with -S */
|
|
data->options |= PRINT_DETAILS;
|
|
break;
|
|
|
|
case 'o':
|
|
/* print objectid map */
|
|
data->options |= PRINT_OBJECTID_MAP;
|
|
break;
|
|
|
|
case 'm': /* print a block map */
|
|
case 'M': /* print a block map with details */
|
|
data->options |= PRINT_BITMAP;
|
|
break;
|
|
|
|
case 'j': /* -j must have a parameter */
|
|
data->options |= PRINT_JOURNAL;
|
|
data->journal_device_name = optarg;
|
|
break;
|
|
|
|
case 'J':
|
|
data->options |= PRINT_JOURNAL_HEADER;
|
|
break;
|
|
|
|
case 'R': /* read block numbers from stdin and look for them in the
|
|
journal */
|
|
data->mode = DO_SCAN_JOURNAL;
|
|
data->JJ++;
|
|
break;
|
|
|
|
case 'B': /*disabled for a while */
|
|
asprintf(&badblocks_file, "%s", optarg);
|
|
data->mode = DO_EXTRACT_BADBLOCKS;
|
|
break;
|
|
case 'q':
|
|
/* this makes packing to not show speed info during -p or -P */
|
|
data->options |= BE_QUIET;
|
|
break;
|
|
case 'Z':
|
|
data->mode = DO_ZERO;
|
|
break;
|
|
|
|
case 'l': /* --logfile */
|
|
data->log_file_name = optarg;
|
|
data->log = fopen(optarg, "w");
|
|
if (!data->log) {
|
|
fprintf(stderr,
|
|
"debugreiserfs: Cannot not open "
|
|
"\'%s\': %s", optarg, strerror(errno));
|
|
}
|
|
break;
|
|
case 'L':
|
|
/* random fs corruption */
|
|
data->mode = DO_RANDOM_CORRUPTION;
|
|
break;
|
|
case 'V':
|
|
data->mode = DO_NOTHING;
|
|
break;
|
|
case 'v':
|
|
data->options |= BE_VERBOSE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (data->mode == DO_NOTHING) {
|
|
print_banner(program_name);
|
|
exit(0);
|
|
}
|
|
|
|
if (optind != argc - 1)
|
|
/* only one non-option argument is permitted */
|
|
print_usage_and_exit();
|
|
|
|
print_banner(program_name);
|
|
|
|
data->device_name = argv[optind];
|
|
return argv[optind];
|
|
}
|
|
|
|
void pack_partition(reiserfs_filsys_t *fs);
|
|
|
|
static void do_pack(reiserfs_filsys_t *fs)
|
|
{
|
|
if (certain_block(fs))
|
|
pack_one_block(fs, certain_block(fs));
|
|
else
|
|
pack_partition(fs);
|
|
}
|
|
|
|
/*
|
|
static int comp (const void * vp1, const void * vp2)
|
|
{
|
|
const int * p1, * p2;
|
|
|
|
p1 = vp1; p2 = vp2;
|
|
|
|
if (*p1 < *p2)
|
|
return -1;
|
|
if (*p1 > *p2)
|
|
return 1;
|
|
return 0;
|
|
}
|
|
*/
|
|
|
|
static void init_bitmap(reiserfs_filsys_t *fs)
|
|
{
|
|
FILE *fp;
|
|
unsigned long block_count;
|
|
|
|
if (reiserfs_open_ondisk_bitmap(fs) < 0)
|
|
reiserfs_exit(1, "Could not open ondisk bitmap");
|
|
|
|
block_count = get_sb_block_count(fs->fs_ondisk_sb);
|
|
|
|
switch (scan_area(fs)) {
|
|
case ALL_BLOCKS:
|
|
input_bitmap(fs) = reiserfs_create_bitmap(block_count);
|
|
reiserfs_bitmap_fill(input_bitmap(fs));
|
|
reiserfs_warning(stderr,
|
|
"Whole device (%u blocks) is to be scanned\n",
|
|
reiserfs_bitmap_ones(input_bitmap(fs)));
|
|
break;
|
|
case USED_BLOCKS:
|
|
reiserfs_warning(stderr, "Loading on-disk bitmap .. ");
|
|
input_bitmap(fs) = reiserfs_create_bitmap(block_count);
|
|
reiserfs_bitmap_copy(input_bitmap(fs), fs->fs_bitmap2);
|
|
reiserfs_warning(stderr, "%lu bits set - done\n",
|
|
reiserfs_bitmap_ones(input_bitmap(fs)));
|
|
break;
|
|
case UNUSED_BLOCKS:
|
|
reiserfs_warning(stderr, "Loading on-disk bitmap .. ");
|
|
input_bitmap(fs) = reiserfs_create_bitmap(block_count);
|
|
reiserfs_bitmap_copy(input_bitmap(fs), fs->fs_bitmap2);
|
|
reiserfs_bitmap_invert(input_bitmap(fs));
|
|
reiserfs_warning(stderr, "%lu bits set - done\n",
|
|
reiserfs_bitmap_ones(input_bitmap(fs)));
|
|
break;
|
|
case EXTERN_BITMAP:
|
|
fp = fopen(input_bitmap_file_name(fs), "r");
|
|
if (!fp) {
|
|
reiserfs_exit(1,
|
|
"init_bitmap: could not load bitmap: %m\n");
|
|
}
|
|
|
|
input_bitmap(fs) = reiserfs_bitmap_load(fp);
|
|
if (!input_bitmap(fs)) {
|
|
reiserfs_exit(1, "could not load fitmap from \"%s\"",
|
|
input_bitmap_file_name(fs));
|
|
}
|
|
reiserfs_warning(stderr,
|
|
"%u blocks marked in the given bitmap\n",
|
|
reiserfs_bitmap_ones(input_bitmap(fs)));
|
|
fclose(fp);
|
|
break;
|
|
default:
|
|
reiserfs_panic("No area to scan specified");
|
|
}
|
|
}
|
|
|
|
/* FIXME: statistics does not work */
|
|
static void do_dump_tree(reiserfs_filsys_t *fs)
|
|
{
|
|
if (certain_block(fs)) {
|
|
print_one_block(fs, certain_block(fs));
|
|
return;
|
|
}
|
|
|
|
if (((data(fs)->options & PRINT_JOURNAL) ||
|
|
(data(fs)->options & PRINT_JOURNAL_HEADER)) &&
|
|
!reiserfs_journal_opened(fs)) {
|
|
if (reiserfs_open_journal(fs, data(fs)->journal_device_name,
|
|
O_RDONLY)) {
|
|
printf("Could not open journal\n");
|
|
return;
|
|
}
|
|
}
|
|
|
|
print_filesystem_state(stdout, fs);
|
|
print_block(stdout, fs, fs->fs_super_bh);
|
|
|
|
if (data(fs)->options & PRINT_JOURNAL)
|
|
print_journal(fs);
|
|
|
|
if (data(fs)->options & PRINT_JOURNAL_HEADER)
|
|
print_journal_header(fs);
|
|
|
|
if (data(fs)->options & PRINT_OBJECTID_MAP)
|
|
print_objectid_map(stdout, fs);
|
|
|
|
if (data(fs)->options & PRINT_BITMAP)
|
|
print_bmap(stdout, fs,
|
|
0 /*opt_print_block_map == 1 ? 1 : 0 */ );
|
|
|
|
if (data(fs)->options & PRINT_DETAILS)
|
|
init_bitmap(fs);
|
|
|
|
if (data(fs)->options & PRINT_DETAILS ||
|
|
data(fs)->options & PRINT_TREE_DETAILS) {
|
|
if (data(fs)->options & PRINT_DETAILS) {
|
|
print_disk_blocks(fs);
|
|
printf("The '%s' device with reiserfs has:\n",
|
|
fs->fs_file_name);
|
|
} else {
|
|
print_disk_tree(fs,
|
|
get_sb_root_block(fs->fs_ondisk_sb));
|
|
printf("The internal reiserfs tree has:\n");
|
|
}
|
|
|
|
/* print the statistic */
|
|
printf("\t%u internal + %u leaves + %u "
|
|
"unformatted nodes = %u blocks\n",
|
|
g_stat_info.nr_internals, g_stat_info.nr_leaves,
|
|
g_stat_info.nr_unformatted, g_stat_info.nr_internals +
|
|
g_stat_info.nr_leaves + g_stat_info.nr_unformatted);
|
|
}
|
|
}
|
|
|
|
static void callback_badblock_print(reiserfs_filsys_t *fs,
|
|
struct reiserfs_path *badblock_path,
|
|
void *data)
|
|
{
|
|
struct item_head *tmp_ih;
|
|
FILE *fd = (FILE *) data;
|
|
__u32 *ind_item;
|
|
__u32 i;
|
|
|
|
tmp_ih = get_ih(badblock_path);
|
|
ind_item = (__u32 *) get_item(badblock_path);
|
|
|
|
for (i = 0; i < I_UNFM_NUM(tmp_ih); i++)
|
|
fprintf(fd, "%u\n", d32_get(ind_item, i));
|
|
|
|
pathrelse(badblock_path);
|
|
}
|
|
|
|
void extract_badblock_list()
|
|
{
|
|
FILE *fd;
|
|
|
|
if (!(fd = fopen(badblocks_file, "w"))) {
|
|
reiserfs_exit(1,
|
|
"debugreiserfs: could not open badblock file %s\n",
|
|
badblocks_file);
|
|
}
|
|
|
|
badblock_list(fs, callback_badblock_print, fd);
|
|
fclose(fd);
|
|
}
|
|
|
|
static int str2int(char *str, int *res)
|
|
{
|
|
int val;
|
|
char *tmp;
|
|
|
|
val = (int)strtol(str, &tmp, 0);
|
|
if (tmp == str)
|
|
/* could not convert string into a number */
|
|
return 0;
|
|
*res = val;
|
|
return 1;
|
|
}
|
|
|
|
void do_corrupt_blocks(reiserfs_filsys_t *fs)
|
|
{
|
|
char *line;
|
|
FILE *fd;
|
|
size_t n = 0;
|
|
int numblock;
|
|
|
|
fd = fopen(corruption_list_file, "r");
|
|
if (fd == NULL) {
|
|
reiserfs_exit(1, "debugreiserfs: could not open corruption "
|
|
"list file %s\n", corruption_list_file);
|
|
}
|
|
|
|
while (1) {
|
|
line = NULL;
|
|
n = 0;
|
|
if (getline(&line, &n, fd) == -1) {
|
|
break;
|
|
}
|
|
|
|
/* remove '\n' */
|
|
line[strlen(line) - 1] = '\0';
|
|
|
|
if (str2int(line, &numblock)) {
|
|
data(fs)->block = (unsigned long)numblock;
|
|
} else {
|
|
do_corrupt_one_block(fs, line);
|
|
}
|
|
printf("before free line : %s\n", line);
|
|
free(line);
|
|
printf("after free\n");
|
|
reiserfs_reopen(fs, O_RDWR);
|
|
}
|
|
fclose(fd);
|
|
return;
|
|
}
|
|
|
|
void debugreiserfs_zero_reiserfs(reiserfs_filsys_t *fs)
|
|
{
|
|
unsigned long done, total, i;
|
|
struct buffer_head *bh;
|
|
|
|
reiserfs_reopen(fs, O_RDWR);
|
|
|
|
total = reiserfs_bitmap_ones(input_bitmap(fs));
|
|
done = 0;
|
|
|
|
for (i = 0; i < input_bitmap(fs)->bm_bit_size; i++) {
|
|
if (!reiserfs_bitmap_test_bit(input_bitmap(fs), i))
|
|
continue;
|
|
|
|
bh = getblk(fs->fs_dev, i, fs->fs_blocksize);
|
|
|
|
if (!bh)
|
|
die("Could not get block %lu\n", i);
|
|
|
|
memset(bh->b_data, 0, fs->fs_blocksize);
|
|
mark_buffer_dirty(bh);
|
|
mark_buffer_uptodate(bh, 0);
|
|
|
|
bwrite(bh);
|
|
|
|
brelse(bh);
|
|
print_how_far(stderr, &done, total, 1, be_quiet(fs));
|
|
}
|
|
|
|
fprintf(stderr, "\n");
|
|
fflush(stderr);
|
|
}
|
|
|
|
/* FIXME: need to open reiserfs filesystem first */
|
|
int main(int argc, char *argv[])
|
|
{
|
|
char *file_name;
|
|
int error;
|
|
struct debugreiserfs_data *data;
|
|
|
|
data = getmem(sizeof(struct debugreiserfs_data));
|
|
file_name = parse_options(data, argc, argv);
|
|
|
|
if (data->mode == DO_UNPACK) {
|
|
do_unpack(file_name, data->journal_device_name,
|
|
data->input_bitmap, data->options & BE_VERBOSE);
|
|
return 0;
|
|
}
|
|
|
|
fs = reiserfs_open(file_name, O_RDONLY, &error, data, 0);
|
|
|
|
if (no_reiserfs_found(fs)) {
|
|
reiserfs_exit(1, "\n\ndebugreiserfs: can not open reiserfs on "
|
|
"\"%s\": %s\n\n", file_name,
|
|
error ? strerror(error)
|
|
: "no filesystem found");
|
|
exit(1);
|
|
}
|
|
|
|
if (reiserfs_open_journal(fs, data(fs)->journal_device_name, O_RDONLY)) {
|
|
fprintf(stderr,
|
|
"\ndebugreiserfs: Failed to open the fs journal.\n");
|
|
}
|
|
|
|
switch (debug_mode(fs)) {
|
|
case DO_STAT:
|
|
init_bitmap(fs);
|
|
do_stat(fs);
|
|
break;
|
|
|
|
case DO_PACK:
|
|
init_bitmap(fs);
|
|
do_pack(fs);
|
|
break;
|
|
|
|
case DO_CORRUPT_ONE:
|
|
reiserfs_reopen(fs, O_RDWR);
|
|
do_corrupt_one_block(fs, (char *)NULL);
|
|
break;
|
|
|
|
case DO_CORRUPT_FILE:
|
|
reiserfs_reopen(fs, O_RDWR);
|
|
do_corrupt_blocks(fs);
|
|
break;
|
|
case DO_RANDOM_CORRUPTION:
|
|
reiserfs_reopen(fs, O_RDWR);
|
|
/*
|
|
do_leaves_corruption (fs);
|
|
do_bitmap_corruption (fs);
|
|
*/
|
|
do_fs_random_corrupt(fs);
|
|
break;
|
|
|
|
case DO_DUMP:
|
|
do_dump_tree(fs);
|
|
break;
|
|
|
|
case DO_SCAN:
|
|
case DO_SCAN_FOR_NAME:
|
|
case DO_LOOK_FOR_NAME:
|
|
case DO_SCAN_JOURNAL:
|
|
init_bitmap(fs);
|
|
do_scan(fs);
|
|
break;
|
|
|
|
case DO_FILE_MAP:
|
|
print_map(fs);
|
|
break;
|
|
|
|
case DO_RECOVER:
|
|
do_recover(fs);
|
|
break;
|
|
|
|
case DO_TEST:
|
|
/*do_test (fs); */
|
|
break;
|
|
case DO_EXTRACT_BADBLOCKS:
|
|
reiserfs_warning(stderr,
|
|
"Will try to extract list of bad blocks "
|
|
"and save it to '%s' file\n", badblocks_file);
|
|
|
|
extract_badblock_list();
|
|
reiserfs_warning(stderr, "Done\n\n");
|
|
break;
|
|
case DO_ZERO:
|
|
init_bitmap(fs);
|
|
debugreiserfs_zero_reiserfs(fs);
|
|
break;
|
|
}
|
|
|
|
reiserfs_close(fs);
|
|
if (data(fs)->log) {
|
|
fclose(data(fs)->log);
|
|
}
|
|
return 0;
|
|
}
|