/* * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README */ #include "debugreiserfs.h" reiserfs_filsys_t fs; #define print_usage_and_exit() die ("Usage: %s [-b block-to-print][-idc] device\n\ -i Causes to print all items of a leaf\n\ -d content of directory items\n\ -c content of direct items\n\ -m bitmap blocks\n\ -t\n\ -C\n\ -p\n\ -s \n\ -n scan for name\n\ -p [filename]\n\ -P [filename]\n\ ..etc\n", argv[0]); #if 1 struct reiserfs_fsstat { int nr_internals; int nr_leaves; int nr_files; int nr_directories; int nr_unformatted; } g_stat_info; #endif int mode = DO_DUMP; /* * options */ int opt_print_regular_file_content = 0;/* -c */ int opt_print_details = 0; /* -d */ int opt_print_leaf_items = 0; /* -i */ int opt_print_objectid_map = 0; /* -o */ int opt_print_block_map = 0; /* -m */ int opt_print_journal; /* -j */ /* when you want print one block specify -b # */ int opt_block_to_print = -1; /* when you want to corrupt block specify -C # */ int opt_block_to_corrupt = -1; int opt_pack = 0; int opt_quiet = 0; int print_mode (void) { int mode = 0; if (opt_print_leaf_items == 1) mode |= PRINT_LEAF_ITEMS; if (opt_print_details == 1) mode |= (PRINT_LEAF_ITEMS | PRINT_ITEM_DETAILS); if (opt_print_regular_file_content == 1) mode |= (PRINT_LEAF_ITEMS | PRINT_DIRECT_ITEMS); return mode; } static void print_disk_tree (reiserfs_filsys_t fs, int block_nr) { struct buffer_head * bh; bh = bread (fs->s_dev, block_nr, fs->s_blocksize); if (!bh) { die ("Could not read block %d\n", block_nr); } if (is_internal_node (bh)) { int i; struct disk_child * dc; g_stat_info.nr_internals ++; print_block (stdout, fs, bh, print_mode (), -1, -1); dc = B_N_CHILD (bh, 0); for (i = 0; i <= B_NR_ITEMS (bh); i ++, dc ++) print_disk_tree (fs, dc->dc_block_number); } else if (is_leaf_node (bh)) { g_stat_info.nr_leaves ++; print_block (stdout, fs, bh, print_mode (), -1, -1); } else { print_block (stdout, fs, bh, print_mode (), -1, -1); die ("print_disk_tree: bad block type"); } brelse (bh); } void pack_one_block (reiserfs_filsys_t fs, unsigned long block); static void print_one_block (reiserfs_filsys_t fs, int block) { struct buffer_head * bh; if (test_bit (block % (fs->s_blocksize * 8), SB_AP_BITMAP (fs)[block / (fs->s_blocksize * 8)]->b_data)) fprintf (stderr, "%d is used in true bitmap\n", block); else fprintf (stderr, "%d is free in true bitmap\n", block); bh = bread (fs->s_dev, block, fs->s_blocksize); if (!bh) { printf ("print_one_block: bread fialed\n"); return; } if (opt_pack) { pack_one_block (fs, bh->b_blocknr); brelse (bh); return; } if (who_is_this (bh->b_data, fs->s_blocksize) != THE_UNKNOWN) print_block (stdout, fs, bh, PRINT_LEAF_ITEMS | PRINT_ITEM_DETAILS | (opt_print_regular_file_content == 1 ? PRINT_DIRECT_ITEMS : 0), -1, -1); else printf ("Looks like unformatted\n"); brelse (bh); return; } static void corrupt_clobber_hash (char * name, struct item_head * ih, struct reiserfs_de_head * deh) { printf ("\tCorrupting deh_offset of entry \"%s\" of [%u %u]\n", name, ih->ih_key.k_dir_id, ih->ih_key.k_objectid); deh->deh_offset = 700; } /* this reads list of desired corruptions from stdin and perform the corruptions. Format of that list: A hash_code C name objectid - 'C'ut entry 'name' from directory item with 'objectid' H name objectid - clobber 'H'hash of entry 'name' of directory 'objectid' I item_num pos_in_item make pos_in_item-th slot of indirect item to point out of device O item_num - destroy item 'O'rder - make 'item_num'-th to have key bigger than 'item_num' + 1-th item D item_num - 'D'elete item_num-th item S item_num value - change file size (item_num-th item must be stat data) F item_num value - change sd_first_direct_byte of stat data J item_num objectid E name objectid new - change entry's deh_objectid to new P - print the block */ static void do_corrupt_one_block (reiserfs_filsys_t fs, int block) { struct buffer_head * bh; int i, j; struct item_head * ih; int item_num; char * line = 0; int n = 0; char code, name [100]; __u32 objectid, new_objectid; int value; int hash_code; int pos_in_item; if (test_bit (block % (fs->s_blocksize * 8), SB_AP_BITMAP (fs)[block / (fs->s_blocksize * 8)]->b_data)) fprintf (stderr, "%d is used in true bitmap\n", block); else fprintf (stderr, "%d is free in true bitmap\n", block); bh = bread (fs->s_dev, block, fs->s_blocksize); if (!bh) { printf ("corrupt_one_block: bread fialed\n"); return; } if (who_is_this (bh->b_data, fs->s_blocksize) != THE_LEAF) { printf ("Can not corrupt not a leaf node\n"); brelse (bh); return; } printf ("Corrupting block %lu..\n", bh->b_blocknr); while (getline (&line, &n, stdin) != -1) { switch (line[0]) { case '#': case '\n': continue; case '?': printf ("A hash_code - reset hAsh code in super block\n" "C name objectid - Cut entry 'name' from directory item with 'objectid'\n" "H name objectid - clobber Hash of entry 'name' of directory 'objectid'\n" "I item_num pos_in_item make pos_in_tem-th slot of Indirect item to point out of device\n" "O item_num - destroy item Order - make 'item_num'-th to have key bigger than 'item_num' + 1-th item\n" "D item_num - Delete item_num-th item\n" "S item_num value - change file Size (item_num-th item must be stat data)\n" "F item_num value - change sd_First_direct_byte of stat data\n" "J item_num objectid - set 'obJectid' of 'item_num'-th item\n" "E name objectid objectid - set deh_objectid of an entry to objectid\n"); continue; case 'P': print_block (stderr, fs, bh, 3, -1, -1); break; case 'A': /* corrupt hash record in super block */ if (sscanf (line, "%c %d\n", &code, &hash_code) != 2) { printf ("Wrong format \'%c\'\n", line [0]); continue; } break; case 'C': /* cut entry */ case 'H': /* make hash wrong */ if (sscanf (line, "%c %s %u\n", &code, name, &objectid) != 3) { printf ("Wrong format \'%c\'\n", line [0]); continue; } break; case 'J': /* set objectid : used to simulate objectid sharing problem */ if (sscanf (line, "%c %d %d\n", &code, &item_num, &objectid) != 3) { printf ("Wrong format \'%c\'\n", line [0]); continue; } break; case 'E': /* set objectid : used to simulate objectid sharing problem */ if (sscanf (line, "%c %s %u %d\n", &code, name, &objectid, &new_objectid) != 4) { printf ("Wrong format \'%c\'\n", line [0]); continue; } break; case 'I': /* break unformatted node pointer */ if (sscanf (line, "%c %d %d\n", &code, &item_num, &pos_in_item) != 3) { printf ("Wrong format \'%c\'\n", line [0]); continue; } break; case 'D': /* delete item */ case 'O': /* make item out of order */ if (sscanf (line, "%c %d\n", &code, &item_num) != 2) { printf ("Wrong format \'%c\'\n", line [0]); continue; } break; case 'S': /* corrupt st_size */ case 'F': /* st_first_direct_byte */ if (sscanf (line, "%c %d %d\n", &code, &item_num, &value) != 3) { printf ("Wrong format \'%c\'\n", line [0]); continue; } break; } if (code == 'A') { reiserfs_warning (stderr, "Changing %s to %s\n", code2name (rs_hash (fs->s_rs)), code2name (hash_code)); set_hash (fs->s_rs, hash_code); mark_buffer_dirty (fs->s_sbh); continue; } ih = B_N_PITEM_HEAD (bh, 0); for (i = 0; i < node_item_number (bh); i ++, ih ++) { struct reiserfs_de_head * deh; if (code == 'I' && i == item_num) { if (!is_indirect_ih (ih) || pos_in_item >= I_UNFM_NUM (ih)) { reiserfs_warning (stderr, "Not an indirect item or there is " "not so many unfm ptrs in it\n"); continue; } * ((__u32 *)B_I_PITEM (bh, ih) + pos_in_item) = SB_BLOCK_COUNT(fs) + 100; mark_buffer_dirty (bh); goto cont; } if (code == 'J' && i == item_num) { ih->ih_key.k_objectid = objectid; mark_buffer_dirty (bh); goto cont; } if (code == 'S' && i == item_num) { /* fixme: old stat data only */ struct stat_data_v1 * sd; sd = (struct stat_data_v1 *)B_I_PITEM (bh, ih); reiserfs_warning (stderr, "Changing sd_size of %k from %d to %d\n", &ih->ih_key, sd->sd_size, value); sd->sd_size = value; mark_buffer_dirty (bh); goto cont; } if (code == 'F' && i == item_num) { /* fixme: old stat data only */ struct stat_data_v1 * sd; sd = (struct stat_data_v1 *)B_I_PITEM (bh, ih); reiserfs_warning (stderr, "Changing sd_first_direct_byte of %k from %d to %d\n", &ih->ih_key, sd->sd_first_direct_byte, value); sd->sd_first_direct_byte = value; mark_buffer_dirty (bh); goto cont; } if (code == 'D' && i == item_num) { delete_item (fs, bh, item_num); mark_buffer_dirty (bh); goto cont; } if (code == 'O' && i == item_num) { /* destroy item order */ struct key * key; if (i == node_item_number (bh) - 1) { printf ("can not destroy order\n"); continue; } key = &(ih + 1)->ih_key; ih->ih_key.k_dir_id = key->k_dir_id + 1; mark_buffer_dirty (bh); } if (ih->ih_key.k_objectid != objectid || !is_direntry_ih (ih)) continue; deh = B_I_DEH (bh, ih); for (j = 0; j < ih_entry_count (ih); j ++, deh ++) { /* look for proper entry */ if (name_length (ih, deh, j) != strlen (name) || strncmp (name, name_in_entry (deh, j), strlen (name))) continue; /* ok, required entry found, make a corruption */ switch (code) { case 'C': /* cut entry */ cut_entry (fs, bh, i, j, 1); mark_buffer_dirty (bh); if (!B_IS_IN_TREE (bh)) { printf ("NOTE: block is deleted from the tree\n"); exit (0); } goto cont; break; case 'H': /* clobber hash */ corrupt_clobber_hash (name, ih, deh); goto cont; break; case 'E': /* change entry's deh_objectid */ deh->deh_objectid = new_objectid; break; default: printf ("Unknown command found\n"); } mark_buffer_dirty (bh); } } cont: } free (line); printf ("Done\n"); brelse (bh); return; } /* this reads stdin and recover file of given key: */ /* the input has to be in the follwong format: K dirid objectid N name B blocknumber .. then recover_file will read every block, look there specified file and put it into */ static void do_recover (reiserfs_filsys_t fs) { char name [100]; char * line = 0; int n = 0; int fd; struct key key = {0, 0, }; struct buffer_head * bh; struct item_head * ih; unsigned long block; char code; loff_t recovered = 0; int i, j; reiserfs_bitmap_t bitmap; int used, not_used; bitmap = reiserfs_create_bitmap (SB_BLOCK_COUNT (fs)); reiserfs_fetch_disk_bitmap (bitmap, fs); /* we check how many blocks recoverd items point to are free or used */ used = 0; not_used = 0; fd = 0; while (getline (&line, &n, stdin) != -1) { if (line [0] == '#' || line [0] == '\n') continue; switch (line [0]) { case 'K': /* get a key of file which is to be recovered */ if (sscanf (line, "%c %u %u\n", &code, &key.k_dir_id, &key.k_objectid) != 3) { die ("recover_file: wrong input K format"); } printf ("Recovering file (%u, %u)\n", key.k_dir_id, key.k_objectid); break; case 'N': /* get a file name */ recovered = 0; if (sscanf (line, "%c %s\n", &code, name) != 2) { die ("recover_file: wrong input N format"); } fd = open (name, O_RDWR | O_CREAT | O_EXCL, 0644); if (fd == -1) die ("recover_file: could not create file %s: %s", name,strerror (errno)); printf ("Recovering file %s..\n", name); break; case 'B': if (!fd) die ("recover_file: file name is not specified"); if (sscanf (line, "%c %lu\n", &code, &block) != 2) { die ("recover_file: wrong input B format"); } bh = bread (fs->s_dev, block, fs->s_blocksize); if (!bh) { printf ("reading block %lu failed\n", block); continue; } printf ("working with block %lu..\n", block); ih = B_N_PITEM_HEAD (bh, 0); for (i = 0; i < node_item_number (bh); i ++, ih ++) { __u32 * indirect; struct buffer_head * tmp_bh; if (!is_indirect_ih (ih) || key.k_dir_id != ih->ih_key.k_dir_id || key.k_objectid != ih->ih_key.k_objectid) continue; indirect = (__u32 *)B_I_PITEM (bh, ih); for (j = 0; j < I_UNFM_NUM (ih); j ++) { block = le32_to_cpu (indirect [j]); if (!block) continue; tmp_bh = bread (fs->s_dev, block, fs->s_blocksize); if (!tmp_bh) { printf ("reading block %Lu failed\n", (loff_t)block * fs->s_blocksize); continue; } if (lseek64 (fd, get_offset (&ih->ih_key) + j * fs->s_blocksize - 1, SEEK_SET) == (loff_t)-1) { printf ("llseek failed to pos %Ld\n", (loff_t)block * fs->s_blocksize); brelse (tmp_bh); continue; } if (reiserfs_bitmap_test_bit (bitmap, block)) used ++; else not_used ++; /*printf ("block of file %Ld gets block %lu\n", (get_offset (&ih->ih_key) - 1) / fs->s_blocksize + j, block);*/ if (write (fd, tmp_bh->b_data, tmp_bh->b_size) != tmp_bh->b_size) { printf ("write failed to pos %Ld\n", (loff_t)block * fs->s_blocksize); brelse (tmp_bh); continue; } recovered += fs->s_blocksize; brelse (tmp_bh); } } brelse (bh); break; } } printf ("recover_file: %Ld bytes recovered of file %s, key %u %u, %d blocks are free and %d are used\n", recovered, name, key.k_dir_id, key.k_objectid, not_used, used); } /* 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; static char * parse_options (int argc, char * argv []) { int c; char * tmp; while ((c = getopt (argc, argv, "b:C:icdmoMp:P:l:jsnrtu:q")) != EOF) { switch (c) { case 'b': /* print a single node */ opt_block_to_print = strtol (optarg, &tmp, 0); if (*tmp) die ("parse_options: bad block number"); break; case 'C': mode = DO_CORRUPT; opt_block_to_corrupt = strtol (optarg, &tmp, 0); if (*tmp) die ("parse_options: bad block number"); break; case 'p': mode = DO_PACK; if (optarg) /* save bitmap of packed blocks in the file 'optarg' */ asprintf (&where_to_save, "%s", optarg); break; case 'P': /* scan whole device and pack all blocks looking like a leaf */ mode = DO_PACK_ALL; fprintf (stderr, "optarg %s\n", optarg); if (optarg) /* save bitmap of packed blocks in the file 'optarg' */ asprintf (&where_to_save, "%s", optarg); break; case 'i': /* print items of a leaf */ opt_print_leaf_items = 1; break; case 'd': /* print directories */ opt_print_details = 1; break; case 'c': /* print contents of a regular file */ opt_print_regular_file_content = 1; break; case 'o': /* print a objectid map */ opt_print_objectid_map = 1; break; case 'm': /* print a block map */ opt_print_block_map = 1; break; case 'M': /* print a block map with details */ opt_print_block_map = 2; break; case 'j': opt_print_journal = 1; break; /* print journal */ case 's': mode = DO_SCAN; break; /* read the device and print what reiserfs blocks were found */ case 'n': mode = DO_SCAN_FOR_NAME; break; case 'r': mode = DO_RECOVER; break; case 't': mode = DO_TEST; break; case 'q': /* this makes packing to not show speed info during -p or -P */ opt_quiet = 1; break; } } if (optind != argc - 1) /* only one non-option argument is permitted */ print_usage_and_exit(); return argv[optind]; } /* print all valid transactions and found dec blocks */ static void print_journal (struct super_block * s) { struct buffer_head * d_bh, * c_bh; struct reiserfs_journal_desc * desc ; struct reiserfs_journal_commit *commit ; int end_journal; int start_journal; int i, j; int first_desc_block = 0; int wrapped = 0; int valid_transactions = 0; start_journal = SB_JOURNAL_BLOCK (s); end_journal = start_journal + JOURNAL_BLOCK_COUNT; reiserfs_warning (stdout, "Start scanning from %d\n", start_journal); d_bh = 0; desc = 0; for (i = start_journal; i < end_journal; i ++) { d_bh = bread (s->s_dev, i, s->s_blocksize); if (who_is_this (d_bh->b_data, d_bh->b_size) == THE_JDESC) { int commit_block; if (first_desc_block == 0) /* store where first desc block found */ first_desc_block = i; print_block (stdout, s, d_bh); /* reiserfs_journal_desc structure will be printed */ desc = (struct reiserfs_journal_desc *)(d_bh->b_data); commit_block = d_bh->b_blocknr + desc->j_len + 1; if (commit_block >= end_journal) { reiserfs_warning (stdout, "-- wrapped?"); wrapped = 1; break; } c_bh = bread (s->s_dev, commit_block, s->s_blocksize); commit = bh_commit (c_bh); if (does_desc_match_commit (desc, commit)) { reiserfs_warning (stdout, "commit block %d (trans_id %ld, j_len %ld) does not match\n", commit_block, commit->j_trans_id, commit->j_len); brelse (c_bh) ; brelse (d_bh); continue; } valid_transactions ++; reiserfs_warning (stdout, "(commit block %d) - logged blocks (", commit_block); #if 1 for (j = 0; j < desc->j_len; j ++) { unsigned long block; if (j < JOURNAL_TRANS_HALF) block = le32_to_cpu (desc->j_realblock[j]); else block = le32_to_cpu (commit->j_realblock[i - JOURNAL_TRANS_HALF]); if (not_journalable (s, block)) reiserfs_warning (stdout, " xxxx"); else { reiserfs_warning (stdout, " %ld", desc->j_realblock[j]); if (block_of_bitmap (s, desc->j_realblock[j])) reiserfs_warning (stdout, "(bmp)"); } if (j && (j + 1) % 10 == 0) reiserfs_warning (stdout, "\n"); } #endif reiserfs_warning (stdout, ")\n"); i += desc->j_len + 1; brelse (c_bh); } brelse (d_bh); } if (wrapped) { c_bh = bread (s->s_dev, first_desc_block - 1, s->s_blocksize); commit = bh_commit (c_bh); if (does_desc_match_commit (desc, commit)) { reiserfs_warning (stdout, "No! commit block %d (trans_id %ld, j_len %ld) does not match\n", first_desc_block - 1, commit->j_trans_id, commit->j_len); } else { reiserfs_warning (stdout, "Yes! (commit block %d) - logged blocks (\n", first_desc_block - 1); #if 1 for (j = 0; j < desc->j_len; j ++) { unsigned long block; if (j < JOURNAL_TRANS_HALF) block = le32_to_cpu (desc->j_realblock[j]); else block = le32_to_cpu (commit->j_realblock[i - JOURNAL_TRANS_HALF]); if (not_journalable (s, block)) reiserfs_warning (stdout, " xxxx"); else { reiserfs_warning (stdout, " %ld", desc->j_realblock[j]); if (block_of_bitmap (s, desc->j_realblock[j])) reiserfs_warning (stdout, "(bmp)"); } } #endif reiserfs_warning (stdout, "\n"); } brelse (c_bh) ; brelse (d_bh); } reiserfs_warning (stdout, "%d valid transactions found\n", valid_transactions); { struct buffer_head * bh; struct reiserfs_journal_header * j_head; bh = bread (s->s_dev, SB_JOURNAL_BLOCK (s) + rs_journal_size (s->s_rs), s->s_blocksize); j_head = (struct reiserfs_journal_header *)(bh->b_data); reiserfs_warning (stdout, "#######################\nJournal header:\n" "j_last_flush_trans_id %ld\n" "j_first_unflushed_offset %ld\n" "j_mount_id %ld\n", j_head->j_last_flush_trans_id, j_head->j_first_unflushed_offset, j_head->j_mount_id); brelse (bh); } } void pack_partition (reiserfs_filsys_t fs); static void do_pack (reiserfs_filsys_t fs) { if (opt_block_to_print != -1) pack_one_block (fs, opt_block_to_print); else pack_partition (fs); } /* FIXME: statistics does not work */ static void do_dump_tree (reiserfs_filsys_t fs) { if (opt_block_to_print != -1) { print_one_block (fs, opt_block_to_print); return; } print_block (stdout, fs, SB_BUFFER_WITH_SB (fs)); if (opt_print_journal) print_journal (fs); if (opt_print_objectid_map == 1) print_objectid_map (stdout, fs); if (opt_print_block_map) print_bmap (stdout, fs, opt_print_block_map == 1 ? 1 : 0); if (opt_print_regular_file_content || opt_print_details || opt_print_leaf_items) { print_disk_tree (fs, SB_ROOT_BLOCK (fs)); /* print the statistic */ printf ("File system uses %d internal + %d leaves + %d unformatted nodes = %d 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); } } FILE * log; static void look_for_key (struct buffer_head * bh, struct key * key) { int i, j; struct item_head * ih; struct reiserfs_de_head * deh; ih = B_N_PITEM_HEAD (bh, 0); for (i = 0; i < B_NR_ITEMS (bh); i ++, ih ++) { if ((ih->ih_key.k_dir_id == key->k_dir_id || (int)key->k_dir_id == -1) && ih->ih_key.k_objectid == key->k_objectid) { reiserfs_warning (log, "%d-th item of block %lu is item of file %K: %H\n", i, bh->b_blocknr, key, ih); } if (!is_direntry_ih (ih)) continue; deh = B_I_DEH (bh, ih); for (j = 0; j < ih_entry_count (ih); j ++, deh ++) { if ((deh->deh_dir_id == key->k_dir_id || (int)key->k_dir_id == -1) && deh->deh_objectid == key->k_objectid) { reiserfs_warning (log, "dir item %d (%H) of block %lu has " "entry (%d-th) %.*s pointing to %K\n", i, ih, bh->b_blocknr, j, name_length (ih, deh, j), name_in_entry (deh, j), key); } } } return; } static void look_for_name (struct buffer_head * bh, char * name) { int i, j; struct item_head * ih; struct reiserfs_de_head * deh; int namelen; char * p; ih = B_N_PITEM_HEAD (bh, 0); for (i = 0; i < B_NR_ITEMS (bh); i ++, ih ++) { if (!is_direntry_ih (ih)) continue; deh = B_I_DEH (bh, ih); for (j = 0; j < ih_entry_count (ih); j ++, deh ++) { p = name_in_entry (deh, j); namelen = name_length (ih, deh, j); if (namelen == strlen (name) && !strncmp (name, p, namelen)) { fprintf (log, "block %lu, item %d, entry %d is %s\n", bh->b_blocknr, i, j, name);fflush (log); } } } return; } static void do_scan (reiserfs_filsys_t fs) { unsigned long i; struct buffer_head * bh; int type; char * answer = 0; size_t n = 0; struct key key = {0, 0, }; unsigned long done, total; reiserfs_bitmap_t bitmap; bitmap = reiserfs_bitmap_load (".bitmap"); total = reiserfs_bitmap_ones (bitmap); /* bitmap = reiserfs_create_bitmap (SB_BLOCK_COUNT (fs)); reiserfs_fetch_disk_bitmap (bitmap, fs); */ log = fopen ("scan.log", "w+"); if (mode == DO_SCAN_FOR_NAME) { printf ("What name do you want to look for?"); getline (&answer, &n, stdin); answer [strlen (answer) - 1] = 0; printf ("Looking for name \"%s\"..\n", answer); key.k_dir_id = 1; } else { printf ("What key do you want to find: dirid?"); getline (&answer, &n, stdin); key.k_dir_id = atoi (answer); printf ("objectid?"); getline (&answer, &n, stdin); key.k_objectid = atoi (answer); printf ("looking for (%u %u)\n", key.k_dir_id, key.k_objectid); } done = 0; for (i = 0; i < SB_BLOCK_COUNT (fs); i ++) { if (!reiserfs_bitmap_test_bit (bitmap, i)) continue; bh = bread (fs->s_dev, i, fs->s_blocksize); if (!bh) { printf ("could not read block %lu\n", i); continue; } type = who_is_this (bh->b_data, bh->b_size); switch (type) { case THE_JDESC: if (!key.k_dir_id) printf ("block %lu is journal descriptor\n", i); break; case THE_SUPER: if (!key.k_dir_id) printf ("block %lu is reiserfs super block\n", i); break; case THE_INTERNAL: if (!key.k_dir_id) printf ("block %lu is reiserfs internal node\n", i); break; case THE_LEAF: if (mode == DO_SCAN_FOR_NAME) { look_for_name (bh, answer); } else if (key.k_dir_id) { look_for_key (bh, &key); } else { printf ("block %lu is reiserfs leaf node\n", i); } break; } brelse (bh); print_how_far (&done, total, 1, 0); } } #if 0 static void do_test (reiserfs_filsys_t fs, unsigned long block) { struct buffer_head * bh; fprintf (stderr, "=========== BLock %lu ============\n", block); bh = bread (fs->s_dev, block, fs->s_blocksize); if (!bh) die ("do_test: bread failed"); if (is_leaf_bad (bh)) fprintf (stderr, "\n######### BAD before repairing ############\n"); else fprintf (stderr, "\n========= OK before repairing ==================\n"); print_block (fs, bh, 3, -1, -1); fprintf (stderr, "\n>>> repairing >>>>........\n\n"); /* function to test */pass0_correct_leaf (fs, bh); if (is_leaf_bad (bh)) fprintf (stderr, "\n######### still BAD after repairing ############\n"); else fprintf (stderr, "\n========= OK after repairing ==================\n"); print_block (fs, bh, 3, -1, -1); brelse (bh); } #endif static void do_test (reiserfs_filsys_t fs) { struct key root_dir_key = {REISERFS_ROOT_PARENT_OBJECTID, REISERFS_ROOT_OBJECTID, {{0, 0},}}; int gen_counter; if (reiserfs_find_entry (fs, &root_dir_key, "lost+found", &gen_counter)) reiserfs_add_entry (fs, &root_dir_key, "lost+found", &root_dir_key, 0); } /* FIXME: need to open reiserfs filesystem first */ int main (int argc, char * argv[]) { char * file_name; int error; print_banner ("debugreiserfs"); file_name = parse_options (argc, argv); fs = reiserfs_open (file_name, O_RDONLY, &error, 0); if (!fs) { fprintf (stderr, "\n\ndumpreiserfs: can not open reiserfs on \"%s\": %s\n\n", file_name, error ? strerror (error) : "there is no one"); return 0; } switch (mode) { case DO_PACK: case DO_PACK_ALL: do_pack (fs); break; case DO_CORRUPT: reiserfs_reopen (fs, O_RDWR); do_corrupt_one_block (fs, opt_block_to_corrupt); break; case DO_DUMP: do_dump_tree (fs); break; case DO_SCAN: case DO_SCAN_FOR_NAME: do_scan (fs); break; case DO_RECOVER: do_recover (fs); break; case DO_TEST: { do_test (fs); #if 0 int i; int arr[] = {53033}; if (opt_block_to_print != -1) { do_test (fs, opt_block_to_print); break; } bad blocks found on Joop partition 53033, 179201, 844702, 844913, 877768, 879067, 907631, 925323, 2241275, 2241343, 2241397, 2241511, 2241553, 2241635, 2241644, 2241654, 2241711, 2241721, 2241727, 2241740, 2241762, 2241766, 2241770, 2241812, 2241820, 2241827, 2241831, 2241878, 2241886, 2241971 }; /* blocks containing broken directory items on Joop's filesystem */ int arr[] = {/*53033,*/ 838396/*, 1597036*//*, 1919589, 2715962*/}; for (i = 0; i < sizeof (arr) / sizeof (arr[0]); i ++) do_test (fs, arr[i]); break; #endif } } reiserfs_close (fs); return 0; }