static void htree_dump_int_block(ext2_filsys fs, ext2_ino_t ino, struct ext2_inode *inode, struct ext2_dx_root_info * rootnode, blk_t blk, char *buf, int level) { char *cbuf; errcode_t errcode; blk_t pblk; cbuf = malloc(fs->blocksize); if (!cbuf) { fprintf(pager, "Couldn't allocate child block.\n"); return; } errcode = ext2fs_bmap(fs, ino, inode, buf, 0, blk, &pblk); if (errcode) { com_err("htree_dump_int_block", errcode, "while mapping logical block %u\n", blk); goto errout; } errcode = io_channel_read_blk(current_fs->io, pblk, 1, buf); if (errcode) { com_err("htree_dump_int_block", errcode, "while reading block %u\n", blk); goto errout; } htree_dump_int_node(fs, ino, inode, rootnode, (struct ext2_dx_entry *) (buf+8), cbuf, level); errout: free(cbuf); }
int empty_pass1(ext2_filsys fs, blk_t *block_nr, e2_blkcnt_t blockcnt, blk_t ref_block, int ref_offset, void *priv_data) { empty_dir_info edi = (empty_dir_info) priv_data; blk_t block, new_block; errcode_t retval; if (blockcnt < 0) return 0; block = *block_nr; do { retval = ext2fs_bmap(fs, edi->ino, &edi->inode, edi->block_buf, 0, edi->logblk, &new_block); if (retval) return DIRENT_ABORT; if (new_block == 0) break; edi->logblk++; } while (ext2fs_test_block_bitmap(edi->empty_dir_blocks, new_block)); if (new_block == block) return 0; if (new_block == 0) edi->freed_blocks++; *block_nr = new_block; return BLOCK_CHANGED; }
/* Kernel compatibility functions for handling the journal. These allow us * to use the recovery.c file virtually unchanged from the kernel, so we * don't have to do much to keep kernel and user recovery in sync. */ int journal_bmap(journal_t *journal, blk_t block, unsigned long *phys) { #ifdef USE_INODE_IO *phys = block; return 0; #else struct inode *inode = journal->j_inode; errcode_t retval; blk_t pblk; if (!inode) { *phys = block; return 0; } retval= ext2fs_bmap(inode->i_ctx->fs, inode->i_ino, &inode->i_ext2, NULL, 0, block, &pblk); *phys = pblk; return (retval); #endif }
static errcode_t parse_bmap(struct field_set_info *info, char *arg) { unsigned long num; blk_t blk; errcode_t retval; char *tmp; num = strtoul(arg, &tmp, 0); if (*tmp) { fprintf(stderr, "Couldn't parse '%s' for field %s.\n", arg, info->name); return EINVAL; } blk = num; retval = ext2fs_bmap(current_fs, set_ino, &set_inode, 0, BMAP_SET, array_idx, &blk); if (retval) { com_err("set_inode", retval, "while setting block map"); } return retval; }
static void htree_dump_leaf_node(ext2_filsys fs, ext2_ino_t ino, struct ext2_inode *inode, struct ext2_dx_root_info * rootnode, blk_t blk, char *buf) { errcode_t errcode; struct ext2_dir_entry *dirent; int thislen, col = 0; unsigned int offset = 0; char name[EXT2_NAME_LEN + 1]; char tmp[EXT2_NAME_LEN + 16]; blk_t pblk; ext2_dirhash_t hash, minor_hash; unsigned int rec_len; int hash_alg; errcode = ext2fs_bmap(fs, ino, inode, buf, 0, blk, &pblk); if (errcode) { com_err("htree_dump_leaf_node", errcode, "while mapping logical block %u\n", blk); return; } printf("Reading directory block %lu, phys %lu\n", (unsigned long) blk, (unsigned long) pblk); errcode = ext2fs_read_dir_block2(current_fs, pblk, buf, 0); if (errcode) { com_err("htree_dump_leaf_node", errcode, "while reading block %lu (%lu)\n", (unsigned long) blk, (unsigned long) pblk); return; } hash_alg = rootnode->hash_version; if ((hash_alg <= EXT2_HASH_TEA) && (fs->super->s_flags & EXT2_FLAGS_UNSIGNED_HASH)) hash_alg += 3; while (offset < fs->blocksize) { dirent = (struct ext2_dir_entry *) (buf + offset); errcode = ext2fs_get_rec_len(fs, dirent, &rec_len); if (errcode) { com_err("htree_dump_leaf_inode", errcode, "while getting rec_len for block %lu", (unsigned long) blk); return; } if (((offset + rec_len) > fs->blocksize) || (rec_len < 8) || ((rec_len % 4) != 0) || ((((unsigned) dirent->name_len & 0xFF)+8) > rec_len)) { fprintf(pager, "Corrupted directory block (%u)!\n", blk); break; } thislen = ((dirent->name_len & 0xFF) < EXT2_NAME_LEN) ? (dirent->name_len & 0xFF) : EXT2_NAME_LEN; strncpy(name, dirent->name, thislen); name[thislen] = '\0'; errcode = ext2fs_dirhash(hash_alg, name, thislen, fs->super->s_hash_seed, &hash, &minor_hash); if (errcode) com_err("htree_dump_leaf_node", errcode, "while calculating hash"); sprintf(tmp, "%u 0x%08x-%08x (%d) %s ", dirent->inode, hash, minor_hash, rec_len, name); thislen = strlen(tmp); if (col + thislen > 80) { fprintf(pager, "\n"); col = 0; } fprintf(pager, "%s", tmp); col += thislen; offset += rec_len; } fprintf(pager, "\n"); }
void do_htree_dump(int argc, char *argv[]) { ext2_ino_t ino; struct ext2_inode inode; int c; int long_opt = 0; blk_t blk; char *buf = NULL; struct ext2_dx_root_info *rootnode; struct ext2_dx_entry *ent; struct ext2_dx_countlimit *limit; errcode_t errcode; if (check_fs_open(argv[0])) return; pager = open_pager(); reset_getopt(); while ((c = getopt (argc, argv, "l")) != EOF) { switch (c) { case 'l': long_opt++; break; default: goto print_usage; } } if (argc > optind+1) { print_usage: com_err(0, 0, "Usage: htree_dump [-l] file"); goto errout; } if (argc == optind) ino = cwd; else ino = string_to_inode(argv[optind]); if (!ino) goto errout; if (debugfs_read_inode(ino, &inode, argv[1])) goto errout; if (!LINUX_S_ISDIR(inode.i_mode)) { com_err(argv[0], 0, "Not a directory"); goto errout; } if ((inode.i_flags & EXT2_BTREE_FL) == 0) { com_err(argv[0], 0, "Not a hash-indexed directory"); goto errout; } buf = malloc(2*current_fs->blocksize); if (!buf) { com_err(argv[0], 0, "Couldn't allocate htree buffer"); goto errout; } errcode = ext2fs_bmap(current_fs, ino, &inode, buf, 0, 0, &blk); if (errcode) { com_err("do_htree_block", errcode, "while mapping logical block 0\n"); goto errout; } errcode = io_channel_read_blk(current_fs->io, blk, 1, buf); if (errcode) { com_err(argv[0], errcode, "Error reading root node"); goto errout; } rootnode = (struct ext2_dx_root_info *) (buf + 24); fprintf(pager, "Root node dump:\n"); fprintf(pager, "\t Reserved zero: %u\n", rootnode->reserved_zero); fprintf(pager, "\t Hash Version: %d\n", rootnode->hash_version); fprintf(pager, "\t Info length: %d\n", rootnode->info_length); fprintf(pager, "\t Indirect levels: %d\n", rootnode->indirect_levels); fprintf(pager, "\t Flags: %d\n", rootnode->unused_flags); ent = (struct ext2_dx_entry *) (buf + 24 + rootnode->info_length); limit = (struct ext2_dx_countlimit *) ent; htree_dump_int_node(current_fs, ino, &inode, rootnode, ent, buf + current_fs->blocksize, rootnode->indirect_levels); errout: free(buf); close_pager(pager); }